001/* 002 * Copyright 2017 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.frontedition; 017 018import java.io.IOException; 019import java.util.Arrays; 020import java.util.HashMap; 021import java.util.Map; 022import java.util.Set; 023 024import javax.jcr.Node; 025import javax.jcr.RepositoryException; 026import javax.jcr.lock.LockManager; 027 028import org.apache.avalon.framework.parameters.Parameters; 029import org.apache.avalon.framework.service.ServiceException; 030import org.apache.avalon.framework.service.ServiceManager; 031import org.apache.cocoon.ProcessingException; 032import org.apache.cocoon.environment.ObjectModelHelper; 033import org.apache.cocoon.environment.Redirector; 034import org.apache.cocoon.environment.Request; 035import org.apache.cocoon.environment.SourceResolver; 036import org.apache.commons.lang.StringUtils; 037 038import org.ametys.cms.content.GetMetadataSetDefAction; 039import org.ametys.cms.content.external.ExternalizableMetadataProviderExtensionPoint; 040import org.ametys.cms.contenttype.ContentTypesHelper; 041import org.ametys.cms.contenttype.MetadataDefinition; 042import org.ametys.cms.contenttype.MetadataType; 043import org.ametys.cms.repository.Content; 044import org.ametys.cms.transformation.RichTextTransformer; 045import org.ametys.core.cocoon.JSonReader; 046import org.ametys.core.right.RightManager; 047import org.ametys.core.user.CurrentUserProvider; 048import org.ametys.plugins.repository.AmetysObject; 049import org.ametys.plugins.repository.AmetysObjectResolver; 050import org.ametys.plugins.repository.AmetysRepositoryException; 051import org.ametys.plugins.repository.jcr.JCRAmetysObject; 052import org.ametys.plugins.repository.lock.LockHelper; 053import org.ametys.plugins.repository.lock.LockableAmetysObject; 054import org.ametys.plugins.repository.metadata.CompositeMetadata; 055import org.ametys.plugins.repository.metadata.ModifiableRichText; 056import org.ametys.plugins.repository.version.VersionableAmetysObject; 057import org.ametys.web.renderingcontext.RenderingContext; 058import org.ametys.web.renderingcontext.RenderingContextHandler; 059 060/** 061 * Check if the content can be edited, and return the value 062 */ 063public class GetServerValueAction extends GetMetadataSetDefAction 064{ 065 066 /** The ametys object resolver */ 067 protected AmetysObjectResolver _resolver; 068 /** The rendering context handler */ 069 protected RenderingContextHandler _renderingContextHandler; 070 071 @Override 072 public void service(ServiceManager serviceManager) throws ServiceException 073 { 074 super.service(serviceManager); 075 _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 076 _rightManager = (RightManager) manager.lookup(RightManager.ROLE); 077 _currentUserProvider = (CurrentUserProvider) manager.lookup(CurrentUserProvider.ROLE); 078 _renderingContextHandler = (RenderingContextHandler) manager.lookup(RenderingContextHandler.ROLE); 079 _contentTypesHelper = (ContentTypesHelper) manager.lookup(ContentTypesHelper.ROLE); 080 _externalizableMetaProvider = (ExternalizableMetadataProviderExtensionPoint) manager.lookup(ExternalizableMetadataProviderExtensionPoint.ROLE); 081 } 082 083 @Override 084 public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception 085 { 086 Request request = ObjectModelHelper.getRequest(objectModel); 087 088 String contentId = parameters.getParameter("contentId"); 089 String metadataPath = parameters.getParameter("metadataPath"); 090 boolean validateContent = parameters.getParameterAsBoolean("validateContent", false); 091 String metadataSetName = parameters.getParameter("metadataSetName", "main"); 092 093 Map<String, Object> jsonObject = new HashMap<>(); 094 boolean success = true; 095 096 Content content = _resolver.resolveById(contentId); 097 if (isContentLocked(content)) 098 { 099 success = false; 100 jsonObject.put("error", "locked"); 101 } 102 else if (validateContent) 103 { 104 RenderingContext context = _renderingContextHandler.getRenderingContext(); 105 if (context == RenderingContext.FRONT && content instanceof VersionableAmetysObject) 106 { 107 String[] labels = ((VersionableAmetysObject) content).getLabels(); 108 if (!Arrays.asList(labels).contains("Live")) 109 { 110 success = false; 111 jsonObject.put("error", "draft"); 112 } 113 } 114 } 115 116 if (success) 117 { 118 jsonObject.putAll(_contentMetadata2Json(metadataSetName, content, metadataPath)); 119 } 120 121 request.setAttribute(JSonReader.OBJECT_TO_READ, jsonObject); 122 return EMPTY_MAP; 123 } 124 125 /** 126 * Check if the content is locked 127 * @param content The content 128 * @return True if the content is locked 129 */ 130 protected boolean isContentLocked(Content content) 131 { 132 if (!(content instanceof JCRAmetysObject)) 133 { 134 return false; 135 } 136 137 try 138 { 139 Node node = ((JCRAmetysObject) content).getNode(); 140 LockManager lockManager = node.getSession().getWorkspace().getLockManager(); 141 142 if (lockManager.isLocked(node.getPath())) 143 { 144 Node lockHolder = lockManager.getLock(node.getPath()).getNode(); 145 146 AmetysObject ao = _resolver.resolve(lockHolder, false); 147 if (ao instanceof LockableAmetysObject) 148 { 149 LockableAmetysObject lockableAO = (LockableAmetysObject) ao; 150 if (!LockHelper.isLockOwner(lockableAO, _currentUserProvider.getUser())) 151 { 152 return true; 153 } 154 } 155 } 156 } 157 catch (RepositoryException e) 158 { 159 getLogger().error(String.format("Repository exception during lock checking for ametys object '%s'", content.getId()), e); 160 throw new AmetysRepositoryException(e); 161 } 162 163 return false; 164 } 165 166 private Map<String, Object> _contentMetadata2Json(String metadataSetName, Content content, String metadataPath) throws ProcessingException 167 { 168 String[] metadataPathSplit = metadataPath.split("/"); 169 MetadataDefinition metaDef = null; 170 CompositeMetadata metadataHolder = content.getMetadataHolder(); 171 String lastPart = null; 172 for (String metadataPathPart : metadataPathSplit) 173 { 174 lastPart = metadataPathPart; 175 if (metaDef == null) 176 { 177 metaDef = _contentTypesHelper.getMetadataDefinition(metadataPathPart, content.getTypes(), content.getMixinTypes()); 178 } 179 else 180 { 181 metaDef = metaDef.getMetadataDefinition(metadataPathPart); 182 } 183 184 if (metaDef == null) 185 { 186 throw new ProcessingException(String.format("Unknown metadata path '%s' in metadata set '%s' of type '%s' for content type(s) '%s'", 187 metadataPath, metadataSetName, "edition", StringUtils.join(content.getTypes(), ','))); 188 } 189 190 if (MetadataType.COMPOSITE.equals(metaDef.getType())) 191 { 192 metadataHolder = metadataHolder.getCompositeMetadata(metadataPathPart); 193 } 194 } 195 196 Set<String> externalAndLocalMetadata = _externalizableMetaProvider.getExternalAndLocalMetadata(content); 197 198 Map<String, Object> jsonObject = metadataDefinition2JsonObject(content, null, metaDef, metadataPath, externalAndLocalMetadata); 199 if (metaDef != null) 200 { 201 if (MetadataType.RICH_TEXT.equals(metaDef.getType())) 202 { 203 RichTextTransformer richTextTransformer = metaDef.getRichTextTransformer(); 204 StringBuilder result = new StringBuilder(2048); 205 if (metadataHolder.hasMetadata(lastPart)) 206 { 207 try 208 { 209 richTextTransformer.transformForEditing((ModifiableRichText) metadataHolder.getRichText(lastPart), result); 210 } 211 catch (IOException e) 212 { 213 throw new AmetysRepositoryException("Unable to transform a rich text into a string", e); 214 } 215 jsonObject.put("value", result.toString()); 216 } 217 else 218 { 219 jsonObject.put("value", ""); 220 } 221 } 222 else 223 { 224 jsonObject.put("value", metaDef.isMultiple() ? metadataHolder.getStringArray(lastPart, null) : metadataHolder.getString(lastPart, null)); 225 } 226 } 227 return jsonObject; 228 } 229 230}