/* * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package com.xpn.xwiki.internal.render; import java.io.StringWriter; import java.util.List; import java.util.Set; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Provider; import javax.inject.Singleton; import org.apache.commons.lang3.StringUtils; import org.apache.velocity.VelocityContext; import org.slf4j.Logger; import org.xwiki.component.annotation.Component; import org.xwiki.component.manager.ComponentManager; import org.xwiki.model.EntityType; import org.xwiki.model.reference.DocumentReference; import org.xwiki.model.reference.DocumentReferenceResolver; import org.xwiki.model.reference.EntityReference; import org.xwiki.model.reference.EntityReferenceResolver; import org.xwiki.model.reference.EntityReferenceSerializer; import org.xwiki.rendering.block.Block; import org.xwiki.rendering.block.XDOM; import org.xwiki.rendering.listener.reference.ResourceReference; import org.xwiki.rendering.listener.reference.ResourceType; import org.xwiki.rendering.renderer.BlockRenderer; import org.xwiki.velocity.VelocityEngine; import org.xwiki.velocity.VelocityManager; import org.xwiki.velocity.XWikiVelocityException; import com.xpn.xwiki.XWiki; import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.XWikiException; import com.xpn.xwiki.doc.XWikiDocument; import com.xpn.xwiki.doc.XWikiLink; import com.xpn.xwiki.internal.cache.rendering.RenderingCache; import com.xpn.xwiki.internal.render.groovy.ParseGroovyFromString; /** * Default implementation of {@link OldRendering} that try as much as possible to do something that makes sense without * using old rendering engine. * * @version $Id: 7e354f300b024534da3630c0a537457e52c8363d $ * @since 7.1M1 */ @Component @Singleton public class DefaultOldRendering implements OldRendering { @Inject protected Provider<RenderingCache> cache; @Inject @Named("context") protected Provider<ComponentManager> contextComponentManagerProvider; @Inject @Named("compact") protected EntityReferenceSerializer<String> compactEntityReferenceSerializer; @Inject protected DocumentReferenceResolver<EntityReference> defaultReferenceDocumentReferenceResolver; @Inject protected EntityReferenceResolver<ResourceReference> resourceReferenceResolver; @Inject protected Provider<VelocityManager> velocityManagerProvider; @Inject protected Provider<ParseGroovyFromString> parseGroovyFromString; @Inject protected Logger logger; @Inject protected LinkedResourceHelper linkedResourceHelper; @Override public void renameLinks(XWikiDocument backlinkDocument, DocumentReference oldReference, DocumentReference newReference, XWikiContext context) throws XWikiException { // FIXME: Duplicate code. See org.xwiki.refactoring.internal.DefaultLinkRefactoring#renameLinks in // xwiki-platform-refactoring-default if (this.contextComponentManagerProvider.get().hasComponent(BlockRenderer.class, backlinkDocument.getSyntax().toIdString())) { refactorDocumentLinks(backlinkDocument, oldReference, newReference, context); } } @Override public void flushCache() { this.cache.get().flushWholeCache(); } /** * @since 2.2M1 */ private void refactorDocumentLinks(XWikiDocument document, DocumentReference oldDocumentReference, DocumentReference newDocumentReference, XWikiContext context) throws XWikiException { // FIXME: Duplicate code. See org.xwiki.refactoring.internal.DefaultLinkRefactoring#renameLinks in // xwiki-platform-refactoring-default DocumentReference currentDocumentReference = document.getDocumentReference(); XDOM xdom = document.getXDOM(); List<Block> blocks = linkedResourceHelper.getBlocks(xdom); for (Block block : blocks) { ResourceReference resourceReference = linkedResourceHelper.getResourceReference(block); if (resourceReference == null) { // Skip invalid blocks. continue; } ResourceType resourceType = resourceReference.getType(); // TODO: support ATTACHMENT as well. if (!ResourceType.DOCUMENT.equals(resourceType) && !ResourceType.SPACE.equals(resourceType)) { // We are currently only interested in Document or Space references. continue; } // Resolve the resource reference. EntityReference linkEntityReference = resourceReferenceResolver.resolve(resourceReference, null, currentDocumentReference); // Resolve the document of the reference. DocumentReference linkTargetDocumentReference = defaultReferenceDocumentReferenceResolver.resolve(linkEntityReference); EntityReference newTargetReference = newDocumentReference; ResourceType newResourceType = resourceType; // If the link was resolved to a space... if (EntityType.SPACE.equals(linkEntityReference.getType())) { if (XWiki.DEFAULT_SPACE_HOMEPAGE.equals(newDocumentReference.getName())) { // If the new document reference is also a space (non-terminal doc), be careful to keep it // serialized as a space still (i.e. without ".WebHome") and not serialize it as a doc by mistake // (i.e. with ".WebHome"). newTargetReference = newDocumentReference.getLastSpaceReference(); } else { // If the new target is a non-terminal document, we can not use a "space:" resource type to access // it anymore. To fix it, we need to change the resource type of the link reference "doc:". newResourceType = ResourceType.DOCUMENT; } } // If the link targets the old (renamed) document reference, we must update it. if (linkTargetDocumentReference.equals(oldDocumentReference)) { String newReferenceString = this.compactEntityReferenceSerializer.serialize(newTargetReference, currentDocumentReference); // Update the reference in the XDOM. linkedResourceHelper.setResourceReferenceString(block, newReferenceString); linkedResourceHelper.setResourceType(block, newResourceType); } } document.setContent(xdom); } @Override public String parseContent(String content, XWikiContext xcontext) { try { if (StringUtils.isNotEmpty(content)) { VelocityManager velocityManager = this.velocityManagerProvider.get(); VelocityContext velocityContext = velocityManager.getVelocityContext(); VelocityEngine velocityEngine = velocityManager.getVelocityEngine(); StringWriter writer = new StringWriter(); velocityEngine.evaluate(velocityContext, writer, xcontext.getDoc().getPrefixedFullName(), content); return writer.toString(); } } catch (XWikiVelocityException e) { this.logger.error("Faield to parse content [" + content + "]", e); } return ""; } @Override public Set<XWikiLink> extractLinks(XWikiDocument doc, XWikiContext context) throws XWikiException { return doc.getUniqueWikiLinkedPages(context); } @Override public void resetRenderingEngine(XWikiContext context) throws XWikiException { // xwiki/1.0 specific API } @Override public String renderText(String text, XWikiDocument doc, XWikiContext xcontext) { return doc.getRenderedContent(text, doc.getSyntaxId(), xcontext); } @Override public String renderTemplate(String template, String skin, XWikiContext xcontext) { return xcontext.getWiki().parseTemplate(template, skin, xcontext); } @Override public String renderTemplate(String template, XWikiContext xcontext) { return xcontext.getWiki().parseTemplate(template, xcontext); } }