001/* 002 * Copyright 2011 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.cms.workflow; 017 018import java.util.HashMap; 019import java.util.Map; 020 021import javax.jcr.Node; 022import javax.jcr.Repository; 023import javax.jcr.RepositoryException; 024import javax.jcr.Session; 025 026import org.apache.avalon.framework.parameters.Parameters; 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.cocoon.environment.ObjectModelHelper; 030import org.apache.cocoon.environment.Redirector; 031import org.apache.cocoon.environment.Request; 032import org.apache.commons.lang.ArrayUtils; 033 034import org.ametys.cms.ObservationConstants; 035import org.ametys.cms.repository.CloneComponent; 036import org.ametys.cms.repository.Content; 037import org.ametys.cms.repository.RequestAttributeWorkspaceSelector; 038import org.ametys.cms.repository.WorkflowAwareContent; 039import org.ametys.core.observation.Event; 040import org.ametys.core.observation.ObservationManager; 041import org.ametys.core.user.UserIdentity; 042import org.ametys.plugins.repository.AmetysObjectResolver; 043import org.ametys.plugins.repository.provider.AbstractRepository; 044import org.ametys.plugins.repository.version.VersionableAmetysObject; 045import org.ametys.plugins.workflow.support.WorkflowProvider.AmetysObjectWorkflow; 046 047import com.opensymphony.workflow.InvalidInputException; 048import com.opensymphony.workflow.WorkflowException; 049 050/** 051 * Unarchive a content. 052 */ 053public class UnarchiveContentAction extends ContentWorkflowAction 054{ 055 /** The repository. */ 056 protected Repository _repository; 057 058 /** The ametys object resolver. */ 059 protected AmetysObjectResolver _resolver; 060 061 /** The clone component. */ 062 protected CloneComponent _cloneComponent; 063 064 /** Observation manager available to subclasses. */ 065 protected ObservationManager _observationManager; 066 067 @Override 068 public void service(ServiceManager serviceManager) throws ServiceException 069 { 070 super.service(serviceManager); 071 _repository = (Repository) serviceManager.lookup(AbstractRepository.ROLE); 072 _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE); 073 _cloneComponent = (CloneComponent) serviceManager.lookup(CloneComponent.ROLE); 074 _observationManager = (ObservationManager) serviceManager.lookup(ObservationManager.ROLE); 075 } 076 077 @Override 078 protected Map<String, String> _act(Redirector redirector, Map objectModel, String source, Parameters parameters, int actionId, Map inputs) throws InvalidInputException, WorkflowException 079 { 080 Request request = ObjectModelHelper.getRequest(objectModel); 081 082 WorkflowAwareContent archivedContent = _getContent(objectModel); 083 UserIdentity user = _getUser(objectModel); 084 085 String contentId = archivedContent.getId(); 086 087 try 088 { 089 // Move the content and its workflow back to the default workspace. 090 unarchiveContent(archivedContent); 091 092 // Resolve the content in the default workspace. 093 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, "default"); 094 WorkflowAwareContent content = _resolver.resolveById(contentId); 095 096 if (content instanceof VersionableAmetysObject) 097 { 098 ((VersionableAmetysObject) content).checkpoint(); 099 } 100 101 request.setAttribute(Content.class.getName(), content); 102 inputs.put(AbstractContentWorkflowComponent.CONTENT_KEY, content); 103 104 // Trigger the action. 105 Map<String, String> result = super._act(redirector, objectModel, source, parameters, actionId, inputs); 106 107 // Notify that a content has been added to the default workspace. 108 Map<String, Object> eventParams = new HashMap<>(); 109 eventParams.put(ObservationConstants.ARGS_CONTENT, content); 110 eventParams.put(ObservationConstants.ARGS_CONTENT_ID, contentId); 111 112 _observationManager.notify(new Event(ObservationConstants.EVENT_CONTENT_ADDED, user, eventParams)); 113 114 return result; 115 } 116 catch (RepositoryException e) 117 { 118 throw new WorkflowException("Error unarchiving the content " + contentId, e); 119 } 120 } 121 122 /** 123 * Test if the action can be executed. 124 * @param content the content 125 * @param actionId the action ID. 126 * @param inputs the workflow inputs. 127 * @return true if the action is valid in the current environment, false otherwise. 128 */ 129 protected boolean isActionValid(WorkflowAwareContent content, int actionId, Map inputs) 130 { 131 long workflowId = content.getWorkflowId(); 132 133 AmetysObjectWorkflow workflow = _workflowProvider.getAmetysObjectWorkflow(content); 134 int[] availableActions = workflow.getAvailableActions(workflowId, inputs); 135 136 return ArrayUtils.contains(availableActions, actionId); 137 } 138 139 /** 140 * Unarchive a content. 141 * @param content the content (in the archives workspace). 142 * @throws RepositoryException If an error occurred 143 */ 144 protected void unarchiveContent(WorkflowAwareContent content) throws RepositoryException 145 { 146 Session defaultSession = null; 147 Session archiveSession = null; 148 149 try 150 { 151 // Open a session on the default workspace. 152 defaultSession = _repository.login("default"); 153 154 // The content node in the archives workspace. 155 Node contentNode = content.getNode(); 156 archiveSession = contentNode.getSession(); 157 158 // Clone the content in the default workspace. 159 _cloneComponent.cloneContentNodeWithWorkflow(defaultSession, contentNode); 160 161 // Remove the content in the archives workspace. 162 content.remove(); 163 164 // Save everything. 165 defaultSession.save(); 166 archiveSession.save(); 167 } 168 finally 169 { 170 if (defaultSession != null) 171 { 172 defaultSession.logout(); 173 } 174 } 175 } 176}