/* * Copyright Siemens AG, 2013-2016. Part of the SW360 Portal Project. * With contributions by Bosch Software Innovations GmbH, 2016. * * 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.licenses; import com.google.common.base.Strings; import com.google.common.collect.ImmutableSet; import com.liferay.portal.kernel.portlet.PortletResponseUtil; import com.liferay.portal.kernel.servlet.SessionMessages; import org.eclipse.sw360.datahandler.common.CommonUtils; import org.eclipse.sw360.datahandler.permissions.PermissionUtils; import org.eclipse.sw360.datahandler.thrift.RequestStatus; import org.eclipse.sw360.datahandler.thrift.SW360Exception; import org.eclipse.sw360.datahandler.thrift.licenses.*; import org.eclipse.sw360.datahandler.thrift.users.User; import org.eclipse.sw360.datahandler.thrift.users.UserGroup; import org.eclipse.sw360.exporter.LicenseExporter; import org.eclipse.sw360.portal.common.ErrorMessages; import org.eclipse.sw360.portal.common.PortalConstants; import org.eclipse.sw360.portal.common.UsedAsLiferayAction; 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 java.io.IOException; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; import static com.google.common.base.Strings.isNullOrEmpty; import static org.eclipse.sw360.datahandler.common.CommonUtils.TMP_TODO_ID_PREFIX; import static org.eclipse.sw360.datahandler.common.CommonUtils.nullToEmptyList; import static org.eclipse.sw360.datahandler.common.SW360Constants.CONTENT_TYPE_OPENXML_SPREADSHEET; import static org.eclipse.sw360.portal.common.PortalConstants.*; /** * License portlet implementation * * @author cedric.bodet@tngtech.com */ public class LicensesPortlet extends Sw360Portlet { private static final Logger log = Logger.getLogger(LicensesPortlet.class); /** * Excel exporter */ private final LicenseExporter exporter; private List<LicenseType> licenseTypes; public LicensesPortlet() throws TException { Function<Logger,List<LicenseType>> getLicenseTypes = log -> { LicenseService.Iface client = thriftClients.makeLicenseClient(); try { return client.getLicenseTypes(); } catch (TException e){ log.error("Error getting license type list.", e); return Collections.emptyList(); } }; exporter = new LicenseExporter(getLicenseTypes); } //! Serve resource and helpers @Override public void serveResource(ResourceRequest request, ResourceResponse response) throws IOException, PortletException { String action = request.getParameter(PortalConstants.ACTION); if (PortalConstants.EXPORT_TO_EXCEL.equals(action)) { exportExcel(request, response); } } private void exportExcel(ResourceRequest request, ResourceResponse response) { try { LicenseService.Iface client = thriftClients.makeLicenseClient(); List<License> licenses = client.getLicenseSummaryForExport(); PortletResponseUtil.sendFile(request, response, "Licenses.xlsx", exporter.makeExcelExport(licenses), CONTENT_TYPE_OPENXML_SPREADSHEET); } catch (IOException | TException e) { log.error("An error occurred while generating the Excel export", e); } } @Override public void doView(RenderRequest request, RenderResponse response) throws IOException, PortletException { String pageName = request.getParameter(PAGENAME); if (PAGENAME_DETAIL.equals(pageName)) { prepareDetailView(request, response); include("/html/licenses/detail.jsp", request, response); } else if (PAGENAME_EDIT.equals(pageName)) { prepareEditView(request, response); include("/html/licenses/edit.jsp", request, response); } else { prepareStandardView(request); super.doView(request, response); } } private void prepareEditView(RenderRequest request, RenderResponse response) { String id = request.getParameter(LICENSE_ID); User user = UserCacheHolder.getUserFromRequest(request); LicenseService.Iface client = thriftClients.makeLicenseClient(); try { licenseTypes = client.getLicenseTypes(); request.setAttribute(LICENSE_TYPE_CHOICE, licenseTypes); }catch(TException e){ log.error("Error fetching license types from backend", e); setSW360SessionError(request, ErrorMessages.ERROR_GETTING_LICENSE); } if (id != null) { try { License license = client.getByID(id, user.getDepartment()); request.setAttribute(KEY_LICENSE_DETAIL, license); addLicenseBreadcrumb(request, response, license); } catch (TException e) { log.error("Error fetching license details from backend", e); setSW360SessionError(request, ErrorMessages.ERROR_GETTING_LICENSE); } } else { if (request.getAttribute(KEY_LICENSE_DETAIL) == null){ SessionMessages.add(request, "request_processed", "New License"); License license = new License(); request.setAttribute(KEY_LICENSE_DETAIL, license); } } } private void prepareStandardView(RenderRequest request) { log.debug("Enter license table view"); List<License> licenses; User user = UserCacheHolder.getUserFromRequest(request); request.setAttribute(IS_USER_AT_LEAST_CLEARING_ADMIN, PermissionUtils.isUserAtLeast(UserGroup.CLEARING_ADMIN, user) ? "Yes" : "Nope"); try { LicenseService.Iface client = thriftClients.makeLicenseClient(); licenses = client.getLicenseSummary(); } catch (TException e) { log.error("Could not fetch license summary from backend!", e); licenses = new ArrayList<>(); } request.setAttribute(LICENSE_LIST, licenses); } private void prepareDetailView(RenderRequest request, RenderResponse response) throws IOException, PortletException { String id = request.getParameter(LICENSE_ID); User user = UserCacheHolder.getUserFromRequest(request); request.setAttribute(IS_USER_AT_LEAST_CLEARING_ADMIN, PermissionUtils.isUserAtLeast(UserGroup.CLEARING_ADMIN, user) ? "Yes" : "Nope"); if (id != null) { try { LicenseService.Iface client = thriftClients.makeLicenseClient(); License moderationLicense = client.getByIDWithOwnModerationRequests(id, user.getDepartment(), user); List<Todo> allTodos = nullToEmptyList(moderationLicense.getTodos()); List<Todo> addedTodos = allTodos .stream() .filter(CommonUtils::isTemporaryTodo) .collect(Collectors.toList()); List<Todo> currentTodos = allTodos .stream() .filter(t -> !CommonUtils.isTemporaryTodo(t)) .collect(Collectors.toList()); request.setAttribute(ADDED_TODOS_FROM_MODERATION_REQUEST, addedTodos); request.setAttribute(DB_TODOS_FROM_MODERATION_REQUEST, currentTodos); request.setAttribute(MODERATION_LICENSE_DETAIL, moderationLicense); License dbLicense = client.getByID(id, user.getDepartment()); request.setAttribute(KEY_LICENSE_DETAIL, dbLicense); List<Obligation> obligations = client.getObligations(); request.setAttribute(KEY_OBLIGATION_LIST, obligations); addLicenseBreadcrumb(request, response, moderationLicense); } catch (TException e) { log.error("Error fetching license details from backend", e); setSW360SessionError(request, ErrorMessages.ERROR_GETTING_LICENSE); } } } private void addLicenseBreadcrumb(RenderRequest request, RenderResponse response, License license) { PortletURL componentUrl = response.createRenderURL(); componentUrl.setParameter(PAGENAME, PAGENAME_DETAIL); componentUrl.setParameter(LICENSE_ID, license.getId()); addBreadcrumbEntry(request, license.getId(), componentUrl); } @UsedAsLiferayAction public void update(ActionRequest request, ActionResponse response) throws PortletException, IOException { LicenseService.Iface client = thriftClients.makeLicenseClient(); String licenseId = request.getParameter(LICENSE_ID); User user = UserCacheHolder.getUserFromRequest(request); License license = prepareLicenseForUpdate(request, client, licenseId, user); boolean isNewLicense = isNullOrEmpty(licenseId); boolean isAttemptToOverwriteExistingByNew = isAttemptToOverwriteExistingByNew(license, user, isNewLicense, client); RequestStatus requestStatus = updateLicense(license, user, isAttemptToOverwriteExistingByNew, client); if (isAttemptToOverwriteExistingByNew){ response.setRenderParameter(PAGENAME, PAGENAME_EDIT); setSW360SessionError(request, ErrorMessages.LICENSE_SHORTNAME_TAKEN); request.setAttribute(KEY_LICENSE_DETAIL, license); } else if (isNewLicense) { response.setRenderParameter(PAGENAME, PAGENAME_VIEW); setSessionMessage(request, requestStatus, "License", "adde"); } else { response.setRenderParameter(LICENSE_ID, licenseId); response.setRenderParameter(PAGENAME, PAGENAME_DETAIL); response.setRenderParameter(SELECTED_TAB, "Details"); setSessionMessage(request, requestStatus, "License", "update"); } } private RequestStatus updateLicense(License license, User user, boolean isAttemptToOverwriteExistingByNew, LicenseService.Iface client) { RequestStatus requestStatus; try { requestStatus = isAttemptToOverwriteExistingByNew ? RequestStatus.FAILURE : client.updateLicense(license, user, user); } catch (TException e) { log.error("Could not add or update license:" + e); requestStatus = RequestStatus.FAILURE; } return requestStatus; } private boolean isAttemptToOverwriteExistingByNew(License license, User user, boolean isNewLicense, LicenseService.Iface client) { return isNewLicense && checkLicenseExists(license, user, client); } private License prepareLicenseForUpdate(ActionRequest request, LicenseService.Iface client, String licenseId, User user) { License license = new License();; if (!isNullOrEmpty(licenseId)) { try { license = client.getByID(licenseId, user.getDepartment()); } catch (TException e) { log.error("Could not find license to update:", e); } } license = updateLicenseFromRequest(license, request); return license; } private boolean checkLicenseExists(License license, User user, LicenseService.Iface client) { try { client.getByID(license.getShortname(), user.getDepartment()); return true; } catch (TException e1) { log.info("No existing license found:", e1); } return false; } private License updateLicenseFromRequest(License license, ActionRequest request) { String text = request.getParameter(License._Fields.TEXT.name()); String fullname = request.getParameter(License._Fields.FULLNAME.name()); String shortname = request.getParameter(License._Fields.SHORTNAME.name()); boolean gpl2compatibility = (request.getParameter(License._Fields.GPLV2_COMPAT.toString()) == null) ? false : true; boolean gpl3compatibility = (request.getParameter(License._Fields.GPLV3_COMPAT.toString()) == null) ? false : true; String licenseTypeString = request.getParameter(License._Fields.LICENSE_TYPE.toString() + LicenseType._Fields.LICENSE_TYPE.toString()); license.setText(CommonUtils.nullToEmptyString(text)); license.setFullname(CommonUtils.nullToEmptyString(fullname)); license.setShortname((CommonUtils.nullToEmptyString(shortname))); license.setGPLv2Compat(gpl2compatibility); license.setGPLv3Compat(gpl3compatibility); try { Optional<String> licenseTypeDatabaseId = getDatabaseIdFromLicenseType(licenseTypeString); if(licenseTypeDatabaseId.isPresent()) { license.setLicenseTypeDatabaseId(licenseTypeDatabaseId.get()); final LicenseType licenseType = thriftClients.makeLicenseClient().getLicenseTypeById(license.getLicenseTypeDatabaseId()); license.setLicenseType(licenseType); } else { license.unsetLicenseTypeDatabaseId(); } } catch (TException e) { log.error("Could not set licenseTypeDatabaseId:" + e); license.unsetLicenseTypeDatabaseId(); } return license; } private Optional<String> getDatabaseIdFromLicenseType(String licenseTypeIdString) throws TException { if (licenseTypeIdString != null && licenseTypeIdString.equals("")){ return Optional.empty(); } if (licenseTypes == null) { LicenseService.Iface client = thriftClients.makeLicenseClient(); try { licenseTypes = client.getLicenseTypes(); } catch (TException e){ throw new SW360Exception("Error getting license type list:"+ e); } } for (LicenseType licenseType : licenseTypes) { if (licenseType.getLicenseTypeId() == Integer.parseInt(licenseTypeIdString)) { return Optional.of(licenseType.getId()); } } throw new SW360Exception("Wrong license type!"); } @UsedAsLiferayAction public void updateWhiteList(ActionRequest request, ActionResponse response) throws PortletException, IOException { // we get a list of todoDatabaseIds and Booleans and we have to update the whiteList of each todo if it changed String licenseId = request.getParameter(LICENSE_ID); String[] whiteList = request.getParameterValues("whiteList"); if (whiteList == null) whiteList = new String[0]; // As empty arrays are not passed as parameters final User user = UserCacheHolder.getUserFromRequest(request); try { LicenseService.Iface client = thriftClients.makeLicenseClient(); RequestStatus requestStatus = client.updateWhitelist(licenseId, ImmutableSet.copyOf(whiteList), user); setSessionMessage(request, requestStatus, "License", "update"); } catch (TException e) { log.error("Error updating whitelist!", e); } response.setRenderParameter(LICENSE_ID, licenseId); response.setRenderParameter(PAGENAME, PAGENAME_DETAIL); response.setRenderParameter(SELECTED_TAB, "Todos"); } @UsedAsLiferayAction public void changeText(ActionRequest request, ActionResponse response) throws PortletException, IOException { String licenseId = request.getParameter(LICENSE_ID); String text = request.getParameter(License._Fields.TEXT.name()); if(!isNullOrEmpty(licenseId)) { try { User user = UserCacheHolder.getUserFromRequest(request); LicenseService.Iface client = thriftClients.makeLicenseClient(); final License license = client.getByID(licenseId,user.getDepartment()); license.setText(CommonUtils.nullToEmptyString(text)); final RequestStatus requestStatus = client.updateLicense(license, user, user); renderRequestStatus(request,response,requestStatus); } catch (TException e) { log.error("Error updating license", e); } } response.setRenderParameter(LICENSE_ID, licenseId); response.setRenderParameter(PAGENAME, PAGENAME_DETAIL); response.setRenderParameter(SELECTED_TAB, "LicenseText"); } @UsedAsLiferayAction public void addTodo(ActionRequest request, ActionResponse response) throws PortletException, IOException { String licenseID = request.getParameter(LICENSE_ID); String[] obligationIds = request.getParameterValues("obligations"); String todoText = request.getParameter("todoText"); String[] bools = request.getParameterValues("bools"); Todo todo = new Todo(); //add temporary id todo.setId(TMP_TODO_ID_PREFIX + UUID.randomUUID().toString()); if (obligationIds != null) { for (String obligationId : obligationIds) { if (obligationId != null && !obligationId.isEmpty()) { todo.addToObligationDatabaseIds(obligationId); } } } else { todo.setObligationDatabaseIds(Collections.emptySet()); } todo.setText(todoText); User user = UserCacheHolder.getUserFromRequest(request); todo.addToWhitelist(user.getDepartment()); if (bools != null) { List<String> theBools = Arrays.asList(bools); todo.setDevelopment(theBools.contains("development")); todo.setDistribution(theBools.contains("distribution")); } else { todo.setDevelopment(false); todo.setDistribution(false); } try { LicenseService.Iface client = thriftClients.makeLicenseClient(); RequestStatus requestStatus = client.addTodoToLicense(todo, licenseID, user); setSessionMessage(request, requestStatus, "License", "update"); } catch (TException e) { log.error("Error updating license details from backend", e); } response.setRenderParameter(LICENSE_ID, licenseID); response.setRenderParameter(PAGENAME, PAGENAME_DETAIL); response.setRenderParameter(SELECTED_TAB, "Todos"); } @UsedAsLiferayAction public void delete(ActionRequest request, ActionResponse response) throws PortletException, IOException { RequestStatus requestStatus = deleteLicense(request); setSessionMessage(request, requestStatus, "License", "remove"); } private RequestStatus deleteLicense(PortletRequest request) { String licenseId = request.getParameter(PortalConstants.LICENSE_ID); final User user = UserCacheHolder.getUserFromRequest(request); try { LicenseService.Iface client = thriftClients.makeLicenseClient(); return client.deleteLicense(licenseId, user); } catch (TException e) { log.error("Error deleting license from backend", e); } return RequestStatus.FAILURE; } @UsedAsLiferayAction public void editExternalLink(ActionRequest request, ActionResponse response) throws PortletException, IOException { String licenseId = request.getParameter(LICENSE_ID); String remoteLink = request.getParameter(License._Fields.EXTERNAL_LICENSE_LINK.name()); if(!Strings.isNullOrEmpty(licenseId)) { try { User user = UserCacheHolder.getUserFromRequest(request); LicenseService.Iface client = thriftClients.makeLicenseClient(); final License license = client.getByID(licenseId,user.getDepartment()); license.setExternalLicenseLink(CommonUtils.nullToEmptyString(remoteLink)); final RequestStatus requestStatus = client.updateLicense(license, user, user); renderRequestStatus(request,response,requestStatus); } catch (TException e) { log.error("Error updating license", e); } } response.setRenderParameter(LICENSE_ID, licenseId); response.setRenderParameter(PAGENAME, PAGENAME_DETAIL); response.setRenderParameter(SELECTED_TAB, "Details"); } }