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.NoSuchWorkspaceException; 022import javax.jcr.Node; 023import javax.jcr.Repository; 024import javax.jcr.RepositoryException; 025import javax.jcr.Session; 026 027import org.apache.avalon.framework.parameters.Parameters; 028import org.apache.avalon.framework.service.ServiceException; 029import org.apache.avalon.framework.service.ServiceManager; 030import org.apache.cocoon.environment.ObjectModelHelper; 031import org.apache.cocoon.environment.Redirector; 032import org.apache.cocoon.environment.Request; 033 034import org.ametys.cms.ObservationConstants; 035import org.ametys.cms.content.archive.ArchiveConstants; 036import org.ametys.cms.repository.CloneComponent; 037import org.ametys.cms.repository.Content; 038import org.ametys.cms.repository.WorkflowAwareContent; 039import org.ametys.core.cocoon.ActionResultGenerator; 040import org.ametys.core.observation.Event; 041import org.ametys.core.observation.ObservationManager; 042import org.ametys.core.user.UserIdentity; 043import org.ametys.plugins.repository.AmetysObjectResolver; 044import org.ametys.plugins.repository.provider.AbstractRepository; 045 046import com.opensymphony.workflow.InvalidInputException; 047import com.opensymphony.workflow.WorkflowException; 048 049/** 050 * Action for archiving a content. 051 */ 052public class ArchiveContentAction extends ContentWorkflowAction 053{ 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 WorkflowAwareContent content = _getContent(objectModel); 081 082 UserIdentity currentUser = _getUser(objectModel); 083 String contentId = content.getId(); 084 085 Event deletingEvent = _prepareDeletingEvent (currentUser, content); 086 Event deletedEvent = _prepareDeletedEvent (currentUser, content); 087 088 try 089 { 090 // Trigger the action. 091 Map<String, String> result = super._act(redirector, objectModel, source, parameters, actionId, inputs); 092 093 Map<String, Object> resultMap = new HashMap<>(); 094 095 _observationManager.notify(deletingEvent); 096 097 // Move the content and its workflow to the "archives" workspace. 098 archiveContent(content, objectModel, resultMap); 099 100 Request request = ObjectModelHelper.getRequest(objectModel); 101 request.setAttribute(ActionResultGenerator.MAP_REQUEST_ATTR, resultMap); 102 103 // Notify that a content has been removed from the default workspace. 104 _observationManager.notify(deletedEvent); 105 106 return result; 107 } 108 catch (RepositoryException e) 109 { 110 throw new WorkflowException("Unable to archive the content " + contentId, e); 111 } 112 } 113 114 /** 115 * Prepare event to notify observers 116 * @param issuer the responsible for the action 117 * @param content the archived content 118 * @return the event 119 */ 120 protected Event _prepareDeletingEvent (UserIdentity issuer, Content content) 121 { 122 Map<String, Object> eventParams = new HashMap<>(); 123 eventParams.put(ObservationConstants.ARGS_CONTENT, content); 124 eventParams.put(ObservationConstants.ARGS_CONTENT_NAME, content.getName()); 125 eventParams.put(ObservationConstants.ARGS_CONTENT_ID, content.getId()); 126 127 return new Event(org.ametys.cms.ObservationConstants.EVENT_CONTENT_DELETING, issuer, eventParams); 128 } 129 130 /** 131 * Prepare event to notify observers 132 * @param issuer the responsible for the action 133 * @param content the archived content 134 * @return the event 135 */ 136 protected Event _prepareDeletedEvent (UserIdentity issuer, Content content) 137 { 138 Map<String, Object> eventParams = new HashMap<>(); 139 eventParams.put(ObservationConstants.ARGS_CONTENT, content); 140 eventParams.put(ObservationConstants.ARGS_CONTENT_NAME, content.getName()); 141 eventParams.put(ObservationConstants.ARGS_CONTENT_ID, content.getId()); 142 143 return new Event(org.ametys.cms.ObservationConstants.EVENT_CONTENT_DELETED, issuer, eventParams); 144 } 145 146 /** 147 * Archive a content. 148 * @param content the content to archive. 149 * @param objectModel the current object model. 150 * @param result the result map 151 * @throws RepositoryException The repository exception 152 */ 153 protected void archiveContent(WorkflowAwareContent content, Map objectModel, Map<String, Object> result) throws RepositoryException 154 { 155 Session session = null; 156 Session archiveSession = null; 157 158 try 159 { 160 archiveSession = getArchiveSession(); 161 162 Node contentNode = content.getNode(); 163 164 session = contentNode.getSession(); 165 166 _cloneComponent.cloneContentNodeWithWorkflow(archiveSession, contentNode); 167 168 archiveSession.save(); 169 170 content.remove(); 171 session.save(); 172 } 173 finally 174 { 175 if (archiveSession != null) 176 { 177 archiveSession.logout(); 178 } 179 } 180 } 181 182 /** 183 * Get a repository session on the archive workspace. 184 * @return the archive session. 185 * @throws RepositoryException The repository exception 186 */ 187 protected Session getArchiveSession() throws RepositoryException 188 { 189 Session session = null; 190 Session archiveSession = null; 191 192 try 193 { 194 archiveSession = _repository.login(ArchiveConstants.ARCHIVE_WORKSPACE); 195 196 return archiveSession; 197 } 198 catch (NoSuchWorkspaceException e) 199 { 200 session = _repository.login(); 201 session.getWorkspace().createWorkspace(ArchiveConstants.ARCHIVE_WORKSPACE); 202 archiveSession = _repository.login(ArchiveConstants.ARCHIVE_WORKSPACE); 203 204 archiveSession.getRootNode().addNode(AmetysObjectResolver.ROOT_REPO, AmetysObjectResolver.ROOT_TYPE); 205 archiveSession.save(); 206 207 return archiveSession; 208 } 209 finally 210 { 211 if (session != null) 212 { 213 session.logout(); 214 } 215 } 216 } 217 218}