001/* 002 * Copyright 2010 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 */ 016 017package org.ametys.cms.content; 018 019import java.io.IOException; 020import java.util.ArrayList; 021import java.util.List; 022import java.util.Map; 023import java.util.Optional; 024 025import org.apache.avalon.framework.service.ServiceException; 026import org.apache.avalon.framework.service.ServiceManager; 027import org.apache.cocoon.ProcessingException; 028import org.apache.cocoon.environment.ObjectModelHelper; 029import org.apache.cocoon.generation.ServiceableGenerator; 030import org.apache.cocoon.xml.AttributesImpl; 031import org.apache.cocoon.xml.XMLUtils; 032import org.apache.commons.lang3.StringUtils; 033import org.xml.sax.SAXException; 034 035import org.ametys.cms.clientsideelement.ContentConsistencyTestClientSideElement; 036import org.ametys.cms.content.references.OutgoingReferences; 037import org.ametys.cms.contenttype.ContentTypesHelper; 038import org.ametys.cms.repository.Content; 039import org.ametys.cms.transformation.ConsistencyChecker; 040import org.ametys.cms.transformation.ConsistencyChecker.CHECK; 041import org.ametys.cms.transformation.ConsistencyChecker.CheckReport; 042import org.ametys.core.right.RightManager; 043import org.ametys.core.right.RightManager.RightResult; 044import org.ametys.plugins.repository.AmetysObjectResolver; 045import org.ametys.plugins.repository.UnknownAmetysObjectException; 046import org.ametys.plugins.repository.data.type.ModelItemTypeConstants; 047import org.ametys.runtime.i18n.I18nizableText; 048import org.ametys.runtime.model.ModelHelper; 049import org.ametys.runtime.model.ModelItem; 050import org.ametys.runtime.model.exception.UndefinedItemPathException; 051 052/** 053 * Generates the consistency report for the given content 054 */ 055public class ConsistencyGenerator extends ServiceableGenerator 056{ 057 /** Repository content */ 058 protected AmetysObjectResolver _resolver; 059 /** The consistency checker */ 060 protected ConsistencyChecker _consistencyChecker; 061 /** The content types helper */ 062 protected ContentTypesHelper _contentTypesHelper; 063 /** The content helper */ 064 protected ContentHelper _contentHelper; 065 /** The right manager */ 066 protected RightManager _rightManager; 067 068 @Override 069 public void service(ServiceManager smanager) throws ServiceException 070 { 071 super.service(smanager); 072 _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE); 073 _consistencyChecker = (ConsistencyChecker) smanager.lookup(ConsistencyChecker.ROLE); 074 _contentTypesHelper = (ContentTypesHelper) smanager.lookup(ContentTypesHelper.ROLE); 075 _contentHelper = (ContentHelper) smanager.lookup(ContentHelper.ROLE); 076 _rightManager = (RightManager) smanager.lookup(RightManager.ROLE); 077 } 078 079 @Override 080 public void generate() throws IOException, SAXException, ProcessingException 081 { 082 contentHandler.startDocument(); 083 XMLUtils.startElement(contentHandler, "contents"); 084 085 @SuppressWarnings("unchecked") 086 Map<String, Object> jsParameters = (Map<String, Object>) objectModel.get(ObjectModelHelper.PARENT_CONTEXT); 087 @SuppressWarnings("unchecked") 088 List<String> contentsId = (List<String>) jsParameters.get("contentsId"); 089 for (String contentId : contentsId) 090 { 091 try 092 { 093 Content content = _resolver.resolveById(contentId); 094 095 boolean hasRight = _rightManager.currentUserHasRight(ContentConsistencyTestClientSideElement.RIGHTS_CONTENT_CONSISTENCY, content) == RightResult.RIGHT_ALLOW; 096 097 AttributesImpl attrs = new AttributesImpl(); 098 attrs.addCDATAAttribute("id", content.getId()); 099 attrs.addCDATAAttribute("title", _contentHelper.getTitle(content)); 100 if (hasRight) 101 { 102 attrs.addCDATAAttribute("name", content.getName()); 103 attrs.addCDATAAttribute("path", content.getPath()); 104 attrs.addCDATAAttribute("type", StringUtils.join(content.getTypes(), ',')); 105 if (content.getLanguage() != null) 106 { 107 attrs.addCDATAAttribute("lang", content.getLanguage()); 108 } 109 } 110 111 XMLUtils.startElement(contentHandler, "content", attrs); 112 113 if (hasRight) 114 { 115 List<ModelItem> modelItemsToSax = new ArrayList<>(); 116 Map<String, OutgoingReferences> referencesByPath = content.getOutgoingReferences(); 117 118 for (String dataPath : referencesByPath.keySet()) 119 { 120 try 121 { 122 List<ModelItem> modelItemPath = _contentTypesHelper.getModelItemPath(dataPath, content); 123 124 // Add these model items to the set of model items to SAX. 125 modelItemsToSax.addAll(modelItemPath); 126 127 saxReferencesConsistency(content, referencesByPath.get(dataPath), dataPath); 128 } 129 catch (UndefinedItemPathException e) 130 { 131 getLogger().warn("Trying to check consistency for a item path that doesn't exist in the model. Reference will be ignored", e); 132 } 133 } 134 135 // SAX model items used for this content 136 for (ModelItem modelItem : modelItemsToSax) 137 { 138 attrs.clear(); 139 attrs.addCDATAAttribute("path", modelItem.getPath()); 140 attrs.addCDATAAttribute("is-repeater", Boolean.toString(ModelItemTypeConstants.REPEATER_TYPE_ID.equals(modelItem.getType().getId()))); 141 XMLUtils.startElement(contentHandler, "metadata-definition", attrs); 142 modelItem.getLabel().toSAX(contentHandler); 143 XMLUtils.endElement(contentHandler, "metadata-definition"); 144 } 145 } 146 else 147 { 148 XMLUtils.createElement(contentHandler, "no-right"); 149 } 150 151 XMLUtils.endElement(contentHandler, "content"); 152 } 153 catch (UnknownAmetysObjectException e) 154 { 155 getLogger().warn("Can not check consistency of non existing content '" + contentId + "'"); 156 } 157 } 158 159 XMLUtils.endElement(contentHandler, "contents"); 160 contentHandler.endDocument(); 161 } 162 163 /** 164 * Check consistency for each outgoing references and generate SAX event for the result. 165 * @param content the content containing the references 166 * @param references the outgoing references 167 * @param dataPath the path of the data containing the outgoing references 168 * @throws SAXException if an error occurred 169 */ 170 protected void saxReferencesConsistency(Content content, OutgoingReferences references, String dataPath) throws SAXException 171 { 172 // SAX'ing consistency info 173 String definitionPath = ModelHelper.getDefinitionPathFromDataPath(dataPath); 174 for (String referenceType : references.keySet()) 175 { 176 for (String referenceValue : references.get(referenceType)) 177 { 178 AttributesImpl attrs = new AttributesImpl(); 179 attrs.addCDATAAttribute("type", referenceType); 180 attrs.addCDATAAttribute("element", referenceValue); 181 attrs.addCDATAAttribute("path", definitionPath); 182 183 CheckReport report; 184 try 185 { 186 report = _consistencyChecker.checkConsistency(referenceType, referenceValue, content.getId(), dataPath, false); 187 } 188 catch (Exception e) 189 { 190 // Consider it a failure. 191 report = new CheckReport(CHECK.SERVER_ERROR, Optional.ofNullable(e.getMessage())); 192 } 193 194 String elementName; 195 switch (report.status()) 196 { 197 case SUCCESS: 198 elementName = "success"; 199 break; 200 case UNKNOWN: 201 elementName = "unknown"; 202 break; 203 case UNAUTHORIZED: 204 elementName = "unauthorized"; 205 break; 206 case NOT_FOUND: 207 elementName = "not-found"; 208 break; 209 case SERVER_ERROR: 210 default: 211 elementName = "server-error"; 212 break; 213 } 214 XMLUtils.startElement(contentHandler, elementName, attrs); 215 I18nizableText label = _consistencyChecker.getLabel(referenceType, referenceValue, content.getId(), dataPath); 216 label.toSAX(contentHandler, "label"); 217 if (report.message().isPresent()) 218 { 219 XMLUtils.createElement(contentHandler, "message", report.message().get()); 220 } 221 XMLUtils.endElement(contentHandler, elementName); 222 } 223 } 224 } 225}