Add modification to app creating flow

feature/appm-store/pbac
lasanthaDLPDS 6 years ago
parent 02b99eb442
commit b2260b6919

@ -0,0 +1,225 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
* 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>application-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.2.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.application.mgt.artifact.retrieve.api</artifactId>
<version>3.2.2-SNAPSHOT</version>
<packaging>war</packaging>
<name>WSO2 Carbon - Application Management Artifact_Retrieve API</name>
<description>WSO2 Carbon - Application Management API for getting application artifacts</description>
<url>http://wso2.org</url>
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<packagingExcludes>WEB-INF/lib/*cxf*.jar</packagingExcludes>
<warName>api#application-mgt-artifact-retrieve#v1.0</warName>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>deploy</id>
<build>
<defaultGoal>compile</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<copy todir="${basedir}/../../../repository/deployment/server/webapps" overwrite="true">
<fileset dir="${basedir}/target">
<include name="api#application-mgt-artifact-retrieve#v1.0.war" />
</fileset>
</copy>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>client</id>
<build>
<defaultGoal>test</defaultGoal>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.5.0</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.utils</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.json.wso2</groupId>
<artifactId>json</artifactId>
</dependency>
<dependency>
<groupId>commons-codec.wso2</groupId>
<artifactId>commons-codec</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.application.mgt.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.application.mgt.common</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-core</artifactId>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.orbit.com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jaxrs</artifactId>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.orbit.com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.apimgt.annotations</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.orbit.com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.application.mgt.addons</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,84 @@
/* 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.application.mgt.api.services;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Extension;
import io.swagger.annotations.ExtensionProperty;
import io.swagger.annotations.Info;
import io.swagger.annotations.SwaggerDefinition;
import org.wso2.carbon.device.application.mgt.common.*;
import org.wso2.carbon.device.application.mgt.common.ErrorResponse;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
* APIs to handle application management related tasks.
*/
@SwaggerDefinition(
info = @Info(
version = "1.0.0",
title = "Application Management Common Service",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "name", value = "ApplicationManagementCommonService"),
@ExtensionProperty(name = "context", value = "/api/application-mgt/v1.0/app-mgt"),
})
}
)
)
@Path("/app-mgt")
@Api(value = "Application Management Common Service", description = "This API carries all application management common services")
@Produces(MediaType.APPLICATION_JSON)
public interface AppMgtAPI {
@GET
@Path("/ui-config")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "get application management UI configuration",
notes = "This will get all UI configuration of application management"
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully got UI config.",
response = ApplicationList.class),
@ApiResponse(
code = 404,
message = "Not Found. There doesn't have an defined UI config." +
"query."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Error occurred while getting the UI config.",
response = ErrorResponse.class)
})
Response getUiConfig();
}

@ -0,0 +1,60 @@
/* 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.application.mgt.api.services.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.application.mgt.api.services.AppMgtAPI;
import org.wso2.carbon.device.application.mgt.common.config.UIConfiguration;
import org.wso2.carbon.device.application.mgt.common.services.ConfigManager;
import org.wso2.carbon.device.application.mgt.core.util.APIUtil;
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
/**
* Implementation of Application Management related APIs.
*/
@Produces({"application/json"})
@Path("/app-mgt")
public class AppMgtAPIImpl implements AppMgtAPI {
private static Log log = LogFactory.getLog(AppMgtAPIImpl.class);
@GET
@Override
@Consumes("application/json")
@Path("/ui-config")
public Response getUiConfig() {
ConfigManager configManager = APIUtil.getConfigManager();
try {
UIConfiguration uiConfiguration = configManager.getUIConfiguration();
return Response.status(Response.Status.OK).entity(uiConfiguration).build();
}catch (ApplicationManagementException e) {
String msg = "Error occurred while getting the application list for publisher ";
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
}
}
}

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* 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.
-->
<!-- This file contains the list of permissions that are associated with URL end points
of the web app. Each permission should contain the name, permission path ,API path
(URL) , HTTP method and OAUTH2 authorization scope (not-required).
When defining dynamic paths for APIs, path variables are denoted by '*' notation.
For ex:
Actual API endpoint: devicemgt_admin/1.0.0/devices/{device-id}
URL to be represented here: /devices/*
NOTE: All the endpoints of the web app should be available in this file. Otherwise
it will result 403 error at the runtime.
-->
<PermissionConfiguration>
<APIVersion></APIVersion>
</PermissionConfiguration>

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
* 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.
-->
<!--
This file defines class loading policy of the whole container. But this behaviour can be overridden by individual webapps by putting this file into the META-INF/ directory.
-->
<Classloading xmlns="http://wso2.org/projects/as/classloading">
<!-- Parent-first or child-first. Default behaviour is child-first.-->
<ParentFirst>false</ParentFirst>
<!--
Default environments that contains provides to all the webapps. This can be overridden by individual webapps by specifing required environments
Tomcat environment is the default and every webapps gets it even if they didn't specify it.
e.g. If a webapps requires CXF, they will get both Tomcat and CXF.
-->
<Environments>CXF,Carbon</Environments>
</Classloading>

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* 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.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
<jaxrs:server id="applicationMgtCommonService" address="/">
<jaxrs:serviceBeans>
<ref bean="applicationMgtCommonServiceBean"/>
<ref bean="swaggerResource"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="jsonProvider"/>
<ref bean="multipartProvider"/>
<ref bean="swaggerWriter"/>
</jaxrs:providers>
</jaxrs:server>
<bean id="swaggerConfig" class="io.swagger.jaxrs.config.BeanConfig">
<property name="resourcePackage" value="org.wso2.carbon.device.application.mgt.publisher.api"/>
<property name="version" value="1.0"/>
<property name="host" value="localhost:9443"/>
<property name="schemes" value="https" />
<property name="basePath" value="/api/application-mgt-publisher/v1.0"/>
<property name="title" value="Application Management Admin Service API Definitions"/>
<property name="contact" value="dev@wso2.org"/>
<property name="license" value="Apache 2.0"/>
<property name="licenseUrl" value="http://www.apache.org/licenses/LICENSE-2.0.html"/>
<property name="scan" value="true"/>
</bean>
<bean id="org.wso2.carbon.device.application.mgt.addons.ValidationInterceptor" class="org.wso2.carbon.device.application.mgt.addons.ValidationInterceptor"/>
<bean id="swaggerWriter" class="io.swagger.jaxrs.listing.SwaggerSerializers" />
<bean id="swaggerResource" class="io.swagger.jaxrs.listing.ApiListingResource" />
<bean id="applicationMgtCommonServiceBean" class="org.wso2.carbon.device.application.mgt.api.services.impl.AppMgtAPIImpl"/>
<bean id="jsonProvider" class="org.wso2.carbon.device.application.mgt.addons.JSONMessageHandler"/>
<bean id="multipartProvider" class="org.wso2.carbon.device.application.mgt.addons.MultipartCustomProvider"/>
<cxf:bus>
<cxf:inInterceptors>
<ref bean="org.wso2.carbon.device.application.mgt.addons.ValidationInterceptor"/>
</cxf:inInterceptors>
</cxf:bus>
</beans>

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* 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.
-->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>Application Management Webapp</display-name>
<servlet>
<description>JAX-WS/JAX-RS Application Management Endpoint</description>
<display-name>JAX-WS/JAX-RS Servlet</display-name>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<!-- configure a security filter -->
<init-param>
<param-name>swagger.security.filter</param-name>
<param-value>ApiAuthorizationFilterImpl</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
<context-param>
<param-name>doAuthentication</param-name>
<param-value>false</param-value>
</context-param>
<!-- Below configuration is used to redirect http requests to https -->
<security-constraint>
<web-resource-collection>
<web-resource-name>ApplicationMgt-Admin</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<!--publish to apim-->
<context-param>
<param-name>managed-api-enabled</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>managed-api-owner</param-name>
<param-value>admin</param-value>
</context-param>
<context-param>
<param-name>isSharedWithAllTenants</param-name>
<param-value>true</param-value>
</context-param>
<filter>
<filter-name>ApiOriginFilter</filter-name>
<filter-class>org.wso2.carbon.device.application.mgt.addons.ApiOriginFilter</filter-class>
</filter>
<filter>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
<init-param>
<param-name>hstsEnabled</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter>
<filter-name>ContentTypeBasedCachePreventionFilter</filter-name>
<filter-class>org.wso2.carbon.ui.filters.cache.ContentTypeBasedCachePreventionFilter</filter-class>
<init-param>
<param-name>patterns</param-name>
<param-value>text/html" ,application/json" ,text/plain</param-value>
</init-param>
<init-param>
<param-name>filterAction</param-name>
<param-value>enforce</param-value>
</init-param>
<init-param>
<param-name>httpHeaders</param-name>
<param-value>Cache-Control: no-store, no-cache, must-revalidate, private</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>ContentTypeBasedCachePreventionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>ApiOriginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

@ -42,7 +42,6 @@
<plugin> <plugin>
<groupId>org.apache.felix</groupId> <groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId> <artifactId>maven-bundle-plugin</artifactId>
<version>1.4.0</version>
<extensions>true</extensions> <extensions>true</extensions>
<configuration> <configuration>
<instructions> <instructions>
@ -58,7 +57,6 @@
com.fasterxml.jackson.annotation, com.fasterxml.jackson.annotation,
javax.validation.constraints, javax.validation.constraints,
javax.xml.bind.annotation.*, javax.xml.bind.annotation.*,
org.wso2.carbon.device.mgt.core.dto
</Import-Package> </Import-Package>
<Export-Package> <Export-Package>
org.wso2.carbon.device.application.mgt.common.* org.wso2.carbon.device.application.mgt.common.*
@ -115,6 +113,11 @@
<groupId>org.hibernate</groupId> <groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId> <artifactId>hibernate-validator</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<scope>provided</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

@ -0,0 +1,38 @@
package org.wso2.carbon.device.application.mgt.common;/* 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.
*/
public class Category {
int id;
String categoryName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
}

@ -0,0 +1,39 @@
package org.wso2.carbon.device.application.mgt.common;/* 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.
*/
public class Tag {
int id;
String tagName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTagName() {
return tagName;
}
public void setTagName(String tagName) {
this.tagName = tagName;
}
}

@ -18,6 +18,7 @@
*/ */
package org.wso2.carbon.device.application.mgt.common.services; package org.wso2.carbon.device.application.mgt.common.services;
import org.apache.cxf.jaxrs.ext.multipart.Attachment;
import org.wso2.carbon.device.application.mgt.common.Application; import org.wso2.carbon.device.application.mgt.common.Application;
import org.wso2.carbon.device.application.mgt.common.ApplicationList; import org.wso2.carbon.device.application.mgt.common.ApplicationList;
import org.wso2.carbon.device.application.mgt.common.ApplicationRelease; import org.wso2.carbon.device.application.mgt.common.ApplicationRelease;
@ -41,7 +42,8 @@ public interface ApplicationManager {
* @return Created application * @return Created application
* @throws ApplicationManagementException Application Management Exception * @throws ApplicationManagementException Application Management Exception
*/ */
Application createApplication(Application application) Application createApplication(Application application, Attachment binaryFile, Attachment iconFile,
Attachment bannerFile, List<Attachment> attachmentList)
throws ApplicationManagementException, RequestValidatingException; throws ApplicationManagementException, RequestValidatingException;
/** /**
@ -182,4 +184,17 @@ public interface ApplicationManager {
InputStream binaryFileStram, InputStream iconFileStream, InputStream bannerFileStream, InputStream binaryFileStram, InputStream iconFileStream, InputStream bannerFileStream,
List<InputStream> attachments) throws ApplicationManagementException; List<InputStream> attachments) throws ApplicationManagementException;
/***
*
* @param release {@link ApplicationRelease}
* @param applicationType Type of the application
* @param binaryFile Uploading binary fila. i.e .apk or .ipa
* @param iconFile Icon file for the application.
* @param bannerFile Banner file for the application.
* @param attachmentList Screenshot list.
* @throws RequestValidatingException
*/
void validateReleaseCreatingRequest(ApplicationRelease release, String applicationType, Attachment binaryFile,
Attachment iconFile, Attachment bannerFile, List<Attachment> attachmentList)
throws RequestValidatingException;
} }

@ -19,8 +19,8 @@
package org.wso2.carbon.device.application.mgt.common.services; package org.wso2.carbon.device.application.mgt.common.services;
import org.apache.cxf.jaxrs.ext.multipart.Attachment;
import org.wso2.carbon.device.application.mgt.common.ApplicationRelease; import org.wso2.carbon.device.application.mgt.common.ApplicationRelease;
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException;
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationStorageManagementException; import org.wso2.carbon.device.application.mgt.common.exception.ApplicationStorageManagementException;
import org.wso2.carbon.device.application.mgt.common.exception.RequestValidatingException; import org.wso2.carbon.device.application.mgt.common.exception.RequestValidatingException;
import org.wso2.carbon.device.application.mgt.common.exception.ResourceManagementException; import org.wso2.carbon.device.application.mgt.common.exception.ResourceManagementException;
@ -43,6 +43,9 @@ public interface ApplicationStorageManager {
ApplicationRelease uploadImageArtifacts(ApplicationRelease applicationRelease, ApplicationRelease uploadImageArtifacts(ApplicationRelease applicationRelease,
InputStream iconFile, InputStream bannerFile, List<InputStream> screenshots) throws ResourceManagementException; InputStream iconFile, InputStream bannerFile, List<InputStream> screenshots) throws ResourceManagementException;
ApplicationRelease uploadImageArtifactsTmp(ApplicationRelease applicationRelease,
Attachment iconFile, Attachment bannerFile, List<Attachment> screenshots) throws ResourceManagementException;
/** /**
* To upload image artifacts related with an Application. * To upload image artifacts related with an Application.
* *
@ -67,6 +70,9 @@ public interface ApplicationStorageManager {
ApplicationRelease uploadReleaseArtifact(ApplicationRelease applicationRelease, String appType, String deviceType, ApplicationRelease uploadReleaseArtifact(ApplicationRelease applicationRelease, String appType, String deviceType,
InputStream binaryFile) throws ResourceManagementException, RequestValidatingException; InputStream binaryFile) throws ResourceManagementException, RequestValidatingException;
ApplicationRelease uploadReleaseArtifactTmp(ApplicationRelease applicationRelease, String appType, String deviceType,
Attachment binaryFile) throws ResourceManagementException, RequestValidatingException;
/** /**
* To upload release artifacts for an Application. * To upload release artifacts for an Application.
* *

@ -71,7 +71,6 @@
org.wso2.carbon.user.api.*, org.wso2.carbon.user.api.*,
org.wso2.carbon.ndatasource.core, org.wso2.carbon.ndatasource.core,
org.wso2.carbon, org.wso2.carbon,
javax.annotation,
org.xml.sax, org.xml.sax,
org.xml.sax.helpers, org.xml.sax.helpers,
org.apache.commons.io, org.apache.commons.io,
@ -197,6 +196,11 @@
<artifactId>commons-validator</artifactId> <artifactId>commons-validator</artifactId>
<version>1.6</version> <version>1.6</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<scope>provided</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

@ -19,7 +19,6 @@
package org.wso2.carbon.device.application.mgt.core.dao; package org.wso2.carbon.device.application.mgt.core.dao;
import org.wso2.carbon.device.application.mgt.common.*; import org.wso2.carbon.device.application.mgt.common.*;
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException;
import org.wso2.carbon.device.application.mgt.core.exception.ApplicationManagementDAOException; import org.wso2.carbon.device.application.mgt.core.exception.ApplicationManagementDAOException;
import java.util.List; import java.util.List;
@ -35,7 +34,7 @@ public interface ApplicationDAO {
* @return Created Application. * @return Created Application.
* @throws ApplicationManagementDAOException Application Management DAO Exception. * @throws ApplicationManagementDAOException Application Management DAO Exception.
*/ */
int createApplication(Application application, int deviceId) throws ApplicationManagementDAOException; int createApplication(Application application, int tenantId) throws ApplicationManagementDAOException;
/** /**
* To add tags for a particular application. * To add tags for a particular application.
@ -43,7 +42,26 @@ public interface ApplicationDAO {
* @param tags tags that need to be added for a application. * @param tags tags that need to be added for a application.
* @throws ApplicationManagementDAOException Application Management DAO Exception. * @throws ApplicationManagementDAOException Application Management DAO Exception.
*/ */
void addTags(List<String> tags, int applicationId, int tenantId) throws ApplicationManagementDAOException; void addTags(List<String> tags, int tenantId) throws ApplicationManagementDAOException;
List<Tag> getAllTags(int tenantId) throws ApplicationManagementDAOException;
List<Integer> getTagIdsForTagNames (List<String> tagNames, int tenantId) throws ApplicationManagementDAOException;
void addTagMapping (List<Integer> tagIds, int applicationId, int tenantId) throws ApplicationManagementDAOException;
List<Category> getAllCategories(int tenantId) throws ApplicationManagementDAOException;
void addCategories(List<String> categories, int tenantId) throws ApplicationManagementDAOException;
void addCategoryMapping (List<Integer> categoryIds, int applicationId, int tenantId) throws ApplicationManagementDAOException;
/** /**
* To check application existence. * To check application existence.

@ -25,15 +25,17 @@ import org.wso2.carbon.device.application.mgt.common.AppLifecycleState;
import org.wso2.carbon.device.application.mgt.common.Application; import org.wso2.carbon.device.application.mgt.common.Application;
import org.wso2.carbon.device.application.mgt.common.ApplicationList; import org.wso2.carbon.device.application.mgt.common.ApplicationList;
import org.wso2.carbon.device.application.mgt.common.ApplicationRelease; import org.wso2.carbon.device.application.mgt.common.ApplicationRelease;
import org.wso2.carbon.device.application.mgt.common.Category;
import org.wso2.carbon.device.application.mgt.common.Filter; import org.wso2.carbon.device.application.mgt.common.Filter;
import org.wso2.carbon.device.application.mgt.common.Pagination; import org.wso2.carbon.device.application.mgt.common.Pagination;
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException; import org.wso2.carbon.device.application.mgt.common.Tag;
import org.wso2.carbon.device.application.mgt.common.exception.DBConnectionException; import org.wso2.carbon.device.application.mgt.common.exception.DBConnectionException;
import org.wso2.carbon.device.application.mgt.core.dao.ApplicationDAO; import org.wso2.carbon.device.application.mgt.core.dao.ApplicationDAO;
import org.wso2.carbon.device.application.mgt.core.dao.common.Util; import org.wso2.carbon.device.application.mgt.core.dao.common.Util;
import org.wso2.carbon.device.application.mgt.core.dao.impl.AbstractDAOImpl; import org.wso2.carbon.device.application.mgt.core.dao.impl.AbstractDAOImpl;
import org.wso2.carbon.device.application.mgt.core.exception.ApplicationManagementDAOException; import org.wso2.carbon.device.application.mgt.core.exception.ApplicationManagementDAOException;
import java.sql.Array;
import java.sql.Connection; import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
@ -50,7 +52,7 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic
private static final Log log = LogFactory.getLog(GenericApplicationDAOImpl.class); private static final Log log = LogFactory.getLog(GenericApplicationDAOImpl.class);
@Override @Override
public int createApplication(Application application, int deviceId) throws ApplicationManagementDAOException { public int createApplication(Application application, int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to create an application"); log.debug("Request received in DAO Layer to create an application");
log.debug("Application Details : "); log.debug("Application Details : ");
@ -63,26 +65,26 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic
int applicationId = -1; int applicationId = -1;
try { try {
conn = this.getDBConnection(); conn = this.getDBConnection();
stmt = conn.prepareStatement("INSERT INTO AP_APP (NAME, TYPE, APP_CATEGORY, SUB_TYPE, RESTRICTED, " stmt = conn.prepareStatement("INSERT INTO AP_APP "
+ "TENANT_ID, DEVICE_TYPE_ID) VALUES (?, ?, ?, ?, ?, ?, ?)", + "(NAME, "
Statement.RETURN_GENERATED_KEYS); + "DESCRIPTION, "
+ "TYPE, "
+ "SUB_TYPE, "
+ "TENANT_ID, "
+ "DEVICE_TYPE_ID) VALUES (?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
stmt.setString(1, application.getName()); stmt.setString(1, application.getName());
stmt.setString(2, application.getType()); stmt.setString(2, application.getDescription());
stmt.setString(3, application.getAppCategory()); stmt.setString(3, application.getType());
stmt.setString(4, application.getSubType()); stmt.setString(4, application.getSubType());
stmt.setBoolean(5, application.getIsRestricted()); stmt.setInt(5, tenantId);
stmt.setInt(6, application.getUser().getTenantId()); stmt.setInt(6, application.getDeviceTypeObj().getId());
stmt.setInt(7, deviceId);
stmt.executeUpdate(); stmt.executeUpdate();
rs = stmt.getGeneratedKeys(); rs = stmt.getGeneratedKeys();
if (rs.next()) { if (rs.next()) {
applicationId = rs.getInt(1); applicationId = rs.getInt(1);
} }
// TODO : throw error if applicationId = -1
return applicationId; return applicationId;
} catch (DBConnectionException e) { } catch (DBConnectionException e) {
throw new ApplicationManagementDAOException( throw new ApplicationManagementDAOException(
"Error occurred while obtaining the DB connection when application creation", e); "Error occurred while obtaining the DB connection when application creation", e);
@ -737,21 +739,22 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic
} }
@Override @Override
public void addTags(List<String> tags, int applicationId, int tenantId) throws ApplicationManagementDAOException { public void addTags(List<String> tags, int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to add tags"); log.debug("Request received in DAO Layer to add tags");
} }
Connection conn; Connection conn;
PreparedStatement stmt = null; PreparedStatement stmt = null;
String sql = "INSERT INTO AP_APP_TAG (TAG, TENANT_ID, AP_APP_ID) VALUES (?, ?, ?)"; String sql = "INSERT INTO AP_APP_TAG "
+ "(TAG,"
+ " TENANT_ID) "
+ "VALUES (?, ?)";
try { try {
conn = this.getDBConnection(); conn = this.getDBConnection();
conn.setAutoCommit(false);
stmt = conn.prepareStatement(sql); stmt = conn.prepareStatement(sql);
for (String tag : tags) { for (String tag : tags) {
stmt.setString(1, tag); stmt.setString(1, tag);
stmt.setInt(2, tenantId); stmt.setInt(2, tenantId);
stmt.setInt(3, applicationId);
stmt.addBatch(); stmt.addBatch();
} }
stmt.executeBatch(); stmt.executeBatch();
@ -766,6 +769,212 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic
} }
} }
@Override
public List<Tag> getAllTags(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to get all tags");
}
Connection conn;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
List<Tag> tags = new ArrayList<>();
String sql = "SELECT "
+ "AP_APP_TAG.ID AS ID, "
+ "AP_APP_TAG.TAG AS TAG "
+ "FROM AP_APP_TAG "
+ "WHERE TENANT_ID = ?";
conn = this.getDBConnection();
stmt = conn.prepareStatement(sql);
stmt.setInt(1, tenantId);
rs = stmt.executeQuery();
while(rs.next()){
Tag tag = new Tag();
tag.setId(rs.getInt("ID"));
tag.setTagName(rs.getString("TAG"));
tags.add(tag);
}
return tags;
} catch (DBConnectionException e) {
throw new ApplicationManagementDAOException(
"Error occurred while obtaining the DB connection when adding tags", e);
} catch (SQLException e) {
throw new ApplicationManagementDAOException("Error occurred while adding tags", e);
} finally {
Util.cleanupResources(stmt, rs);
}
}
@Override
public List<Category> getAllCategories(int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to get all tags");
}
Connection conn;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
List<Category> categories = new ArrayList<>();
String sql = "SELECT "
+ "AP_APP_CATEGORY.ID AS ID, "
+ "AP_APP_CATEGORY.CATEGORY AS CATEGORY "
+ "FROM AP_APP_CATEGORY "
+ "WHERE TENANT_ID = ?";
conn = this.getDBConnection();
stmt = conn.prepareStatement(sql);
stmt.setInt(1, tenantId);
rs = stmt.executeQuery();
while(rs.next()){
Category category = new Category();
category.setId(rs.getInt("ID"));
category.setCategoryName(rs.getString("CATEGORY"));
categories.add(category);
}
return categories;
} catch (DBConnectionException e) {
throw new ApplicationManagementDAOException(
"Error occurred while obtaining the DB connection when getting categories", e);
} catch (SQLException e) {
throw new ApplicationManagementDAOException("Error occurred while getting categories", e);
} finally {
Util.cleanupResources(stmt, rs);
}
}
@Override
public void addCategories(List<String> categories, int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to add tags");
}
Connection conn;
PreparedStatement stmt = null;
String sql = "INSERT INTO AP_APP_CATEGORY "
+ "(CATEGORY,"
+ " TENANT_ID) "
+ "VALUES (?, ?)";
try {
conn = this.getDBConnection();
stmt = conn.prepareStatement(sql);
for (String category : categories) {
stmt.setString(1, category);
stmt.setInt(2, tenantId);
stmt.addBatch();
}
stmt.executeBatch();
} catch (DBConnectionException e) {
throw new ApplicationManagementDAOException(
"Error occurred while obtaining the DB connection when adding categories.", e);
} catch (SQLException e) {
throw new ApplicationManagementDAOException("Error occurred while adding categories.", e);
} finally {
Util.cleanupResources(stmt, null);
}
}
@Override
public void addCategoryMapping (List<Integer> categoryIds, int applicationId, int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to add categories");
}
Connection conn;
PreparedStatement stmt = null;
String sql = "INSERT INTO AP_APP_CATEGORY_MAPPING "
+ "(AP_APP_CATEGORY_ID, "
+ "AP_APP_ID, "
+ " TENANT_ID) "
+ "VALUES (?, ?, ?)";
try {
conn = this.getDBConnection();
stmt = conn.prepareStatement(sql);
for (Integer categoryId : categoryIds) {
stmt.setInt(1, categoryId);
stmt.setInt(2, applicationId);
stmt.setInt(3, tenantId);
stmt.addBatch();
}
stmt.executeBatch();
} catch (DBConnectionException e) {
throw new ApplicationManagementDAOException(
"Error occurred while obtaining the DB connection when adding data into category mapping.", e);
} catch (SQLException e) {
throw new ApplicationManagementDAOException("Error occurred while adding data into category mapping.", e);
} finally {
Util.cleanupResources(stmt, null);
}
}
@Override
public List<Integer> getTagIdsForTagNames(List<String> tagNames, int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to get tag ids for given tag names");
}
Connection conn;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
List<Integer> tagIds = new ArrayList<>();
String sql = "SELECT "
+ "AP_APP_TAG.ID AS ID "
+ "FROM AP_APP_TAG "
+ "WHERE AP_APP_TAG..NAME IN ( ? ) AND TENANT_ID = ?";
conn = this.getDBConnection();
Array array = conn.createArrayOf("VARCHAR", new List[] { tagNames });
stmt = conn.prepareStatement(sql);
stmt.setArray(1, array);
stmt.setInt(2, tenantId);
rs = stmt.executeQuery();
while(rs.next()){
tagIds.add(rs.getInt("ID"));
}
return tagIds;
} catch (DBConnectionException e) {
throw new ApplicationManagementDAOException(
"Error occurred while obtaining the DB connection when adding tags", e);
} catch (SQLException e) {
throw new ApplicationManagementDAOException("Error occurred while adding tags", e);
} finally {
Util.cleanupResources(stmt, rs);
}
}
public void addTagMapping (List<Integer> tagIds, int applicationId, int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to add tags");
}
Connection conn;
PreparedStatement stmt = null;
String sql = "INSERT INTO AP_APP_TAG_MAPPING "
+ "(AP_APP_TAG_ID, "
+ "AP_APP_ID, "
+ " TENANT_ID) "
+ "VALUES (?, ?, ?)";
try {
conn = this.getDBConnection();
stmt = conn.prepareStatement(sql);
for (Integer tagId : tagIds) {
stmt.setInt(1, tagId);
stmt.setInt(2, applicationId);
stmt.setInt(3, tenantId);
stmt.addBatch();
}
stmt.executeBatch();
} catch (DBConnectionException e) {
throw new ApplicationManagementDAOException(
"Error occurred while obtaining the DB connection when adding tags", e);
} catch (SQLException e) {
throw new ApplicationManagementDAOException("Error occurred while adding tags", e);
} finally {
Util.cleanupResources(stmt, null);
}
}
@Override @Override
public void deleteTags(List<String> tags, int applicationId, int tenantId) throws ApplicationManagementDAOException { public void deleteTags(List<String> tags, int applicationId, int tenantId) throws ApplicationManagementDAOException {
Connection conn; Connection conn;
@ -784,9 +993,6 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic
stmt.addBatch(); stmt.addBatch();
} }
stmt.executeBatch(); stmt.executeBatch();
} catch (DBConnectionException e) { } catch (DBConnectionException e) {
throw new ApplicationManagementDAOException("Error occurred while obtaining the DB connection.", e); throw new ApplicationManagementDAOException("Error occurred while obtaining the DB connection.", e);
} catch (SQLException e) { } catch (SQLException e) {

@ -18,6 +18,8 @@
*/ */
package org.wso2.carbon.device.application.mgt.core.impl; package org.wso2.carbon.device.application.mgt.core.impl;
import org.apache.commons.lang.StringUtils;
import org.apache.cxf.jaxrs.ext.multipart.Attachment;
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.wso2.carbon.CarbonConstants; import org.wso2.carbon.CarbonConstants;
@ -29,8 +31,10 @@ import org.wso2.carbon.device.application.mgt.common.ApplicationList;
import org.wso2.carbon.device.application.mgt.common.ApplicationRelease; import org.wso2.carbon.device.application.mgt.common.ApplicationRelease;
import org.wso2.carbon.device.application.mgt.common.ApplicationSubscriptionType; import org.wso2.carbon.device.application.mgt.common.ApplicationSubscriptionType;
import org.wso2.carbon.device.application.mgt.common.ApplicationType; import org.wso2.carbon.device.application.mgt.common.ApplicationType;
import org.wso2.carbon.device.application.mgt.common.Category;
import org.wso2.carbon.device.application.mgt.common.Filter; import org.wso2.carbon.device.application.mgt.common.Filter;
import org.wso2.carbon.device.application.mgt.common.LifecycleState; import org.wso2.carbon.device.application.mgt.common.LifecycleState;
import org.wso2.carbon.device.application.mgt.common.Tag;
import org.wso2.carbon.device.application.mgt.common.User; import org.wso2.carbon.device.application.mgt.common.User;
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException; import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException;
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationStorageManagementException; import org.wso2.carbon.device.application.mgt.common.exception.ApplicationStorageManagementException;
@ -65,6 +69,7 @@ import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -73,6 +78,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Queue; import java.util.Queue;
import java.util.Set; import java.util.Set;
import java.util.UUID;
/** /**
* Default Concrete implementation of Application Management related implementations. * Default Concrete implementation of Application Management related implementations.
@ -105,35 +111,87 @@ public class ApplicationManagerImpl implements ApplicationManager {
* @throws RequestValidatingException if application creating request is invalid, returns {@link RequestValidatingException} * @throws RequestValidatingException if application creating request is invalid, returns {@link RequestValidatingException}
* @throws ApplicationManagementException Catch all other throwing exceptions and returns {@link ApplicationManagementException} * @throws ApplicationManagementException Catch all other throwing exceptions and returns {@link ApplicationManagementException}
*/ */
@Override public Application createApplication(Application application) @Override
public Application createApplication(Application application, Attachment binaryFile, Attachment iconFile,
Attachment bannerFile, List<Attachment> attachmentList)
throws RequestValidatingException, ApplicationManagementException { throws RequestValidatingException, ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
ApplicationStorageManager applicationStorageManager = Util.getApplicationStorageManager();
application.setUser(new User(userName, tenantId)); application.setUser(new User(userName, tenantId));
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Create Application received for the tenant : " + tenantId + " From" + " the user : " + userName); log.debug("Create Application received for the tenant : " + tenantId + " From" + " the user : " + userName);
} }
validateAppCreatingRequest(application, tenantId); DeviceType deviceType = null;
//todo throw different exception List<DeviceType> deviceTypes;
validateAppReleasePayload(application.getApplicationReleases().get(0));
DeviceType deviceType;
ApplicationRelease applicationRelease; ApplicationRelease applicationRelease;
List<ApplicationRelease> applicationReleases = new ArrayList<>(); List<ApplicationRelease> applicationReleases = new ArrayList<>();
try { try {
validateAppCreatingRequest(application, binaryFile, iconFile, bannerFile, attachmentList);
// Getting the device type details to get device type ID for internal mappings // Getting the device type details to get device type ID for internal mappings
deviceType = Util.getDeviceManagementService().getDeviceType(application.getDeviceType()); // deviceType = Util.getDeviceManagementService().getDeviceType(application.getDeviceType());
deviceTypes = Util.getDeviceManagementService().getDeviceTypes();
for (DeviceType dt : deviceTypes) {
if (dt.getName().equals(application.getDeviceType())) {
deviceType = dt;
application.setDeviceTypeObj(dt);
break;
}
}
ConnectionManagerUtil.beginDBTransaction();
if (deviceType == null) { if (deviceType == null) {
log.error("Device type is not matched with application type"); log.error("Invalid device type is found with the request. Requested Device Type is: " + application
.getDeviceType());
return null; return null;
} }
if (!application.getUnrestrictedRoles().isEmpty()) {
application.setIsRestricted(true); applicationRelease = application.getApplicationReleases().get(0);
// The application executable artifacts such as apks are uploaded.
if (!ApplicationType.ENTERPRISE.toString().equals(application.getType())) {
applicationRelease = applicationStorageManager
.uploadReleaseArtifactTmp(applicationRelease, application.getType(),
application.getDeviceType(), null);
} else {
applicationRelease = applicationStorageManager
.uploadReleaseArtifactTmp(applicationRelease, application.getType(),
application.getDeviceType(), binaryFile);
}
// Upload images
applicationRelease = applicationStorageManager
.uploadImageArtifactsTmp(applicationRelease, iconFile, bannerFile, attachmentList);
applicationRelease.setUuid(UUID.randomUUID().toString());
applicationReleases.add(applicationRelease);
application.setApplicationReleases(applicationReleases);
} catch (ResourceManagementException e) {
throw new ApplicationManagementException("");
} catch (DeviceManagementException e) {
throw new ApplicationManagementException(
"Error occurred while getting device type id of " + application.getType(), e);
}
try {
Filter filter = new Filter();
filter.setFullMatch(true);
filter.setAppName(application.getName().trim());
filter.setDeviceType(deviceType);
filter.setOffset(0);
filter.setLimit(1);
ConnectionManagerUtil.beginDBTransaction();
ApplicationList applicationList = applicationDAO.getApplications(filter, tenantId);
if (!applicationList.getApplications().isEmpty()) {
throw new RequestValidatingException(
"Already an application registered with same name - " + applicationList.getApplications().get(0)
.getName());
} }
// Insert to application table // Insert to application table
int appId = this.applicationDAO.createApplication(application, deviceType.getId()); int appId = this.applicationDAO.createApplication(application, tenantId);
if (appId == -1) { if (appId == -1) {
log.error("Application creation is Failed"); log.error("Application creation is Failed");
@ -143,19 +201,78 @@ public class ApplicationManagerImpl implements ApplicationManager {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("New Application entry added to AP_APP table. App Id:" + appId); log.debug("New Application entry added to AP_APP table. App Id:" + appId);
} }
if (!application.getTags().isEmpty()) {
this.applicationDAO.addTags(application.getTags(), appId, tenantId); //adding application unrestricted roles
if (log.isDebugEnabled()) { if (!application.getUnrestrictedRoles().isEmpty()) {
log.debug("New tags entry added to AP_APP_TAG table. App Id:" + appId); if (!isValidRestrictedRole(application.getUnrestrictedRoles())) {
String msg = "Unrestricted role list contain role/roles which are not in the user store.";
log.error(msg);
throw new ApplicationManagementException(msg);
} }
}
if (application.getIsRestricted()) {
this.visibilityDAO.addUnrestrictedRoles(application.getUnrestrictedRoles(), appId, tenantId); this.visibilityDAO.addUnrestrictedRoles(application.getUnrestrictedRoles(), appId, tenantId);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("New restricted roles to app ID mapping added to AP_UNRESTRICTED_ROLE table." log.debug("New restricted roles to app ID mapping added to AP_UNRESTRICTED_ROLE table."
+ " App Id:" + appId); + " App Id:" + appId);
} }
} }
List<Category> registeredCatehgories = this.applicationDAO.getAllCategories(tenantId);
if (registeredCatehgories.isEmpty() || !registeredCatehgories.contains(application.getAppCategory())) {
ConnectionManagerUtil.rollbackDBTransaction();
String msg = "Registered application category set is empty.";
log.error(msg);
throw new ApplicationManagementException(msg);
}
boolean isValidAppCategory = false;
for (Category category : registeredCatehgories) {
if (category.getCategoryName().equals(application.getAppCategory())) {
isValidAppCategory = true;
break;
}
}
// if (!isValidAppCategory){
// ConnectionManagerUtil.rollbackDBTransaction();
// String msg = "Invalid category type is found. Category: " + application. getAppCategory();
// log.error(msg);
// throw new RequestValidatingException(msg);
// }
// todo add categories
//adding application tags
if (!application.getTags().isEmpty()) {
List<Tag> allRegisteredTags = applicationDAO.getAllTags(tenantId);
List<String> allRegisteredTagNames = new ArrayList<>();
List<Integer> tagIds = new ArrayList<>();
for (Tag tag : allRegisteredTags) {
allRegisteredTagNames.add(tag.getTagName());
}
List<String> newTags = getDifference(application.getTags(), allRegisteredTagNames);
if (!newTags.isEmpty()) {
this.applicationDAO.addTags(newTags, tenantId);
if (log.isDebugEnabled()) {
log.debug("New tags entry added to AP_APP_TAG table. App Id:" + appId);
}
tagIds = this.applicationDAO.getTagIdsForTagNames(application.getTags(), tenantId);
} else {
for (Tag tag : allRegisteredTags) {
for (String tagName : application.getTags()) {
if (tagName.equals(tag.getTagName())) {
tagIds.add(tag.getId());
break;
}
}
}
}
this.applicationDAO.addTagMapping(tagIds, appId, tenantId);
}
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Creating a new release. App Id:" + appId); log.debug("Creating a new release. App Id:" + appId);
} }
@ -176,9 +293,6 @@ public class ApplicationManagerImpl implements ApplicationManager {
ConnectionManagerUtil.commitDBTransaction(); ConnectionManagerUtil.commitDBTransaction();
} }
return application; return application;
} catch (DeviceManagementException e) {
throw new ApplicationManagementException(
"Error occurred while getting device type id of " + application.getType(), e);
} catch (LifeCycleManagementDAOException e) { } catch (LifeCycleManagementDAOException e) {
ConnectionManagerUtil.rollbackDBTransaction(); ConnectionManagerUtil.rollbackDBTransaction();
throw new ApplicationManagementException( throw new ApplicationManagementException(
@ -198,6 +312,8 @@ public class ApplicationManagerImpl implements ApplicationManager {
+ " application type: " + application.getType(), e); + " application type: " + application.getType(), e);
} catch (TransactionManagementException e) { } catch (TransactionManagementException e) {
throw new ApplicationManagementException("Error occured while disabling AutoCommit. ", e); throw new ApplicationManagementException("Error occured while disabling AutoCommit. ", e);
} catch (UserStoreException e) {
throw new ApplicationManagementException("Error occured while disabling AutoCommit. ", e);
} finally { } finally {
ConnectionManagerUtil.closeDBConnection(); ConnectionManagerUtil.closeDBConnection();
} }
@ -271,7 +387,7 @@ public class ApplicationManagerImpl implements ApplicationManager {
throws ApplicationManagementException { throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
validateAppReleasePayload(applicationRelease); // validateAppReleasePayload(applicationRelease);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Application release request is received for the application id: " + applicationId); log.debug("Application release request is received for the application id: " + applicationId);
} }
@ -433,13 +549,32 @@ public class ApplicationManagerImpl implements ApplicationManager {
return false; return false;
} }
private boolean isValidRestrictedRole(Collection<String> unrestrictedRoleList) throws UserStoreException {
List<String> roleList = new ArrayList<>(Arrays.asList(getRoleNames()));
return roleList.containsAll(unrestrictedRoleList);
}
private String[] getRoleNames() throws UserStoreException {
UserRealm userRealm = CarbonContext.getThreadLocalCarbonContext().getUserRealm();
if (userRealm != null) {
return userRealm.getUserStoreManager().getRoleNames();
} else {
String msg = "User realm is not initiated.";
log.error(msg);
throw new UserStoreException(msg);
}
}
private String[] getRolesOfUser(String userName) throws UserStoreException { private String[] getRolesOfUser(String userName) throws UserStoreException {
UserRealm userRealm = CarbonContext.getThreadLocalCarbonContext().getUserRealm(); UserRealm userRealm = CarbonContext.getThreadLocalCarbonContext().getUserRealm();
String[] roleList = {}; String[] roleList = {};
if (userRealm != null) { if (userRealm != null) {
userRealm.getUserStoreManager().getRoleNames();
roleList = userRealm.getUserStoreManager().getRoleListOfUser(userName); roleList = userRealm.getUserStoreManager().getRoleListOfUser(userName);
} else { } else {
log.error("role list is empty of user :" + userName); String msg = "User realm is not initiated. Logged in user: " + userName;
log.error(msg);
throw new UserStoreException(msg);
} }
return roleList; return roleList;
} }
@ -780,74 +915,12 @@ public class ApplicationManagerImpl implements ApplicationManager {
CarbonConstants.UI_PERMISSION_ACTION); CarbonConstants.UI_PERMISSION_ACTION);
} }
/**
* To validate the application creating request
*
* @param application Application that need to be created
* @throws RequestValidatingException Validation Exception
*/
private void validateAppCreatingRequest(Application application, int tenantId) throws RequestValidatingException {
Boolean isValidApplicationType;
Filter filter = new Filter();
try {
filter.setFullMatch(true);
filter.setAppName(application.getName().trim());
filter.setOffset(0);
filter.setLimit(1);
if (application.getName() == null) {
throw new RequestValidatingException("Application name cannot be empty");
}
if (application.getUser() == null || application.getUser().getUserName() == null
|| application.getUser().getTenantId() == -1) {
throw new RequestValidatingException("Username and tenant Id cannot be empty");
}
if (application.getAppCategory() == null) {
throw new RequestValidatingException("Application category can't be empty");
}
isValidApplicationType = isValidAppType(application.getType());
if (!isValidApplicationType) {
throw new RequestValidatingException(
"App Type contains in the application creating payload doesn't match with supported app types");
}
if (application.getApplicationReleases().size() > 1) {
throw new RequestValidatingException(
"Invalid payload. Application creating payload should contains one application release, but "
+ "the payload contains more than one");
}
//Check whether application is already existing one or not
ConnectionManagerUtil.openDBConnection();
ApplicationList applicationList = applicationDAO.getApplications(filter, tenantId);
if (applicationList != null && applicationList.getApplications() != null && !applicationList
.getApplications().isEmpty()) {
throw new RequestValidatingException(
"Already an application registered with same name - " + applicationList.getApplications().get(0)
.getName());
}
} catch (ApplicationManagementDAOException e) {
throw new RequestValidatingException(
"Error occured while getting existing applications for application name: " + application.getName()
+ " and application type " + application.getType() + ". Tenant ID is " + tenantId, e);
} catch (DBConnectionException e) {
throw new RequestValidatingException(
"Error occured while getting database connection to get existing applications for application name: "
+ application.getName() + " and application type: " + application.getType()
+ ". Tenant id is " + tenantId, e);
} finally {
ConnectionManagerUtil.closeDBConnection();
}
}
/*** /***
* To verify whether application type is valid one or not * To verify whether application type is valid one or not
* @param appType application type {@link ApplicationType} * @param appType application type {@link ApplicationType}
* @return true returns if appType is valid on, otherwise returns false * @return true returns if appType is valid on, otherwise returns false
*/ */
private Boolean isValidAppType(String appType) { private boolean isValidAppType(String appType) {
if (appType == null) { if (appType == null) {
return false; return false;
} }
@ -1173,7 +1246,7 @@ public class ApplicationManagerImpl implements ApplicationManager {
addingTags = getDifference(existingApplication.getTags(), application.getTags()); addingTags = getDifference(existingApplication.getTags(), application.getTags());
removingTags = getDifference(application.getTags(), existingApplication.getTags()); removingTags = getDifference(application.getTags(), existingApplication.getTags());
if (!addingTags.isEmpty()) { if (!addingTags.isEmpty()) {
applicationDAO.addTags(addingTags, application.getId(), tenantId); // applicationDAO.addTags(addingTags, application.getId(), tenantId);
} }
if (!removingTags.isEmpty()) { if (!removingTags.isEmpty()) {
applicationDAO.deleteTags(removingTags, application.getId(), tenantId); applicationDAO.deleteTags(removingTags, application.getId(), tenantId);
@ -1376,4 +1449,105 @@ public class ApplicationManagerImpl implements ApplicationManager {
+ " Application release UUID: " + releaseUuid); + " Application release UUID: " + releaseUuid);
} }
} }
/***
* To validate the application creating request
*
* @param application {@link Application}
* @param binaryFile Uploading binary fila. i.e .apk or .ipa
* @param iconFile Icon file for the application.
* @param bannerFile Banner file for the application.
* @param attachmentList Screenshot list.
* @throws RequestValidatingException
*/
private void validateAppCreatingRequest(Application application, Attachment binaryFile, Attachment iconFile,
Attachment bannerFile, List<Attachment> attachmentList) throws RequestValidatingException{
boolean isValidApplicationType;
String applicationType = application.getType();
if (StringUtils.isEmpty(application.getName())) {
String msg = "";
log.error(msg);
throw new RequestValidatingException("Application name cannot be empty");
}
if (StringUtils.isEmpty(application.getAppCategory())) {
throw new RequestValidatingException("Application category can't be empty");
}
if (StringUtils.isEmpty(applicationType)) {
throw new RequestValidatingException("Application type can't be empty");
}
if (StringUtils.isEmpty(application.getDeviceType())) {
throw new RequestValidatingException("Device type can't be empty for the application");
}
isValidApplicationType = isValidAppType(application.getType());
if (!isValidApplicationType) {
throw new RequestValidatingException(
"App Type contains in the application creating payload doesn't match with supported app types");
}
List<ApplicationRelease> appReleases;
appReleases = application.getApplicationReleases();
if (appReleases == null || appReleases.size() != 1) {
String msg =
"Invalid application creating request. Application creating request must have single application "
+ "release. Application name:" + application.getName() + " and type: " + application
.getType();
throw new RequestValidatingException(msg);
}
validateReleaseCreatingRequest(appReleases.get(0), applicationType, binaryFile, iconFile, bannerFile,
attachmentList);
}
/***
*
* @param release {@link ApplicationRelease}
* @param applicationType Type of the application
* @param binaryFile Uploading binary fila. i.e .apk or .ipa
* @param iconFile Icon file for the application.
* @param bannerFile Banner file for the application.
* @param attachmentList Screenshot list.
* @throws RequestValidatingException
*/
public void validateReleaseCreatingRequest(ApplicationRelease release, String applicationType,
Attachment binaryFile, Attachment iconFile, Attachment bannerFile, List<Attachment> attachmentList)
throws RequestValidatingException {
if (ApplicationType.WEB_CLIP.toString().equals(applicationType) && release.getUrl() == null){
String msg = "URL should't be null for the application release creating request for application type: "
+ applicationType;
log.error(msg);
throw new RequestValidatingException(msg);
}
validateArtifacts(binaryFile, iconFile, bannerFile, attachmentList, applicationType);
}
private void validateArtifacts(Attachment binaryFile, Attachment iconFile, Attachment bannerFile,
List<Attachment> attachmentList, String applicationType) throws RequestValidatingException {
if (iconFile == null) {
String msg = "Icon file is not found with the application release creating request.";
log.error(msg);
throw new RequestValidatingException(msg);
}
if (bannerFile == null) {
String msg = "Banner file is not found with the application release creating request.";
log.error(msg);
throw new RequestValidatingException(msg);
}
if (attachmentList == null || attachmentList.isEmpty()) {
String msg = "Screenshots are not found with the application release creating request.";
log.error(msg);
throw new RequestValidatingException(msg);
}
if (binaryFile == null && ApplicationType.ENTERPRISE.toString().equals(applicationType)) {
String msg = "Binary file is not found with the application release creating request. Application type: "
+ applicationType;
log.error(msg);
throw new RequestValidatingException(msg);
}
}
} }

@ -29,6 +29,7 @@ import org.apache.commons.io.IOUtils;
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.commons.validator.routines.UrlValidator; import org.apache.commons.validator.routines.UrlValidator;
import org.apache.cxf.jaxrs.ext.multipart.Attachment;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.application.mgt.common.ApplicationRelease; import org.wso2.carbon.device.application.mgt.common.ApplicationRelease;
import org.wso2.carbon.device.application.mgt.common.ApplicationType; import org.wso2.carbon.device.application.mgt.common.ApplicationType;
@ -46,6 +47,7 @@ import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import java.io.*; import java.io.*;
import java.text.ParseException; import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -131,6 +133,78 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager
} }
} }
public ApplicationRelease uploadImageArtifactsTmp(ApplicationRelease applicationRelease,
Attachment iconFile, Attachment bannerFile, List<Attachment> screenshots) throws ResourceManagementException{
InputStream iconFileStream;
InputStream bannerFileStream;
List<InputStream> screenshotStreams = new ArrayList<>();
List<String> scFileExtensions = new ArrayList<>();
String iconFileExtension;
String bannerFileExtension;
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
String artifactDirectoryPath;
String iconStoredLocation;
String bannerStoredLocation;
String scStoredLocation;
try {
iconFileStream = iconFile.getDataHandler().getInputStream();
iconFileExtension = iconFile.getDataHandler().getContentType();
bannerFileExtension = bannerFile.getDataHandler().getContentType();
bannerFileStream = bannerFile.getDataHandler().getInputStream();
for (Attachment screenshot : screenshots) {
screenshotStreams.add(screenshot.getDataHandler().getInputStream());
scFileExtensions.add(screenshot.getDataHandler().getContentType());
}
artifactDirectoryPath = storagePath + applicationRelease.getAppHashValue();
StorageManagementUtil.createArtifactDirectory(artifactDirectoryPath);
iconStoredLocation = artifactDirectoryPath + File.separator + Constants.IMAGE_ARTIFACTS[0] + iconFileExtension;
bannerStoredLocation = artifactDirectoryPath + File.separator + Constants.IMAGE_ARTIFACTS[1] + bannerFileExtension;
if (iconFileStream != null) {
saveFile(iconFileStream, iconStoredLocation);
applicationRelease.setIconLoc(iconStoredLocation);
}
if (bannerFileStream != null) {
saveFile(bannerFileStream, bannerStoredLocation);
applicationRelease.setBannerLoc(bannerStoredLocation);
}
if (!screenshotStreams.isEmpty()) {
if (screenshotStreams.size() > screenShotMaxCount) {
throw new ApplicationStorageManagementException("Maximum limit for the screen-shot exceeds");
}
int count = 0;
for (InputStream screenshotStream : screenshotStreams) {
scStoredLocation = artifactDirectoryPath + File.separator + Constants.IMAGE_ARTIFACTS[2] + count
+ scFileExtensions.get(count);
count ++;
if (count == 1) {
applicationRelease.setScreenshotLoc1(scStoredLocation);
}
if (count == 2) {
applicationRelease.setScreenshotLoc2(scStoredLocation);
}
if (count == 3) {
applicationRelease.setScreenshotLoc3(scStoredLocation);
}
saveFile(screenshotStream, scStoredLocation);
}
}
return applicationRelease;
} catch (IOException e) {
throw new ApplicationStorageManagementException("IO Exception while saving the screens hots for " +
"the application " + applicationRelease.getUuid(), e);
} catch (ApplicationStorageManagementException e) {
throw new ApplicationStorageManagementException("Application Management DAO exception while trying to "
+ "update the screen-shot count for the application " + applicationRelease.getUuid() +
" for the tenant id " + tenantId, e);
}
}
@Override @Override
public ApplicationRelease updateImageArtifacts(ApplicationRelease applicationRelease, InputStream public ApplicationRelease updateImageArtifacts(ApplicationRelease applicationRelease, InputStream
iconFileStream, InputStream bannerFileStream, List<InputStream> screenShotStreams) iconFileStream, InputStream bannerFileStream, List<InputStream> screenShotStreams)
@ -176,72 +250,160 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager
@Override @Override
public ApplicationRelease uploadReleaseArtifact(ApplicationRelease applicationRelease, String appType, public ApplicationRelease uploadReleaseArtifact(ApplicationRelease applicationRelease, String appType,
String deviceType, InputStream binaryFile) throws ResourceManagementException, RequestValidatingException { String deviceType, InputStream binaryFile) throws ResourceManagementException, RequestValidatingException {
try { try {
if (ApplicationType.WEB_CLIP.toString().equals(appType)) { if (ApplicationType.WEB_CLIP.toString().equals(appType)) {
applicationRelease.setVersion(Constants.DEFAULT_VERSION); applicationRelease.setVersion(Constants.DEFAULT_VERSION);
UrlValidator urlValidator = new UrlValidator(); UrlValidator urlValidator = new UrlValidator();
if (applicationRelease.getUrl() == null || !urlValidator.isValid(applicationRelease.getUrl())) { if (applicationRelease.getUrl() == null || !urlValidator.isValid(applicationRelease.getUrl())) {
throw new RequestValidatingException("Request payload doesn't contains Web Clip URL " + String msg = "Request payload doesn't contains Web Clip URL with application release object or Web Clip URL is invalid";
"with application release object or Web " + log.error(msg);
"Clip URL is invalid"); throw new RequestValidatingException(msg);
} }
applicationRelease.setAppStoredLoc(applicationRelease.getUrl()); applicationRelease.setAppStoredLoc(applicationRelease.getUrl());
applicationRelease.setAppHashValue(null); applicationRelease.setAppHashValue(null);
return applicationRelease; return applicationRelease;
} }
String artifactDirectoryPath; String artifactDirectoryPath;
String md5OfApp; String md5OfApp;
String artifactPath;
InputStream[] cloneInputStream = cloneInputStream(binaryFile); InputStream[] cloneInputStream = cloneInputStream(binaryFile);
md5OfApp = getMD5(binaryFile); md5OfApp = getMD5(binaryFile);
if (md5OfApp == null) { if (md5OfApp == null) {
throw new ApplicationStorageManagementException( String msg =
"Error occurred while md5sum value retrieving process: " + "Error occurred while md5sum value retrieving process: application UUID " + applicationRelease
"application UUID " + applicationRelease.getUuid()); .getUuid();
log.error(msg);
throw new ApplicationStorageManagementException(msg);
} }
artifactDirectoryPath = storagePath + md5OfApp;
if (DeviceTypes.ANDROID.toString().equalsIgnoreCase(deviceType)) { if (DeviceTypes.ANDROID.toString().equalsIgnoreCase(deviceType)) {
ApkMeta apkMeta = ArtifactsParser.readAndroidManifestFile(cloneInputStream[2]); ApkMeta apkMeta = ArtifactsParser.readAndroidManifestFile(cloneInputStream[2]);
applicationRelease.setVersion(apkMeta.getVersionName()); applicationRelease.setVersion(apkMeta.getVersionName());
applicationRelease.setPackageName(apkMeta.getPackageName()); applicationRelease.setPackageName(apkMeta.getPackageName());
artifactPath = artifactDirectoryPath + File.separator + Constants.RELEASE_ARTIFACT
+ Constants.ANDROID_INSTALLER_EXT;
} else if (DeviceTypes.IOS.toString().equalsIgnoreCase(deviceType)) { } else if (DeviceTypes.IOS.toString().equalsIgnoreCase(deviceType)) {
NSDictionary plistInfo = ArtifactsParser.readiOSManifestFile(binaryFile); NSDictionary plistInfo = ArtifactsParser.readiOSManifestFile(binaryFile);
applicationRelease applicationRelease
.setVersion(plistInfo.objectForKey(ArtifactsParser.IPA_BUNDLE_VERSION_KEY).toString()); .setVersion(plistInfo.objectForKey(ArtifactsParser.IPA_BUNDLE_VERSION_KEY).toString());
applicationRelease applicationRelease
.setPackageName(plistInfo.objectForKey(ArtifactsParser.IPA_BUNDLE_IDENTIFIER_KEY).toString()); .setPackageName(plistInfo.objectForKey(ArtifactsParser.IPA_BUNDLE_IDENTIFIER_KEY).toString());
artifactPath = artifactDirectoryPath + File.separator + Constants.RELEASE_ARTIFACT
+ Constants.IOS_INSTALLER_EXT;
} else { } else {
throw new ApplicationStorageManagementException("Application Type doesn't match with supporting " + String msg = "Application Type doesn't match with supporting application types " + applicationRelease
"application types " + applicationRelease.getUuid()); .getUuid();
log.error(msg);
throw new ApplicationStorageManagementException(msg);
} }
artifactDirectoryPath = storagePath + md5OfApp;
StorageManagementUtil.createArtifactDirectory(artifactDirectoryPath);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Artifact Directory Path for saving the application release related artifacts related with " log.debug("Artifact Directory Path for saving the application release related artifacts related with "
+ "application UUID " + applicationRelease.getUuid() + " is " + artifactDirectoryPath); + "application UUID " + applicationRelease.getUuid() + " is " + artifactDirectoryPath);
} }
// TODO : handle ios StorageManagementUtil.createArtifactDirectory(artifactDirectoryPath);
String artifactPath = artifactDirectoryPath + File.separator + Constants.RELEASE_ARTIFACT +".apk";
saveFile(cloneInputStream[1], artifactPath); saveFile(cloneInputStream[1], artifactPath);
applicationRelease.setAppStoredLoc(artifactPath); applicationRelease.setAppStoredLoc(artifactPath);
applicationRelease.setAppHashValue(md5OfApp); applicationRelease.setAppHashValue(md5OfApp);
} catch (IOException e) { } catch (IOException e) {
// TODO : String msg = "IO Exception while saving the release artifacts in the server for the application UUID "
throw new ApplicationStorageManagementException( + applicationRelease.getUuid();
"IO Exception while saving the release artifacts in the server for the application UUID " log.error(msg);
+ applicationRelease.getUuid(), e); throw new ApplicationStorageManagementException( msg, e);
} catch (ParsingException e) { } catch (ParsingException e) {
throw new ApplicationStorageManagementException( String msg =
"Error occurred while parsing the artifact file. Application release UUID is " + applicationRelease "Error occurred while parsing the artifact file. Application release UUID is " + applicationRelease
.getUuid(), e); .getUuid();
log.error(msg);
throw new ApplicationStorageManagementException(msg, e);
} }
return applicationRelease;
}
public ApplicationRelease uploadReleaseArtifactTmp(ApplicationRelease applicationRelease, String appType, String deviceType,
Attachment binaryFileAttachment) throws ResourceManagementException, RequestValidatingException{
try {
InputStream binaryFile = binaryFileAttachment.getDataHandler().getInputStream();
String installerExtension = binaryFileAttachment.getDataHandler().getContentType();
if (ApplicationType.WEB_CLIP.toString().equals(appType)) {
applicationRelease.setVersion(Constants.DEFAULT_VERSION);
UrlValidator urlValidator = new UrlValidator();
if (applicationRelease.getUrl() == null || !urlValidator.isValid(applicationRelease.getUrl())) {
String msg = "Request payload doesn't contains Web Clip URL with application release object or Web Clip URL is invalid";
log.error(msg);
throw new RequestValidatingException(msg);
}
applicationRelease.setAppStoredLoc(applicationRelease.getUrl());
applicationRelease.setAppHashValue(null);
return applicationRelease;
}
String artifactDirectoryPath;
String md5OfApp;
String artifactPath;
InputStream[] cloneInputStream = cloneInputStream(binaryFile);
md5OfApp = getMD5(binaryFile);
if (md5OfApp == null) {
String msg =
"Error occurred while md5sum value retrieving process: application UUID " + applicationRelease
.getUuid();
log.error(msg);
throw new ApplicationStorageManagementException(msg);
}
artifactDirectoryPath = storagePath + md5OfApp;
if (DeviceTypes.ANDROID.toString().equalsIgnoreCase(deviceType)) {
ApkMeta apkMeta = ArtifactsParser.readAndroidManifestFile(cloneInputStream[2]);
applicationRelease.setVersion(apkMeta.getVersionName());
applicationRelease.setPackageName(apkMeta.getPackageName());
} else if (DeviceTypes.IOS.toString().equalsIgnoreCase(deviceType)) {
NSDictionary plistInfo = ArtifactsParser.readiOSManifestFile(binaryFile);
applicationRelease
.setVersion(plistInfo.objectForKey(ArtifactsParser.IPA_BUNDLE_VERSION_KEY).toString());
applicationRelease
.setPackageName(plistInfo.objectForKey(ArtifactsParser.IPA_BUNDLE_IDENTIFIER_KEY).toString());
} else {
String msg = "Application Type doesn't match with supporting application types " + applicationRelease
.getUuid();
log.error(msg);
throw new ApplicationStorageManagementException(msg);
}
artifactPath = artifactDirectoryPath + File.separator + Constants.RELEASE_ARTIFACT
+ installerExtension;
if (log.isDebugEnabled()) {
log.debug("Artifact Directory Path for saving the application release related artifacts related with "
+ "application UUID " + applicationRelease.getUuid() + " is " + artifactDirectoryPath);
}
StorageManagementUtil.createArtifactDirectory(artifactDirectoryPath);
saveFile(cloneInputStream[1], artifactPath);
applicationRelease.setAppStoredLoc(artifactPath);
applicationRelease.setAppHashValue(md5OfApp);
} catch (IOException e) {
String msg = "IO Exception while saving the release artifacts in the server for the application UUID "
+ applicationRelease.getUuid();
log.error(msg);
throw new ApplicationStorageManagementException( msg, e);
} catch (ParsingException e) {
String msg =
"Error occurred while parsing the artifact file. Application release UUID is " + applicationRelease
.getUuid();
log.error(msg);
throw new ApplicationStorageManagementException(msg, e);
}
return applicationRelease; return applicationRelease;
} }
private InputStream[] cloneInputStream(InputStream inputStream) throws ApplicationStorageManagementException { private InputStream[] cloneInputStream(InputStream inputStream) throws ApplicationStorageManagementException {

@ -37,6 +37,9 @@ public class Constants {
public static final String CF_BUNDLE_VERSION = "CFBundleVersion"; public static final String CF_BUNDLE_VERSION = "CFBundleVersion";
public static final String APP_EXTENSION = ".app"; public static final String APP_EXTENSION = ".app";
public static final String ANDROID_INSTALLER_EXT = ".apk";
public static final String IOS_INSTALLER_EXT = ".ipa";
/** /**
* Database types supported by Application Management. * Database types supported by Application Management.
*/ */
@ -51,12 +54,6 @@ public class Constants {
public static final String DB_TYPE_POSTGRESQL = "PostgreSQL"; public static final String DB_TYPE_POSTGRESQL = "PostgreSQL";
} }
/**
* Lifecycle states of the application life-cycle.
*/
public static final String[] LIFE_CYCLES = {"CREATED", "IN REVIEW", "APPROVED", "REJECTED", "PUBLISHED",
"UNPUBLISHED", "RETIRED"};
/** /**
* Name of the image artifacts that are saved in the file system. * Name of the image artifacts that are saved in the file system.

@ -132,14 +132,10 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
@Multipart("screenshot2") Attachment screenshot2, @Multipart("screenshot2") Attachment screenshot2,
@Multipart("screenshot3") Attachment screenshot3) { @Multipart("screenshot3") Attachment screenshot3) {
ApplicationManager applicationManager = APIUtil.getApplicationManager(); ApplicationManager applicationManager = APIUtil.getApplicationManager();
ApplicationStorageManager applicationStorageManager = APIUtil.getApplicationStorageManager();
InputStream iconFileStream;
InputStream bannerFileStream;
List<InputStream> attachments = new ArrayList<>();
List<ApplicationRelease> applicationReleases = new ArrayList<>();
ApplicationRelease applicationRelease;
List<Attachment> attachmentList = new ArrayList<>(); List<Attachment> attachmentList = new ArrayList<>();
attachmentList.add(screenshot1); if (screenshot1 != null){
attachmentList.add(screenshot1);
}
if (screenshot2 != null) { if (screenshot2 != null) {
attachmentList.add(screenshot2); attachmentList.add(screenshot2);
} }
@ -148,52 +144,9 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
} }
try { try {
//TODO : catch the error message
if (isInvalidReleaseCreatingRequest(binaryFile, iconFile, bannerFile, attachmentList, application.getType())) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("Invalid request for creating an application.").build();
}
// The application executable artifacts such as apks are uploaded.
if (!ApplicationType.ENTERPRISE.toString().equals(application.getType())) {
// TODO Null check
applicationRelease = application.getApplicationReleases().get(0);
applicationRelease = applicationStorageManager
.uploadReleaseArtifact(applicationRelease, application.getType(), application.getDeviceType(),
null);
} else {
if (application.getApplicationReleases().size() > 1) {
String msg =
"Invalid application creating request. Application creating request must have single application "
+ "release. Application name:" + application.getName() + " and type: "
+ application.getType();
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
}
applicationRelease = application.getApplicationReleases().get(0);
applicationRelease = applicationStorageManager
.uploadReleaseArtifact(applicationRelease, application.getType(), application.getDeviceType(),
binaryFile.getDataHandler().getInputStream());
if (applicationRelease.getAppStoredLoc() == null || applicationRelease.getAppHashValue() == null) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
}
iconFileStream = iconFile.getDataHandler().getInputStream();
bannerFileStream = bannerFile.getDataHandler().getInputStream();
for (Attachment screenshot : attachmentList) {
attachments.add(screenshot.getDataHandler().getInputStream());
}
// Upload images
applicationRelease = applicationStorageManager
.uploadImageArtifacts(applicationRelease, iconFileStream, bannerFileStream, attachments);
applicationRelease.setUuid(UUID.randomUUID().toString());
applicationReleases.add(applicationRelease);
application.setApplicationReleases(applicationReleases);
// Created new application entry // Created new application entry
Application createdApplication = applicationManager.createApplication(application); Application createdApplication = applicationManager
.createApplication(application, binaryFile, iconFile, bannerFile, attachmentList);
if (createdApplication != null) { if (createdApplication != null) {
return Response.status(Response.Status.CREATED).entity(createdApplication).build(); return Response.status(Response.Status.CREATED).entity(createdApplication).build();
} else { } else {
@ -204,23 +157,24 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
} catch (ApplicationManagementException e) { } catch (ApplicationManagementException e) {
String msg = "Error occurred while creating the application"; String msg = "Error occurred while creating the application";
log.error(msg, e); log.error(msg, e);
// todo add msg into return return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); }
} catch (ResourceManagementException e) { // catch (ResourceManagementException e) {
String msg = // String msg =
"Error occurred while uploading the releases artifacts of the application " + application.getName(); // "Error occurred while uploading the releases artifacts of the application " + application.getName();
log.error(msg, e); // log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); // return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
} catch (IOException e) { // } catch (IOException e) {
String msg = // String msg =
"Error while uploading binary file and resources for the application release of the application " // "Error while uploading binary file and resources for the application release of the application "
+ application.getName(); // + application.getName();
log.error(msg, e); // log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); // return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
} catch (RequestValidatingException e) { // }
catch (RequestValidatingException e) {
String msg = "Error occurred while handling the application creating request"; String msg = "Error occurred while handling the application creating request";
log.error(msg, e); log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).build(); return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
} }
} }
@ -253,9 +207,9 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
} }
try { try {
if (isInvalidReleaseCreatingRequest(binaryFile, iconFile, bannerFile, attachmentList, appType)) { applicationManager
return Response.status(Response.Status.BAD_REQUEST).build(); .validateReleaseCreatingRequest(applicationRelease, appType, binaryFile, iconFile, bannerFile,
} attachmentList);
// The application executable artifacts such as apks are uploaded. // The application executable artifacts such as apks are uploaded.
if (!ApplicationType.ENTERPRISE.toString().equals(appType)) { if (!ApplicationType.ENTERPRISE.toString().equals(appType)) {
@ -633,27 +587,4 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
return Response.status(Response.Status.CREATED).entity("Lifecycle state added successfully.").build(); return Response.status(Response.Status.CREATED).entity("Lifecycle state added successfully.").build();
} }
private boolean isInvalidReleaseCreatingRequest(Attachment binaryFile, Attachment iconFile, Attachment bannerFile,
List<Attachment> attachmentList, String appType) {
if (iconFile == null) {
log.error("Icon file is not found with the application release creating request.");
return true;
}
if (bannerFile == null) {
log.error("Banner file is not found with the application release creating request.");
return true;
}
if (attachmentList == null || attachmentList.isEmpty()) {
log.error("Screenshots are not found with the application release creating request.");
return true;
}
if (binaryFile == null && ApplicationType.ENTERPRISE.toString().equals(appType)) {
log.error("Binary file is not found with the application release creating request. Application type: "
+ appType);
return true;
}
return false;
}
} }

@ -44,6 +44,7 @@
<module>org.wso2.carbon.device.application.mgt.store.ui</module> <module>org.wso2.carbon.device.application.mgt.store.ui</module>
<module>org.wso2.carbon.device.application.mgt.handler</module> <module>org.wso2.carbon.device.application.mgt.handler</module>
<module>org.wso2.carbon.device.application.mgt.api</module> <module>org.wso2.carbon.device.application.mgt.api</module>
<module>org.wso2.carbon.device.application.mgt.artifact.retrieve.api</module>
</modules> </modules>
<build> <build>

@ -50,12 +50,16 @@
<artifactId>dd-plist</artifactId> <artifactId>dd-plist</artifactId>
<version>${googlecode.plist.version}</version> <version>${googlecode.plist.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>commons-validator</groupId> <groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId> <artifactId>commons-validator</artifactId>
<version>${commons-validator.version}</version> <version>${commons-validator.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>${cxf.version}</version>
</dependency>
<!--<dependency>--> <!--<dependency>-->
<!--<groupId>javax.servlet.jsp</groupId>--> <!--<groupId>javax.servlet.jsp</groupId>-->

@ -318,6 +318,7 @@ DEFAULT CHARACTER SET utf8
-- ----------------------------------------------------- -- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS APP_MANAGER.AP_APP_TAG_MAPPING( CREATE TABLE IF NOT EXISTS APP_MANAGER.AP_APP_TAG_MAPPING(
ID int NOT NULL AUTO_INCREMENT, ID int NOT NULL AUTO_INCREMENT,
TENANT_ID varchar(45) NOT NULL,
AP_APP_TAG_ID int NOT NULL, AP_APP_TAG_ID int NOT NULL,
AP_APP_ID int NOT NULL, AP_APP_ID int NOT NULL,
PRIMARY KEY (ID), PRIMARY KEY (ID),
@ -339,6 +340,7 @@ DEFAULT CHARACTER SET utf8
-- ----------------------------------------------------- -- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS APP_MANAGER.AP_APP_CATEGORY_MAPPING( CREATE TABLE IF NOT EXISTS APP_MANAGER.AP_APP_CATEGORY_MAPPING(
ID int NOT NULL AUTO_INCREMENT, ID int NOT NULL AUTO_INCREMENT,
TENANT_ID varchar(45) NOT NULL,
AP_APP_CATEGORY_ID int NOT NULL, AP_APP_CATEGORY_ID int NOT NULL,
AP_APP_ID int NOT NULL, AP_APP_ID int NOT NULL,
PRIMARY KEY (ID), PRIMARY KEY (ID),

@ -1842,7 +1842,7 @@
<plugin> <plugin>
<groupId>org.apache.felix</groupId> <groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId> <artifactId>maven-bundle-plugin</artifactId>
<version>2.5.3</version> <version>4.1.0</version>
<extensions>true</extensions> <extensions>true</extensions>
<configuration> <configuration>
<obrRepository>NONE</obrRepository> <obrRepository>NONE</obrRepository>

Loading…
Cancel
Save