org.opencms.workflow.CmsDefaultWorkflowManager Maven / Gradle / Ivy
Show all versions of opencms-test Show documentation
/*
* This library is part of OpenCms -
* the Open Source Content Management System
*
* Copyright (C) Alkacon Software (http://www.alkacon.com)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* For further information about Alkacon Software, please see the
* company website: http://www.alkacon.com
*
* For further information about OpenCms, please see the
* project website: http://www.opencms.org
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.opencms.workflow;
import org.opencms.ade.publish.CmsCurrentPageProject;
import org.opencms.ade.publish.CmsDirectPublishProject;
import org.opencms.ade.publish.CmsMyChangesProject;
import org.opencms.ade.publish.CmsPublish;
import org.opencms.ade.publish.CmsRealProjectVirtualWrapper;
import org.opencms.ade.publish.I_CmsVirtualProject;
import org.opencms.ade.publish.shared.CmsProjectBean;
import org.opencms.ade.publish.shared.CmsPublishListToken;
import org.opencms.ade.publish.shared.CmsPublishOptions;
import org.opencms.ade.publish.shared.CmsPublishResource;
import org.opencms.ade.publish.shared.CmsWorkflow;
import org.opencms.ade.publish.shared.CmsWorkflowAction;
import org.opencms.ade.publish.shared.CmsWorkflowResponse;
import org.opencms.file.CmsObject;
import org.opencms.file.CmsProject;
import org.opencms.file.CmsResource;
import org.opencms.i18n.CmsMessages;
import org.opencms.main.CmsException;
import org.opencms.main.CmsLog;
import org.opencms.main.OpenCms;
import org.opencms.security.CmsOrganizationalUnit;
import org.opencms.security.CmsRole;
import org.opencms.util.CmsUUID;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.apache.commons.logging.Log;
import com.google.common.collect.Maps;
/**
* The default implementation of the workflow manager interface, which offers only publish functionality.
*/
public class CmsDefaultWorkflowManager extends A_CmsWorkflowManager {
/** The forced publish workflow action. */
public static final String ACTION_FORCE_PUBLISH = "forcepublish";
/** The publish workflow action. */
public static final String ACTION_PUBLISH = "publish";
/** Default value for the maximum number of resources in the initial publish list. */
public static int DEFAULT_RESOURCE_LIMIT = 1000;
/** The parameter name for the resource limit. */
public static final String PARAM_RESOURCE_LIMIT = "resourceLimit";
/** The name for the publish action. */
public static final String WORKFLOW_PUBLISH = "WORKFLOW_PUBLISH";
/** The log instance for this class. */
private static final Log LOG = CmsLog.getLog(CmsDefaultWorkflowManager.class);
/** The map of registered virtual projects. */
protected Map m_virtualProjects = Maps.newHashMap();
/** The number of resources in the initial publish list above which the resources are not being displayed to the user. */
private int m_resourceLimit = DEFAULT_RESOURCE_LIMIT;
/**
* Constructor.
*/
public CmsDefaultWorkflowManager() {
m_virtualProjects.put(CmsCurrentPageProject.ID, new CmsCurrentPageProject());
m_virtualProjects.put(CmsMyChangesProject.ID, new CmsMyChangesProject());
m_virtualProjects.put(CmsDirectPublishProject.ID, new CmsDirectPublishProject());
}
/**
* Creates a project bean from a real project.
*
* @param cms the CMS context
* @param project the project
*
* @return the bean containing the project information
*/
public static CmsProjectBean createProjectBeanFromProject(CmsObject cms, CmsProject project) {
CmsProjectBean manProj = new CmsProjectBean(
project.getUuid(),
project.getType().getMode(),
org.opencms.ade.publish.Messages.get().getBundle(OpenCms.getWorkplaceManager().getWorkplaceLocale(cms)).key(
org.opencms.ade.publish.Messages.GUI_NORMAL_PROJECT_1,
getOuAwareName(cms, project.getName())),
project.getDescription());
return manProj;
}
/**
* Returns the simple name if the ou is the same as the current user's ou.
*
* @param cms the CMS context
* @param name the fully qualified name to check
*
* @return the simple name if the ou is the same as the current user's ou
*/
protected static String getOuAwareName(CmsObject cms, String name) {
String ou = CmsOrganizationalUnit.getParentFqn(name);
if (ou.equals(cms.getRequestContext().getCurrentUser().getOuFqn())) {
return CmsOrganizationalUnit.getSimpleName(name);
}
return CmsOrganizationalUnit.SEPARATOR + name;
}
/**
* @see org.opencms.workflow.I_CmsWorkflowManager#createFormatter(org.opencms.file.CmsObject, org.opencms.ade.publish.shared.CmsWorkflow, org.opencms.ade.publish.shared.CmsPublishOptions)
*/
public I_CmsPublishResourceFormatter createFormatter(
CmsObject cms,
CmsWorkflow workflow,
CmsPublishOptions options) {
CmsDefaultPublishResourceFormatter formatter = new CmsDefaultPublishResourceFormatter(cms);
return formatter;
}
/**
* @see org.opencms.workflow.I_CmsWorkflowManager#executeAction(org.opencms.file.CmsObject, org.opencms.ade.publish.shared.CmsWorkflowAction, org.opencms.ade.publish.shared.CmsPublishListToken)
*/
public CmsWorkflowResponse executeAction(CmsObject cms, CmsWorkflowAction action, CmsPublishListToken token)
throws CmsException {
if (action.getAction().equals(CmsWorkflowAction.ACTION_CANCEL)) {
// Don't need to get the resource list for canceling
return new CmsWorkflowResponse(true, action.getAction(), null, null, null);
}
List resources = getWorkflowResources(
cms,
token.getWorkflow(),
token.getOptions(),
false).getWorkflowResources();
return executeAction(cms, action, token.getOptions(), resources);
}
/**
* @see org.opencms.workflow.I_CmsWorkflowManager#executeAction(org.opencms.file.CmsObject, org.opencms.ade.publish.shared.CmsWorkflowAction, org.opencms.ade.publish.shared.CmsPublishOptions, java.util.List)
*/
@Override
public CmsWorkflowResponse executeAction(
CmsObject userCms,
CmsWorkflowAction action,
CmsPublishOptions options,
List resources) throws CmsException {
String actionKey = action.getAction();
if (CmsWorkflowAction.ACTION_CANCEL.equals(actionKey)) {
return new CmsWorkflowResponse(true, actionKey, null, null, null);
} else if (ACTION_PUBLISH.equals(actionKey)) {
return actionPublish(userCms, options, resources);
} else if (ACTION_FORCE_PUBLISH.equals(actionKey)) {
return actionForcePublish(userCms, options, resources);
}
throw new CmsInvalidActionException(actionKey);
}
/**
* Gets the localized label for a given CMS context and key.
*
* @param cms the CMS context
* @param key the localization key
*
* @return the localized label
*/
public String getLabel(CmsObject cms, String key) {
CmsMessages messages = Messages.get().getBundle(getLocale(cms));
return messages.key(key);
}
/**
* @see org.opencms.workflow.I_CmsWorkflowManager#getManageableProjects(org.opencms.file.CmsObject, java.util.Map)
*/
public List getManageableProjects(CmsObject cms, Map params) {
List manProjs = new ArrayList();
List projects;
try {
projects = OpenCms.getOrgUnitManager().getAllManageableProjects(cms, "", true);
} catch (CmsException e) {
// should never happen
LOG.error(e.getLocalizedMessage(), e);
return manProjs;
}
for (CmsProject project : projects) {
CmsProjectBean manProj = createProjectBeanFromProject(cms, project);
manProjs.add(manProj);
}
for (I_CmsVirtualProject handler : m_virtualProjects.values()) {
CmsProjectBean projectBean = handler.getProjectBean(cms, params);
if (projectBean != null) {
manProjs.add(projectBean);
}
}
return manProjs;
}
/**
* @see org.opencms.workflow.I_CmsWorkflowManager#getPublishListToken(org.opencms.file.CmsObject, org.opencms.ade.publish.shared.CmsWorkflow, org.opencms.ade.publish.shared.CmsPublishOptions)
*/
public CmsPublishListToken getPublishListToken(CmsObject cms, CmsWorkflow workflow, CmsPublishOptions options) {
return new CmsPublishListToken(workflow, options);
}
/**
* @see org.opencms.workflow.I_CmsWorkflowManager#getRealOrVirtualProject(org.opencms.util.CmsUUID)
*/
public I_CmsVirtualProject getRealOrVirtualProject(CmsUUID projectId) {
I_CmsVirtualProject project = m_virtualProjects.get(projectId);
if (project == null) {
project = new CmsRealProjectVirtualWrapper(projectId);
}
return project;
}
/**
* @see org.opencms.workflow.I_CmsWorkflowManager#getResourceLimit()
*/
public int getResourceLimit() {
return m_resourceLimit;
}
/**
* @see org.opencms.workflow.I_CmsWorkflowManager#getWorkflowForWorkflowProject(org.opencms.util.CmsUUID)
*/
public String getWorkflowForWorkflowProject(CmsUUID projectId) {
return WORKFLOW_PUBLISH;
}
/**
* @see org.opencms.workflow.I_CmsWorkflowManager#getWorkflowResources(org.opencms.file.CmsObject, org.opencms.ade.publish.shared.CmsWorkflow, org.opencms.ade.publish.shared.CmsPublishOptions, boolean)
*/
@Override
public CmsWorkflowResources getWorkflowResources(
CmsObject cms,
CmsWorkflow workflow,
CmsPublishOptions options,
boolean canOverride) {
try {
List rawResourceList = new ArrayList();
I_CmsVirtualProject projectHandler = null;
projectHandler = getRealOrVirtualProject(options.getProjectId());
if (projectHandler != null) {
rawResourceList = projectHandler.getResources(cms, options.getParameters(), workflow.getId());
return new CmsWorkflowResources(rawResourceList);
}
return new CmsWorkflowResources(rawResourceList);
} catch (Exception e) {
LOG.error(e.getLocalizedMessage(), e);
return new CmsWorkflowResources(Collections. emptyList());
}
}
/**
* @see org.opencms.workflow.I_CmsWorkflowManager#getWorkflows(org.opencms.file.CmsObject)
*/
public Map getWorkflows(CmsObject cms) {
Map result = new LinkedHashMap();
List actions = new ArrayList();
String publishLabel = getLabel(cms, Messages.GUI_WORKFLOW_ACTION_PUBLISH_0);
CmsWorkflowAction publishAction = new CmsWorkflowAction(ACTION_PUBLISH, publishLabel, true, true);
actions.add(publishAction);
String workflowLabel = getLabel(cms, Messages.GUI_WORKFLOW_PUBLISH_0);
CmsWorkflow publishWorkflow = new CmsWorkflow(WORKFLOW_PUBLISH, workflowLabel, actions);
result.put(WORKFLOW_PUBLISH, publishWorkflow);
return result;
}
/**
* @see org.opencms.workflow.A_CmsWorkflowManager#initialize(org.opencms.file.CmsObject)
*/
@Override
public void initialize(CmsObject adminCms) {
super.initialize(adminCms);
String resourceLimitStr = getParameter(PARAM_RESOURCE_LIMIT, "invalid").trim();
try {
m_resourceLimit = Integer.parseInt(resourceLimitStr);
} catch (NumberFormatException e) {
// ignore, resource limit will remain at the default setting
}
}
/**
* The implementation of the "forcepublish" workflow action.
*
* @param userCms the user CMS context
* @param resources the resources which the action should process
* @param options the publish options to use
* @return the workflow response
*
* @throws CmsException if something goes wrong
*/
protected CmsWorkflowResponse actionForcePublish(
CmsObject userCms,
CmsPublishOptions options,
List resources) throws CmsException {
CmsPublish publish = new CmsPublish(userCms, options.getParameters());
publish.publishResources(resources);
CmsWorkflowResponse response = new CmsWorkflowResponse(
true,
"",
new ArrayList(),
new ArrayList(),
null);
return response;
}
/**
* The implementation of the "publish" workflow action.
*
* @param userCms the user CMS context
* @param options the publish options
* @param resources the resources which the action should process
*
* @return the workflow response
* @throws CmsException if something goes wrong
*/
protected CmsWorkflowResponse actionPublish(
CmsObject userCms,
CmsPublishOptions options,
final List resources) throws CmsException {
final CmsPublish publish = new CmsPublish(userCms, options);
// use FutureTask to get the broken links, because we can then use a different thread if it takes too long
final FutureTask> brokenResourcesGetter = new FutureTask>(
new Callable>() {
public List call() throws Exception {
return publish.getBrokenResources(resources);
}
});
Thread brokenResourcesThread = new Thread(brokenResourcesGetter);
brokenResourcesThread.start();
try {
List brokenResources = brokenResourcesGetter.get(10, TimeUnit.SECONDS);
if (brokenResources.size() == 0) {
publish.publishResources(resources);
CmsWorkflowResponse response = new CmsWorkflowResponse(
true,
"",
new ArrayList(),
new ArrayList(),
null);
return response;
} else {
String brokenResourcesLabel = getLabel(userCms, Messages.GUI_BROKEN_LINKS_0);
boolean canForcePublish = OpenCms.getWorkplaceManager().getDefaultUserSettings().isAllowBrokenRelations()
|| OpenCms.getRoleManager().hasRole(userCms, CmsRole.VFS_MANAGER);
List actions = new ArrayList();
if (canForcePublish) {
String forceLabel = getLabel(userCms, Messages.GUI_WORKFLOW_ACTION_FORCE_PUBLISH_0);
actions.add(new CmsWorkflowAction(ACTION_FORCE_PUBLISH, forceLabel, true, true));
}
CmsWorkflowResponse response = new CmsWorkflowResponse(
false,
brokenResourcesLabel,
brokenResources,
actions,
null);
return response;
}
} catch (TimeoutException e) {
// Things are taking too long, do them in a different thread and just return "OK" to the client
Thread thread = new Thread() {
@SuppressWarnings("synthetic-access")
@Override
public void run() {
LOG.info(
"Checking broken relations is taking too long, using a different thread for checking and publishing now.");
try {
// Make sure the computation is finished by calling get() without a timeout parameter
// We don't need the actual result of the get(), though; we just get the set of resource paths from the validator object
brokenResourcesGetter.get();
List resourcesToPublish = new ArrayList(resources);
Iterator resIter = resourcesToPublish.iterator();
while (resIter.hasNext()) {
CmsResource currentRes = resIter.next();
if (publish.getRelationValidator().keySet().contains(currentRes.getRootPath())) {
resIter.remove();
LOG.info(
"Excluding resource from publish list because relations would be broken: "
+ currentRes.getRootPath());
}
}
publish.publishResources(resourcesToPublish);
} catch (Exception ex) {
LOG.error(ex.getLocalizedMessage(), ex);
}
}
};
thread.start();
CmsWorkflowResponse response = new CmsWorkflowResponse(
true,
"",
new ArrayList(),
new ArrayList(),
null);
return response;
} catch (InterruptedException e) {
// shouldn't happen; log exception
LOG.error(e.getLocalizedMessage());
return null;
} catch (ExecutionException e) {
// shouldn't happen; log exception
LOG.error(e.getLocalizedMessage());
return null;
}
}
}