001/* 002 * Copyright 2015 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.plugins.workspaces.threads; 017 018import java.io.IOException; 019import java.util.ArrayList; 020import java.util.HashMap; 021import java.util.List; 022import java.util.Map; 023 024import org.apache.avalon.framework.context.Context; 025import org.apache.avalon.framework.context.ContextException; 026import org.apache.avalon.framework.context.Contextualizable; 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.cocoon.components.ContextHelper; 030import org.apache.cocoon.environment.Request; 031import org.apache.commons.io.IOUtils; 032import org.apache.commons.lang.IllegalClassException; 033import org.apache.excalibur.source.Source; 034import org.apache.excalibur.source.SourceResolver; 035 036import org.ametys.core.ui.Callable; 037import org.ametys.plugins.explorer.resources.ModifiableResourceCollection; 038import org.ametys.plugins.explorer.threads.actions.ThreadDAO; 039import org.ametys.plugins.explorer.threads.jcr.JCRPost; 040import org.ametys.plugins.explorer.threads.jcr.JCRThread; 041import org.ametys.plugins.repository.AmetysObject; 042import org.ametys.plugins.repository.AmetysRepositoryException; 043import org.ametys.plugins.workspaces.html.HTMLTransformer; 044import org.ametys.plugins.workspaces.project.ProjectManager; 045import org.ametys.plugins.workspaces.project.modules.WorkspaceModule; 046import org.ametys.plugins.workspaces.project.modules.WorkspaceModuleExtensionPoint; 047import org.ametys.plugins.workspaces.project.objects.Project; 048import org.ametys.runtime.plugin.component.PluginAware; 049 050/** 051 * DAO for manipulating thread of a project 052 * 053 */ 054public class WorkspaceThreadDAO extends ThreadDAO implements PluginAware, Contextualizable 055{ 056 /** Avalon Role */ 057 @SuppressWarnings("hiding") 058 public static final String ROLE = WorkspaceThreadDAO.class.getName(); 059 060 private HTMLTransformer _htmlTransformer; 061 private SourceResolver _sourceResolver; 062 private String _pluginName; 063 private ProjectManager _projectManager; 064 065 private Context _context; 066 067 private WorkspaceModuleExtensionPoint _moduleEP; 068 069 @Override 070 public void service(ServiceManager manager) throws ServiceException 071 { 072 super.service(manager); 073 _htmlTransformer = (HTMLTransformer) manager.lookup(HTMLTransformer.ROLE); 074 _sourceResolver = (SourceResolver) manager.lookup(SourceResolver.ROLE); 075 _projectManager = (ProjectManager) manager.lookup(ProjectManager.ROLE); 076 _moduleEP = (WorkspaceModuleExtensionPoint) manager.lookup(WorkspaceModuleExtensionPoint.ROLE); 077 } 078 079 @Override 080 public void setPluginInfo(String pluginName, String featureName, String id) 081 { 082 _pluginName = pluginName; 083 } 084 085 @Override 086 public void contextualize(Context context) throws ContextException 087 { 088 _context = context; 089 } 090 091 /** 092 * Get the list of threads of a project 093 * @param includeChildren True to also include threads messages 094 * @return The list of threads 095 */ 096 @Callable 097 public Map<String, Object> getThreadsList(boolean includeChildren) 098 { 099 Request request = ContextHelper.getRequest(_context); 100 String projectName = (String) request.getAttribute("projectName"); 101 102 Project project = _projectManager.getProject(projectName); 103 104 WorkspaceModule module = _moduleEP.getModule(ThreadWorkspaceModule.THREAD_MODULE_ID); 105 ModifiableResourceCollection threadRoot = module.getModuleRoot(project, false); 106 107 Map<String, Object> result = new HashMap<>(); 108 List<Map<String, Object>> threadsList = new ArrayList<>(); 109 if (threadRoot != null) 110 { 111 for (AmetysObject ametysObject : threadRoot.getChildren()) 112 { 113 AmetysObject threadObject = _resolver.resolveById(ametysObject.getId()); 114 115 if (!(threadObject instanceof JCRThread)) 116 { 117 throw new IllegalClassException(JCRThread.class, threadObject.getClass()); 118 } 119 120 JCRThread thread = (JCRThread) threadObject; 121 threadsList.add(getThreadData(thread, includeChildren)); 122 } 123 } 124 125 result.put("threads", threadsList); 126 return result; 127 } 128 129 /** 130 * Add a thread 131 * @param name The desired name for the thread 132 * @param description The thread description 133 * @return The result map with id, parentId and name keys 134 * @throws IllegalAccessException If the user has no sufficient rights 135 * @throws AmetysRepositoryException If a repository error occurred 136 */ 137 @Callable 138 public Map<String, Object> addThread(String name, String description) throws IllegalAccessException, AmetysRepositoryException 139 { 140 Request request = ContextHelper.getRequest(_context); 141 String projectName = (String) request.getAttribute("projectName"); 142 143 Project project = _projectManager.getProject(projectName); 144 145 WorkspaceModule module = _moduleEP.getModule(ThreadWorkspaceModule.THREAD_MODULE_ID); 146 ModifiableResourceCollection threadRoot = module.getModuleRoot(project, false); 147 148 assert threadRoot != null; 149 150 return addThread(threadRoot.getId(), name, description); 151 } 152 153 @Override 154 protected void setPostContent(JCRPost post, String content) 155 { 156 try 157 { 158 _htmlTransformer.transform(content, post.getContent()); 159 } 160 catch (IOException e) 161 { 162 throw new AmetysRepositoryException("Failed to transform post content into rich text", e); 163 } 164 } 165 166 @Override 167 protected String getPostContent(JCRPost post) throws AmetysRepositoryException 168 { 169 Source contentSource = null; 170 try 171 { 172 Map<String, Object> parameters = new HashMap<>(); 173 parameters.put("source", post.getContent().getInputStream()); 174 contentSource = _sourceResolver.resolveURI("cocoon://_plugins/" + _pluginName + "/convert/html2html", null, parameters); 175 return IOUtils.toString(contentSource.getInputStream(), "UTF-8"); 176 } 177 catch (IOException e) 178 { 179 throw new AmetysRepositoryException("Failed to transform rich text into string", e); 180 } 181 finally 182 { 183 _sourceResolver.release(contentSource); 184 } 185 } 186 187 @Override 188 protected String getPostContentForEditing(JCRPost post) throws AmetysRepositoryException 189 { 190 try 191 { 192 StringBuilder sb = new StringBuilder(); 193 _htmlTransformer.transformForEditing(post.getContent(), sb); 194 return sb.toString(); 195 } 196 catch (IOException e) 197 { 198 throw new AmetysRepositoryException("Failed to transform rich text into string", e); 199 } 200 } 201}