summaryrefslogtreecommitdiffstats
path: root/ecomp-portal-widget-ms/widget-ms
diff options
context:
space:
mode:
Diffstat (limited to 'ecomp-portal-widget-ms/widget-ms')
-rw-r--r--ecomp-portal-widget-ms/widget-ms/.gitignore39
-rw-r--r--ecomp-portal-widget-ms/widget-ms/README.md189
-rw-r--r--ecomp-portal-widget-ms/widget-ms/docs/Deployment Guide Portal Microservices and Consul.docxbin0 -> 92934 bytes
-rw-r--r--ecomp-portal-widget-ms/widget-ms/pom.xml170
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/certificates/be1/widget-keystore.p12bin0 -> 2614 bytes
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/certificates/be2/widget-keystore.p12bin0 -> 2614 bytes
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/docker/Dockerfile6
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/MicroserviceApplication.java19
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/constant/WidgetConstant.java11
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/controller/DatabaseFileUploadController.java79
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/controller/HealthController.java35
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/controller/WidgetsCatalogController.java261
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/dao/WidgetDataSource.java34
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/App.java47
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/MicroserviceData.java126
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/MicroserviceParameter.java70
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/RoleApp.java95
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/ValidationRespond.java34
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/WidgetCatalog.java134
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/WidgetFile.java96
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/excetpion/StorageException.java15
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/excetpion/StorageFileNotFoundException.java14
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/filters/CorsConfiguration.java15
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/hibernate/HibernateConfiguration.java44
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/listener/WidgetEventListener.java36
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/InitializationService.java7
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/MicroserviceService.java17
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/StorageService.java34
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/WidgetCatalogService.java28
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/InitializationServiceImpl.java133
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/MicroserviceServiceImpl.java86
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/StorageServiceImpl.java493
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/WidgetCatalogServiceImpl.java243
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/utils/AuthorizationUtil.java19
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/utils/UnzipUtil.java110
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/resources/application-properties28
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/resources/application.properties.templated35
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/resources/framework-template.js173
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/resources/logback.xml138
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/resources/templates/Upload.html17
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/resources/templates/widgetsPage.html15
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/main/resources/widget-keystore.p12bin0 -> 2638 bytes
-rwxr-xr-xecomp-portal-widget-ms/widget-ms/src/main/resources/widget_ms_start.sh4
-rwxr-xr-xecomp-portal-widget-ms/widget-ms/src/main/resources/widget_ms_stop.sh5
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/test/java/org/openecomp/portalapp/widget/test/controller/WidgetFileControllerTest.java74
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/test/java/org/openecomp/portalapp/widget/test/controller/WidgetsCatalogControllerTest.java195
-rw-r--r--ecomp-portal-widget-ms/widget-ms/src/test/java/org/openecomp/portalapp/widget/test/service/WidgetCatalogServiceTest.java124
-rw-r--r--ecomp-portal-widget-ms/widget-ms/testadd.txt1
-rw-r--r--ecomp-portal-widget-ms/widget-ms/website.urlbin0 -> 103 bytes
49 files changed, 3548 insertions, 0 deletions
diff --git a/ecomp-portal-widget-ms/widget-ms/.gitignore b/ecomp-portal-widget-ms/widget-ms/.gitignore
new file mode 100644
index 00000000..172a425c
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/.gitignore
@@ -0,0 +1,39 @@
+.classpath
+.project
+/bin/
+target/
+logs/
+DEV_HOME_IS_UNDEFINED/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.factorypath
+.settings
+.springBeans
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+nbproject/private/
+build/
+nbbuild/
+dist/
+nbdist/
+.nb-gradle/
+
+/target/
+/catalina.base_IS_UNDEFINED/
+.mvn
+.settings/
+.springBeans
+bin/
+debug-logs/
+logs/
+/application.properties
+mvnw
+mvnw.cmd
diff --git a/ecomp-portal-widget-ms/widget-ms/README.md b/ecomp-portal-widget-ms/widget-ms/README.md
new file mode 100644
index 00000000..ceb9dd2b
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/README.md
@@ -0,0 +1,189 @@
+# Portal Widget Microservice
+
+For security, the server listens only on localhost (127.0.0.1) and requires HTTP Basic
+Authentication. No outside network traffic is accepted or processed (packets never leave
+the host). Currently, the server uses a self signed certificate - details below.
+
+## Build Prerequisites
+
+1. Java version 1.8
+2. Maven version 3
+3. Connectivity to AT&T Maven Central
+
+## Run Prerequisites
+
+1. Java version 1.8
+2. A Mysql database using the same database as the Portal
+
+## Build and Package
+
+Use maven to build and package the microservice into a jar using this command:
+
+ mvn clean package
+
+## Configuring
+
+All configuration parameters are entered in a file called application.properties. A version with default values can be found in the top level of this project.
+
+Details about the database are configured in this file. The default entries for the database configuration are shown here:
+
+ spring.datasource.url=jdbc:mariadb:failover://{db_host:db_port/{portal_db}
+ spring.datasource.username={username}
+ spring.datasource.password=ENC({encrypted_password})
+
+The HTTP server's username and password are configured in this file. Only one username/password is used to secure the REST endpoint. The default entries for the server are shown here:
+
+ security.user.name={basic_auth_username}
+ security.user.password=ENC({encrypted_basic_auth_password})
+
+When you package the application into a jar file and launch the microservice using that jar, the configuration file must be in the current working directory where you launch the service.
+
+## Generating Encrypted Passwords
+
+Use the following command to generate an encrypted password for the database and the
+micro service. The entire command must be entered on one line; the command shown
+below uses backslashes to break lines for readability:
+
+ java -cp ~/.m2/repository/org/jasypt/jasypt/1.9.2/jasypt-1.9.2.jar \
+ org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI \
+ algorithm=PBEWithMD5AndDES \
+ input='YourPasswordHere' \
+ password='EncryptionKey'
+
+Note, 'YourPasswordHere' is the actual database password, as supplied in the 'password'
+parameter. The value 'EncryptionKey' is used to encrypt the input, and must be supplied
+at run time in one of two ways:
+
+* On the command line with a JVM argument "-Djasypt.encryptor.password". Here's an example
+of using maven with the Spring-Boot goal:
+
+ mvn -Djasypt.encryptor.password=EncryptionKey spring-boot:run
+
+Here's an example of using java and the jar file:
+
+ java -jar dbc-microservice.jar -Djasypt.encryptor.password=EncryptionKey
+
+* In the application.properties file using the key jasypt.encryptor.password. For example:
+
+ jasypt.encryptor.password=EncryptionKey
+
+## Development Launch
+
+Check the configuration properties in file src/main/resources/application.properties. Then launch the microservice for development and testing like this:
+
+ mvn clean spring-boot:run
+
+## Production Launch
+
+Ensure a valid configuration is present in file application.properties in the current working directory. Then launch the microservice for production like this:
+
+ widget-service.sh start
+
+## Release Notes
+
+### Release 1702, February 2017
+
+#### Consul Release Notes
+
+Build 1702.3.48, 5 Feb 2017
+- DE264319 - Corrected spelling for output file from 'consule.out' to 'consul.out' - Please do not miss re-deploying consul build. Widget-ms build is not enough (or required) for this bug fix to be validated.
+
+#### Widget-ms Release Notes
+
+Build 1.2.175
+- Def 120258 Fixed the widget displaying issues in Internet Explorer 11
+
+Build 1.2.145
+- Def 143148 - fixed the defect, common widgets work on Firefox version 45
+- Def 142432 - Widget-ms: InputStream is not getting closed in file StorageServiceImpl.java
+
+Build 1.2.140
+- St 164888 allow partner applications to trigger a new app tab through portal
+- St 164847 CCD Widgets
+- Def 141951 Fixed the issue for inappropriate location of framework-template.js file
+- Def 141352 Widget Onboarding Page, download icon is not clickable in FF 45 version, Revise widget upload service temporary storage to /tmp
+- St 164902 One copy of framework.js hidden in the Portal instead of being part of the widgets
+- St 164905 Download the widget
+- St 164711 Widget Personalization: Allow user to define his/her own parameters on widgets
+- St 164863 Widgets to use service onboarding feature
+
+Build 1702.3.86
+- MariaDB connector / failover fix
+
+Build 1702.3.79, 10 Feb 2017
+- Updated application.properties to correct database schema name from dbca to portal
+- US799260 appended complete hostname to widget certificate for irvine
+- US799260 appended complete hostname to consul config.json file in prod1 and prod2
+- US799260 fixed the bar chart issue on devn1, the bar chart shows up on devn1 Home Page
+
+Build 1702.3.78, 9 Feb 2017
+- US799260 fixed the firefox compatibility issue; and y-scales issue in bar chart
+- US799260 Added the three new widgets in dashboard-widgets folder; removed all testing logs in all widgets; fixed a bug in widget-test
+
+Build 1702.3.75, 07 Feb 2017
+DE267061 - Removed a hardcoded intance of loginId used in the query.
+
+Build 1702.3.73, 06 Feb 2017
+DE267061 - Fixed - user should only see widgets that were uploaded against app/roles that they have OR if they were uploaded by checking All Users checkbox.
+Build 1702.3.71, 5 Feb 2017
+- Important Note: Copied all these build notes from Portal WebApp to here (widget-ms) - in order not to confuse folks, we have removed Portal's build numbers for these notes. Going forward, will add widget-ms's own build number. Also note that we've changed the version series in POM.xml from 1702.0 to 1702.3 in pom.xml - Although Jenkins/SWM overrides and doesn't care about maven's versioning, but did this to synch with what Portal Web App POM.
+- DE261560 Portal App: Widgets MS logs are not getting rolled over
+- DE261655 Unable to delete standard widgets
+- DE262487 EP-Portal App: News widget not adapting when tile size is changed by user
+- DE257516 Common widgets reload in a single tab
+- DE262505 Upload Duplicate Widget Issue
+- DE262610 Widget Microservice logging is not following EELF guidelines
+- DE262800 Issues with widget name this requires database modifications
+- DE263090 Issues with widget roles
+- US799260 BE now 'discovers' widget-service using Consul. If consul is not running, it fallbacks to the current implemenation which is https://localhost and the port of your choosing in system.properties - Ex: localhost:8082
+- US799260 Fix delete feature for the three special widgets news, events, resources widget can have spaces in its name
+- US799260 Widget feature:
+ + Add the editing feature in widgetOnboarding page
+ + Move widget catalog and onboarding to new directories
+- US811188 Log / Audit widgets logging in DB
+- US818934 Allow basic authentication
+- US814730 Make news / Events and Resources as widgets
+- US827836 Portal Widget Framework
+
+## Contact
+
+Ikram Ikramullah
+
+## Certificate
+
+### Create self signed certificate
+
+1. Create a self signed certificate for the microservice
+keytool -genkey -alias widget-microservice -storetype PKCS12 -keyalg RSA -keystore widget-keystore.p12
+
+### Import into client's trust store
+
+1. Export certificate from microservice's keystore - default password is 'microservice'
+keytool -exportcert -keystore widget-keystore.p12 -alias widget-microservice -file widget-cert.cer
+
+2. Import the exported certificate of microservice from step 1 and import it into Portal JRE's cacerts file. The location of this file is %JRE%/lib/secuirty/cacerts.
+
+keytool -import -trustcacerts -keystore "C:\Program Files\Java\jre1.8.0_91\lib\security\cacerts" -noprompt -alias widget-microservice -file widget-cert.cer
+
+OR
+;
+keytool -import -trustcacerts -keystore /usr/local/add-on/jdk1.8.0_60/jre/lib/security/ -noprompt -alias widget-microservice -file widget-cert.cer
+
+### Runing on http (not https)
+
+If the intent is to run this microservice without https i.e run on plain http, comment out (put a leading #) infront of all properties in 'Certificate Properties' section of application.properties - these properties are
+
+server.ssl.key-store=classpath:widget-keystore.p12
+server.ssl.key-store-password=ENC(DiIYnAMab4u7rEW2yKhF9zBL00uU55q8)
+server.ssl.keyStoreType=PKCS12
+server.ssl.keyAlias=widget-microservice
+
+## Running service in docker
+
+a). Build docker image: mvn docker:build
+b). Run the service in docker: docker run -p <port>:<port-in> -t <image-name>
+c). Check running docker containers: docker ps
+
+## Migration Instruction
+1. Due to changes in the existing tables, the user will have to remove all the existing widgets in 1702 release
+2. Re-upload the latest version of widgets under dashboard-widgets folder
diff --git a/ecomp-portal-widget-ms/widget-ms/docs/Deployment Guide Portal Microservices and Consul.docx b/ecomp-portal-widget-ms/widget-ms/docs/Deployment Guide Portal Microservices and Consul.docx
new file mode 100644
index 00000000..683b1e92
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/docs/Deployment Guide Portal Microservices and Consul.docx
Binary files differ
diff --git a/ecomp-portal-widget-ms/widget-ms/pom.xml b/ecomp-portal-widget-ms/widget-ms/pom.xml
new file mode 100644
index 00000000..14820b65
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/pom.xml
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.openecomp.portal</groupId>
+ <artifactId>widget-ms</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+ <name>widget-microservice</name>
+
+ <parent>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-parent</artifactId>
+ <version>1.4.2.RELEASE</version>
+ <relativePath /> <!-- lookup parent from repository -->
+ </parent>
+
+ <properties>
+ <docker.imagename>widget-ms</docker.imagename>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+ <java.version>1.8</java.version>
+ <hibernate.version>4.3.11.Final</hibernate.version>
+ <skipTests>true</skipTests>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <!-- Setup Spring Data JPA Repository support -->
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-jpa</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-security</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-thymeleaf</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-devtools</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-configuration-processor</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-core</artifactId>
+ <!-- <version>${hibernate.version}</version> -->
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <!-- <version>1.10</version> -->
+ </dependency>
+ <dependency>
+ <groupId>org.mariadb.jdbc</groupId>
+ <artifactId>mariadb-java-client</artifactId>
+ <!-- <version>1.5.8</version> -->
+ </dependency>
+ <dependency>
+ <groupId>com.github.ulisesbocchio</groupId>
+ <artifactId>jasypt-spring-boot-starter</artifactId>
+ <version>1.9</version>
+ </dependency>
+ <!-- hibernate-core depends on dom4j, which has optional dependencies.
+ On jenkins, contrary to doc, mvn 3.0.5 packages the optional dependencies
+ in the war. Workaround: exclude them explicitly. -->
+ <dependency>
+ <groupId>dom4j</groupId>
+ <artifactId>dom4j</artifactId>
+ <!-- <version>1.6.1</version> -->
+ <exclusions>
+ <exclusion>
+ <groupId>jaxme</groupId>
+ <artifactId>jaxme-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>jaxen</groupId>
+ <artifactId>jaxen</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>msv</groupId>
+ <artifactId>xsdlib</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>msv</groupId>
+ <artifactId>relaxngDatatype</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>pull-parser</groupId>
+ <artifactId>pull-parser</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>xpp3</groupId>
+ <artifactId>xpp3</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>stax</groupId>
+ <artifactId>stax-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+
+ <build>
+
+ <finalName>${project.artifactId}</finalName>
+
+ <!-- To add resources, must name all including usual src/main/resources -->
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ <resource>
+ <directory>../common-widgets/target</directory>
+ <includes>
+ <include>**/*.zip</include>
+ </includes>
+ </resource>
+ </resources>
+
+ <plugins>
+
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ </plugin>
+
+ <plugin>
+ <groupId>com.spotify</groupId>
+ <artifactId>docker-maven-plugin</artifactId>
+ <version>0.4.11</version>
+ <configuration>
+ <imageName>${project.artifactId}</imageName>
+ <dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
+ <resources>
+ <resource>
+ <targetPath>/</targetPath>
+ <directory>${project.build.directory}</directory>
+ <include>${project.build.finalName}.jar</include>
+ </resource>
+ </resources>
+ </configuration>
+ </plugin>
+
+ </plugins>
+
+ </build>
+
+</project>
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/certificates/be1/widget-keystore.p12 b/ecomp-portal-widget-ms/widget-ms/src/main/certificates/be1/widget-keystore.p12
new file mode 100644
index 00000000..9dcdb1a0
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/certificates/be1/widget-keystore.p12
Binary files differ
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/certificates/be2/widget-keystore.p12 b/ecomp-portal-widget-ms/widget-ms/src/main/certificates/be2/widget-keystore.p12
new file mode 100644
index 00000000..600dc01d
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/certificates/be2/widget-keystore.p12
Binary files differ
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/docker/Dockerfile b/ecomp-portal-widget-ms/widget-ms/src/main/docker/Dockerfile
new file mode 100644
index 00000000..7e25c222
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/docker/Dockerfile
@@ -0,0 +1,6 @@
+FROM frolvlad/alpine-oraclejdk8:slim
+VOLUME /tmp
+ADD widget-ms.jar app.jar
+RUN sh -c 'touch /app.jar'
+ENV JAVA_OPTS=""
+ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/MicroserviceApplication.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/MicroserviceApplication.java
new file mode 100644
index 00000000..6516c364
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/MicroserviceApplication.java
@@ -0,0 +1,19 @@
+ package org.openecomp.portalapp.widget;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.web.client.RestTemplate;
+
+@SpringBootApplication
+@ComponentScan(basePackages = "org.openecomp.portalapp.widget")
+public class MicroserviceApplication {
+ @Bean
+ public RestTemplate getRestTemplate(){
+ return new RestTemplate();
+ }
+ public static void main(String[] args) {
+ SpringApplication.run(MicroserviceApplication.class, args);
+ }
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/constant/WidgetConstant.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/constant/WidgetConstant.java
new file mode 100644
index 00000000..b1a939b1
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/constant/WidgetConstant.java
@@ -0,0 +1,11 @@
+package org.openecomp.portalapp.widget.constant;
+
+public final class WidgetConstant {
+
+ public static final String WIDGET_MARKUP_LOCATION = "markup/markup.html";
+ public static final String WIDGET_CONTROLLER_LOCATION = "js/controller.js";
+ public static final String WIDGET_STYLE_LOCATION = "styles/styles.css";
+ public static final String VALIDATION_MESSAGE_ZIP = "Please upload a zip file";
+ public static final String VALIDATION_MESSAGE_FILES = "Please check your files (should contains js, styles and markup folder)";
+}
+
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/controller/DatabaseFileUploadController.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/controller/DatabaseFileUploadController.java
new file mode 100644
index 00000000..ec32e42f
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/controller/DatabaseFileUploadController.java
@@ -0,0 +1,79 @@
+package org.openecomp.portalapp.widget.controller;
+
+import java.io.UnsupportedEncodingException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.openecomp.portalapp.widget.service.StorageService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@Controller
+public class DatabaseFileUploadController {
+
+ @Autowired
+ private StorageService storageService;
+
+ private static final Logger logger = LoggerFactory.getLogger(DatabaseFileUploadController.class);
+
+ @ResponseBody
+ @RequestMapping(value = "/microservices/markup/{widgetId}", method = RequestMethod.GET)
+ public String getWidgetMarkup(HttpServletRequest request, HttpServletResponse response, @PathVariable("widgetId") long widgetId){
+ String markup = null;
+ try{
+ logger.debug("DatabaseFileUploadController.getWidgetMarkup: getting markup.html for widget with widgetId = {}" , widgetId);
+ markup = storageService.getWidgetMarkup(widgetId);
+ }catch(Exception e){
+ logger.error("Exception occurred while performing DatabaseFileUploadController.getWidgetMarkup in widget microservices. Details:" + e.getMessage());
+ }
+ return markup;
+ }
+
+ @ResponseBody
+ @RequestMapping(value = "/microservices/{widgetId}/controller.js", method = RequestMethod.GET)
+ public String getWidgetController(HttpServletRequest request, HttpServletResponse response, @PathVariable("widgetId") long widgetId){
+ String controller = null;
+ try{
+ logger.debug("DatabaseFileUploadController.getWidgetController: getting controller.js for widget with widgetId = {}" , widgetId);
+ controller = storageService.getWidgetController(widgetId);
+ }catch(Exception e){
+ logger.error("Exception occurred while performing DatabaseFileUploadController.getWidgetController in widget microservices. Details:" + e.getMessage());
+ }
+ return controller;
+ }
+
+ @ResponseBody
+ @RequestMapping(value = "/microservices/{widgetId}/framework.js", method = RequestMethod.GET)
+ public String getWidgetFramework(HttpServletRequest request, HttpServletResponse response,
+ @PathVariable("widgetId") long widgetId){
+ String framework = null;
+ try{
+ logger.debug("DatabaseFileUploadController.getWidgetFramework: getting framework.js for widget with widgetId = {}" , widgetId);
+ framework = storageService.getWidgetFramework(widgetId);
+ }catch(Exception e){
+ logger.error("Exception occurred while performing DatabaseFileUploadController.getWidgetFramework in widget microservices. Details:" + e.getMessage());
+ }
+ return framework;
+ }
+
+ @ResponseBody
+ @RequestMapping(value = "/microservices/{widgetId}/styles.css", method = RequestMethod.GET)
+ public String getWidgetCSS(HttpServletRequest request, HttpServletResponse response,
+ @PathVariable("widgetId") long widgetId){
+ String css = null;
+ try {
+ logger.debug("DatabaseFileUploadController.getWidgetCSS: getting styles.css for widget with widgetId = {}" , widgetId);
+ css = storageService.getWidgetCSS(widgetId);
+ } catch (UnsupportedEncodingException e) {
+ logger.error("Exception occurred while performing DatabaseFileUploadController.getWidgetCSS in widget microservices. Details:" + e.getMessage());
+ }
+ return css;
+ }
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/controller/HealthController.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/controller/HealthController.java
new file mode 100644
index 00000000..fc324ab1
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/controller/HealthController.java
@@ -0,0 +1,35 @@
+package org.openecomp.portalapp.widget.controller;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class HealthController {
+
+ @RequestMapping(value = { "/health" }, method = RequestMethod.GET, produces = "application/json")
+ public HealthStatus getWidgetCatalog(HttpServletRequest request, HttpServletResponse response) {
+ return new HealthStatus("ok");
+ }
+
+ class HealthStatus {
+ private String status;
+
+ public HealthStatus(String status){
+ this.status = status;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+
+ }
+} \ No newline at end of file
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/controller/WidgetsCatalogController.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/controller/WidgetsCatalogController.java
new file mode 100644
index 00000000..1af5a3cc
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/controller/WidgetsCatalogController.java
@@ -0,0 +1,261 @@
+package org.openecomp.portalapp.widget.controller;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.openecomp.portalapp.widget.domain.ValidationRespond;
+import org.openecomp.portalapp.widget.domain.WidgetCatalog;
+import org.openecomp.portalapp.widget.service.StorageService;
+import org.openecomp.portalapp.widget.service.WidgetCatalogService;
+import org.openecomp.portalapp.widget.utils.AuthorizationUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.multipart.MultipartFile;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@Controller
+@org.springframework.context.annotation.Configuration
+@EnableAspectJAutoProxy
+public class WidgetsCatalogController {
+
+ @Value("${server.port}")
+ String port;
+ @Value("${server.contextPath}")
+ String context;
+
+ @Value("${security.user.name}")
+ String security_user;
+ @Value("${security.user.password}")
+ String security_pass;
+
+ @Autowired
+ WidgetCatalogService widgetCatalogService;
+
+ @Autowired
+ StorageService storageService;
+
+ @Autowired
+ RestTemplate restTemplate;
+
+ AuthorizationUtil util = new AuthorizationUtil();
+
+ private static final Logger logger = LoggerFactory.getLogger(WidgetsCatalogController.class);
+
+ @ResponseBody
+ @RequestMapping(value = { "/microservices/widgetCatalog" }, method = RequestMethod.GET, produces = "application/json")
+ public List<WidgetCatalog> getWidgetCatalog(HttpServletRequest request, HttpServletResponse response
+ ,@RequestHeader(value="Authorization") String auth) throws IOException{
+
+ List<WidgetCatalog> widgetCatalog = null;
+ if(!util.authorization(auth, security_user, security_pass)){
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ logger.error("Basic Authentication Error while performing WidgetsCatalogController.getWidgetCatalog in widget microserivce. Please check your username and password.");
+ return widgetCatalog;
+ }
+ try {
+ widgetCatalog = widgetCatalogService.getWidgetCatalog();
+ logger.debug("WidgetsCatalogController.getWidgetCatalog: getting widget list {}", widgetCatalog);
+ } catch (Exception e) {
+ logger.error("Exception occurred while performing WidgetsCatalogController.getWidgetCatalog in widget microservices. Details:" + e.getMessage());
+ }
+ return widgetCatalog;
+ }
+
+ @ResponseBody
+ @RequestMapping(value = { "/microservices/widgetCatalog/{loginName}" }, method = RequestMethod.GET, produces = "application/json")
+ public List<WidgetCatalog> getUserWidgetCatalog(HttpServletRequest request, HttpServletResponse response,
+ @PathVariable("loginName") String loginName, @RequestHeader(value="Authorization") String auth) throws IOException {
+ List<WidgetCatalog> widgetCatalog = null;
+ if(!util.authorization(auth, security_user, security_pass)){
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ logger.error("Basic Authentication Error while performing WidgetsCatalogController.getUserWidgetCatalog in widget microserivce. Please check your username and password.");
+ return widgetCatalog;
+ }
+ try {
+ widgetCatalog = widgetCatalogService.getUserWidgetCatalog(loginName);
+ logger.debug("WidgetsCatalogController.getUserWidgetCatalog: getting widget list {}", widgetCatalog);
+ } catch (Exception e) {
+ logger.error("Exception occurred while performing WidgetsCatalogController.getUserWidgetCatalog in widget microservices. Details:" + e.getMessage());
+ }
+ return widgetCatalog;
+ }
+
+ @ResponseBody
+ @RequestMapping(value = { "/microservices/widgetCatalog/{widgetId}" }, method = RequestMethod.PUT, produces = "application/json")
+ public void updateWidgetCatalog(HttpServletRequest request, HttpServletResponse response,
+ @RequestBody WidgetCatalog newWidgetCatalog, @PathVariable("widgetId") long widgetId,
+ @RequestHeader(value="Authorization") String auth) throws IOException {
+
+ if(!util.authorization(auth, security_user, security_pass)){
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ logger.error("Basic Authentication Error while performing WidgetsCatalogController.updateWidgetCatalog in widget microserivce. Please check your username and password.");
+ return;
+ }
+ try {
+ widgetCatalogService.updateWidgetCatalog(widgetId, newWidgetCatalog);
+ logger.debug("WidgetsCatalogController.updateWidgetCatalog: updating widget {}", newWidgetCatalog);
+ } catch (Exception e) {
+ logger.error("Exception occurred while performing WidgetsCatalogController.updateWidgetCatalog in widget microservices. Details:" + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ @ResponseBody
+ @RequestMapping(value = { "/microservices/widgetCatalog" }, method = RequestMethod.POST, produces = "application/json")
+ public ValidationRespond saveWidgetCatalog(HttpServletRequest request, HttpServletResponse response, @RequestHeader(value="Authorization") String auth,
+ @RequestParam("file") MultipartFile file, @RequestParam("widget") String widget) throws IOException {
+
+ ValidationRespond respond = null;
+ if(!util.authorization(auth, security_user, security_pass)){
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ logger.error("Basic Authentication Error while performing WidgetsCatalogController.saveWidgetCatalog in widget microserivce. Please check your username and password.");
+ return new ValidationRespond(false, "Basic Authentication Error, please check your username and password.");
+ }
+ try {
+ //check the zip file structure first
+ respond = storageService.checkZipFile(file);
+
+ if(respond.isValid()){
+ //save the widget catalog
+ WidgetCatalog newWidget = new ObjectMapper().readValue(widget, WidgetCatalog.class);
+
+ long widgetId = widgetCatalogService.saveWidgetCatalog(newWidget);
+ logger.debug("WidgetsCatalogController.saveWidgetCatalog: saving widget={}", newWidget);
+ //save the widget zip file ;
+ storageService.save(file, newWidget, widgetId);
+ }
+
+ } catch (Exception e) {
+ logger.error("Exception occurred while performing WidgetsCatalogController.saveWidgetCatalog in widget microservices. Details:", e);
+ }
+ return respond;
+ }
+
+ @ResponseBody
+ @RequestMapping(value = { "/microservices/widgetCatalog/{widgetId}" }, method = RequestMethod.POST, produces = "application/json")
+ public ValidationRespond updateWidgetCatalogwithFiles(HttpServletRequest request, HttpServletResponse response, @RequestHeader(value="Authorization") String auth,
+ @RequestParam("file") MultipartFile file, @RequestParam("widget") String widget, @PathVariable("widgetId") long widgetId) throws IOException {
+ System.out.println("microserivces updating with files" + widgetId);
+ ValidationRespond respond = null;
+ if(!util.authorization(auth, security_user, security_pass)){
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ logger.error("Basic Authentication Error while performing WidgetsCatalogController.saveWidgetCatalog in widget microserivce. Please check your username and password.");
+ return new ValidationRespond(false, "Basic Authentication Error, please check your username and password.");
+ }
+ try {
+ //check the zip file structure first
+ respond = storageService.checkZipFile(file);
+ if(respond.isValid()){
+ //update the widget catalog
+ WidgetCatalog newWidget = new ObjectMapper().readValue(widget, WidgetCatalog.class);
+ widgetCatalogService.updateWidgetCatalog(widgetId, newWidget);
+ logger.debug("WidgetsCatalogController.saveWidgetCatalog: updating widget with widgetId={}", widgetId);
+ //update the widget zip file
+ storageService.update(file, newWidget, widgetId);
+ }
+ } catch (Exception e) {
+ logger.error("Exception occurred while performing WidgetsCatalogController.saveWidgetCatalog in widget microservices. Details:" + e.getMessage());
+ e.printStackTrace();
+ }
+ return respond;
+ }
+
+ @ResponseBody
+ @RequestMapping(value = { "/microservices/widgetCatalog/{widgetId}" }, method = {
+ RequestMethod.DELETE }, produces = "application/json")
+ public void deleteOnboardingWidget(HttpServletRequest request, HttpServletResponse response,
+ @PathVariable("widgetId") long widgetId, @RequestHeader(value="Authorization") String auth) throws IOException{
+ if(!util.authorization(auth, security_user, security_pass)){
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ logger.error("Basic Authentication Error while performing WidgetsCatalogController.deleteOnboardingWidget in widget microserivce. Please check your username and password.");
+ return;
+ }
+ try {
+ logger.debug("WidgetsCatalogController.deleteOnboardingWidget: deleting widget {}", widgetId);
+ //WidgetCatalog widget = widgetCatalogService.getWidgetCatalog(widgetId);
+ widgetCatalogService.deleteWidgetCatalog(widgetId);
+ storageService.deleteWidgetFile(widgetId);
+ } catch (Exception e) {
+ logger.error("Exception occurred while performing WidgetsCatalogController.deleteOnboardingWidget in widget microservices. Details:" + e.getMessage());
+ }
+ }
+
+ @ResponseBody
+ @RequestMapping(value = { "/microservices/widgetCatalog/parameters/{widgetId}" }, method = RequestMethod.GET, produces = "application/json")
+ public Long getServiceIdByWidget(HttpServletRequest request, HttpServletResponse response,
+ @PathVariable("widgetId") Long widgetId, @RequestHeader(value="Authorization") String auth) throws IOException {
+
+ Long serviceId = null;
+ if(!util.authorization(auth, security_user, security_pass)){
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ logger.error("Basic Authentication Error while performing WidgetsCatalogController.getServiceIdByWidget in widget microserivce. Please check your username and password.");
+ return serviceId;
+ }
+ try{
+ logger.debug("WidgetsCatalogController.getServiceIdByWidget: getting service Id for widget {}", widgetId);
+ serviceId = widgetCatalogService.getServiceIdByWidget(widgetId);
+ }catch(Exception e){
+ logger.error("Exception occurred while performing WidgetsCatalogController.getServiceIdByWidget in widget microservices. Details:" + e.getMessage());
+ }
+ return serviceId;
+ }
+
+
+ @ResponseBody
+ @RequestMapping(value = { "/microservices/widgetCatalog/service/{serviceId}" }, method = RequestMethod.GET, produces = "application/json")
+ public List<WidgetCatalog> getWidgetByServiceId(HttpServletRequest request, HttpServletResponse response,
+ @PathVariable("serviceId") Long serviceId, @RequestHeader(value="Authorization") String auth) throws IOException {
+ List<WidgetCatalog> list = new ArrayList<WidgetCatalog>();
+ if(!util.authorization(auth, security_user, security_pass)){
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ logger.error("Basic Authentication Error while performing WidgetsCatalogController.getWidgetByServiceId in widget microserivce. Please check your username and password.");
+ return null;
+ }
+ try{
+ logger.debug("WidgetsCatalogController.getWidgetByServiceId: getting service Id for widget {}", serviceId);
+ list = widgetCatalogService.getWidgetsByServiceId(serviceId);
+ }catch(Exception e){
+ logger.error("Exception occurred while performing WidgetsCatalogController.getWidgetByServiceId in widget microservices. Details:" + e.getMessage());
+ }
+ return list;
+ }
+
+
+ @ResponseBody
+ @RequestMapping(value = { "/microservices/download/{widgetId}" }, method = RequestMethod.GET, produces = "application/json")
+ public byte[] getWidgetZipFile(HttpServletRequest request, HttpServletResponse response,
+ @PathVariable("widgetId") long widgetId, @RequestHeader(value="Authorization") String auth) throws Exception {
+ byte[] byteFile = null;
+ if(!util.authorization(auth, security_user, security_pass)){
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ logger.error("Basic Authentication Error while performing WidgetsCatalogController.getWidgetZipFile in widget microserivce. Please check your username and password.");
+ return byteFile;
+ }
+ try {
+ byteFile = storageService.getWidgetCatalogContent(widgetId);
+ logger.debug("WidgetsCatalogController.getWidgetZipFile: getting widget zip file for widget with id {}", widgetId);
+ } catch (Exception e) {
+ logger.error("Exception occurred while performing WidgetsCatalogController.getWidgetZipFile in widget microservices. Details:" + e.getMessage());
+ }
+ return byteFile;
+ }
+
+
+} \ No newline at end of file
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/dao/WidgetDataSource.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/dao/WidgetDataSource.java
new file mode 100644
index 00000000..0a950c54
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/dao/WidgetDataSource.java
@@ -0,0 +1,34 @@
+package org.openecomp.portalapp.widget.dao;
+
+import javax.sql.DataSource;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+import org.springframework.stereotype.Component;
+
+@Component
+public class WidgetDataSource{
+
+ @Value("${spring.database.driver.classname}")
+ private String dbDriverClassName;
+
+ @Value("${spring.datasource.url}")
+ private String dbUrl;
+
+ @Value("${spring.datasource.username}")
+ private String dbUsername;
+
+ @Value("${spring.datasource.password}")
+ private String dbPassword;
+
+ @Bean
+ public DataSource dataSource() {
+ DriverManagerDataSource dataSource = new DriverManagerDataSource();
+ dataSource.setDriverClassName(dbDriverClassName);
+ dataSource.setUrl(dbUrl);
+ dataSource.setUsername(dbUsername);
+ dataSource.setPassword(dbPassword);
+ return dataSource;
+ }
+} \ No newline at end of file
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/App.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/App.java
new file mode 100644
index 00000000..19c6311b
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/App.java
@@ -0,0 +1,47 @@
+package org.openecomp.portalapp.widget.domain;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "FN_APP")
+public class App implements Serializable{
+
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @Column(name = "APP_ID")
+ @GeneratedValue(strategy=GenerationType.AUTO)
+ private Long appId;
+
+ @Column(name = "APP_Name")
+ private String appName;
+
+ public Long getAppId() {
+ return appId;
+ }
+
+ public void setAppId(Long appId) {
+ this.appId = appId;
+ }
+
+ public String getAppName() {
+ return appName;
+ }
+
+ public void setAppName(String appName) {
+ this.appName = appName;
+ }
+
+ @Override
+ public String toString() {
+ return "App [appId=" + appId + ", appName=" + appName + "]";
+ }
+
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/MicroserviceData.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/MicroserviceData.java
new file mode 100644
index 00000000..831b1e65
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/MicroserviceData.java
@@ -0,0 +1,126 @@
+package org.openecomp.portalapp.widget.domain;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * TODO: moved all microservice-related code (domain, controller, service)
+ * from ecomp portal Backend to widget microservice
+ */
+@Entity
+@Table(name="EP_MICROSERVICE")
+public class MicroserviceData {
+
+ @Id
+ @Column(name = "id")
+ @GeneratedValue(strategy=GenerationType.AUTO)
+ private Long id;
+
+ @Column(name = "name")
+ private String name;
+
+ @Column(name = "description")
+ private String desc;
+
+ @Column(name = "appId")
+ private long appId;
+
+ @Column(name = "endpoint_url")
+ private String url;
+
+ @Column(name = "security_type")
+ private String securityType;
+
+ @Column(name = "username")
+ private String username;
+
+ @Column(name = "password")
+ private String password;
+
+ @Column(name = "active")
+ private String active;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDesc() {
+ return desc;
+ }
+
+ public void setDesc(String desc) {
+ this.desc = desc;
+ }
+
+ public long getAppId() {
+ return appId;
+ }
+
+ public void setAppId(long appId) {
+ this.appId = appId;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public String getSecurityType() {
+ return securityType;
+ }
+
+ public void setSecurityType(String securityType) {
+ this.securityType = securityType;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getActive() {
+ return active;
+ }
+
+ public void setActive(String active) {
+ this.active = active;
+ }
+
+ @Override
+ public String toString() {
+ return "MicroserviceData [name=" + name + ", desc=" + desc + ", appId=" + appId + ", url=" + url
+ + ", securityType=" + securityType + ", username=" + username + ", password=" + password + ", active="
+ + active + "]";
+ }
+
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/MicroserviceParameter.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/MicroserviceParameter.java
new file mode 100644
index 00000000..9f19c0d4
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/MicroserviceParameter.java
@@ -0,0 +1,70 @@
+package org.openecomp.portalapp.widget.domain;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * TODO: moved all microservice-related code (domain, controller, service)
+ * from ecomp portal Backend to widget microservice
+ */
+@Entity
+@Table(name="EP_MICROSERVICE_PARAMETER")
+public class MicroserviceParameter {
+
+ @Id
+ @Column(name = "id")
+ @GeneratedValue(strategy=GenerationType.AUTO)
+ private Long id;
+
+ @Column(name = "service_id")
+ private long serviceId;
+
+ @Column(name = "para_key")
+ private String para_key;
+
+ @Column(name = "para_value")
+ private String para_value;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public long getServiceId() {
+ return serviceId;
+ }
+
+ public void setServiceId(long serviceId) {
+ this.serviceId = serviceId;
+ }
+
+ public String getPara_key() {
+ return para_key;
+ }
+
+ public void setPara_key(String para_key) {
+ this.para_key = para_key;
+ }
+
+ public String getPara_value() {
+ return para_value;
+ }
+
+ public void setPara_value(String para_value) {
+ this.para_value = para_value;
+ }
+
+ @Override
+ public String toString() {
+ return "MicroserviceParameter [serviceId=" + serviceId + ", para_key=" + para_key + ", para_value=" + para_value
+ + "]";
+ }
+
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/RoleApp.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/RoleApp.java
new file mode 100644
index 00000000..ca73f313
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/RoleApp.java
@@ -0,0 +1,95 @@
+package org.openecomp.portalapp.widget.domain;
+
+import java.io.Serializable;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+@Entity
+@Table(name = "FN_ROLE")
+public class RoleApp implements Serializable{
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @Column(name = "ROLE_ID")
+ @GeneratedValue(strategy=GenerationType.AUTO)
+ private Long roleId;
+
+
+ @Column(name = "ROLE_Name")
+ private String roleName;
+
+ @ManyToOne(fetch = FetchType.EAGER)
+ @JoinColumn(name="APP_ID")
+ private App app;
+
+ @JsonIgnore
+ @ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}, mappedBy="widgetRoles")
+ private Set<WidgetCatalog> widgets;
+
+ /*@PreRemove
+ private void removeGroupsFromUsers() {
+ for (WidgetCatalog w : widgets) {
+ w.getWidgetRoles().remove(this);
+ }
+ }*/
+
+ /*@ManyToOne
+ @JoinColumn(name = "WIDGET_ID", nullable = false)
+ WidgetCatalog widgetCatalog;*/
+
+ //@JsonIgnore
+ //@ManyToMany(mappedBy = "widgetRoles")
+ //@ManyToMany(fetch = FetchType.EAGER, mappedBy = "widgetRoles")
+ //private Set<WidgetCatalog> widgets = new HashSet<WidgetCatalog>();
+
+ public Long getRoleId() {
+ return roleId;
+ }
+
+ public void setRoleId(Long roleId) {
+ this.roleId = roleId;
+ }
+
+ public String getRoleName() {
+ return roleName;
+ }
+
+ public void setRoleName(String roleName) {
+ this.roleName = roleName;
+ }
+
+ public App getApp() {
+ return app;
+ }
+
+ public void setApp(App app) {
+ this.app = app;
+ }
+
+ public Set<WidgetCatalog> getWidgets() {
+ return widgets;
+ }
+
+ public void setWidgets(Set<WidgetCatalog> widgets) {
+ this.widgets = widgets;
+ }
+
+ @Override
+ public String toString() {
+ return "RoleApp [roleId=" + roleId + ", roleName=" + roleName + ", app=" + app + "]";
+ }
+
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/ValidationRespond.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/ValidationRespond.java
new file mode 100644
index 00000000..25c74af1
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/ValidationRespond.java
@@ -0,0 +1,34 @@
+package org.openecomp.portalapp.widget.domain;
+
+public class ValidationRespond {
+ private boolean valid;
+ private String error;
+
+ public ValidationRespond(boolean valid, String error){
+ this.valid = valid;
+ this.error = error;
+ }
+
+ public boolean isValid() {
+ return valid;
+ }
+
+ public void setValid(boolean valid) {
+ this.valid = valid;
+ }
+
+ public String getError() {
+ return error;
+ }
+
+ public void setError(String error) {
+ this.error = error;
+ }
+
+ @Override
+ public String toString() {
+ return "ValidationRespond [valid=" + valid + ", error=" + error + "]";
+ }
+
+
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/WidgetCatalog.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/WidgetCatalog.java
new file mode 100644
index 00000000..6b7823e6
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/WidgetCatalog.java
@@ -0,0 +1,134 @@
+package org.openecomp.portalapp.widget.domain;
+
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+
+
+@Entity
+@Table(name="EP_WIDGET_CATALOG")
+public class WidgetCatalog{
+
+ @Id
+ @Column(name = "widget_id")
+ @GeneratedValue(strategy=GenerationType.AUTO)
+ private long id;
+
+ @Column(name = "wdg_name")
+ private String name;
+
+ @Column(name = "wdg_desc")
+ private String desc;
+
+ @Column(name = "wdg_file_loc")
+ private String fileLocation;
+
+ @Column(name = "all_user_flag")
+ private String allowAllUser;
+
+ @Column(name = "service_id")
+ private Long serviceId;
+
+ @Transient
+ private String sortOrder;
+
+ @Transient
+ private String statusCode;
+
+ @ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
+ @JoinTable(name = "ep_widget_catalog_role",
+ joinColumns = {@JoinColumn(name = "WIDGET_ID")},
+ inverseJoinColumns = {@JoinColumn(name = "ROLE_ID")}
+ )
+ private Set<RoleApp> widgetRoles;
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDesc() {
+ return desc;
+ }
+
+ public void setDesc(String desc) {
+ this.desc = desc;
+ }
+
+ public String getFileLocation() {
+ return fileLocation;
+ }
+
+ public void setFileLocation(String fileLocation) {
+ this.fileLocation = fileLocation;
+ }
+
+ public Set<RoleApp> getWidgetRoles() {
+ return widgetRoles;
+ }
+
+ public void setWidgetRoles(Set<RoleApp> widgetRoles) {
+ this.widgetRoles = widgetRoles;
+ }
+
+ public String getAllowAllUser() {
+ return allowAllUser;
+ }
+
+ public void setAllowAllUser(String allowAllUser) {
+ this.allowAllUser = allowAllUser;
+ }
+
+ public String getSortOrder() {
+ return sortOrder;
+ }
+
+ public void setSortOrder(String sortOrder) {
+ this.sortOrder = sortOrder;
+ }
+
+ public String getStatusCode() {
+ return statusCode;
+ }
+
+ public void setStatusCode(String statusCode) {
+ this.statusCode = statusCode;
+ }
+
+ public Long getServiceId() {
+ return serviceId;
+ }
+
+ public void setServiceId(Long serviceId) {
+ this.serviceId = serviceId;
+ }
+
+ @Override
+ public String toString() {
+ return "WidgetCatalog [id=" + id + ", name=" + name + ", desc=" + desc + ", fileLocation=" + fileLocation
+ + ", allowAllUser=" + allowAllUser + ", serviceId=" + serviceId + ", sortOrder=" + sortOrder
+ + ", statusCode=" + statusCode + ", widgetRoles=" + widgetRoles + "]";
+ }
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/WidgetFile.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/WidgetFile.java
new file mode 100644
index 00000000..7eb3c1ef
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/domain/WidgetFile.java
@@ -0,0 +1,96 @@
+package org.openecomp.portalapp.widget.domain;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "ep_widget_catalog_files")
+public class WidgetFile {
+ @Id
+ @Column (name = "file_id")
+ private int id;
+
+ @Column(name = "widget_name")
+ private String name;
+
+ @Column(name = "widget_id")
+ private long widgetId;
+
+ @Column(name = "markup_html")
+ private byte[] markup;
+
+ @Column(name = "controller_js")
+ private byte[] controller;
+
+ @Column(name = "framework_js")
+ private byte[] framework;
+
+ @Column(name = "widget_css")
+ private byte[] css;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public byte[] getMarkup() {
+ return markup;
+ }
+
+ public void setMarkup(byte[] markup) {
+ this.markup = markup;
+ }
+
+ public byte[] getController() {
+ return controller;
+ }
+
+ public void setController(byte[] controller) {
+ this.controller = controller;
+ }
+
+ public byte[] getFramework() {
+ return framework;
+ }
+
+ public void setFramework(byte[] framework) {
+ this.framework = framework;
+ }
+
+ public byte[] getCss() {
+ return css;
+ }
+
+ public void setCss(byte[] css) {
+ this.css = css;
+ }
+
+ public long getWidgetId() {
+ return widgetId;
+ }
+
+ public void setWidgetId(long widgetId) {
+ this.widgetId = widgetId;
+ }
+
+ @Override
+ public String toString() {
+ return "WidgetFile [name=" + name + ", widgetId=" + widgetId + "]";
+ }
+
+
+
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/excetpion/StorageException.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/excetpion/StorageException.java
new file mode 100644
index 00000000..65b71454
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/excetpion/StorageException.java
@@ -0,0 +1,15 @@
+package org.openecomp.portalapp.widget.excetpion;
+
+public class StorageException extends RuntimeException {
+
+
+ private static final long serialVersionUID = 4142203582273176386L;
+
+ public StorageException(String message) {
+ super(message);
+ }
+
+ public StorageException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/excetpion/StorageFileNotFoundException.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/excetpion/StorageFileNotFoundException.java
new file mode 100644
index 00000000..44fb7286
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/excetpion/StorageFileNotFoundException.java
@@ -0,0 +1,14 @@
+package org.openecomp.portalapp.widget.excetpion;
+
+public class StorageFileNotFoundException extends StorageException {
+
+ private static final long serialVersionUID = -930114778119283188L;
+
+ public StorageFileNotFoundException(String message) {
+ super(message);
+ }
+
+ public StorageFileNotFoundException(String message, Throwable cause) {
+ super(message, cause);
+ }
+} \ No newline at end of file
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/filters/CorsConfiguration.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/filters/CorsConfiguration.java
new file mode 100644
index 00000000..2fdb5480
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/filters/CorsConfiguration.java
@@ -0,0 +1,15 @@
+package org.openecomp.portalapp.widget.filters;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+
+@Configuration
+public class CorsConfiguration extends WebSecurityConfigurerAdapter {
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/microservices/widgetCatalog/").permitAll();
+ http.csrf().disable();
+ }
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/hibernate/HibernateConfiguration.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/hibernate/HibernateConfiguration.java
new file mode 100644
index 00000000..a376da0a
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/hibernate/HibernateConfiguration.java
@@ -0,0 +1,44 @@
+package org.openecomp.portalapp.widget.hibernate;
+
+import java.util.Properties;
+
+import javax.sql.DataSource;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
+import org.springframework.orm.jpa.JpaTransactionManager;
+import org.springframework.transaction.PlatformTransactionManager;
+
+/**
+ * Provides a Hibernate session factory.
+ */
+@org.springframework.context.annotation.Configuration
+public class HibernateConfiguration {
+
+ @Autowired
+ private DataSource dataSource;
+
+ @Bean
+ public LocalSessionFactoryBean sessionFactory() {
+
+ LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
+ sessionFactory.setDataSource(dataSource);
+ sessionFactory.setHibernateProperties(hibernateProperties());
+ sessionFactory.setPackagesToScan(new String[] { "org.openecomp.portalapp.widget.domain" });
+ return sessionFactory;
+ }
+
+ private Properties hibernateProperties() {
+ Properties properties = new Properties();
+ properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
+ properties.put("hibernate.show_sql", "false");
+ return properties;
+ }
+
+ @Bean
+ public PlatformTransactionManager transactionManager() {
+ return new JpaTransactionManager();
+ }
+
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/listener/WidgetEventListener.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/listener/WidgetEventListener.java
new file mode 100644
index 00000000..25eadfa7
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/listener/WidgetEventListener.java
@@ -0,0 +1,36 @@
+package org.openecomp.portalapp.widget.listener;
+
+import org.openecomp.portalapp.widget.service.InitializationService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.event.ApplicationReadyEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.stereotype.Component;
+
+@Component
+public class WidgetEventListener implements ApplicationListener<ApplicationReadyEvent>{
+
+ private static final Logger logger = LoggerFactory.getLogger(WidgetEventListener.class);
+
+ @Autowired
+ InitializationService initializationService;
+
+ @Value("${initialization.default.widgets}")
+ String init_default_widget;
+
+ @Override
+ public void onApplicationEvent(ApplicationReadyEvent event) {
+
+ logger.debug("Listening event " + event.toString());
+ try {
+ if(Boolean.parseBoolean(init_default_widget))
+ initializationService.initialize();
+ } catch (Exception e) {
+ logger.error("onApplicationEvent: InitializationService#initialize failed", e);
+ }
+
+ }
+
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/InitializationService.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/InitializationService.java
new file mode 100644
index 00000000..4a34606a
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/InitializationService.java
@@ -0,0 +1,7 @@
+package org.openecomp.portalapp.widget.service;
+
+public interface InitializationService {
+
+ void initialize();
+
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/MicroserviceService.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/MicroserviceService.java
new file mode 100644
index 00000000..32eb48b1
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/MicroserviceService.java
@@ -0,0 +1,17 @@
+package org.openecomp.portalapp.widget.service;
+
+import org.openecomp.portalapp.widget.domain.MicroserviceData;
+import org.openecomp.portalapp.widget.domain.MicroserviceParameter;
+
+/**
+ * TODO: moved all microservice-related code (domain, controller, service)
+ * from ecomp portal Backend to widget microservice
+ */
+public interface MicroserviceService {
+
+ Long saveMicroserivce(MicroserviceData newService);
+
+ void saveMicroserviceParameter(MicroserviceParameter newParameter);
+
+ Long getMicroserviceIdByName(String newServiceName);
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/StorageService.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/StorageService.java
new file mode 100644
index 00000000..1eb14704
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/StorageService.java
@@ -0,0 +1,34 @@
+package org.openecomp.portalapp.widget.service;
+
+import java.io.File;
+import java.io.UnsupportedEncodingException;
+
+import org.openecomp.portalapp.widget.domain.ValidationRespond;
+import org.openecomp.portalapp.widget.domain.WidgetCatalog;
+import org.openecomp.portalapp.widget.domain.WidgetFile;
+import org.springframework.web.multipart.MultipartFile;
+
+public interface StorageService {
+
+ void deleteWidgetFile(long widgetId);
+
+ WidgetFile getWidgetFile(long widgetId);
+
+ String getWidgetMarkup(long widgetId) throws UnsupportedEncodingException;
+
+ String getWidgetController(long widgetId) throws UnsupportedEncodingException;
+
+ String getWidgetFramework(long widgetId) throws UnsupportedEncodingException;
+
+ String getWidgetCSS(long widgetId) throws UnsupportedEncodingException;
+
+ ValidationRespond checkZipFile(MultipartFile file);
+
+ void save(MultipartFile file, WidgetCatalog newWidget, long widgetId);
+
+ void initSave(File file, WidgetCatalog newWidget, long widgetId);
+
+ void update(MultipartFile file, WidgetCatalog newWidget, long widgetId);
+
+ byte[] getWidgetCatalogContent(long widgetId) throws Exception;
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/WidgetCatalogService.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/WidgetCatalogService.java
new file mode 100644
index 00000000..e9bd0f33
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/WidgetCatalogService.java
@@ -0,0 +1,28 @@
+package org.openecomp.portalapp.widget.service;
+
+import java.util.List;
+
+import org.openecomp.portalapp.widget.domain.WidgetCatalog;
+
+public interface WidgetCatalogService {
+
+ List<WidgetCatalog> getWidgetCatalog();
+
+ List<WidgetCatalog> getUserWidgetCatalog(String loginName);
+
+ WidgetCatalog getWidgetCatalog(Long widgetCatalogId);
+
+ void deleteWidgetCatalog(long WidgetCatalogId);
+
+ long saveWidgetCatalog(WidgetCatalog newWidgetCatalog);
+
+ void updateWidgetCatalog(Long widgetCatalogId, WidgetCatalog newWidgetCatalog);
+
+ Long getServiceIdByWidget(Long widgetCatalogId);
+
+ boolean getWidgetIdByName(String newWidgetName);
+
+ List<WidgetCatalog> getWidgetsByServiceId(Long serviceId);
+
+
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/InitializationServiceImpl.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/InitializationServiceImpl.java
new file mode 100644
index 00000000..7a45d71e
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/InitializationServiceImpl.java
@@ -0,0 +1,133 @@
+package org.openecomp.portalapp.widget.service.impl;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashSet;
+
+import javax.transaction.Transactional;
+
+import org.openecomp.portalapp.widget.domain.MicroserviceData;
+import org.openecomp.portalapp.widget.domain.MicroserviceParameter;
+import org.openecomp.portalapp.widget.domain.RoleApp;
+import org.openecomp.portalapp.widget.domain.WidgetCatalog;
+import org.openecomp.portalapp.widget.service.InitializationService;
+import org.openecomp.portalapp.widget.service.MicroserviceService;
+import org.openecomp.portalapp.widget.service.StorageService;
+import org.openecomp.portalapp.widget.service.WidgetCatalogService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.stereotype.Service;
+
+/**
+ * Uploads widget zip archives to Portal.
+ */
+@Service("initService")
+@Transactional
+@org.springframework.context.annotation.Configuration
+@EnableAspectJAutoProxy
+public class InitializationServiceImpl implements InitializationService {
+
+ private static final String BASIC_AUTH = "Basic Authentication";
+ private static final String PARAMETER_KEY = "resourceType";
+ private static final Logger logger = LoggerFactory.getLogger(InitializationServiceImpl.class);
+
+ @Autowired
+ WidgetCatalogService widgetCatalogService;
+
+ @Autowired
+ StorageService storageService;
+
+ @Autowired
+ MicroserviceService microserviceService;
+
+ @Value("${account.user.name}")
+ String account_user;
+
+ @Value("${account.user.password}")
+ String account_password;
+
+ @Value("${initialization.widgetData.url}")
+ String widgetData_url;
+
+ @Override
+ public void initialize() {
+ initCommonWidget("News");
+ initCommonWidget("Events");
+ initCommonWidget("Resources");
+ }
+
+ private void initCommonWidget(String name) {
+
+ final String newServiceName = name + " Microservice";
+
+ Long serviceId = microserviceService.getMicroserviceIdByName(newServiceName);
+
+ if (serviceId == null) {
+ MicroserviceData newService = new MicroserviceData();
+ newService.setName(newServiceName);
+ newService.setDesc(name);
+ newService.setAppId(1);
+ newService.setUrl(widgetData_url);
+ newService.setSecurityType(BASIC_AUTH);
+ newService.setUsername(account_user);
+ newService.setPassword(account_password);
+ newService.setActive("Y");
+ serviceId = microserviceService.saveMicroserivce(newService);
+
+ MicroserviceParameter parameter = new MicroserviceParameter();
+ parameter.setServiceId(serviceId);
+ parameter.setPara_key(PARAMETER_KEY);
+ String parameter_value = null;
+ switch (name.toLowerCase()) {
+ case "news":
+ parameter_value = "NEWS";
+ break;
+ case "events":
+ parameter_value = "EVENTS";
+ break;
+ case "resources":
+ parameter_value = "IMPORTANTRESOURCES";
+ break;
+ }
+ parameter.setPara_value(parameter_value);
+ microserviceService.saveMicroserviceParameter(parameter);
+ }
+
+ if (!widgetCatalogService.getWidgetIdByName(name)) {
+ WidgetCatalog newWidget = new WidgetCatalog();
+ newWidget.setName(name);
+ newWidget.setDesc(name);
+ newWidget.setAllowAllUser("1");
+ String fileLocation = name.toLowerCase() + "-widget.zip";
+ newWidget.setFileLocation(fileLocation);
+ newWidget.setServiceId(serviceId);
+ newWidget.setWidgetRoles(new HashSet<RoleApp>());
+ long widgetId = widgetCatalogService.saveWidgetCatalog(newWidget);
+
+ File tmpZipFile = new File("/tmp/" + fileLocation);
+ InputStream fileInputStream = null;
+ OutputStream outputStream = null;
+ try {
+ fileInputStream = this.getClass().getClassLoader().getResourceAsStream(fileLocation);
+ outputStream = new FileOutputStream(tmpZipFile);
+ int read = 0;
+ byte[] bytes = new byte[4096];
+ while ((read = fileInputStream.read(bytes)) != -1) {
+ outputStream.write(bytes, 0, read);
+ }
+ outputStream.close();
+ fileInputStream.close();
+ } catch (Exception e) {
+ logger.error(
+ "Exception occurred while performing InitializationServiceImpl.initCommonWidget in widget microservices. Details:", e);
+ }
+ storageService.initSave(tmpZipFile, newWidget, widgetId);
+ tmpZipFile.delete();
+ }
+ }
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/MicroserviceServiceImpl.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/MicroserviceServiceImpl.java
new file mode 100644
index 00000000..80c45a2e
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/MicroserviceServiceImpl.java
@@ -0,0 +1,86 @@
+package org.openecomp.portalapp.widget.service.impl;
+
+import java.util.List;
+
+import javax.transaction.Transactional;
+
+import org.hibernate.Criteria;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
+import org.hibernate.criterion.Restrictions;
+import org.openecomp.portalapp.widget.domain.MicroserviceData;
+import org.openecomp.portalapp.widget.domain.MicroserviceParameter;
+import org.openecomp.portalapp.widget.service.MicroserviceService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.stereotype.Service;
+
+/**
+ * TODO: moved all microservice-related code (domain, controller, service)
+ * from ecomp portal Backend to widget microservice
+ */
+@Service("microserviceService")
+@Transactional
+@org.springframework.context.annotation.Configuration
+@EnableAspectJAutoProxy
+public class MicroserviceServiceImpl implements MicroserviceService{
+
+ private static final Logger logger = LoggerFactory.getLogger(MicroserviceServiceImpl.class);
+
+ @Autowired
+ private SessionFactory sessionFactory;
+
+ @Override
+ public Long saveMicroserivce(MicroserviceData newService) {
+ try{
+ logger.debug("MicroserviceServiceImpl.saveMicroserivce: microservice={}", newService);
+ Session session = sessionFactory.openSession();
+ Transaction tx = session.beginTransaction();
+ session.save(newService);
+ tx.commit();
+ session.flush();
+ session.close();
+ }
+ catch(Exception e){
+ logger.error("Exception occurred while performing MicroserviceServiceImpl.saveMicroserivce in widget microservices. Details:" + e.getMessage());
+ }
+ return newService.getId();
+ }
+
+ @Override
+ public void saveMicroserviceParameter(MicroserviceParameter newParameter) {
+ try{
+ logger.debug("MicroserviceServiceImpl.saveMicroserviceData: microservice={}", newParameter);
+ Session session = sessionFactory.openSession();
+ Transaction tx = session.beginTransaction();
+ session.save(newParameter);
+ tx.commit();
+ session.flush();
+ session.close();
+ }
+ catch(Exception e){
+ logger.error("Exception occurred while performing MicroserviceServiceImpl.saveMicroserviceData in widget microservices. Details:" + e.getMessage());
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Long getMicroserviceIdByName(String newServiceName) {
+
+ Session session = sessionFactory.openSession();
+ Criteria criteria = session.createCriteria(MicroserviceData.class)
+ .add(Restrictions.eq("name", newServiceName))
+ .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
+
+ List<MicroserviceData> services = criteria.list();
+ logger.debug("MicroserviceServiceImpl.getMicroserviceByName: result={}", services);
+ session.flush();
+ session.close();
+
+ return (services.size() > 0) ? services.get(0).getId() : null;
+ }
+
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/StorageServiceImpl.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/StorageServiceImpl.java
new file mode 100644
index 00000000..f459ffc4
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/StorageServiceImpl.java
@@ -0,0 +1,493 @@
+package org.openecomp.portalapp.widget.service.impl;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import org.hibernate.Criteria;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
+import org.hibernate.criterion.Restrictions;
+import org.openecomp.portalapp.widget.constant.WidgetConstant;
+import org.openecomp.portalapp.widget.domain.ValidationRespond;
+import org.openecomp.portalapp.widget.domain.WidgetCatalog;
+import org.openecomp.portalapp.widget.domain.WidgetFile;
+import org.openecomp.portalapp.widget.excetpion.StorageException;
+import org.openecomp.portalapp.widget.service.StorageService;
+import org.openecomp.portalapp.widget.service.WidgetCatalogService;
+import org.openecomp.portalapp.widget.utils.UnzipUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+@Service
+public class StorageServiceImpl implements StorageService {
+
+ private static final Logger logger = LoggerFactory.getLogger(StorageServiceImpl.class);
+
+ @Autowired
+ private SessionFactory sessionFactory;
+
+ @Autowired
+ WidgetCatalogService widgetCatalogService;
+
+ @Override
+ @Transactional
+ public void deleteWidgetFile(long widgetId) {
+ WidgetFile widgetFile = getWidgetFile(widgetId);
+ logger.debug("StorageServiceImpl.deleteWidgetFile: deleting widget file {}", widgetId);
+ if (widgetFile == null) {
+ logger.debug(
+ "StorageServiceImpl.deleteWidgetFile: No widget file found in database while performing StorageServiceImpl.deleteWidgetFile.");
+ return;
+ }
+ Session session = sessionFactory.getCurrentSession();
+ Transaction tx = session.beginTransaction();
+ session.delete(widgetFile);
+ tx.commit();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ @Transactional
+ public WidgetFile getWidgetFile(long widgetId) {
+ logger.debug("StorageServiceImpl.getWidgetFile: getting widget file {}", widgetId);
+ WidgetFile widgetFile = null;
+ Session session = sessionFactory.openSession();
+ Criteria criteria = session.createCriteria(WidgetFile.class);
+ criteria.add(Restrictions.eq("widgetId", widgetId));
+ List<WidgetFile> widgetFiles = criteria.list();
+ session.flush();
+ session.close();
+ if (widgetFiles.size() > 0)
+ widgetFile = widgetFiles.get(0);
+ return widgetFile;
+ }
+
+ @Override
+ public ValidationRespond checkZipFile(MultipartFile file) {
+ StringBuilder error_msg = new StringBuilder();
+ UnzipUtil unzipper = new UnzipUtil();
+ Map<String, byte[]> map;
+ File convFile;
+ boolean isValid = true;
+ if (!file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.')).equals(".zip")) {
+ isValid = false;
+ error_msg.append(WidgetConstant.VALIDATION_MESSAGE_ZIP);
+ logger.error("StorageServiceImpl.checkZipFile: invalid file format");
+ }
+ try {
+ if (file.isEmpty()) {
+ logger.error(
+ "StorageServiceImpl.checkZipFile: Failed to store empty file " + file.getOriginalFilename());
+ throw new StorageException(
+ "StorageServiceImpl.checkZipFile: Failed to store empty file " + file.getOriginalFilename());
+ }
+ String fileLocation = file.getOriginalFilename();
+ logger.debug("StorageServiceImpl.checkZipFile: store the widget to:" + fileLocation);
+ convFile = new File(fileLocation);
+ FileOutputStream fos = new FileOutputStream(convFile);
+ fos.write(file.getBytes());
+ fos.close();
+ map = unzipper.unzip_db(fileLocation, ".", "tempWidgets");
+ convFile.delete();
+ } catch (IOException e) {
+ logger.error("StorageServiceImpl.checkZipFile: Failed to store file " + file.getOriginalFilename(), e);
+ throw new StorageException(
+ "torageServiceImpl.checkZipFile: Failed to store file " + file.getOriginalFilename(), e);
+ }
+
+ for (byte[] b : map.values()) {
+ if (isValid && b == null) {
+ isValid = false;
+ error_msg.append(WidgetConstant.VALIDATION_MESSAGE_FILES);
+ break;
+ }
+ }
+ return new ValidationRespond(isValid, error_msg.toString());
+ }
+
+ @Override
+ @Transactional
+ public void save(MultipartFile file, WidgetCatalog newWidget, long widgetId) {
+
+ UnzipUtil unzipper = new UnzipUtil();
+ Map<String, byte[]> map;
+ File convFile;
+ try {
+ if (file.isEmpty()) {
+ logger.error("Failed to store empty file " + file.getOriginalFilename());
+ throw new StorageException("Failed to store empty file " + file.getOriginalFilename());
+ }
+ String fileLocation = file.getOriginalFilename();
+ logger.debug("StorageServiceImpl.save: store the widget to:" + fileLocation);
+ convFile = new File(fileLocation);
+ FileOutputStream fos = new FileOutputStream(convFile);
+ fos.write(file.getBytes());
+ fos.close();
+ map = unzipper.unzip_db(fileLocation, ".", "tempWidgets");
+ convFile.delete();
+ } catch (IOException e) {
+ logger.error("StorageServiceImpl.save: Failed to store file " + file.getOriginalFilename(), e);
+ throw new StorageException("Failed to store file " + file.getOriginalFilename(), e);
+ }
+ saveHelper(newWidget, widgetId, map);
+ }
+
+ @Override
+ @Transactional
+ public void initSave(File file, WidgetCatalog newWidget, long widgetId) {
+
+ UnzipUtil unzipper = new UnzipUtil();
+ Map<String, byte[]> map;
+
+ try {
+ String fileLocation = file.getPath();
+ logger.debug("StorageServiceImpl.save: store the widget to:" + fileLocation);
+ map = unzipper.unzip_db(fileLocation, ".", "tempWidgets");
+ } catch (IOException e) {
+ logger.error("StorageServiceImpl.save: Failed to store file " + file.getName(), e);
+ throw new StorageException("Failed to store file " + file.getName(), e);
+ }
+
+ saveHelper(newWidget, widgetId, map);
+ }
+
+ /**
+ * Helper method for saving widget files (controller.js, framework.js,
+ * markup.html and style.css) to ep_widget_catalog_files table in database
+ *
+ * @param newWidget
+ * @param widgetId
+ * @param map
+ */
+ private void saveHelper(WidgetCatalog newWidget, long widgetId, Map<String, byte[]> map) {
+
+ logger.debug("Going to save widget " + newWidget);
+ WidgetFile widgetFile = new WidgetFile();
+ widgetFile.setName(newWidget.getName());
+ widgetFile.setWidgetId(widgetId);
+
+ InputStream fileInputStream = this.getClass().getClassLoader().getResourceAsStream("framework-template.js");
+
+ String sb = null;
+ try {
+ byte[] bytes = new byte[fileInputStream.available()];
+ fileInputStream.read(bytes);
+ sb = new String(bytes, "UTF-8");
+ } catch (IOException e) {
+ logger.error("StorageServiceImpl.save: Failed to load framework-template.js file ", e);
+ e.printStackTrace();
+ } finally {
+ if (fileInputStream != null) {
+ try {
+ fileInputStream.close();
+ } catch (IOException e) {
+ logger.error("StorageServiceImpl.update: Failed to close the fileInputStream ", e);
+ }
+ }
+ }
+
+ String namespace = "Portal" + widgetId + "Widget";
+ String controllerName = "Portal" + widgetId + "Ctrl";
+ String cssName = "portal" + widgetId + "-css-ready";
+ String colorArg1 = "color: #fff";
+ String framework = sb.replaceAll("ARUGMENT1", namespace).replaceAll("ARUGMENT2", controllerName)
+ .replaceAll("ARUGMENT3", cssName).replaceAll("CSS_ARG1", colorArg1)
+ .replaceAll("MICROSERVICE_ID", newWidget.getServiceId().toString())
+ .replaceAll("WIDGET_ID", Long.toString(widgetId));
+
+ widgetFile.setFramework(framework.getBytes());
+
+ final byte[] controllerLoc = map.get(WidgetConstant.WIDGET_CONTROLLER_LOCATION);
+ if (controllerLoc == null || controllerLoc.length == 0)
+ throw new IllegalArgumentException(
+ "Map is missing required key " + WidgetConstant.WIDGET_CONTROLLER_LOCATION);
+ String javascript = new String(controllerLoc);
+ String functionHeader = javascript.substring(javascript.indexOf("function"), javascript.indexOf(")") + 1);
+ String functionName = functionHeader.substring(functionHeader.indexOf(" "), functionHeader.indexOf("(")).trim();
+ javascript = javascript.replaceFirst(functionName, controllerName);
+ String functionParam = functionHeader.substring(functionHeader.indexOf("(") + 1, functionHeader.indexOf(")"));
+ List<String> paramList = Arrays.asList(functionParam.split(","));
+
+ int left_bracket_index = javascript.indexOf("{") + 1;
+ String widgetData = namespace + "=" + namespace + "||{};" + "var res = " + namespace + ".widgetData;";
+ javascript = javascript.substring(0, left_bracket_index) + widgetData
+ + javascript.substring(left_bracket_index);
+
+ StringBuilder injectStr = new StringBuilder().append("[");
+ for (int i = 0; i < paramList.size(); i++) {
+ if (i == paramList.size() - 1)
+ injectStr.append("'" + paramList.get(i).trim() + "'];");
+ else
+ injectStr.append("'" + paramList.get(i).trim() + "',");
+ }
+ javascript = namespace + ".controller = " + javascript + ";" + namespace + ".controller.$inject = "
+ + injectStr.toString();
+
+ String html = new String(map.get(WidgetConstant.WIDGET_MARKUP_LOCATION)).replaceFirst(functionName,
+ controllerName);
+ ;
+
+ Pattern cssPattern = Pattern.compile("#.*-css-ready");
+ Matcher cssMatcher = cssPattern.matcher(new String(map.get(WidgetConstant.WIDGET_STYLE_LOCATION)));
+ if (cssMatcher.find()) {
+ widgetFile.setCss(new String(map.get(WidgetConstant.WIDGET_STYLE_LOCATION))
+ .replace(cssMatcher.group(0), "#" + cssName).getBytes());
+ }
+
+ widgetFile.setMarkup(html.getBytes());
+ widgetFile.setController(javascript.getBytes());
+ Session session = sessionFactory.openSession();
+ session.save(widgetFile);
+ session.flush();
+ session.close();
+ // sessionFactory.getCurrentSession().save(widgetFile);
+ logger.debug(
+ "StorageServiceImpl.save: saved fraemwork.js controller.js, markup.html and style.css files to the database for widget {}",
+ widgetId);
+
+ }
+
+ @Override
+ public void update(MultipartFile file, WidgetCatalog newWidget, long widgetId) {
+ UnzipUtil unzipper = new UnzipUtil();
+ Map<String, byte[]> map;
+ File convFile;
+ try {
+ if (file.isEmpty()) {
+ logger.error("StorageServiceImpl.update: Failed to store empty file " + file.getOriginalFilename());
+ throw new StorageException("Failed to store empty file " + file.getOriginalFilename());
+ }
+ String fileLocation = file.getOriginalFilename();
+ logger.debug("StorageServiceImpl.update: store the widget to:" + fileLocation);
+ convFile = new File(fileLocation);
+ FileOutputStream fos = new FileOutputStream(convFile);
+ fos.write(file.getBytes());
+ fos.close();
+ map = unzipper.unzip_db(fileLocation, ".", "tempWidgets");
+ convFile.delete();
+ } catch (IOException e) {
+ logger.error("StorageServiceImpl.update: Failed to store file " + file.getOriginalFilename(), e);
+ throw new StorageException("StorageServiceImpl.update: Failed to store file " + file.getOriginalFilename(),
+ e);
+ }
+ WidgetFile widgetFile = getWidgetFile(widgetId);
+
+ InputStream fileInputStream = this.getClass().getClassLoader().getResourceAsStream("framework-template.js");
+ String sb = null;
+ try {
+ byte[] bytes = new byte[fileInputStream.available()];
+ fileInputStream.read(bytes);
+ sb = new String(bytes, "UTF-8");
+ } catch (IOException e) {
+ logger.error("StorageServiceImpl.save: Failed to load framework-template.js file ", e);
+ e.printStackTrace();
+ } finally {
+ if (fileInputStream != null) {
+ try {
+ fileInputStream.close();
+ } catch (IOException e) {
+ logger.error("StorageServiceImpl.update: Failed to close the fileInputStream ", e);
+ e.printStackTrace();
+ }
+ }
+ }
+
+ String namespace = "Portal" + widgetId + "Widget";
+ String controllerName = "Portal" + widgetId + "Ctrl";
+ String cssName = "portal" + widgetId + "-css-ready";
+ String colorArg1 = "color: #fff";
+ String framework = sb.replaceAll("ARUGMENT1", namespace).replaceAll("ARUGMENT2", controllerName)
+ .replaceAll("ARUGMENT3", cssName).replaceAll("CSS_ARG1", colorArg1)
+ .replaceAll("MICROSERVICE_ID", newWidget.getServiceId().toString())
+ .replaceAll("WIDGET_ID", Long.toString(widgetId));
+ widgetFile.setFramework(framework.getBytes());
+
+ String javascript = new String(map.get(WidgetConstant.WIDGET_CONTROLLER_LOCATION));
+ String functionHeader = javascript.substring(javascript.indexOf("function"), javascript.indexOf(")") + 1);
+ String functionName = functionHeader.substring(functionHeader.indexOf(" "), functionHeader.indexOf("(")).trim();
+ javascript = javascript.replaceFirst(functionName, controllerName);
+ String functionParam = functionHeader.substring(functionHeader.indexOf("(") + 1, functionHeader.indexOf(")"));
+ List<String> paramList = Arrays.asList(functionParam.split(","));
+
+ int left_bracket_index = javascript.indexOf("{") + 1;
+ String widgetData = namespace + "=" + namespace + "||{};" + "var res = " + namespace + ".widgetData;";
+ javascript = javascript.substring(0, left_bracket_index) + widgetData
+ + javascript.substring(left_bracket_index);
+
+ StringBuilder injectStr = new StringBuilder().append("[");
+ for (int i = 0; i < paramList.size(); i++) {
+ if (i == paramList.size() - 1)
+ injectStr.append("'" + paramList.get(i).trim() + "'];");
+ else
+ injectStr.append("'" + paramList.get(i).trim() + "',");
+ }
+ javascript = namespace + ".controller = " + javascript + ";" + namespace + ".controller.$inject = "
+ + injectStr.toString();
+
+ String html = new String(map.get(WidgetConstant.WIDGET_MARKUP_LOCATION)).replaceFirst(functionName,
+ controllerName);
+ ;
+
+ Pattern cssPattern = Pattern.compile("#.*-css-ready");
+ Matcher cssMatcher = cssPattern.matcher(new String(map.get(WidgetConstant.WIDGET_STYLE_LOCATION)));
+ if (cssMatcher.find()) {
+ widgetFile.setCss(new String(map.get(WidgetConstant.WIDGET_STYLE_LOCATION))
+ .replace(cssMatcher.group(0), "#" + cssName).getBytes());
+ }
+
+ widgetFile.setMarkup(html.getBytes());
+ widgetFile.setController(javascript.getBytes());
+ // widgetFile.setCss(map.get(WidgetConstant.WIDGET_STYLE_LOCATION));
+ Session session = sessionFactory.openSession();
+ Transaction tx = session.beginTransaction();
+ session.update(widgetFile);
+ tx.commit();
+ session.flush();
+ session.close();
+ logger.debug(
+ "StorageServiceImpl.save: updated fraemwork.js controller.js, markup.html and style.css files to the database for widget {}",
+ widgetId);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ @Transactional
+ public String getWidgetMarkup(long widgetId) throws UnsupportedEncodingException {
+ String markup = null;
+ Session session = sessionFactory.getCurrentSession();
+ Criteria criteria = session.createCriteria(WidgetFile.class);
+ criteria.add(Restrictions.eq("widgetId", widgetId));
+ List<WidgetFile> widgetFile = criteria.list();
+ logger.debug("StorageServiceImpl.getWidgetMarkup: getting widget markup result={}", widgetFile);
+
+ if (widgetFile.size() > 0)
+ markup = new String(widgetFile.get(0).getMarkup(), "UTF-8");
+ return markup;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ @Transactional
+ public String getWidgetController(long widgetId) throws UnsupportedEncodingException {
+ String controller = null;
+ Session session = sessionFactory.getCurrentSession();
+ Criteria criteria = session.createCriteria(WidgetFile.class);
+ criteria.add(Restrictions.eq("widgetId", widgetId));
+ List<WidgetFile> widgetFile = criteria.list();
+ logger.debug("StorageServiceImpl.getWidgetController: getting widget controller result={}", widgetFile);
+
+ if (widgetFile.size() > 0)
+ controller = new String(widgetFile.get(0).getController(), "UTF-8");
+ return controller;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ @Transactional
+ public String getWidgetFramework(long widgetId) throws UnsupportedEncodingException {
+ String framework = null;
+ Session session = sessionFactory.getCurrentSession();
+ Criteria criteria = session.createCriteria(WidgetFile.class);
+ criteria.add(Restrictions.eq("widgetId", widgetId));
+ List<WidgetFile> widgetFile = criteria.list();
+ logger.debug("StorageServiceImpl.getWidgetFramework: getting widget framework result={}", widgetFile);
+
+ if (widgetFile.size() > 0)
+ framework = new String(widgetFile.get(0).getFramework(), "UTF-8");
+ return framework;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ @Transactional
+ public String getWidgetCSS(long widgetId) throws UnsupportedEncodingException {
+ String css = null;
+ Session session = sessionFactory.getCurrentSession();
+ Criteria criteria = session.createCriteria(WidgetFile.class);
+ criteria.add(Restrictions.eq("widgetId", widgetId));
+ List<WidgetFile> widgetFile = criteria.list();
+ logger.debug("StorageServiceImpl.getWidgetCSS: getting widget css result={}", widgetFile);
+
+ if (widgetFile.size() > 0)
+ css = new String(widgetFile.get(0).getCss(), "UTF-8");
+ return css;
+ }
+
+ @Override
+ @Transactional
+ public byte[] getWidgetCatalogContent(long widgetId) throws Exception {
+
+ WidgetCatalog widget = widgetCatalogService.getWidgetCatalog(widgetId);
+ String namespace = "Portal" + widgetId + "Widget";
+ String controllerName = "Portal" + widgetId + "Ctrl";
+ String cssName = "portal" + widgetId + "-css-ready";
+
+ String styles = getWidgetCSS(widgetId).replaceAll(cssName, widget.getName() + "-css-ready");
+ File f = File.createTempFile("temp", ".zip");
+ ZipOutputStream out = new ZipOutputStream(new FileOutputStream(f));
+ ZipEntry e = new ZipEntry(widget.getName() + "/styles/styles.css");
+ out.putNextEntry(new ZipEntry(widget.getName() + "/"));
+ out.putNextEntry(new ZipEntry(widget.getName() + "/styles/"));
+ out.putNextEntry(e);
+ byte[] data = styles.getBytes();
+ out.write(data, 0, data.length);
+
+ String widgetData = namespace + "=" + namespace + "||{};" + "var res = " + namespace + ".widgetData;";
+ String javascript = getWidgetController(widgetId).replace(widgetData, "").replace(namespace + ".controller =",
+ "");
+
+ String functionHeader = javascript.substring(javascript.indexOf("function"), javascript.indexOf(")") + 1);
+ javascript = javascript.replaceFirst(controllerName, widget.getName() + "Ctrl");
+ String functionParam = functionHeader.substring(functionHeader.indexOf("(") + 1, functionHeader.indexOf(")"));
+ StringBuilder injectStr = new StringBuilder().append("[");
+ List<String> paramList = Arrays.asList(functionParam.split(","));
+ for (int i = 0; i < paramList.size(); i++) {
+ if (i == paramList.size() - 1)
+ injectStr.append("'" + paramList.get(i).trim() + "'];");
+ else
+ injectStr.append("'" + paramList.get(i).trim() + "',");
+ }
+ javascript = javascript.replace(";" + namespace + ".controller.$inject = " + injectStr.toString(), "");
+
+ e = new ZipEntry(widget.getName() + "/js/controller.js");
+ out.putNextEntry(new ZipEntry(widget.getName() + "/js/"));
+ out.putNextEntry(e);
+ data = javascript.getBytes();
+ out.write(data, 0, data.length);
+
+ String html = getWidgetMarkup(widgetId).replaceFirst(controllerName, widget.getName() + "Ctrl");
+
+ // new
+ // String(map.get(WidgetConstant.WIDGET_MARKUP_LOCATION)).replaceFirst(functionName,
+ // controllerName);;
+
+ e = new ZipEntry(widget.getName() + "/markup/markup.html");
+ out.putNextEntry(new ZipEntry(widget.getName() + "/markup/"));
+ out.putNextEntry(e);
+ data = html.getBytes();
+ out.write(data, 0, data.length);
+ out.closeEntry();
+ out.close();
+ byte[] result = Files.readAllBytes(Paths.get(f.getPath()));
+ f.delete();
+ return result;
+ }
+
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/WidgetCatalogServiceImpl.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/WidgetCatalogServiceImpl.java
new file mode 100644
index 00000000..51f78227
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/service/impl/WidgetCatalogServiceImpl.java
@@ -0,0 +1,243 @@
+package org.openecomp.portalapp.widget.service.impl;
+
+import java.util.List;
+import java.util.Set;
+
+import javax.transaction.Transactional;
+
+import org.hibernate.Criteria;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
+import org.hibernate.criterion.Restrictions;
+import org.openecomp.portalapp.widget.domain.MicroserviceData;
+import org.openecomp.portalapp.widget.domain.RoleApp;
+import org.openecomp.portalapp.widget.domain.WidgetCatalog;
+import org.openecomp.portalapp.widget.service.WidgetCatalogService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.stereotype.Service;
+
+@Service("widgetCatalogService")
+@Transactional
+@org.springframework.context.annotation.Configuration
+@EnableAspectJAutoProxy
+public class WidgetCatalogServiceImpl implements WidgetCatalogService {
+
+ private static final Logger logger = LoggerFactory.getLogger(WidgetCatalogServiceImpl.class);
+
+ @Autowired
+ private SessionFactory sessionFactory;
+
+ @SuppressWarnings("unchecked")
+ @Override
+ @Transactional
+ public List<WidgetCatalog> getWidgetCatalog(){
+ Session session = sessionFactory.getCurrentSession();
+ Criteria criteria = session.createCriteria(WidgetCatalog.class)
+ .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
+ List<WidgetCatalog> widgets = criteria.list();
+ logger.debug("WidgetCatalogServiceImpl.getWidgetCatalog: result={}", widgets);
+ return widgets;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Transactional
+ public List<WidgetCatalog> getUserWidgetCatalog(String loginName){
+ Session session = sessionFactory.getCurrentSession();
+ StringBuilder sql = new StringBuilder()
+
+
+ .append(" select userWidgets.widget_id, userWidgets.wdg_name, userWidgets.wdg_desc, b.x, b.status_cd, b.y, b.height, b.width from ")
+ .append(" ( ")
+ .append(" select distinct w.widget_id, w.wdg_name, w.wdg_desc from ")
+ .append(" ep_widget_catalog w, ")
+ .append(" ep_widget_catalog_role wr, ")
+ .append(" fn_user_role ur, ")
+ .append(" fn_app app, ")
+ .append(" fn_user u ")
+ .append(" where ")
+ .append(" w.widget_id = wr.WIDGET_ID and ")
+ .append(" ur.app_id = app.app_id and ")
+ .append(" app.enabled = 'Y' and ")
+ .append(" wr.role_id = ur.role_id and ")
+ .append(" ur.user_id = u.user_id and ")
+ .append(" u.login_id = '" + loginName + "' and (w.all_user_flag = 'N' or w.all_user_flag is null) ")
+ .append(" ")
+ .append(" union all ")
+ .append(" ")
+ .append(" ")
+ .append(" select distinct w.widget_id, w.wdg_name, w.wdg_desc from ")
+ .append(" ep_widget_catalog w ")
+ .append(" where w.all_user_flag = 'Y' ")
+ .append(" ")
+ .append(" ) userWidgets ")
+ .append(" ")
+ .append(" left join ")
+ .append(" ")
+ .append(" ( ")
+ .append(" select case when pers.user_id is null then sel.user_id else pers.user_id end as 'user_id', case when sel.widget_id is null then ")
+ .append(" pers.widget_id else sel.widget_id end as 'widget_id', pers.x, sel.status_cd, pers.y, pers.height, pers.width ")
+ .append(" from (select * from ep_pers_user_widget_placement where user_id = (select user_id from fn_user where login_id = '" + loginName + "')) pers ")
+ .append(" left outer join ")
+ .append(" (select * from ep_pers_user_widget_sel where user_id = (select user_id from fn_user where login_id = '" + loginName + "')) sel ")
+ .append(" on (pers.user_id = sel.user_id and pers.widget_id = sel.widget_id) ")
+ .append(" ")
+ .append(" union ")
+ .append(" ")
+ .append(" select case when pers.user_id is null then sel.user_id else pers.user_id end as 'user_id', case when sel.widget_id is null ")
+ .append(" then pers.widget_id else sel.widget_id end as 'widget_id', pers.x, sel.status_cd, pers.y, pers.height, pers.width ")
+ .append(" from (select * from ep_pers_user_widget_placement where user_id = (select user_id from fn_user where login_id = '" + loginName + "')) pers ")
+ .append(" right outer join ")
+ .append(" (select * from ep_pers_user_widget_sel where user_id = (select user_id from fn_user where login_id = '" + loginName + "')) sel ")
+ .append(" on (pers.user_id = sel.user_id and pers.widget_id = sel.widget_id) ")
+ .append(" ")
+ .append(" order by user_id, widget_id ")
+ .append(" )b ")
+ .append(" on ")
+ .append(" (userWidgets.widget_id = b.widget_id) order by b.x; ");
+
+
+
+ Query query = session.createSQLQuery(sql.toString());
+ List<WidgetCatalog> widgets = query.list();
+ logger.debug("WidgetCatalogServiceImpl.getUserWidgetCatalog: result size={}", widgets);
+ return widgets;
+ }
+
+ @Override
+ public WidgetCatalog getWidgetCatalog(Long widgetCatalogId) {
+ Session session = sessionFactory.getCurrentSession();
+ Transaction tx = session.beginTransaction();
+ WidgetCatalog widget = (WidgetCatalog) session.get(WidgetCatalog.class, widgetCatalogId);
+ tx.commit();
+ logger.debug("WidgetCatalogServiceImpl.getWidgetCatalog: getting widget={}", widget);
+ return widget;
+ }
+
+ @Override
+ public void deleteWidgetCatalog(long widgetCatalogId) {
+ logger.debug("WidgetCatalogServiceImpl.deleteWidgetCatalog: deleting the widget with widgetId={}", widgetCatalogId);
+ WidgetCatalog widget = getWidgetCatalog(widgetCatalogId);
+ if (widget == null){
+ logger.error("No widget found in database while performing WidgetCatalogServiceImpl.deleteWidgetCatalog.");
+ return;
+ }
+ Session session = sessionFactory.getCurrentSession();
+ Transaction tx = session.beginTransaction();
+ Query query = session.createSQLQuery("delete from ep_pers_user_widget_sel where widget_id = :widgetId ").setParameter("widgetId", widgetCatalogId);
+ query.executeUpdate();
+ query = session.createSQLQuery("delete from ep_pers_user_widget_placement where widget_id = :widgetId ").setParameter("widgetId", widgetCatalogId);
+ query.executeUpdate();
+ query = session.createSQLQuery("delete from ep_widget_catalog_files where widget_id = :widgetId ").setParameter("widgetId", widgetCatalogId);
+ query.executeUpdate();
+ query = session.createSQLQuery("delete from ep_widget_catalog_parameter where widget_id = :widgetId ").setParameter("widgetId", widgetCatalogId);
+ query.executeUpdate();
+ session.delete(widget);
+ tx.commit();
+ }
+
+ @Override
+ public long saveWidgetCatalog(WidgetCatalog newWidgetCatalog) {
+
+ try{
+ if(newWidgetCatalog.getAllowAllUser().equals("1"))
+ newWidgetCatalog.setAllowAllUser("Y");
+ else
+ newWidgetCatalog.setAllowAllUser("N");
+
+ logger.debug("WidgetCatalogServiceImpl.saveWidgetCatalog: widget={}", newWidgetCatalog);
+ Session session = sessionFactory.openSession();
+ Transaction tx = session.beginTransaction();
+ session.save(newWidgetCatalog);
+ tx.commit();
+ session.flush();
+ session.close();
+ updateAppId(newWidgetCatalog.getId(), newWidgetCatalog.getWidgetRoles());
+ }
+ catch(Exception e){
+ logger.error("Exception occurred while performing WidgetCatalogServiceImpl.saveWidgetCatalog in widget microservices. Details:" + e.getMessage());
+ }
+ return newWidgetCatalog.getId();
+ }
+
+ @Override
+ public void updateWidgetCatalog(Long widgetCatalogId, WidgetCatalog newWidgetCatalog) {
+ logger.debug("WidgetCatalogServiceImpl.updateWidgetCatalog: widget={}", newWidgetCatalog);
+ WidgetCatalog oldWidget = getWidgetCatalog(widgetCatalogId);
+ try{
+ if (newWidgetCatalog.getAllowAllUser().equals("1"))
+ newWidgetCatalog.setAllowAllUser("Y");
+ else
+ newWidgetCatalog.setAllowAllUser("N");
+
+ newWidgetCatalog.setId(widgetCatalogId);
+ newWidgetCatalog.setServiceId(oldWidget.getServiceId());
+ Session session = sessionFactory.openSession();
+ Transaction tx = session.beginTransaction();
+ session.update(newWidgetCatalog);
+ tx.commit();
+ session.flush();
+ session.close();
+ updateAppId(newWidgetCatalog.getId(), newWidgetCatalog.getWidgetRoles());
+ }catch(Exception e){
+ logger.error("Exception occurred while performing WidgetCatalogServiceImpl.updateWidgetCatalog in widget microservices. Details:" + e.getMessage());
+ }
+
+ }
+
+ @Override
+ public Long getServiceIdByWidget(Long widgetCatalogId) {
+ Session session = sessionFactory.getCurrentSession();
+ WidgetCatalog widget = (WidgetCatalog) session.get(WidgetCatalog.class, widgetCatalogId);
+ logger.debug("WidgetCatalogServiceImpl.getServiceIdByWidget: result={}", widget);
+ return widget.getServiceId();
+ }
+
+ @Override
+ public List<WidgetCatalog> getWidgetsByServiceId(Long serviceId) {
+ Session session = sessionFactory.getCurrentSession();
+ Criteria criteria = session.createCriteria(WidgetCatalog.class)
+ .add(Restrictions.eq("serviceId", serviceId))
+ .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
+ List<WidgetCatalog> widgets = criteria.list();
+ logger.debug("WidgetCatalogServiceImpl.getWidgetCatalog: result={}", widgets);
+ return widgets;
+ }
+
+
+
+
+
+ private void updateAppId(long widgetId, Set<RoleApp> roles){
+ Session session = sessionFactory.openSession();
+ for(RoleApp role: roles){
+ String sql = "UPDATE ep_widget_catalog_role SET app_id = " + role.getApp().getAppId() + " WHERE widget_id = " + widgetId + " AND ROLE_ID = " + role.getRoleId() ;
+ Query query = session.createSQLQuery(sql);
+ query.executeUpdate();
+ }
+ session.flush();
+ session.close();
+ }
+
+ @Override
+ public boolean getWidgetIdByName(String newWidgetName) {
+ Session session = sessionFactory.openSession();
+ Criteria criteria = session.createCriteria(WidgetCatalog.class)
+ .add(Restrictions.eq("name", newWidgetName))
+ .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
+
+ List<MicroserviceData> widgets = criteria.list();
+ logger.debug("WidgetCatalogServiceImpl.getWidgetIdByName: result={}", widgets);
+ session.flush();
+ session.close();
+
+ return (widgets.size() > 0) ? true : false;
+ }
+
+
+}
+
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/utils/AuthorizationUtil.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/utils/AuthorizationUtil.java
new file mode 100644
index 00000000..f25f0db6
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/utils/AuthorizationUtil.java
@@ -0,0 +1,19 @@
+package org.openecomp.portalapp.widget.utils;
+
+import java.nio.charset.Charset;
+import java.util.Base64;
+
+public class AuthorizationUtil {
+
+ public boolean authorization(String auth, String security_user, String security_pass){
+ if (auth != null && auth.startsWith("Basic")) {
+ String base64Credentials = auth.substring("Basic".length()).trim();
+ String credentials = new String(Base64.getDecoder().decode(base64Credentials),
+ Charset.forName("UTF-8"));
+ final String[] values = credentials.split(":",2);
+ if(security_user.equals(values[0]) && security_pass.equals(values[1]))
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/utils/UnzipUtil.java b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/utils/UnzipUtil.java
new file mode 100644
index 00000000..1d61d587
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/java/org/openecomp/portalapp/widget/utils/UnzipUtil.java
@@ -0,0 +1,110 @@
+package org.openecomp.portalapp.widget.utils;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Stack;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.openecomp.portalapp.widget.constant.WidgetConstant;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class UnzipUtil {
+
+ /**
+ * Size of the buffer to read/write data
+ */
+ private static final int BUFFER_SIZE = 4096;
+ private static final Logger logger = LoggerFactory.getLogger(UnzipUtil.class);
+
+ /**
+ * Extracts a zip file specified by the zipFilePath to a directory specified by
+ * destDirectory (will be created if does not exists)
+ *
+ * @param zipFilePath
+ * path
+ * @param destDirectory
+ * directory
+ * @param widgetName
+ * name
+ * @return Map of contents
+ * @throws IOException
+ * On error
+ */
+ public Map<String, byte[]> unzip_db(String zipFilePath, String destDirectory, String widgetName)
+ throws IOException {
+
+ logger.debug("UnzipUtil.unzip_db: unzip widget file {}", widgetName);
+ File destDir = new File(destDirectory);
+ if (!destDir.exists())
+ destDir.mkdir();
+ ZipInputStream zipIn = new ZipInputStream(new FileInputStream(zipFilePath));
+ ZipEntry entry = zipIn.getNextEntry();
+ Map<String, byte[]> map = new HashMap<>();
+
+ String[] requiredKeys = { WidgetConstant.WIDGET_CONTROLLER_LOCATION, WidgetConstant.WIDGET_MARKUP_LOCATION,
+ WidgetConstant.WIDGET_STYLE_LOCATION };
+ for (String k : requiredKeys)
+ map.put(k, null);
+
+ // iterates over entries in the zip file
+ Stack<File> stack = new Stack<>();
+ while (entry != null) {
+ String filePath = destDirectory + File.separator + widgetName + File.separator
+ + entry.getName().substring(entry.getName().indexOf("/") + 1);
+ final String entryShortName = entry.getName().substring(entry.getName().indexOf("/") + 1);
+ logger.debug("UnzipUtil.unzip_db: file path {}, short name {}", filePath, entryShortName);
+ if (!entry.isDirectory()) {
+ // if the entry is a file, extracts it
+ logger.debug("UnzipUtil.unzip_db: unzip and save widget file {}", filePath);
+ stack.push(new File(filePath));
+ extractFile(zipIn, filePath);
+ } else {
+ // if the entry is a directory, make the directory
+ logger.debug("UnzipUtil.unzip_db: unzip and create widget folder {}", filePath);
+ File dir = new File(filePath);
+ stack.push(new File(filePath));
+ dir.mkdir();
+ }
+ // Is this one we need?
+ if (map.containsKey(entryShortName))
+ map.put(entryShortName, Files.readAllBytes(Paths.get(filePath)));
+ zipIn.closeEntry();
+ entry = zipIn.getNextEntry();
+ }
+ zipIn.close();
+ while (!stack.isEmpty())
+ stack.pop().delete();
+
+ for (String k : requiredKeys)
+ if (!map.containsKey(k))
+ logger.warn("UnzipUtil.unzip_db: no zip archive entry found for required key {}", k);
+
+ return map;
+ }
+
+ /**
+ * Extracts a zip entry (file entry)
+ *
+ * @param zipIn
+ * @param filePath
+ * @throws IOException
+ */
+ private void extractFile(ZipInputStream zipIn, String filePath) throws IOException {
+ BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));
+ byte[] bytesIn = new byte[BUFFER_SIZE];
+ int read = 0;
+ while ((read = zipIn.read(bytesIn)) != -1) {
+ bos.write(bytesIn, 0, read);
+ }
+ bos.close();
+ }
+} \ No newline at end of file
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/resources/application-properties b/ecomp-portal-widget-ms/widget-ms/src/main/resources/application-properties
new file mode 100644
index 00000000..77d2b78d
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/resources/application-properties
@@ -0,0 +1,28 @@
+## General App Properties
+server.contextPath=/widget
+server.port=8082
+spring.http.multipart.max-file-size=128MB
+spring.http.multipart.max-request-size=128MB
+microservice.widget.location=/demeter/WebApps/dev/ECOMPPORTAL/microservices/widgets-dir/
+
+## App DB Properties
+spring.datasource.url=jdbc:mariadb:failover://demeter.homer.att.com:3306/ecomp_portal_1702&connectTimeout=2000
+spring.datasource.username=portal
+spring.datasource.password=ENC(8tWrJAXdOKaMqvrVy5e2Jg==)
+spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
+spring.database.driver.classname=org.mariadb.jdbc.Driver
+spring.jpa.show-sql=false
+spring.jpa.properties.hibernate.format_sql=false
+
+## Basic Authentication Properties
+security.user.name=widget_user
+security.user.password=ENC(IjywcRnI9+nuVEh9+OFFiRWAjBT1n718)
+
+## Certificate Properties
+#server.ssl.key-store=classpath:widget-keystore.p12
+#server.ssl.key-store-password=ENC(DiIYnAMab4u7rEW2yKhF9zBL00uU55q8)
+#server.ssl.keyStoreType=PKCS12
+#server.ssl.keyAlias=widget-microservice
+
+## Jasypt Properties
+jasypt.encryptor.password=EncryptionKey
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/resources/application.properties.templated b/ecomp-portal-widget-ms/widget-ms/src/main/resources/application.properties.templated
new file mode 100644
index 00000000..ec4803f0
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/resources/application.properties.templated
@@ -0,0 +1,35 @@
+## General App Properties
+server.contextPath=/widget
+server.port=8082
+spring.http.multipart.max-file-size=128MB
+spring.http.multipart.max-request-size=128MB
+
+## App DB Properties
+spring.datasource.url=jdbc:mariadb:failover://{db_host:db_port/{portal_db}
+spring.datasource.username={username}
+spring.datasource.password=ENC({encrypted_password})
+spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
+spring.database.driver.classname=org.mariadb.jdbc.Driver
+spring.jpa.show-sql=false
+spring.jpa.properties.hibernate.format_sql=false
+
+## Basic Authentication Properties
+security.user.name={basic_auth_username}
+security.user.password=ENC({encrypted_basic_auth_password})
+
+## Initalization setting
+initialization.default.widgets=true
+initialization.widgetData.url={widgetData_url}
+
+## Account Basic Authentication Properties
+account.user.name=portal
+account.user.password=6APqvG4AU2rfLgCvMdySwQ==
+
+## Certificate Properties
+#server.ssl.key-store=classpath:widget-keystore.p12
+#server.ssl.key-store-password=ENC(DiIYnAMab4u7rEW2yKhF9zBL00uU55q8)
+#server.ssl.keyStoreType=PKCS12
+#server.ssl.keyAlias=widget-microservice
+
+## Jasypt Properties
+jasypt.encryptor.password=EncryptionKey \ No newline at end of file
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/resources/framework-template.js b/ecomp-portal-widget-ms/widget-ms/src/main/resources/framework-template.js
new file mode 100644
index 00000000..45350d91
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/resources/framework-template.js
@@ -0,0 +1,173 @@
+var ARUGMENT1 = (function(window, undefined) {
+
+ var ARUGMENT1 = ARUGMENT1 || {};
+ function extractHostPortApp(src) {
+ ARUGMENT1.microserviceId = MICROSERVICE_ID;
+ ARUGMENT1.pathArray = src.split( '/' );
+ ARUGMENT1.widgetName = ARUGMENT1.pathArray[ARUGMENT1.pathArray.length - 2];
+ ARUGMENT1.serviceSeperator = ARUGMENT1.pathArray[ARUGMENT1.pathArray.length - 4];
+ ARUGMENT1.commonUrl = src.substring(0, src.lastIndexOf("/" + ARUGMENT1.widgetName));
+ ARUGMENT1.recipientDivDataAttrib = 'data-' + ARUGMENT1.widgetName;
+ ARUGMENT1.controllerName = 'ARUGMENT2';
+ ARUGMENT1.readyCssFlag = 'ARUGMENT3';
+ ARUGMENT1.readyCssFlagExpectedValue = '#bada55';
+ ARUGMENT1.serviceURL = src.substring(0, src.lastIndexOf("/" + ARUGMENT1.serviceSeperator)) + '/portalApi/microservice/proxy/parameter/' + WIDGET_ID;
+ }
+
+ extractHostPortApp(document.currentScript.src);
+
+ function loadStylesheet(url) {
+ var link = document.createElement('link');
+ link.rel = 'stylesheet';
+ link.type = 'text/css';
+ link.href = url;
+ var entry = document.getElementsByTagName('script')[0];
+ entry.parentNode.insertBefore(link, entry);
+ }
+
+ function isCssReady(callback) {
+ var testElem = document.createElement('span');
+ testElem.id = ARUGMENT1.readyCssFlag;
+ testElem.style = 'CSS_ARG1';
+ var entry = document.getElementsByTagName('script')[0];
+ entry.parentNode.insertBefore(testElem, entry);
+
+ (function poll() {
+ var node = document.getElementById('css-ready');
+ var value;
+ if (window.getComputedStyle) {
+ value = document.defaultView.getComputedStyle(testElem, null)
+ .getPropertyValue('color');
+ }
+ else if (node.currentStyle) {
+ value = node.currentStyle.color;
+ }
+ if (value && value === 'rgb(186, 218, 85)' || value.toLowerCase() === ARUGMENT1.readyCssFlagExpectedValue) {
+ callback();
+ } else {
+ setTimeout(poll, 500);
+ }
+ })();
+ }
+
+ function injectCss(css) {
+ var style = document.createElement('style');
+ style.type = 'text/css';
+ css = css.replace(/\}/g, "}\n");
+
+ if (style.styleSheet) {
+ style.styleSheet.cssText = css;
+ } else {
+ style.appendChild(document.createTextNode(css));
+ }
+ var entry = document.getElementsByTagName('script')[0];
+ entry.parentNode.insertBefore(style, entry);
+ }
+
+ function loadScript(url, callback) {
+ var script = document.createElement('script');
+ script.src = url;
+ var entry = document.getElementsByTagName('script')[0];
+ entry.parentNode.insertBefore(script, entry);
+ script.onload = script.onreadystatechange = function() {
+ var rdyState = script.readyState;
+ if (!rdyState || /complete|loaded/.test(script.readyState)) {
+ callback();
+ script.onload = null;
+ script.onreadystatechange = null;
+ }
+ };
+ }
+
+ function loadSupportingFiles(callback) {
+ callback();
+ }
+
+ function getWidgetParams() {
+
+ }
+
+ function getWidgetData(widgetUrl, callback) {
+ var responseData;
+ try{
+ jQuery.ajax({
+ url: widgetUrl,
+ method: "GET",
+ xhrFields: {
+ withCredentials: true
+ },
+ crossDomain: true,
+ success: function (result) {
+ if (result.isOk == false){
+
+ }else{
+ callback(result);
+ }
+ }
+ });
+ }
+ catch(e){
+
+ }
+
+ }
+
+ function getMarkupContent(markupLocation, target){
+
+ jQuery.ajax({
+ url: markupLocation,
+ success: function (result) {
+ if (result.isOk == false){
+
+ }else{
+ target.innerHTML = result;
+ }
+ },
+ async: false
+ });
+ }
+
+ function renderWidget(data, location, $controllerProvider) {
+ var div = document.createElement('div');
+ getMarkupContent(ARUGMENT1.commonUrl + "/markup/" + ARUGMENT1.widgetName, div);
+ location.append(div);
+ ARUGMENT1.widgetData = data;
+ app.controllerProvider.register(ARUGMENT1.controllerName, ARUGMENT1.controller);
+ var mController = angular.element(document.getElementById("widgets"));
+ mController.scope().activateThis(location);
+ }
+
+ function printAllArtifacts(moduleName, controllerName) {
+ var queue = angular.module(moduleName)._invokeQueue;
+ for(var i=0;i<queue.length;i++) {
+ var call = queue[i];
+ console.log(i + '. ' + call[0] + ' - ' + call[1] + ' - ' + call[2][0]);
+ }
+ }
+
+ function get(name){
+ if(name=(new RegExp('[?&]'+encodeURIComponent(name)+'=([^&]*)')).exec(location.search))
+ return decodeURIComponent(name[1]);
+ }
+
+ loadSupportingFiles(function() {
+ loadStylesheet(ARUGMENT1.commonUrl + '/' + ARUGMENT1.widgetName + '/style.css');
+ loadScript(ARUGMENT1.commonUrl + '/' + ARUGMENT1.widgetName + '/controller.js',
+ function() {
+ $('['+ ARUGMENT1.recipientDivDataAttrib + ']').each(function() {
+ var location = jQuery(this);
+ location.removeAttr(ARUGMENT1.recipientDivDataAttrib);
+ var id = location.attr(ARUGMENT1.recipientDivDataAttrib);
+ getWidgetData(ARUGMENT1.serviceURL, function(data) {
+ isCssReady(function(){
+ renderWidget(data, location);
+ });
+ });
+ });
+ }
+ );
+ });
+
+ return ARUGMENT1;
+})(window);
+ \ No newline at end of file
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/resources/logback.xml b/ecomp-portal-widget-ms/widget-ms/src/main/resources/logback.xml
new file mode 100644
index 00000000..204a6598
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/resources/logback.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+ <property name="WIDGET_LOG_HOME" value="logs" />
+
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <Pattern>
+ %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
+ </Pattern>
+ </layout>
+ </appender>
+
+ <logger name="org.springframework.web" level="info" additivity="false">
+ <appender-ref ref="STDOUT" />
+ </logger>
+
+ <contextName>${HOSTNAME}</contextName>
+
+
+ <appender name="ADUIT"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${WIDGET_LOG_HOME}/aduit.log</file>
+ <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+ <Pattern>
+ %date{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%X{RequestId}|%logger{0}|%-5level|%contextName| %msg%n"
+ </Pattern>
+ </encoder>
+ <!-- %d{yyyy-MM-dd HH:mm:ss} - %msg%n -->
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${WIDGET_LOG_HOME}/archived/aduit.%d{yyyy-MM-dd}.%i.zip
+ </fileNamePattern>
+ <maxHistory>30</maxHistory>
+ <timeBasedFileNamingAndTriggeringPolicy
+ class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+ <maxFileSize>100KB</maxFileSize>
+ </timeBasedFileNamingAndTriggeringPolicy>
+ </rollingPolicy>
+ </appender>
+
+ <appender name="APPLICATION"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${WIDGET_LOG_HOME}/application.log</file>
+ <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+ <Pattern>
+ %date{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%X{RequestId}|%logger{0}|%-5level|%contextName| %msg%n"
+ </Pattern>
+ </encoder>
+ <!-- %d{yyyy-MM-dd HH:mm:ss} - %msg%n -->
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${WIDGET_LOG_HOME}/archived/application.%d{yyyy-MM-dd}.%i.zip
+ </fileNamePattern>
+ <maxHistory>30</maxHistory>
+ <timeBasedFileNamingAndTriggeringPolicy
+ class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+ <maxFileSize>100KB</maxFileSize>
+ </timeBasedFileNamingAndTriggeringPolicy>
+ </rollingPolicy>
+ </appender>
+
+
+ <appender name="DEBUG"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${WIDGET_LOG_HOME}/debug.log</file>
+ <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+ <Pattern>
+ %date{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%X{RequestId}|%logger{0}|%-5level|%contextName| %msg%n"
+ </Pattern>
+ </encoder>
+ <!-- %d{yyyy-MM-dd HH:mm:ss} - %msg%n -->
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${WIDGET_LOG_HOME}/archived/debug.%d{yyyy-MM-dd}.%i.zip
+ </fileNamePattern>
+ <maxHistory>30</maxHistory>
+ <timeBasedFileNamingAndTriggeringPolicy
+ class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+ <maxFileSize>100KB</maxFileSize>
+ </timeBasedFileNamingAndTriggeringPolicy>
+ </rollingPolicy>
+ </appender>
+
+
+ <appender name="ERROR"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${WIDGET_LOG_HOME}/error.log</file>
+ <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+ <Pattern>
+ %date{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%X{RequestId}|%logger{0}|%-5level|%contextName| %msg%n"
+ </Pattern>
+ </encoder>
+
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${WIDGET_LOG_HOME}/archived/error.%d{yyyy-MM-dd}.%i.zip
+ </fileNamePattern>
+ <maxHistory>30</maxHistory>
+ <timeBasedFileNamingAndTriggeringPolicy
+ class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+ <maxFileSize>100KB</maxFileSize>
+ </timeBasedFileNamingAndTriggeringPolicy>
+ </rollingPolicy>
+ </appender>
+
+
+ <appender name="METRICS"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${WIDGET_LOG_HOME}/metrics.log</file>
+ <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+ <Pattern>
+ %date{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%X{RequestId}|%logger{0}|%-5level|%contextName| %msg%n"
+ </Pattern>
+ </encoder>
+
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${WIDGET_LOG_HOME}/archived/metrics.%d{yyyy-MM-dd}.%i.zip
+ </fileNamePattern>
+ <maxHistory>30</maxHistory>
+ <timeBasedFileNamingAndTriggeringPolicy
+ class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+ <maxFileSize>100KB</maxFileSize>
+ </timeBasedFileNamingAndTriggeringPolicy>
+ </rollingPolicy>
+ </appender>
+
+ <logger name="org.openecomp.portalapp.widget" level="debug" additivity="false">
+ <appender-ref ref="ERROR" />
+ <appender-ref ref="DEBUG" />
+ <appender-ref ref="APPLICATION" />
+ <appender-ref ref="STDOUT" />
+ </logger>
+
+ <root level="info">
+ <appender-ref ref="DEBUG" />
+ <appender-ref ref="APPLICATION" />
+ <appender-ref ref="STDOUT" />
+ </root>
+
+</configuration> \ No newline at end of file
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/resources/templates/Upload.html b/ecomp-portal-widget-ms/widget-ms/src/main/resources/templates/Upload.html
new file mode 100644
index 00000000..a5e7c632
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/resources/templates/Upload.html
@@ -0,0 +1,17 @@
+<html>
+<body>
+ <div align="center">
+ <form method="post" action="doUpload/widget-resources" enctype="multipart/form-data">
+ <table border="0">
+ <tr>
+ <td>Pick file:</td>
+ <td><input type="file" name="fileUpload" size="50" /></td>
+ </tr>
+ <tr>
+ <td colspan="2" align="center"><input type="submit" value="Upload" /></td>
+ </tr>
+ </table>
+ </form>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/resources/templates/widgetsPage.html b/ecomp-portal-widget-ms/widget-ms/src/main/resources/templates/widgetsPage.html
new file mode 100644
index 00000000..440f64ca
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/resources/templates/widgetsPage.html
@@ -0,0 +1,15 @@
+<html xmlns:th="http://www.thymeleaf.org">
+<body>
+
+ <p> Uploaded Widgets: </p>
+
+ <div>
+ <ul>
+ <li th:each="file : ${files}">
+ <a th:href="${file}" th:text="${file}" />
+ </li>
+ </ul>
+ </div>
+
+</body>
+</html>
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/resources/widget-keystore.p12 b/ecomp-portal-widget-ms/widget-ms/src/main/resources/widget-keystore.p12
new file mode 100644
index 00000000..b2dd42ff
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/resources/widget-keystore.p12
Binary files differ
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/resources/widget_ms_start.sh b/ecomp-portal-widget-ms/widget-ms/src/main/resources/widget_ms_start.sh
new file mode 100755
index 00000000..8405fe99
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/resources/widget_ms_start.sh
@@ -0,0 +1,4 @@
+APP_PROPERTY_LOCATION=/tmp/application.properties
+echo "Starting ecomp-portal-widget-ms image in a new container !!!"
+docker run -d --name "ecomp-portal-widget-ms" -p 8083:8082 -v $APP_PROPERTY_LOCATION:/application.properties ecompportal-widget-ms
+
diff --git a/ecomp-portal-widget-ms/widget-ms/src/main/resources/widget_ms_stop.sh b/ecomp-portal-widget-ms/widget-ms/src/main/resources/widget_ms_stop.sh
new file mode 100755
index 00000000..8c9abf56
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/main/resources/widget_ms_stop.sh
@@ -0,0 +1,5 @@
+echo "Stopping ecomp-portal-widget-ms container !!!"
+docker stop ecomp-portal-widget-ms
+echo "Removing docker image portal-widget-ms !!!"
+docker rm ecomp-portal-widget-ms
+
diff --git a/ecomp-portal-widget-ms/widget-ms/src/test/java/org/openecomp/portalapp/widget/test/controller/WidgetFileControllerTest.java b/ecomp-portal-widget-ms/widget-ms/src/test/java/org/openecomp/portalapp/widget/test/controller/WidgetFileControllerTest.java
new file mode 100644
index 00000000..2045435c
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/test/java/org/openecomp/portalapp/widget/test/controller/WidgetFileControllerTest.java
@@ -0,0 +1,74 @@
+package org.openecomp.portalapp.widget.test.controller;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.times;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.openecomp.portalapp.widget.controller.DatabaseFileUploadController;
+import org.openecomp.portalapp.widget.service.impl.StorageServiceImpl;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+
+@RunWith(MockitoJUnitRunner.class)
+public class WidgetFileControllerTest {
+ private MockMvc mockMvc;
+
+ @Mock
+ private StorageServiceImpl storageService;
+
+ @InjectMocks
+ private DatabaseFileUploadController controller;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
+ }
+
+ @Test
+ public void getWidgetMarkup_NoError() throws Exception{
+ ArgumentCaptor<Long> storageServiceArg = ArgumentCaptor.forClass(Long.class);
+ Long widgetId = new Long(1);
+ mockMvc.perform(MockMvcRequestBuilders.get("/microservices/markup/" + widgetId)).andReturn();;
+ Mockito.verify(storageService, times(1)).getWidgetMarkup(storageServiceArg.capture());
+ assertEquals(storageServiceArg.getValue(), widgetId);
+ }
+
+ @Test
+ public void getWidgetController_NoError() throws Exception{
+ ArgumentCaptor<Long> storageServiceArg = ArgumentCaptor.forClass(Long.class);
+ Long widgetId = new Long(1);
+ mockMvc.perform(MockMvcRequestBuilders.get("/microservices/" + widgetId + "/controller.js")).andReturn();;
+ Mockito.verify(storageService, times(1)).getWidgetController(storageServiceArg.capture());
+ assertEquals(storageServiceArg.getValue(), widgetId);
+ }
+
+ @Test
+ public void getWidgetFramework_NoError() throws Exception{
+ ArgumentCaptor<Long> storageServiceArg = ArgumentCaptor.forClass(Long.class);
+ Long widgetId = new Long(1);
+ mockMvc.perform(MockMvcRequestBuilders.get("/microservices/" + widgetId + "/framework.js")).andReturn();;
+ Mockito.verify(storageService, times(1)).getWidgetFramework(storageServiceArg.capture());
+ assertEquals(storageServiceArg.getValue(), widgetId);
+ }
+
+ @Test
+ public void getWidgetCSS_NoError() throws Exception{
+ ArgumentCaptor<Long> storageServiceArg = ArgumentCaptor.forClass(Long.class);
+ Long widgetId = new Long(1);
+ mockMvc.perform(MockMvcRequestBuilders.get("/microservices/" + widgetId + "/styles.css")).andReturn();;
+ Mockito.verify(storageService, times(1)).getWidgetCSS(storageServiceArg.capture());
+ assertEquals(storageServiceArg.getValue(), widgetId);
+ }
+
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/test/java/org/openecomp/portalapp/widget/test/controller/WidgetsCatalogControllerTest.java b/ecomp-portal-widget-ms/widget-ms/src/test/java/org/openecomp/portalapp/widget/test/controller/WidgetsCatalogControllerTest.java
new file mode 100644
index 00000000..bd7eba3a
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/test/java/org/openecomp/portalapp/widget/test/controller/WidgetsCatalogControllerTest.java
@@ -0,0 +1,195 @@
+package org.openecomp.portalapp.widget.test.controller;
+
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.times;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.codec.binary.Base64;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.openecomp.portalapp.widget.controller.WidgetsCatalogController;
+import org.openecomp.portalapp.widget.domain.ValidationRespond;
+import org.openecomp.portalapp.widget.domain.WidgetCatalog;
+import org.openecomp.portalapp.widget.service.StorageService;
+import org.openecomp.portalapp.widget.service.WidgetCatalogService;
+import org.springframework.http.MediaType;
+import org.springframework.test.util.ReflectionTestUtils;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.multipart.MultipartFile;
+
+@RunWith(MockitoJUnitRunner.class)
+public class WidgetsCatalogControllerTest {
+
+ private MockMvc mockMvc;
+
+ @Mock
+ private WidgetCatalogService widgetService;
+
+ @Mock
+ private StorageService storageService;
+
+ @InjectMocks
+ private WidgetsCatalogController controller;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
+ }
+
+ @Test
+ public void getWidgetCatalog_ValidAuthorization_NoError() throws Exception {
+ List<WidgetCatalog> list = new ArrayList<WidgetCatalog>();
+ WidgetCatalog widget = new WidgetCatalog();
+ widget.setId(1);
+ widget.setName("junit");
+ list.add(widget);
+ Mockito.when(widgetService.getWidgetCatalog()).thenReturn(list);
+
+ String security_user = "user";
+ String security_pass = "password";
+
+ ReflectionTestUtils.setField(controller, "security_user", security_user, String.class);
+ ReflectionTestUtils.setField(controller, "security_pass", security_pass, String.class);
+
+ String basic_auth = "Basic " + new String(Base64.encodeBase64((security_user + ":" + security_pass).getBytes()));
+ mockMvc.perform(get("/microservices/widgetCatalog/").header("Authorization", basic_auth))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$[0].id", is(1)))
+ .andExpect(jsonPath("$[0].name", is("junit")));
+ }
+
+ @Test
+ public void getWidgetCatalog_InValidAuthorization_Unauthorized() throws Exception {
+
+ String security_user = "user";
+ String security_pass = "password";
+ String wrong_pass = "wrong";
+
+ ReflectionTestUtils.setField(controller, "security_user", security_user, String.class);
+ ReflectionTestUtils.setField(controller, "security_pass", security_pass, String.class);
+
+ String basic_auth = "Basic " + new String(Base64.encodeBase64((security_user + ":" + wrong_pass).getBytes()));
+ mockMvc.perform(get("/microservices/widgetCatalog/").header("Authorization", basic_auth))
+ .andExpect(status().isUnauthorized());
+ }
+
+ @Test
+ public void getWidgetCatalog_NoAuthorization_BadRequest() throws Exception {
+ List<WidgetCatalog> list = new ArrayList<WidgetCatalog>();
+ WidgetCatalog widget = new WidgetCatalog();
+ list.add(widget);
+ Mockito.when(widgetService.getWidgetCatalog()).thenReturn(list);
+
+ mockMvc.perform(get("/microservices/widgetCatalog/"))
+ .andExpect(status().isBadRequest());
+ }
+
+
+ @Test
+ public void saveWidgetCatalog_ValidAuthorization_NoError() throws Exception {
+ ValidationRespond respond = new ValidationRespond(true, null);
+ Mockito.when(storageService.checkZipFile(any(MultipartFile.class))).thenReturn(respond);
+
+ String security_user = "user";
+ String security_pass = "password";
+
+ ReflectionTestUtils.setField(controller, "security_user", security_user, String.class);
+ ReflectionTestUtils.setField(controller, "security_pass", security_pass, String.class);
+
+ String basic_auth = "Basic " + new String(Base64.encodeBase64((security_user + ":" + security_pass).getBytes()));
+ mockMvc.perform(MockMvcRequestBuilders.fileUpload("/microservices/widgetCatalog/").file("file", null)
+ .param("widget", "{}")
+ .header("Authorization", basic_auth)
+ .contentType(MediaType.MULTIPART_FORM_DATA))
+ .andExpect(jsonPath("$.valid", is(true)));
+
+ Mockito.verify(widgetService, times(1)).saveWidgetCatalog(any(WidgetCatalog.class));
+ }
+
+
+ @Test
+ public void updateWidgetCatalog_ValidAuthorization_NoError() throws Exception {
+ String security_user = "user";
+ String security_pass = "password";
+ Long widgetId = new Long(1);
+ ArgumentCaptor<Long> widgetServiceArg = ArgumentCaptor.forClass(Long.class);
+
+ ReflectionTestUtils.setField(controller, "security_user", security_user, String.class);
+ ReflectionTestUtils.setField(controller, "security_pass", security_pass, String.class);
+
+ String basic_auth = "Basic " + new String(Base64.encodeBase64((security_user + ":" + security_pass).getBytes()));
+ mockMvc.perform(put("/microservices/widgetCatalog/" + widgetId).contentType(MediaType.APPLICATION_JSON).content("{}").header("Authorization", basic_auth));
+
+ Mockito.verify(widgetService, times(1)).updateWidgetCatalog(widgetServiceArg.capture(), any(WidgetCatalog.class));
+ assertEquals(widgetServiceArg.getValue(), widgetId);
+ }
+
+
+ @Test
+ public void updateWidgetCatalogwithFiles_ValidAuthorization_NoError() throws Exception {
+ ValidationRespond respond = new ValidationRespond(true, null);
+ Mockito.when(storageService.checkZipFile(any(MultipartFile.class))).thenReturn(respond);
+
+ String security_user = "user";
+ String security_pass = "password";
+ Long widgetId = new Long(1);
+ ArgumentCaptor<Long> widgetServiceArg = ArgumentCaptor.forClass(Long.class);
+ ArgumentCaptor<Long> storageServiceArg = ArgumentCaptor.forClass(Long.class);
+
+ ReflectionTestUtils.setField(controller, "security_user", security_user, String.class);
+ ReflectionTestUtils.setField(controller, "security_pass", security_pass, String.class);
+
+ String basic_auth = "Basic " + new String(Base64.encodeBase64((security_user + ":" + security_pass).getBytes()));
+ mockMvc.perform(MockMvcRequestBuilders.fileUpload("/microservices/widgetCatalog/" + widgetId).file("file", null)
+ .param("widget", "{}")
+ .header("Authorization", basic_auth)
+ .contentType(MediaType.MULTIPART_FORM_DATA))
+ .andExpect(jsonPath("$.valid", is(true)));
+
+ Mockito.verify(widgetService, times(1)).updateWidgetCatalog(widgetServiceArg.capture(), any(WidgetCatalog.class));
+ assertEquals(widgetServiceArg.getValue(), widgetId);
+ }
+
+ @Test
+ public void deleteOnboardingWidget_ValidAuthorization_NoError() throws Exception {
+
+ String security_user = "user";
+ String security_pass = "password";
+ Long widgetId = new Long(1);
+
+ ReflectionTestUtils.setField(controller, "security_user", security_user, String.class);
+ ReflectionTestUtils.setField(controller, "security_pass", security_pass, String.class);
+
+ String basic_auth = "Basic " + new String(Base64.encodeBase64((security_user + ":" + security_pass).getBytes()));
+ mockMvc.perform(MockMvcRequestBuilders.delete("/microservices/widgetCatalog/" + widgetId)
+ .header("Authorization", basic_auth));
+ ArgumentCaptor<Long> widgetServiceArg = ArgumentCaptor.forClass(Long.class);
+ ArgumentCaptor<Long> storageServiceArg = ArgumentCaptor.forClass(Long.class);
+
+ Mockito.verify(widgetService, times(1)).deleteWidgetCatalog(widgetServiceArg.capture());
+ assertEquals(widgetServiceArg.getValue(), widgetId);
+ Mockito.verify(storageService, times(1)).deleteWidgetFile(storageServiceArg.capture());
+ assertEquals(storageServiceArg.getValue(), widgetId);
+ }
+
+
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/src/test/java/org/openecomp/portalapp/widget/test/service/WidgetCatalogServiceTest.java b/ecomp-portal-widget-ms/widget-ms/src/test/java/org/openecomp/portalapp/widget/test/service/WidgetCatalogServiceTest.java
new file mode 100644
index 00000000..3def6062
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/src/test/java/org/openecomp/portalapp/widget/test/service/WidgetCatalogServiceTest.java
@@ -0,0 +1,124 @@
+package org.openecomp.portalapp.widget.test.service;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.hibernate.Criteria;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.openecomp.portalapp.widget.domain.RoleApp;
+import org.openecomp.portalapp.widget.domain.WidgetCatalog;
+import org.openecomp.portalapp.widget.service.impl.WidgetCatalogServiceImpl;
+
+
+@RunWith(MockitoJUnitRunner.class)
+public class WidgetCatalogServiceTest {
+
+ @Mock
+ private SessionFactory mockedSessionFactory;
+
+ @InjectMocks
+ private WidgetCatalogServiceImpl widgetCatalogService;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void getWidgetCatalog_NoError() throws Exception{
+ Session mockedSession = Mockito.mock(Session.class);
+ Criteria mockedCriteria = Mockito.mock(Criteria.class);
+
+ List<WidgetCatalog> list = new ArrayList<WidgetCatalog>();
+ WidgetCatalog widget = new WidgetCatalog();
+ widget.setId(1);
+ widget.setName("junit");
+ list.add(widget);
+
+ Mockito.when(mockedSessionFactory.getCurrentSession()).thenReturn(mockedSession);
+ Mockito.when(mockedSession.createCriteria(WidgetCatalog.class)).thenReturn(mockedCriteria);
+ Mockito.when(mockedCriteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)).thenReturn(mockedCriteria);
+ Mockito.when(mockedCriteria.list()).thenReturn(list);
+
+ List<WidgetCatalog> result = widgetCatalogService.getWidgetCatalog();
+ assertNotNull(result);
+ assertEquals(result, list);
+ }
+
+
+ @Test
+ public void saveWidgetCatalog_NoError() throws Exception{
+ Set<RoleApp> set = new HashSet<RoleApp>();
+ WidgetCatalog widget = new WidgetCatalog();
+ widget.setId(1);
+ widget.setName("junit");
+ widget.setAllowAllUser("1");
+ widget.setWidgetRoles(set);
+
+ Session mockedSession = Mockito.mock(Session.class);
+ Transaction mockedTransaction = Mockito.mock(Transaction.class);
+ Mockito.when(mockedSessionFactory.openSession()).thenReturn(mockedSession);
+ Mockito.when(mockedSession.beginTransaction()).thenReturn(mockedTransaction);
+ long widgetId = widgetCatalogService.saveWidgetCatalog(widget);
+ assertNotNull(widgetId);
+ assertEquals(widgetId, 1);
+ }
+
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+
+ @Test
+ public void deleteWidgetCatalog_NoError() throws Exception{
+ long widgetId =1 ;
+ WidgetCatalog widget = new WidgetCatalog();
+ widget.setId(1);
+ widget.setName("junit");
+
+ Session mockedSession = Mockito.mock(Session.class, RETURNS_DEEP_STUBS);
+ Transaction mockedTransaction = Mockito.mock(Transaction.class);
+
+ Mockito.when(mockedSessionFactory.getCurrentSession()).thenReturn(mockedSession);
+ Mockito.when(mockedSession.beginTransaction()).thenReturn(mockedTransaction);
+ Mockito.when(mockedSession.get(WidgetCatalog.class, widgetId)).thenReturn(widget);
+
+ widgetCatalogService.deleteWidgetCatalog(widgetId);
+ }
+
+ @Test
+ public void updateWidgetCatalog_NoError() throws Exception{
+ long widgetId =1 ;
+ WidgetCatalog widget = new WidgetCatalog();
+ widget.setId(1);
+ widget.setName("junit");
+
+ Session mockedSession = Mockito.mock(Session.class, RETURNS_DEEP_STUBS);
+ Transaction mockedTransaction = Mockito.mock(Transaction.class);
+
+ Mockito.when(mockedSessionFactory.getCurrentSession()).thenReturn(mockedSession);
+ Mockito.when(mockedSession.beginTransaction()).thenReturn(mockedTransaction);
+ Mockito.when(mockedSession.get(WidgetCatalog.class, widgetId)).thenReturn(widget);
+
+ widgetCatalogService.deleteWidgetCatalog(widgetId);
+ }
+
+
+}
diff --git a/ecomp-portal-widget-ms/widget-ms/testadd.txt b/ecomp-portal-widget-ms/widget-ms/testadd.txt
new file mode 100644
index 00000000..bdf08de0
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/testadd.txt
@@ -0,0 +1 @@
+test file \ No newline at end of file
diff --git a/ecomp-portal-widget-ms/widget-ms/website.url b/ecomp-portal-widget-ms/widget-ms/website.url
new file mode 100644
index 00000000..4b50369c
--- /dev/null
+++ b/ecomp-portal-widget-ms/widget-ms/website.url
Binary files differ