Add windows enterprise app install feature

revert-dabc3590
Saad Sahibjan 6 years ago
parent ab40b7b6b8
commit 8838286f9a

@ -0,0 +1,277 @@
/*
* 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.windows.api.bean;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.SyncmlOperationException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.ProfileConfigurationException;
import org.wso2.carbon.device.mgt.mobile.windows.api.operations.*;
import org.wso2.carbon.device.mgt.mobile.windows.api.operations.util.Constants;
import org.wso2.carbon.device.mgt.mobile.windows.api.operations.util.OperationCode;
import org.wso2.carbon.device.mgt.mobile.windows.api.operations.util.SyncmlGenerator;
import java.util.ArrayList;
import java.util.List;
@ApiModel(value = "EnterpriseApplication", description = "Information related to Enterprise Application.")
public class EnterpriseApplication extends WindowsOperation {
private static Log log = LogFactory.getLog(EnterpriseApplication.class);
@ApiModelProperty(name = "packageURL", value = "Package URL.")
private HostedAppxApplication hostedAppxApplication;
@ApiModelProperty(name = "packageFamilyName", value = "Package family name.")
private HostedMSIApplication hostedMSIApplication;
public HostedAppxApplication getHostedAppxApplication() {
return hostedAppxApplication;
}
public void setHostedAppxApplication(HostedAppxApplication hostedAppxApplication) {
this.hostedAppxApplication = hostedAppxApplication;
}
public HostedMSIApplication getHostedMSIApplication() {
return hostedMSIApplication;
}
public void setHostedMSIApplication(HostedMSIApplication hostedMSIApplication) {
this.hostedMSIApplication = hostedMSIApplication;
}
public void validateRequest() throws ProfileConfigurationException {
if (getHostedAppxApplication() != null) {
if (isNullOrEmpty(getHostedAppxApplication().getpackageUri())) {
throw new ProfileConfigurationException(
"Appx package URL is not found for enterprise app installation");
}
if (isNullOrEmpty(getHostedAppxApplication().getpackageFamilyName())) {
throw new ProfileConfigurationException(
"Appx package Family Name is not found for enterprise app installation");
}
} else if (getHostedMSIApplication() != null) {
if (isNullOrEmpty(getHostedMSIApplication().getProductId())) {
throw new ProfileConfigurationException(
"MSI product ID is not found for enterprise app installation");
}
if (isNullOrEmpty(getHostedMSIApplication().getContentUrl())) {
throw new ProfileConfigurationException(
"MSI product content download URL is not found for enterprise app installation");
}
if (isNullOrEmpty(getHostedMSIApplication().getFileHash())) {
throw new ProfileConfigurationException(
"MSI product file hash is not found for enterprise app installation");
}
} else {
throw new ProfileConfigurationException("MSI or APPX payload is not found for enterprise app installation");
}
}
@Override
public List<Object> createOperationContent(Operation operation) throws WindowsOperationException {
List<Object> enterpriseApplicationContent = new ArrayList<>();
if (getHostedAppxApplication() != null) {
enterpriseApplicationContent.addAll(createAddTag(operation.getId(),
OperationCode.Command.INSTALL_ENTERPRISE_APPX_APPLICATION.getCode(),
PluginConstants.ApplicationInstallProperties.PACKAGE_FAMILY_NAME,
getHostedAppxApplication().getpackageFamilyName(),
PluginConstants.ApplicationInstallProperties.TYPE_APPX));
enterpriseApplicationContent.addAll(createExecuteTag(operation.getId(),
OperationCode.Command.INSTALL_ENTERPRISE_APPX_APPLICATION.getCode(),
PluginConstants.ApplicationInstallProperties.PACKAGE_FAMILY_NAME,
getHostedAppxApplication().getpackageFamilyName()
+ PluginConstants.ApplicationInstallProperties.HOSTED_INSTALL,
PluginConstants.ApplicationInstallProperties.TYPE_APPX));
} else if (getHostedMSIApplication() != null) {
enterpriseApplicationContent.addAll(createAddTag(operation.getId(),
OperationCode.Command.INSTALL_ENTERPRISE_MSI_APPLICATION.getCode(),
PluginConstants.ApplicationInstallProperties.PRODUCT_ID, getHostedMSIApplication().getProductId(),
PluginConstants.ApplicationInstallProperties.TYPE_MSI));
enterpriseApplicationContent.addAll(createExecuteTag(operation.getId(),
OperationCode.Command.INSTALL_ENTERPRISE_MSI_APPLICATION.getCode(),
PluginConstants.ApplicationInstallProperties.PRODUCT_ID, getHostedMSIApplication().getProductId(),
PluginConstants.ApplicationInstallProperties.TYPE_MSI));
}
return enterpriseApplicationContent;
}
/***
* Create add objects required for APPX or MSI application installation which then will be converted as AddTag
* elements to add in SyncML XML.
*
* @param operationId used to set as command ID
* @param operationCode is the LocURI
* @param replaceOld operation code placeholder
* @param replaceNew replace value of operation code placeholder
* @param appType APPX or MSI
* @return list of AddTag objects
*/
private List<AddTag> createAddTag(int operationId, String operationCode, String replaceOld, String replaceNew,
String appType) {
List<AddTag> addTagList = new ArrayList<>();
List<ItemTag> itemTagList = new ArrayList<>();
AddTag addTag = new AddTag();
ItemTag itemTag = new ItemTag();
TargetTag targetTag = new TargetTag();
String locUri = operationCode.replace(replaceOld, replaceNew);
targetTag.setLocURI(locUri);
itemTag.setTarget(targetTag);
itemTagList.add(itemTag);
addTag.setCommandId(operationId);
addTag.setItems(itemTagList);
addTagList.add(addTag);
if (PluginConstants.ApplicationInstallProperties.TYPE_APPX.equals(appType)) {
if (!isNullOrEmpty(getHostedAppxApplication().getCertificateHash()) && !isNullOrEmpty(
getHostedAppxApplication().getEncodedCertificate())) {
List<ItemTag> certItemTagList = new ArrayList<>();
AddTag certAddTag = new AddTag();
ItemTag certItemTag = new ItemTag();
MetaTag certMetaTag = new MetaTag();
TargetTag certTargetTag = new TargetTag();
certTargetTag.setLocURI(OperationCode.Command.INSTALL_ENTERPRISE_APPX_CERTIFICATE.getCode()
.replace(PluginConstants.ApplicationInstallProperties.CERT_HASH,
getHostedAppxApplication().getCertificateHash()));
certMetaTag.setFormat(Constants.META_FORMAT_B64);
certItemTag.setTarget(certTargetTag);
certItemTag.setMeta(certMetaTag);
certItemTag.setData(getHostedAppxApplication().getEncodedCertificate());
certItemTagList.add(certItemTag);
certAddTag.setCommandId(operationId);
certAddTag.setItems(certItemTagList);
addTagList.add(certAddTag);
}
}
return addTagList;
}
/***
* Create execute objects required for APPX or MSI application installation which then will be converted as
* ExecuteTag elements to add in SyncML XML.
*
* @param operationId used to set as command ID
* @param operationCode is the LocURI
* @param replaceOld operation code placeholder
* @param replaceNew replace value of operation code placeholder
* @param appType APPX or MSI
* @return list of ExecuteTag objects
* @throws WindowsOperationException
*/
private List<ExecuteTag> createExecuteTag(int operationId, String operationCode, String replaceOld,
String replaceNew, String appType) throws WindowsOperationException {
List<ExecuteTag> executeTagList = new ArrayList<>();
List<ItemTag> itemTagList = new ArrayList<>();
ExecuteTag executeTag = new ExecuteTag();
ItemTag itemTag = new ItemTag();
MetaTag metaTag = new MetaTag();
TargetTag targetTag = new TargetTag();
Document document;
Element dependencyElement;
targetTag.setLocURI(operationCode.replace(replaceOld, replaceNew));
metaTag.setFormat(Constants.META_FORMAT_XML);
try {
if (PluginConstants.ApplicationInstallProperties.TYPE_APPX.equals(appType)) {
document = SyncmlGenerator.generateDocument();
Element applicationElement = document
.createElement(PluginConstants.ApplicationInstallProperties.APPLICATION);
applicationElement.setAttribute(PluginConstants.ApplicationInstallProperties.PACKAGE_URI,
getHostedAppxApplication().getpackageUri());
if (!isNullOrEmpty(getHostedAppxApplication().getDependencyPackageUri())) {
Element dependenciesElement = document
.createElement(PluginConstants.ApplicationInstallProperties.DEPENDENCIES);
for (String dependency : getHostedAppxApplication().getDependencyPackageUri()) {
dependencyElement = document
.createElement(PluginConstants.ApplicationInstallProperties.DEPENDENCY);
dependencyElement
.setAttribute(PluginConstants.ApplicationInstallProperties.PACKAGE_URI, dependency);
dependenciesElement.appendChild(dependencyElement);
}
applicationElement.appendChild(dependenciesElement);
}
itemTag.setElementData(applicationElement);
} else if (PluginConstants.ApplicationInstallProperties.TYPE_MSI.equals(appType)) {
metaTag.setType(Constants.META_TYPE_TEXT_PLAIN);
document = SyncmlGenerator.generateDocument();
Element contentURLElement = document
.createElement(PluginConstants.ApplicationInstallProperties.CONTENT_URL);
contentURLElement.setTextContent(getHostedMSIApplication().getContentUrl());
Element contentURLListElement = document
.createElement(PluginConstants.ApplicationInstallProperties.CONTENT_URL_LIST);
contentURLListElement.appendChild(contentURLElement);
Element downloadElement = document.createElement(PluginConstants.ApplicationInstallProperties.DOWNLOAD);
downloadElement.appendChild(contentURLListElement);
Element fileHashElement = document
.createElement(PluginConstants.ApplicationInstallProperties.FILE_HASH);
fileHashElement.setTextContent(getHostedMSIApplication().getFileHash());
Element validationElement = document
.createElement(PluginConstants.ApplicationInstallProperties.VALIDATION);
validationElement.appendChild(fileHashElement);
Element enforcementElement = document
.createElement(PluginConstants.ApplicationInstallProperties.ENFORCEMENT);
Element commandLineElement = document
.createElement(PluginConstants.ApplicationInstallProperties.COMMAND_LINE);
commandLineElement.setTextContent(PluginConstants.ApplicationInstallProperties.COMMAND_LINE_VALUE);
enforcementElement.appendChild(commandLineElement);
Element timeOutElement = document.createElement(PluginConstants.ApplicationInstallProperties.TIMEOUT);
timeOutElement.setTextContent(PluginConstants.ApplicationInstallProperties.TIMEOUT_VALUE);
enforcementElement.appendChild(timeOutElement);
Element retryCountElement = document
.createElement(PluginConstants.ApplicationInstallProperties.RETRY_COUNT);
retryCountElement.setTextContent(PluginConstants.ApplicationInstallProperties.RETRY_COUNT_VALUE);
enforcementElement.appendChild(retryCountElement);
Element retryIntervalElement = document
.createElement(PluginConstants.ApplicationInstallProperties.RETRY_INTERVAL);
retryIntervalElement.setTextContent(PluginConstants.ApplicationInstallProperties.RETRY_INTERVAL_VALUE);
enforcementElement.appendChild(retryIntervalElement);
Element productElement = document.createElement(PluginConstants.ApplicationInstallProperties.PRODUCT);
productElement.setAttribute(PluginConstants.ApplicationInstallProperties.VERSION,
PluginConstants.ApplicationInstallProperties.VERSION_VALUE);
productElement.appendChild(downloadElement);
productElement.appendChild(validationElement);
productElement.appendChild(enforcementElement);
Element msiInstallJobElement = document
.createElement(PluginConstants.ApplicationInstallProperties.MSI_INSTALL_JOB);
msiInstallJobElement.setAttribute(PluginConstants.ApplicationInstallProperties.ID,
PluginConstants.ApplicationInstallProperties.URL_ESCAPED_OPEN_CURLY + getHostedMSIApplication()
.getProductId() + PluginConstants.ApplicationInstallProperties.URL_ESCAPED_CLOSE_CURLY);
msiInstallJobElement.appendChild(productElement);
itemTag.setElementData(msiInstallJobElement);
}
} catch (SyncmlOperationException e) {
String errorMsg = "Error occurred while generating a document to add as a node to Data element of Execute "
+ "command which is required to Install " + appType + " application.";
log.error(errorMsg);
throw new WindowsOperationException(errorMsg, e);
}
itemTag.setTarget(targetTag);
itemTag.setMeta(metaTag);
itemTagList.add(itemTag);
executeTag.setCommandId(operationId);
executeTag.setItems(itemTagList);
executeTagList.add(executeTag);
return executeTagList;
}
}

@ -0,0 +1,77 @@
/*
* 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.windows.api.bean;
import io.swagger.annotations.ApiModelProperty;
import java.util.List;
public class HostedAppxApplication {
@ApiModelProperty(name = "packageUri", value = "Package URL.", required = true)
private String packageUri;
@ApiModelProperty(name = "packageFamilyName", value = "Package family name.", required = true)
private String packageFamilyName;
@ApiModelProperty(name = "dependencyPackageURLs", value = "Dependency Package URLs.")
private List<String> dependencyPackageUri;
@ApiModelProperty(name = "certificateHash", value = "Application signed SHA1 certificate hash.")
private String certificateHash;
@ApiModelProperty(name = "encodedCertificate", value = "Application signed Base64 encoded certificate.")
private String encodedCertificate;
public String getpackageUri() {
return packageUri;
}
public void setpackageUri (String packageUri) {
this.packageUri = packageUri;
}
public String getpackageFamilyName() {
return packageFamilyName;
}
public void setpackageFamilyName(String packageFamilyName) {
this.packageFamilyName = packageFamilyName;
}
public List<String> getDependencyPackageUri() {
return dependencyPackageUri;
}
public void setDependencyPackageUri(List<String> dependencyPackageUri) {
this.dependencyPackageUri = dependencyPackageUri;
}
public String getCertificateHash() {
return certificateHash;
}
public void setCertificateHash(String certificateHash) {
this.certificateHash = certificateHash;
}
public String getEncodedCertificate() {
return encodedCertificate;
}
public void setEncodedCertificate(String encodedCertificate) {
this.encodedCertificate = encodedCertificate;
}
}

@ -0,0 +1,55 @@
/*
* 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.windows.api.bean;
import io.swagger.annotations.ApiModelProperty;
public class HostedMSIApplication {
@ApiModelProperty(name = "productId", value = "Product ID.", required = true)
private String productId;
@ApiModelProperty(name = "contentUrl", value = "Content URL.", required = true)
private String contentUrl;
@ApiModelProperty(name = "fileHash", value = "File Hash.", required = true)
private String fileHash;
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public String getContentUrl() {
return contentUrl;
}
public void setContentUrl(String contentUrl) {
this.contentUrl = contentUrl;
}
public String getFileHash() {
return fileHash;
}
public void setFileHash(String fileHash) {
this.fileHash = fileHash;
}
}

@ -0,0 +1,63 @@
/*
* 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.windows.api.bean;
import com.google.gson.Gson;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.mobile.windows.api.operations.WindowsOperationException;
import java.util.List;
/***
* This abstract class is used for extending generic functions with regard to operation.
*/
public abstract class WindowsOperation {
public abstract List<Object> createOperationContent(Operation operation) throws WindowsOperationException;
/***
* Converts operation object to a json format.
*
* @return JSON formatted String
*/
public String toJSON() {
Gson gson = new Gson();
return gson.toJson(this);
}
/**
* Checks if the given string is null or empty
*
* @param value string value to check
* @return boolean value of null or empty
*/
public boolean isNullOrEmpty(String value) {
return value == null || value.trim().isEmpty();
}
/***
* Checks if the given list is null or empty
*
* @param value string list value to check
* @return boolean value of null or empty
*/
public boolean isNullOrEmpty(List<String> value) {
return value == null || value.isEmpty();
}
}

@ -0,0 +1,53 @@
/*
* 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.windows.api.bean.wrapper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.wso2.carbon.device.mgt.mobile.windows.api.bean.EnterpriseApplication;
import java.util.List;
@ApiModel(value = "EnterpriseApplicationBeanWrapper",
description = "Information related to Enterprise Application.")
public class EnterpriseApplicationBeanWrapper {
@ApiModelProperty(name = "deviceIDs",
value = "List of device Ids to be need to execute operation.", required = true)
private List<String> deviceIDs;
@ApiModelProperty(name = "operation",
value = "Enterprise Application.", required = true)
private EnterpriseApplication operation;
public List<String> getDeviceIDs() {
return deviceIDs;
}
public void setDeviceIDs(List<String> deviceIDs) {
this.deviceIDs = deviceIDs;
}
public EnterpriseApplication getOperation() {
return operation;
}
public void setOperation(EnterpriseApplication operation) {
this.operation = operation;
}
}

@ -14,6 +14,23 @@
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * 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.windows.api.common; package org.wso2.carbon.device.mgt.mobile.windows.api.common;
@ -167,6 +184,7 @@ public final class PluginConstants {
public static final String SYNCML_SOURCE = "Source"; public static final String SYNCML_SOURCE = "Source";
public static final String SYNCML_DATA = "Data"; public static final String SYNCML_DATA = "Data";
public static final String SYNCML_META = "Meta";
public static final String SYNCML_CMD = "Cmd"; public static final String SYNCML_CMD = "Cmd";
public static final String SYNCML_CHAL = "ChallengeTag"; public static final String SYNCML_CHAL = "ChallengeTag";
public static final String SYNCML_CMD_ID = "CmdID"; public static final String SYNCML_CMD_ID = "CmdID";
@ -221,6 +239,7 @@ public final class PluginConstants {
public static final String LONGITUDE = "LONGITUDE"; public static final String LONGITUDE = "LONGITUDE";
public static final String LATITUDE = "LATITUDE"; public static final String LATITUDE = "LATITUDE";
public static final String DEVICE_UNENROLL_META_TYPE = "com.microsoft:mdm.unenrollment.userrequest";
} }
/** /**
@ -274,6 +293,7 @@ public final class PluginConstants {
public static final String LONGITUDE = "LONGITUDE"; public static final String LONGITUDE = "LONGITUDE";
public static final String LATITUDE = "LATITUDE"; public static final String LATITUDE = "LATITUDE";
public static final String DEVICE_REBOOT = "DEVICE_REBOOT"; public static final String DEVICE_REBOOT = "DEVICE_REBOOT";
public static final String INSTALL_ENTERPRISE_APPLICATION = "INSTALL_ENTERPRISE_APPLICATION";
} }
/** /**
@ -358,4 +378,45 @@ public final class PluginConstants {
public static final String IMEI = "MobileEquipmentId"; public static final String IMEI = "MobileEquipmentId";
public static final String TYPE = "DeviceType"; public static final String TYPE = "DeviceType";
} }
public final class ApplicationInstallProperties {
private ApplicationInstallProperties() {
throw new AssertionError();
}
public static final String APPLICATION = "Application";
public static final String TYPE_APPX = "APPX";
public static final String TYPE_MSI = "MSI";
public static final String PACKAGE_FAMILY_NAME = "{PackageFamilyName}";
public static final String PRODUCT_ID = "{ProductId}";
public static final String CERT_HASH = "{CertHash}";
public static final String HOSTED_INSTALL = "/HostedInstall";
//XML Related Constants
public static final String ID = "id";
public static final String PACKAGE_URI = "PackageUri";
public static final String DEPENDENCIES = "Dependencies";
public static final String DEPENDENCY = "Dependency";
public static final String CONTENT_URL = "ContentURL";
public static final String CONTENT_URL_LIST = "ContentURLList";
public static final String DOWNLOAD = "Download";
public static final String COMMAND_LINE = "CommandLine";
public static final String COMMAND_LINE_VALUE = "/quiet";
public static final String FILE_HASH = "FileHash";
public static final String VALIDATION = "Validation";
public static final String ENFORCEMENT = "Enforcement";
public static final String TIMEOUT = "TimeOut";
public static final String RETRY_COUNT = "RetryCount";
public static final String RETRY_INTERVAL = "RetryInterval";
public static final String PRODUCT = "Product";
public static final String MSI_INSTALL_JOB = "MsiInstallJob";
public static final String VERSION = "version";
public static final String VERSION_VALUE = "1.0.0";
public static final String TIMEOUT_VALUE = "5";
public static final String RETRY_COUNT_VALUE = "3";
public static final String RETRY_INTERVAL_VALUE = "5";
public static final String LICENSE = "License";
public static final String CONTENT = "Content";
public static final String URL_ESCAPED_OPEN_CURLY = "%7B";
public static final String URL_ESCAPED_CLOSE_CURLY = "%7D";
}
} }

@ -0,0 +1,32 @@
/*
* 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.windows.api.common.exceptions;
public class ProfileConfigurationException extends Exception {
private static final long serialVersionUID = 8025559931927889261L;
public ProfileConfigurationException(String errorMsg) {
super(errorMsg);
}
public ProfileConfigurationException(String errorMsg, Throwable throwable) {
super(errorMsg, throwable);
}
}

@ -14,6 +14,23 @@
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * 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.windows.api.operations; package org.wso2.carbon.device.mgt.mobile.windows.api.operations;
@ -22,6 +39,9 @@ import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.wso2.carbon.device.mgt.mobile.windows.api.operations.util.Constants; import org.wso2.carbon.device.mgt.mobile.windows.api.operations.util.Constants;
import java.util.Iterator;
import java.util.List;
/** /**
* Inform an event occurred from device to server. * Inform an event occurred from device to server.
*/ */
@ -29,6 +49,7 @@ public class AlertTag {
int commandId = -1; int commandId = -1;
String data; String data;
List<ItemTag> items;
public int getCommandId() { public int getCommandId() {
return commandId; return commandId;
@ -46,6 +67,14 @@ public class AlertTag {
this.data = data; this.data = data;
} }
public List<ItemTag> getItems() {
return items;
}
public void setItems(List<ItemTag> items) {
this.items = items;
}
public void buildAlertElement(Document doc, Element rootElement) { public void buildAlertElement(Document doc, Element rootElement) {
Element alert = doc.createElement(Constants.ALERT); Element alert = doc.createElement(Constants.ALERT);
rootElement.appendChild(alert); rootElement.appendChild(alert);
@ -59,5 +88,13 @@ public class AlertTag {
data.appendChild(doc.createTextNode(getData())); data.appendChild(doc.createTextNode(getData()));
alert.appendChild(data); alert.appendChild(data);
} }
if (getItems() != null) {
for (Iterator<ItemTag> itemIterator = getItems().iterator(); itemIterator.hasNext();) {
ItemTag item = itemIterator.next();
if (item != null) {
item.buildItemElement(doc, alert);
}
}
}
} }
} }

@ -14,12 +14,30 @@
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * 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.windows.api.operations; package org.wso2.carbon.device.mgt.mobile.windows.api.operations;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.wso2.carbon.device.mgt.mobile.windows.api.operations.util.Constants; import org.wso2.carbon.device.mgt.mobile.windows.api.operations.util.Constants;
/** /**
@ -31,6 +49,7 @@ public class ItemTag {
SourceTag source; SourceTag source;
String data; String data;
MetaTag meta; MetaTag meta;
Element elementData;
public MetaTag getMeta() { public MetaTag getMeta() {
return meta; return meta;
@ -64,6 +83,14 @@ public class ItemTag {
this.target = target; this.target = target;
} }
public Element getElementData() {
return elementData;
}
public void setElementData(Element elementData) {
this.elementData = elementData;
}
public void buildItemElement(Document doc, Element rootElement) { public void buildItemElement(Document doc, Element rootElement) {
Element item = doc.createElement(Constants.ITEM); Element item = doc.createElement(Constants.ITEM);
rootElement.appendChild(item); rootElement.appendChild(item);
@ -77,14 +104,19 @@ public class ItemTag {
getSource().buildSourceElement(doc, item); getSource().buildSourceElement(doc, item);
} }
} }
if (getData() != null) {
Element data = doc.createElement(Constants.DATA);
data.appendChild(doc.createTextNode(getData()));
item.appendChild(data);
}
if (getMeta() != null) { if (getMeta() != null) {
getMeta().buildMetaElement(doc, item); getMeta().buildMetaElement(doc, item);
} }
if (getData() != null || getElementData()!= null) {
Element data = doc.createElement(Constants.DATA);
if (getData() != null) {
data.appendChild(doc.createTextNode(getData()));
}
if (getElementData() != null) {
Node node = doc.importNode(getElementData(), true);
data.appendChild(node);
}
item.appendChild(data);
}
} }
} }

@ -14,6 +14,23 @@
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * 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.windows.api.operations.util; package org.wso2.carbon.device.mgt.mobile.windows.api.operations.util;
@ -78,9 +95,14 @@ public class Constants {
public static final String SEQUENCE = "Sequence"; public static final String SEQUENCE = "Sequence";
public static final String META_FORMAT_INT = "int"; public static final String META_FORMAT_INT = "int";
public static final String META_FORMAT_CHARACTER = "chr"; public static final String META_FORMAT_CHARACTER = "chr";
public static final String META_FORMAT_XML = "xml";
public static final String META_FORMAT_B64 = "b64";
public static final String META_TYPE_TEXT_PLAIN = "text/plain";
public static final String SCOPE = "scope"; public static final String SCOPE = "scope";
public static final String FORWARD_SLASH = "/";
/** /**
* SynclML service related constants. * SynclML service related constants.
*/ */

@ -14,6 +14,23 @@
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * 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.windows.api.operations.util; package org.wso2.carbon.device.mgt.mobile.windows.api.operations.util;
@ -94,7 +111,10 @@ public class OperationCode {
LONGITUDE("./Vendor/MSFT/RemoteFind/Location/Longitude"), LONGITUDE("./Vendor/MSFT/RemoteFind/Location/Longitude"),
LATITUDE("./Vendor/MSFT/RemoteFind/Location/Latitude"), LATITUDE("./Vendor/MSFT/RemoteFind/Location/Latitude"),
TEST("./Vendor/MSFT/DiagnosticLog/EtwLog/Collectors"), TEST("./Vendor/MSFT/DiagnosticLog/EtwLog/Collectors"),
DEVICE_REBOOT("./Vendor/MSFT/Reboot/RebootNow"); DEVICE_REBOOT("./Vendor/MSFT/Reboot/RebootNow"),
INSTALL_ENTERPRISE_APPX_APPLICATION("./Device/Vendor/MSFT/EnterpriseModernAppManagement/AppInstallation/{PackageFamilyName}"),
INSTALL_ENTERPRISE_APPX_CERTIFICATE("./Device/Vendor/MSFT/RootCATrustedCertificates/Root/{CertHash}/EncodedCertificate"),
INSTALL_ENTERPRISE_MSI_APPLICATION("./Device/Vendor/MSFT/EnterpriseDesktopAppManagement/MSI/%7B{ProductId}%7D/DownloadInstall");
private final String code; private final String code;

@ -14,6 +14,23 @@
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * 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.windows.api.operations.util; package org.wso2.carbon.device.mgt.mobile.windows.api.operations.util;
@ -21,10 +38,9 @@ package org.wso2.carbon.device.mgt.mobile.windows.api.operations.util;
import com.google.gson.Gson; import com.google.gson.Gson;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.mobile.windows.api.bean.EnterpriseApplication;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants; import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.SyncmlCommandType; import org.wso2.carbon.device.mgt.mobile.windows.api.common.SyncmlCommandType;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.SyncmlMessageFormatException; import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.SyncmlMessageFormatException;
@ -87,7 +103,7 @@ public class OperationReply {
* @throws org.wso2.carbon.policy.mgt.common.FeatureManagementException * @throws org.wso2.carbon.policy.mgt.common.FeatureManagementException
*/ */
public String generateReply(SyncmlDocument syncmlDocument, List<? extends Operation> operations) public String generateReply(SyncmlDocument syncmlDocument, List<? extends Operation> operations)
throws SyncmlMessageFormatException, SyncmlOperationException { throws SyncmlMessageFormatException, SyncmlOperationException, WindowsOperationException {
OperationReply operationReply; OperationReply operationReply;
SyncmlGenerator generator; SyncmlGenerator generator;
@ -102,7 +118,8 @@ public class OperationReply {
return generator.generatePayload(syncmlResponse); return generator.generatePayload(syncmlResponse);
} }
public SyncmlDocument generateReply() throws SyncmlMessageFormatException, SyncmlOperationException { public SyncmlDocument generateReply()
throws SyncmlMessageFormatException, SyncmlOperationException, WindowsOperationException {
generateHeader(); generateHeader();
generateBody(); generateBody();
return replySyncmlDocument; return replySyncmlDocument;
@ -146,14 +163,11 @@ public class OperationReply {
replySyncmlDocument.setHeader(header); replySyncmlDocument.setHeader(header);
} }
private void generateBody() throws SyncmlMessageFormatException, SyncmlOperationException { private void generateBody()
throws SyncmlMessageFormatException, SyncmlOperationException, WindowsOperationException {
SyncmlBody syncmlBody = generateStatuses(); SyncmlBody syncmlBody = generateStatuses();
try { try {
appendOperations(syncmlBody); appendOperations(syncmlBody);
} catch (PolicyManagementException e) {
throw new SyncmlOperationException("Error occurred while retrieving policy operations.", e);
} catch (FeatureManagementException e) {
throw new SyncmlOperationException("Error occurred while retrieving effective policy operations.", e);
} catch (JSONException e) { } catch (JSONException e) {
throw new SyncmlMessageFormatException("Error Occurred while parsing operation object.", e); throw new SyncmlMessageFormatException("Error Occurred while parsing operation object.", e);
} }
@ -235,8 +249,8 @@ public class OperationReply {
return syncmlBodyReply; return syncmlBodyReply;
} }
private void appendOperations(SyncmlBody syncmlBody) throws PolicyManagementException, private void appendOperations(SyncmlBody syncmlBody)
FeatureManagementException, JSONException, SyncmlOperationException { throws JSONException, SyncmlOperationException, WindowsOperationException {
GetTag getElement = new GetTag(); GetTag getElement = new GetTag();
List<ItemTag> getElements = new ArrayList<>(); List<ItemTag> getElements = new ArrayList<>();
List<ExecuteTag> executeElements = new ArrayList<>(); List<ExecuteTag> executeElements = new ArrayList<>();
@ -359,8 +373,23 @@ public class OperationReply {
} }
} }
} }
break;
} }
break;
case PROFILE:
if (PluginConstants.OperationCodes.INSTALL_ENTERPRISE_APPLICATION.equals(operation.getCode())) {
EnterpriseApplication enterpriseApplication = gson
.fromJson((String) operation.getPayLoad(), EnterpriseApplication.class);
List<Object> enterpriseApplicationContent = enterpriseApplication
.createOperationContent(operation);
for (Object object : enterpriseApplicationContent) {
if (object instanceof AddTag) {
addElements.add((AddTag) object);
} else if (object instanceof ExecuteTag) {
executeElements.add((ExecuteTag) object);
}
}
}
break;
} }
} }
if (!replaceItems.isEmpty()) { if (!replaceItems.isEmpty()) {

@ -14,6 +14,23 @@
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * 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.windows.api.operations.util; package org.wso2.carbon.device.mgt.mobile.windows.api.operations.util;
@ -48,7 +65,7 @@ public class SyncmlGenerator {
return transformDocument(doc); return transformDocument(doc);
} }
private static Document generateDocument() throws SyncmlOperationException { public static Document generateDocument() throws SyncmlOperationException {
DocumentBuilderFactory documentFactory = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory documentFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder; DocumentBuilder docBuilder;
try { try {

@ -14,13 +14,33 @@
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * 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.windows.api.operations.util; package org.wso2.carbon.device.mgt.mobile.windows.api.operations.util;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.wso2.carbon.device.mgt.mobile.windows.api.bean.EnterpriseApplication;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants; import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import org.wso2.carbon.device.mgt.mobile.windows.api.operations.*; import org.wso2.carbon.device.mgt.mobile.windows.api.operations.*;
@ -375,8 +395,15 @@ public class SyncmlParser {
AlertTag alert = new AlertTag(); AlertTag alert = new AlertTag();
String commandID = node.getChildNodes().item(0).getTextContent().trim(); String commandID = node.getChildNodes().item(0).getTextContent().trim();
String data = node.getChildNodes().item(1).getTextContent().trim(); String data = node.getChildNodes().item(1).getTextContent().trim();
List<ItemTag> items = new ArrayList<>();
for (int i = 1; i < node.getChildNodes().getLength() - 1; i++) {
items.add(generateItem(node.getChildNodes().item(i + 1)));
}
alert.setCommandId(Integer.valueOf(commandID)); alert.setCommandId(Integer.valueOf(commandID));
alert.setData(data); alert.setData(data);
if (!items.isEmpty()) {
alert.setItems(items);
}
return alert; return alert;
} }
@ -423,6 +450,15 @@ public class SyncmlParser {
throw new IllegalStateException(); throw new IllegalStateException();
} }
item.setData(data); item.setData(data);
} else if (PluginConstants.SyncML.SYNCML_META.equals(nodeName)) {
MetaTag metaTag = new MetaTag();
if (itemNode.getChildNodes().item(0) != null) {
metaTag.setType(itemNode.getChildNodes().item(0).getTextContent().trim());
}
if (itemNode.getChildNodes().item(1) != null) {
metaTag.setFormat(itemNode.getChildNodes().item(1).getTextContent().trim());
}
item.setMeta(metaTag);
} }
} }
return item; return item;

@ -14,6 +14,23 @@
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * 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.windows.api.services; package org.wso2.carbon.device.mgt.mobile.windows.api.services;
@ -23,6 +40,7 @@ import io.swagger.annotations.*;
import org.wso2.carbon.apimgt.annotations.api.Scope; import org.wso2.carbon.apimgt.annotations.api.Scope;
import org.wso2.carbon.apimgt.annotations.api.Scopes; import org.wso2.carbon.apimgt.annotations.api.Scopes;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.mobile.windows.api.bean.wrapper.EnterpriseApplicationBeanWrapper;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsDeviceEnrolmentException; import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsDeviceEnrolmentException;
import org.wso2.carbon.device.mgt.mobile.windows.api.operations.util.Constants; import org.wso2.carbon.device.mgt.mobile.windows.api.operations.util.Constants;
@ -107,6 +125,12 @@ import java.util.List;
description = "Lock reset on Windows devices", description = "Lock reset on Windows devices",
key = "perm:windows:location", key = "perm:windows:location",
permissions = {"/device-mgt/devices/owning-device/operations/windows/location"} permissions = {"/device-mgt/devices/owning-device/operations/windows/location"}
),
@Scope(
name = "Install Enterprise Application",
description = "Installing an Enterprise Application",
key = "perm:windows:enterprise-app",
permissions = {"/device-mgt/devices/owning-device/operations/windows/enterprise-application"}
) )
} }
) )
@ -536,5 +560,65 @@ public interface DeviceManagementAdminService {
required = true) required = true)
List<String> deviceIDs); List<String> deviceIDs);
@POST
@Path("/enterprise-application")
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
httpMethod = "POST",
value = "Installing an Enterprise Application",
notes = "Install an enterprise application on Windows devices.",
response = Activity.class,
tags = "Windows Device Management Administrative Service",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:windows:enterprise-app")
})
}
)
@ApiResponses(value = {
@ApiResponse(
code = 201,
message = "Created. \n Successfully added Enterprise application operation.",
response = Activity.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "URL of the activity instance that refers to the scheduled operation."),
@ResponseHeader(
name = "Content-Type",
description = "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 = 303,
message = "See Other. \n The source can be retrieved from the URL specified in the location header.\n",
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "The Source URL of the document.")}),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error."),
@ApiResponse(
code = 415,
message = "Unsupported media type. \n The format of the requested entity was not supported.\n"),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n " +
"Server error occurred while adding the enterprise application operation.")
})
Response installEnterpriseApplication(
@ApiParam(
name = "enterpriseApplicationBeanWrapper",
value = "Enterprise application configuration and Device IDs",
required = true)
EnterpriseApplicationBeanWrapper enterpriseApplicationBeanWrapper);
} }

@ -14,19 +14,39 @@
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * 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.windows.api.services.impl; package org.wso2.carbon.device.mgt.mobile.windows.api.services.impl;
import com.ibm.wsdl.OperationImpl;
import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiParam;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpStatus;
import org.wso2.carbon.device.mgt.common.DeviceManagementException; import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.InvalidDeviceException; import org.wso2.carbon.device.mgt.common.InvalidDeviceException;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation; import org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation;
import org.wso2.carbon.device.mgt.core.operation.mgt.ProfileOperation;
import org.wso2.carbon.device.mgt.mobile.windows.api.bean.EnterpriseApplication;
import org.wso2.carbon.device.mgt.mobile.windows.api.bean.wrapper.EnterpriseApplicationBeanWrapper;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants; import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.beans.ErrorResponse; import org.wso2.carbon.device.mgt.mobile.windows.api.common.beans.ErrorResponse;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.BadRequestException; import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.BadRequestException;
@ -35,6 +55,7 @@ import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsDe
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsOperationsException; import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsOperationsException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.util.Message; import org.wso2.carbon.device.mgt.mobile.windows.api.common.util.Message;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.util.WindowsAPIUtils; import org.wso2.carbon.device.mgt.mobile.windows.api.common.util.WindowsAPIUtils;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.ProfileConfigurationException;
import org.wso2.carbon.device.mgt.mobile.windows.api.services.DeviceManagementAdminService; import org.wso2.carbon.device.mgt.mobile.windows.api.services.DeviceManagementAdminService;
import javax.ws.rs.*; import javax.ws.rs.*;
@ -51,7 +72,7 @@ import java.util.List;
@Path("/admin/devices") @Path("/admin/devices")
public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminService { public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminService {
private static Log log = LogFactory.getLog(OperationImpl.class); private static Log log = LogFactory.getLog(DeviceManagementAdminServiceImpl.class);
/** /**
* REST endpoint for the Device Lock operation * REST endpoint for the Device Lock operation
@ -336,4 +357,58 @@ public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminSe
new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(errorMessage).build()); new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(errorMessage).build());
} }
} }
/**
* Rest endpoint for Enterprise Application (MSI or APPX) installation
*
* @param enterpriseApplicationBeanWrapper Enterprise application installation payload object
* @return Response object for client.
*/
@POST
@Path("/enterprise-application")
public Response installEnterpriseApplication(@ApiParam(
name = "enterpriseApplicationBeanWrapper",
value = "Enterprise application configuration and Device IDs",
required = true) EnterpriseApplicationBeanWrapper enterpriseApplicationBeanWrapper) {
if (log.isDebugEnabled()) {
log.debug("Invoking Windows install enterprise application device operation");
}
if (enterpriseApplicationBeanWrapper == null || enterpriseApplicationBeanWrapper.getOperation() == null) {
String errorMessage = "The payload of the application installing operation is incorrect";
log.error(errorMessage);
throw new BadRequestException(
new ErrorResponse.ErrorResponseBuilder().setCode(HttpStatus.SC_BAD_REQUEST).setMessage(errorMessage)
.build());
}
try {
EnterpriseApplication enterpriseApplication = enterpriseApplicationBeanWrapper.getOperation();
enterpriseApplication.validateRequest();
ProfileOperation operation = new ProfileOperation();
operation.setCode(PluginConstants.OperationCodes.INSTALL_ENTERPRISE_APPLICATION);
operation.setType(Operation.Type.PROFILE);
operation.setPayLoad(enterpriseApplication.toJSON());
return WindowsAPIUtils.getOperationResponse(enterpriseApplicationBeanWrapper.getDeviceIDs(), operation);
} catch (ProfileConfigurationException e) {
throw new BadRequestException(new ErrorResponse.ErrorResponseBuilder().setCode(HttpStatus.SC_BAD_REQUEST)
.setMessage(e.getMessage()).build());
} catch (OperationManagementException e) {
String errorMessage = "Issue in retrieving operation management service instance";
log.error(errorMessage, e);
throw new UnexpectedServerErrorException(
new ErrorResponse.ErrorResponseBuilder().setCode(HttpStatus.SC_INTERNAL_SERVER_ERROR)
.setMessage(errorMessage).build());
} catch (DeviceManagementException e) {
String errorMessage = "Issue in retrieving device management service instance";
log.error(errorMessage, e);
throw new UnexpectedServerErrorException(
new ErrorResponse.ErrorResponseBuilder().setCode(HttpStatus.SC_INTERNAL_SERVER_ERROR)
.setMessage(errorMessage).build());
} catch (InvalidDeviceException e) {
String errorMessage = "Invalid Device Identifiers found.";
log.error(errorMessage, e);
throw new BadRequestException(
new ErrorResponse.ErrorResponseBuilder().setCode(HttpStatus.SC_BAD_REQUEST).setMessage(errorMessage)
.build());
}
}
} }

@ -14,6 +14,23 @@
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * 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.windows.api.services.impl; package org.wso2.carbon.device.mgt.mobile.windows.api.services.impl;
@ -26,7 +43,6 @@ import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; import org.wso2.carbon.device.mgt.common.DeviceManagementConstants;
import org.wso2.carbon.device.mgt.common.DeviceManagementException; import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagementException;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants; import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
@ -38,6 +54,7 @@ import org.wso2.carbon.device.mgt.mobile.windows.api.common.util.AuthenticationI
import org.wso2.carbon.device.mgt.mobile.windows.api.common.util.DeviceUtil; import org.wso2.carbon.device.mgt.mobile.windows.api.common.util.DeviceUtil;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.util.WindowsAPIUtils; import org.wso2.carbon.device.mgt.mobile.windows.api.common.util.WindowsAPIUtils;
import org.wso2.carbon.device.mgt.mobile.windows.api.operations.ItemTag; import org.wso2.carbon.device.mgt.mobile.windows.api.operations.ItemTag;
import org.wso2.carbon.device.mgt.mobile.windows.api.operations.MetaTag;
import org.wso2.carbon.device.mgt.mobile.windows.api.operations.ReplaceTag; import org.wso2.carbon.device.mgt.mobile.windows.api.operations.ReplaceTag;
import org.wso2.carbon.device.mgt.mobile.windows.api.operations.SyncmlDocument; import org.wso2.carbon.device.mgt.mobile.windows.api.operations.SyncmlDocument;
import org.wso2.carbon.device.mgt.mobile.windows.api.operations.SyncmlHeader; import org.wso2.carbon.device.mgt.mobile.windows.api.operations.SyncmlHeader;
@ -61,10 +78,8 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
private static Log log = LogFactory.getLog( private static Log log = LogFactory.getLog(
org.wso2.carbon.device.mgt.mobile.windows.api.services.syncml.impl.SyncmlServiceImpl.class); org.wso2.carbon.device.mgt.mobile.windows.api.services.syncml.impl.SyncmlServiceImpl.class);
@Override @Override public Response getResponse(Document request)
public Response getResponse(Document request) throws WindowsDeviceEnrolmentException, WindowsOperationException, throws WindowsDeviceEnrolmentException, WindowsOperationException, WindowsConfigurationException {
NotificationManagementException, WindowsConfigurationException {
int msgId; int msgId;
int sessionId; int sessionId;
String user; String user;
@ -127,12 +142,17 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
carbonCtx.setTenantId(cacheToken.getTenanatID()); carbonCtx.setTenantId(cacheToken.getTenanatID());
} }
if ((syncmlDocument.getBody().getAlert() != null)) { if ((syncmlDocument.getBody().getAlert() != null)) {
if (!syncmlDocument.getBody().getAlert().getData().equals(Constants.DISENROLL_ALERT_DATA)) { List<ItemTag> disEnrollItemList = syncmlDocument.getBody().getAlert().getItems();
pendingOperations = operationHandler.getPendingOperations(syncmlDocument); String disEnrollMetaType = null;
operationHandler.checkForDeviceWipe(pendingOperations, deviceIdentifier); if (disEnrollItemList != null && !disEnrollItemList.isEmpty()) {
return Response.ok().entity(operationReply.generateReply( MetaTag disEnrollMetaTag = disEnrollItemList.get(0).getMeta();
syncmlDocument, pendingOperations)).build(); if (disEnrollMetaTag != null) {
} else { disEnrollMetaType = disEnrollMetaTag.getType();
}
}
if (syncmlDocument.getBody().getAlert().getData().equals(Constants.DISENROLL_ALERT_DATA)
&& disEnrollMetaType != null && PluginConstants.SyncML.DEVICE_UNENROLL_META_TYPE
.equals(disEnrollMetaType.trim())) {
if (WindowsAPIUtils.getDeviceManagementService().getDevice(deviceIdentifier, false) != null) { if (WindowsAPIUtils.getDeviceManagementService().getDevice(deviceIdentifier, false) != null) {
operationHandler.updateDisenrollOperationStatus(deviceIdentifier); operationHandler.updateDisenrollOperationStatus(deviceIdentifier);
WindowsAPIUtils.getDeviceManagementService().disenrollDevice(deviceIdentifier); WindowsAPIUtils.getDeviceManagementService().disenrollDevice(deviceIdentifier);
@ -142,12 +162,17 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
log.error(msg); log.error(msg);
return Response.status(Response.Status.NOT_FOUND).entity(msg).build(); return Response.status(Response.Status.NOT_FOUND).entity(msg).build();
} }
} else {
pendingOperations = operationHandler.getPendingOperations(syncmlDocument);
operationHandler.checkForDeviceWipe(pendingOperations, deviceIdentifier);
return Response.ok().entity(operationReply.generateReply(syncmlDocument, pendingOperations))
.build();
} }
} else { } else {
pendingOperations = operationHandler.getPendingOperations(syncmlDocument); pendingOperations = operationHandler.getPendingOperations(syncmlDocument);
operationHandler.checkForDeviceWipe(pendingOperations, deviceIdentifier); operationHandler.checkForDeviceWipe(pendingOperations, deviceIdentifier);
return Response.ok().entity(operationReply.generateReply( return Response.ok().entity(operationReply.generateReply(syncmlDocument, pendingOperations))
syncmlDocument, pendingOperations)).build(); .build();
} }
} }
} }

@ -14,6 +14,22 @@
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * 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 go
*/ */
package org.wso2.carbon.device.mgt.mobile.windows.api.services.syncml.impl; package org.wso2.carbon.device.mgt.mobile.windows.api.services.syncml.impl;
@ -371,7 +387,7 @@ public class SyncmlServiceImpl implements SyncmlService {
* @throws org.wso2.carbon.policy.mgt.common.FeatureManagementException * @throws org.wso2.carbon.policy.mgt.common.FeatureManagementException
*/ */
public String generateReply(SyncmlDocument syncmlDocument, List<? extends Operation> operations) public String generateReply(SyncmlDocument syncmlDocument, List<? extends Operation> operations)
throws SyncmlMessageFormatException, SyncmlOperationException { throws SyncmlMessageFormatException, SyncmlOperationException, WindowsOperationException {
OperationReply operationReply; OperationReply operationReply;
SyncmlGenerator generator; SyncmlGenerator generator;

Loading…
Cancel
Save