/** * Copyright (C) 2011 BonitaSoft S.A. * BonitaSoft, 32 rue Gustave Eiffel - 38000 Grenoble * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2.0 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.bonitasoft.web.rest.server.datastore.bpm.process; import java.io.File; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import org.bonitasoft.console.common.server.page.CustomPageService; import org.bonitasoft.console.common.server.preferences.properties.ConfigurationFile; import org.bonitasoft.console.common.server.preferences.properties.PropertiesFactory; import org.bonitasoft.console.common.server.utils.BPMEngineException; import org.bonitasoft.console.common.server.utils.BonitaHomeFolderAccessor; import org.bonitasoft.console.common.server.utils.FormsResourcesUtils; import org.bonitasoft.console.common.server.utils.PlatformManagementUtils; import org.bonitasoft.console.common.server.utils.UnauthorizedFolderException; import org.bonitasoft.engine.api.PageAPI; import org.bonitasoft.engine.api.TenantAPIAccessor; import org.bonitasoft.engine.bpm.bar.BusinessArchive; import org.bonitasoft.engine.bpm.bar.BusinessArchiveFactory; import org.bonitasoft.engine.bpm.process.ProcessDefinition; import org.bonitasoft.engine.bpm.process.ProcessDefinitionNotFoundException; import org.bonitasoft.engine.bpm.process.ProcessDeploymentInfo; import org.bonitasoft.engine.bpm.process.ProcessDeploymentInfoUpdater; import org.bonitasoft.engine.page.Page; import org.bonitasoft.engine.page.PageSearchDescriptor; import org.bonitasoft.engine.search.SearchOptionsBuilder; import org.bonitasoft.engine.search.SearchResult; import org.bonitasoft.engine.session.APISession; import org.bonitasoft.web.rest.model.bpm.process.ProcessItem; import org.bonitasoft.web.rest.server.datastore.CommonDatastore; import org.bonitasoft.web.rest.server.datastore.bpm.process.helper.ProcessItemConverter; import org.bonitasoft.web.rest.server.datastore.bpm.process.helper.SearchProcessHelper; import org.bonitasoft.web.rest.server.engineclient.EngineAPIAccessor; import org.bonitasoft.web.rest.server.engineclient.EngineClientFactory; import org.bonitasoft.web.rest.server.engineclient.ProcessEngineClient; import org.bonitasoft.web.rest.server.framework.api.DatastoreHasAdd; import org.bonitasoft.web.rest.server.framework.api.DatastoreHasDelete; import org.bonitasoft.web.rest.server.framework.api.DatastoreHasGet; import org.bonitasoft.web.rest.server.framework.api.DatastoreHasSearch; import org.bonitasoft.web.rest.server.framework.api.DatastoreHasUpdate; import org.bonitasoft.web.rest.server.framework.search.ItemSearchResult; import org.bonitasoft.web.toolkit.client.common.exception.api.APIException; import org.bonitasoft.web.toolkit.client.common.exception.api.APIForbiddenException; import org.bonitasoft.web.toolkit.client.data.APIID; /** * Process data store * * @author Vincent Elcrin */ public class ProcessDatastore extends CommonDatastore<ProcessItem, ProcessDeploymentInfo> implements DatastoreHasAdd<ProcessItem>, DatastoreHasUpdate<ProcessItem>, DatastoreHasGet<ProcessItem>, DatastoreHasSearch<ProcessItem>, DatastoreHasDelete { private static final Logger logger = Logger.getLogger(ProcessDatastore.class.getName()); /** * process file */ private static final String FILE_UPLOAD = "fileupload"; private static final int DELETE_PAGES_BUNCH_SIZE = 100; public ProcessDatastore(final APISession engineSession) { super(engineSession); } @Override public ProcessItem add(final ProcessItem process) { final ProcessEngineClient engineClient = getProcessEngineClient(); File processFile; try { processFile = getTenantFolder().getTempFile(process.getAttributes().get(FILE_UPLOAD), getEngineSession().getTenantId()); } catch (final UnauthorizedFolderException e) { throw new APIForbiddenException(e.getMessage()); } catch (final IOException e) { throw new APIException(e); } final BusinessArchive businessArchive = readBusinessArchive(processFile); final ProcessDefinition deployedArchive = engineClient.deploy(businessArchive); final ProcessDeploymentInfo processDeploymentInfo = engineClient.getProcessDeploymentInfo(deployedArchive.getId()); try { FormsResourcesUtils.retrieveApplicationFiles( getEngineSession(), processDeploymentInfo.getProcessId(), processDeploymentInfo.getDeploymentDate()); } catch (final IOException e) { throw new APIException("", e); } catch (final ProcessDefinitionNotFoundException e) { throw new APIException("", e); } catch (final BPMEngineException e) { throw new APIException("", e); } return convertEngineToConsoleItem(processDeploymentInfo); } protected BonitaHomeFolderAccessor getTenantFolder() { final BonitaHomeFolderAccessor tenantFolder = new BonitaHomeFolderAccessor(); return tenantFolder; } /* * Overridden in SP */ protected BusinessArchive readBusinessArchive(final File file) { try { return BusinessArchiveFactory.readBusinessArchive(file); } catch (final Exception e) { throw new APIException(e); } } @Override public ProcessItem update(final APIID id, final Map<String, String> attributes) { final ProcessDeploymentInfoUpdater updater = new ProcessDeploymentInfoUpdater(); final ProcessEngineClient engineClient = getProcessEngineClient(); if (attributes.containsKey(ProcessItem.ATTRIBUTE_DISPLAY_DESCRIPTION)) { updater.setDisplayDescription(attributes.get(ProcessItem.ATTRIBUTE_DISPLAY_DESCRIPTION)); } if (attributes.containsKey(ProcessItem.ATTRIBUTE_DISPLAY_NAME)) { updater.setDisplayName(attributes.get(ProcessItem.ATTRIBUTE_DISPLAY_NAME)); } // specific engine methods if (attributes.containsKey(ProcessItem.ATTRIBUTE_ACTIVATION_STATE)) { changeProcessState(engineClient, id.toLong(), attributes.get(ProcessItem.ATTRIBUTE_ACTIVATION_STATE)); } if (!updater.getFields().isEmpty()) { final ProcessDeploymentInfo processDeploymentInfo = engineClient.updateProcessDeploymentInfo(id.toLong(), updater); return convertEngineToConsoleItem(processDeploymentInfo); } else { return convertEngineToConsoleItem(engineClient.getProcessDeploymentInfo(id.toLong())); } } private void changeProcessState(final ProcessEngineClient engineClient, final Long processId, final String state) { if (ProcessItem.VALUE_ACTIVATION_STATE_DISABLED.equals(state)) { engineClient.disableProcess(processId); } else if (ProcessItem.VALUE_ACTIVATION_STATE_ENABLED.equals(state)) { engineClient.enableProcess(processId); } refreshAutologinConfiguration(); } protected void refreshAutologinConfiguration() { try { final PlatformManagementUtils platformManagementUtils = getPlatformManagementUtils(); platformManagementUtils.retrieveAutologinConfiguration(getEngineSession().getTenantId()); } catch (final Exception e) { throw new APIException(e); } } protected PlatformManagementUtils getPlatformManagementUtils() { return new PlatformManagementUtils(); } @Override public ProcessItem get(final APIID id) { final ProcessEngineClient engineClient = getProcessEngineClient(); final ProcessDeploymentInfo processDeploymentInfo = engineClient.getProcessDeploymentInfo(id.toLong()); return convertEngineToConsoleItem(processDeploymentInfo); } @Override public void delete(final List<APIID> ids) { for (final APIID id : ids) { removeProcessPagesFromHome(id); } final ProcessEngineClient engineClient = getProcessEngineClient(); engineClient.deleteDisabledProcesses(APIID.toLongList(ids)); } protected void removeProcessPagesFromHome(final APIID id) { try { int startIndex = 0; int count = 0; do { final SearchOptionsBuilder searchOptionsBuilder = new SearchOptionsBuilder(startIndex, DELETE_PAGES_BUNCH_SIZE); searchOptionsBuilder.filter(PageSearchDescriptor.PROCESS_DEFINITION_ID, id.toLong()); final SearchResult<Page> result = getPageAPI().searchPages(searchOptionsBuilder.done()); if (count == 0) { count = (int) result.getCount(); } startIndex = startIndex + result.getResult().size(); for (final Page page : result.getResult()) { getCustomPageService().removePage(getEngineSession(), page); getCompoundPermissionsMapping().removeProperty(page.getName()); } } while (startIndex < count); } catch (final Exception e) { if (logger.isLoggable(Level.WARNING)) { logger.log(Level.WARNING, "Error when deleting pages for process with ID " + id, e); } } } protected ConfigurationFile getCompoundPermissionsMapping() { return PropertiesFactory.getCompoundPermissionsMapping(getEngineSession().getTenantId()); } protected CustomPageService getCustomPageService() { return new CustomPageService(); } protected PageAPI getPageAPI() { try { return TenantAPIAccessor.getCustomPageAPI(getEngineSession()); } catch (final Exception e) { throw new APIException(e); } } @Override public ItemSearchResult<ProcessItem> search(final int page, final int resultsByPage, final String search, final String orders, final Map<String, String> filters) { final ProcessEngineClient engineClient = getProcessEngineClient(); return new SearchProcessHelper(engineClient).search(page, resultsByPage, search, orders, filters); } @Override protected ProcessItem convertEngineToConsoleItem(final ProcessDeploymentInfo item) { if (item != null) { return new ProcessItemConverter(getProcessEngineClient().getProcessApi()).convert(item); } return null; } protected ProcessEngineClient getProcessEngineClient() { return getEngineClientFactory().createProcessEngineClient(); } private EngineClientFactory getEngineClientFactory() { return new EngineClientFactory(new EngineAPIAccessor(getEngineSession())); } }