/*
* Copyright (c) Bosch Software Innovations GmbH 2015.
* Part of the SW360 Portal Project.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.sw360.portal.portlets.projects;
/**
* Created by andreas.reichel@tngtech.com on 19.11.15.
*/
import com.fasterxml.jackson.core.JsonProcessingException;
import com.liferay.portal.kernel.json.JSONArray;
import com.liferay.portal.kernel.json.JSONFactoryUtil;
import com.liferay.portal.kernel.json.JSONObject;
import org.eclipse.sw360.datahandler.thrift.RequestStatus;
import org.eclipse.sw360.datahandler.thrift.ThriftClients;
import org.eclipse.sw360.datahandler.thrift.projects.Project;
import org.eclipse.sw360.datahandler.thrift.bdpimport.BdpImportService;
import org.eclipse.sw360.datahandler.thrift.bdpimport.RemoteCredentials;
import org.eclipse.sw360.datahandler.thrift.importstatus.ImportStatus;
import org.eclipse.sw360.datahandler.thrift.users.User;
import org.eclipse.sw360.portal.common.PortalConstants;
import org.eclipse.sw360.portal.portlets.Sw360Portlet;
import org.eclipse.sw360.portal.users.UserCacheHolder;
import org.apache.log4j.Logger;
import org.apache.thrift.TException;
import javax.portlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.base.Strings.nullToEmpty;
public class ProjectImportPortlet extends Sw360Portlet {
private static final Logger log = Logger.getLogger(ProjectImportPortlet.class);
private static BdpImportService.Iface bdpImportClient = new ThriftClients().makeBdpImportClient();
static class LoginState {
private Boolean loggedIn;
private String loggedInServerUrl;
public LoginState() {
loggedIn = false;
loggedInServerUrl = "";
}
public void login(String serverUrl) {
loggedIn = true;
loggedInServerUrl = serverUrl;
}
public void logout() {
loggedIn = false;
loggedInServerUrl = "";
}
public String getServerUrl() {
return loggedInServerUrl;
}
boolean isLoggedIn() {
return loggedIn;
}
}
private RemoteCredentials getRemoteCredentialsFromSession(PortletSession session) {
String dbUserName = (String) session.getAttribute(PortalConstants.SESSION_IMPORT_USER);
String dbUserPass = (String) session.getAttribute(PortalConstants.SESSION_IMPORT_PASS);
String dbUrl = (String) session.getAttribute(PortalConstants.SESSION_IMPORT_URL);
return new RemoteCredentials()
.setPassword(dbUserPass)
.setUsername(dbUserName)
.setServerUrl(dbUrl);
}
private void putRemoteCredentialsIntoSession(PortletSession session, RemoteCredentials remoteCredentials) {
session.setAttribute(PortalConstants.SESSION_IMPORT_USER, nullToEmpty(remoteCredentials.getUsername()));
session.setAttribute(PortalConstants.SESSION_IMPORT_PASS, nullToEmpty(remoteCredentials.getPassword()));
session.setAttribute(PortalConstants.SESSION_IMPORT_URL, nullToEmpty(remoteCredentials.getServerUrl()));
}
@Override
public void doView(RenderRequest request, RenderResponse response) throws IOException, PortletException {
List<Project> importables = new ArrayList<>();
Boolean loggedIn = false;
String loggedInServer = "";
RemoteCredentials reCred = getRemoteCredentialsFromSession(request.getPortletSession());
if (!nullToEmpty(reCred.getServerUrl()).isEmpty()) {
importables = loadImportables(reCred);
loggedIn = true;
loggedInServer = reCred.getServerUrl();
}
String idName = getIdName();
request.setAttribute("idName", idName);
request.setAttribute("importables", importables);
request.setAttribute("loggedIn", loggedIn);
request.setAttribute("loggedInServer", loggedInServer);
super.doView(request, response);
}
private List<String> getProjectIdsForImport(PortletRequest request) throws PortletException, IOException {
String[] checked = request.getParameterValues("checked[]");
List<String> checkedIds = new ArrayList<>();
if (checked != null) {
for (String s : checked) {
checkedIds.add(s.substring(PortalConstants.CHECKED_PROJECT.length()));
}
}
return checkedIds;
}
private boolean isImportSuccessful(ImportStatus importStatus) {
return (importStatus.isSetRequestStatus() && importStatus.getRequestStatus().equals(RequestStatus.SUCCESS) && importStatus.getFailedIds().isEmpty());
}
private ImportStatus importDatasources(List<String> toImport, User user, RemoteCredentials remoteCredentials) {
ImportStatus importStatus = new ImportStatus();
try {
importStatus = bdpImportClient.importDatasources(toImport, user, remoteCredentials);
if (!isImportSuccessful(importStatus)) {
if(importStatus.getRequestStatus().equals(RequestStatus.FAILURE)){
log.error("Importing of data sources failed.");
} else {
log.error("Importing has not succeeded for the following IDs: " + importStatus.getFailedIds().toString());
}
}
} catch (TException e) {
log.error("ImportDatasources: Exception ".concat(e.getMessage()));
}
return importStatus;
}
private List<Project> loadImportables(RemoteCredentials remoteCredentials) {
List<Project> importable;
try {
importable = bdpImportClient.loadImportables(remoteCredentials);
} catch (TException e) {
log.error("Thrift failed, (uncaught TException)", e);
importable = new ArrayList<>();
}
return importable;
}
private String getIdName(){
try{
return bdpImportClient.getIdName();
} catch (TException e) {
log.error("Thrift failed, (uncaught TException)", e);
return "";
}
}
@Override
public void serveResource(ResourceRequest request, ResourceResponse response) throws IOException, PortletException {
LoginState loginState = new LoginState();
String requestedAction = request.getParameter(PortalConstants.IMPORT_USER_ACTION);
JSONObject responseData = handleRequestedAjaxAction(requestedAction, request, response, loginState);
PrintWriter writer = response.getWriter();
writer.write(responseData.toString());
}
public JSONObject handleRequestedAjaxAction(String requestedAction, ResourceRequest request, ResourceResponse response, LoginState loginState) throws IOException, PortletException {
PortletSession session = request.getPortletSession();
RemoteCredentials remoteCredentials = getRemoteCredentialsFromSession(session);
JSONObject responseData = JSONFactoryUtil.createJSONObject();
switch(requestedAction) {
case PortalConstants.IMPORT_USER_ACTION__IMPORTBDP:
User user = UserCacheHolder.getUserFromRequest(request);
List<String> selectedIds = getProjectIdsForImport(request);
importBdpProjects(user, selectedIds, responseData, remoteCredentials);
break;
case PortalConstants.IMPORT_USER_ACTION__NEWIMPORTSOURCE:
RemoteCredentials newCredentials = new RemoteCredentials()
.setUsername(request.getParameter(PortalConstants.SESSION_IMPORT_USER))
.setPassword(request.getParameter(PortalConstants.SESSION_IMPORT_PASS))
.setServerUrl(request.getParameter(PortalConstants.SESSION_IMPORT_URL));
if (!validateCredentials(newCredentials)){
responseData.put(PortalConstants.IMPORT_RESPONSE__STATUS,
PortalConstants.IMPORT_RESPONSE__UNAUTHORIZED);
} else {
setNewImportSource(newCredentials, session, responseData, loginState);
}
break;
case PortalConstants.IMPORT_USER_ACTION__UPDATEIMPORTABLES:
updateImportables(responseData, loginState, remoteCredentials);
break;
case PortalConstants.IMPORT_USER_ACTION__DISCONNECT:
putRemoteCredentialsIntoSession(session, new RemoteCredentials());
loginState.logout();
break;
default:
loginState.logout();
break;
}
return responseData;
}
private boolean validateCredentials(RemoteCredentials credentials) {
try {
return bdpImportClient.validateCredentials(credentials);
} catch (TException e) {
log.error("Thrift failed, (uncaught TException)", e);
return false;
}
}
private void importBdpProjects(User user, List<String> selectedIds, JSONObject responseData, RemoteCredentials remoteCredentials) throws PortletException, IOException {
ImportStatus importStatus = importDatasources(selectedIds, user, remoteCredentials);
JSONArray jsonFailedIds = JSONFactoryUtil.createJSONArray();
JSONArray jsonSuccessfulIds = JSONFactoryUtil.createJSONArray();
if(importStatus.isSetRequestStatus() && importStatus.getRequestStatus().equals(RequestStatus.SUCCESS)) {
importStatus.getFailedIds().forEach(id -> jsonFailedIds.put(id));
importStatus.getSuccessfulIds().forEach(id -> jsonSuccessfulIds.put(id));
responseData.put(PortalConstants.IMPORT_RESPONSE__FAILED_IDS, jsonFailedIds);
responseData.put(PortalConstants.IMPORT_RESPONSE__SUCCESSFUL_IDS, jsonSuccessfulIds);
}
if (isImportSuccessful(importStatus)) {
responseData.put(PortalConstants.IMPORT_RESPONSE__STATUS, PortalConstants.IMPORT_RESPONSE__IMPORT_BDP_SUCCESS);
} else if (importStatus.isSetRequestStatus() && importStatus.getRequestStatus().equals(RequestStatus.SUCCESS)) {
responseData.put(PortalConstants.IMPORT_RESPONSE__STATUS, PortalConstants.IMPORT_RESPONSE__IMPORT_BDP_FAILURE);
} else {
responseData.put(PortalConstants.IMPORT_RESPONSE__STATUS, PortalConstants.IMPORT_RESPONSE__IMPORT_BDP_GENERAL_FAILURE);
}
}
void setNewImportSource(RemoteCredentials newCredentials, PortletSession session, JSONObject responseData, LoginState loginState) {
String serverUrl = nullToEmpty(newCredentials.getServerUrl());
if (serverUrl.isEmpty()) {
loginState.logout();
responseData.put(PortalConstants.IMPORT_RESPONSE__STATUS,
PortalConstants.IMPORT_RESPONSE__DB_URL_NOTSET);
} else {
putRemoteCredentialsIntoSession(session, newCredentials);
responseData.put(PortalConstants.IMPORT_RESPONSE__STATUS,
PortalConstants.IMPORT_RESPONSE__DB_CHANGED);
responseData.put(PortalConstants.IMPORT_RESPONSE__DBURL, serverUrl);
loginState.login(serverUrl);
}
}
private void updateImportables(JSONObject responseData, LoginState loginState, RemoteCredentials remoteCredentials) throws JsonProcessingException {
if (!nullToEmpty(remoteCredentials.getServerUrl()).isEmpty()) {
List<Project> importables = loadImportables(remoteCredentials);
JSONArray serializedProjects = JSONFactoryUtil.createJSONArray();
for (Project p : importables) {
JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
if (p.isSetExternalIds() && ! isNullOrEmpty(p.getExternalIds().get(getIdName())))
jsonObject.put("externalId", p.getExternalIds().get(getIdName()));
jsonObject.put("name", p.getName());
serializedProjects.put(jsonObject.toString());
}
responseData.put(PortalConstants.IMPORT_RESPONSE__NEW_IMPORTABLES, serializedProjects);
}
responseData.put(PortalConstants.IMPORT_RESPONSE__DBURL, remoteCredentials.getServerUrl());
loginState.login(remoteCredentials.getServerUrl());
}
}