com.xpn.xwiki.internal.render.XWiki10OldRendering.java Source code

Java tutorial

Introduction

Here is the source code for com.xpn.xwiki.internal.render.XWiki10OldRendering.java

Source

/*
 * 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.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import javax.inject.Inject;
import javax.inject.Singleton;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.xwiki.component.annotation.Component;
import org.xwiki.component.phase.Initializable;
import org.xwiki.component.phase.InitializationException;
import org.xwiki.context.Execution;
import org.xwiki.context.ExecutionContext;
import org.xwiki.localization.ContextualLocalizationManager;
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.rendering.renderer.BlockRenderer;

import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.XWikiException;
import com.xpn.xwiki.content.Link;
import com.xpn.xwiki.content.parsers.DocumentParser;
import com.xpn.xwiki.content.parsers.RenamePageReplaceLinkHandler;
import com.xpn.xwiki.content.parsers.ReplacementResultCollection;
import com.xpn.xwiki.doc.XWikiDocument;
import com.xpn.xwiki.doc.XWikiLink;
import com.xpn.xwiki.render.XWikiRenderer;
import com.xpn.xwiki.render.XWikiRenderingEngine;
import com.xpn.xwiki.web.Utils;

/**
 * Override and extends {@link DefaultOldRendering} with xwiki/1.0 and old rendering framework based implementation
 * specific behaviors.
 * 
 * @version $Id: 4378083bc5212309a3d802f1eecb0f573989b679 $
 * @since 7.1M1
 */
@Component
@Singleton
public class XWiki10OldRendering extends DefaultOldRendering {
    @Inject
    private XWikiRenderingEngine engine;

    @Inject
    private ContextualLocalizationManager localization;

    @Inject
    private Execution execution;

    @Override
    public void flushCache() {
        this.engine.flushCache();

        super.flushCache();
    }

    @Override
    public void resetRenderingEngine(XWikiContext xcontext) throws XWikiException {
        if (this.engine instanceof Initializable) {
            try {
                ((Initializable) engine).initialize();
            } catch (InitializationException e) {
                throw new XWikiException(XWikiException.MODULE_XWIKI_RENDERING, XWikiException.ERROR_XWIKI_UNKNOWN,
                        "Failed to initialize rendering engine", e);
            }
        }

        super.resetRenderingEngine(xcontext);
    }

    @Override
    public void renameLinks(XWikiDocument backlinkDocument, DocumentReference oldReference,
            DocumentReference newReference, XWikiContext context) throws XWikiException {
        if (backlinkDocument.is10Syntax()) {
            Link oldLink = createLink(oldReference);
            Link newLink = createLink(newReference);

            // For each backlink to rename, parse the backlink document and replace the links with the new name.
            // Note: we ignore invalid links here. Invalid links should be shown to the user so
            // that they fix them but the rename feature ignores them.
            DocumentParser documentParser = new DocumentParser();

            // This link handler recognizes that 2 links are the same when they point to the same
            // document (regardless of query string, target or alias). It keeps the query string,
            // target and alias from the link being replaced.
            RenamePageReplaceLinkHandler linkHandler = new RenamePageReplaceLinkHandler();

            // Note: Here we cannot do a simple search/replace as there are several ways to point
            // to the same document. For example [Page], [Page?param=1], [currentwiki:Page],
            // [CurrentSpace.Page] all point to the same document. Thus we have to parse the links
            // to recognize them and do the replace.
            ReplacementResultCollection result = documentParser.parseLinksAndReplace(backlinkDocument.getContent(),
                    oldLink, newLink, linkHandler,
                    backlinkDocument.getDocumentReference().getLastSpaceReference().getName());

            backlinkDocument.setContent((String) result.getModifiedContent());
        } else if (Utils.getContextComponentManager().hasComponent(BlockRenderer.class,
                backlinkDocument.getSyntax().toIdString())) {
            super.renameLinks(backlinkDocument, oldReference, newReference, context);
        }

        // Save if content changed
        if (backlinkDocument.isContentDirty()) {
            String saveMessage = localizePlainOrKey("core.comment.renameLink",
                    this.compactEntityReferenceSerializer.serialize(newReference));
            backlinkDocument.setAuthorReference(context.getUserReference());
            context.getWiki().saveDocument(backlinkDocument, saveMessage, true, context);
        }
    }

    private Link createLink(DocumentReference documentReference) {
        Link link = new Link();

        link.setVirtualWikiAlias(documentReference.getWikiReference().getName());
        link.setSpace(documentReference.getLastSpaceReference().getName());
        link.setPage(documentReference.getName());

        return link;
    }

    @Override
    public String renderText(String text, XWikiDocument doc, XWikiContext xcontext) {
        return this.engine.renderText(text, doc, xcontext);
    }

    @Override
    public String renderTemplate(String template, XWikiContext xcontext) {
        return this.engine.getRenderer("wiki").render(xcontext.getWiki().parseTemplate(template, xcontext),
                xcontext.getDoc(), xcontext.getDoc(), xcontext);
    }

    @Override
    public String renderTemplate(String template, String skin, XWikiContext xcontext) {
        return this.engine.getRenderer("wiki").render(xcontext.getWiki().parseTemplate(template, skin, xcontext),
                xcontext.getDoc(), xcontext.getDoc(), xcontext);
    }

    @Override
    public String parseContent(String content, XWikiContext xcontext) {
        String parsedContent;

        if (StringUtils.isNotEmpty(content)) {
            parsedContent = this.engine.interpretText(content, xcontext.getDoc(), xcontext);
        } else {
            parsedContent = "";
        }

        return parsedContent;
    }

    private String localizePlainOrKey(String key, Object... parameters) {
        return StringUtils.defaultString(this.localization.getTranslationPlain(key, parameters), key);
    }

    @Override
    public Set<XWikiLink> extractLinks(XWikiDocument doc, XWikiContext xcontext) throws XWikiException {
        if (doc.is10Syntax()) {
            // call to RenderEngine and converting the list of links into a list of backlinks
            // Note: We need to set the passed document as the current document as the "wiki"
            // renderer uses context.getDoc().getSpace() to find out the space name if no
            // space is specified in the link. A better implementation would be to pass
            // explicitly the current space to the render() method.
            ExecutionContext econtext = this.execution.getContext();

            List<String> linkReferences;
            try {
                // Create new clean context to avoid wiki module requests in same session
                XWikiContext renderContext = xcontext.clone();

                renderContext.setDoc(doc);
                econtext.setProperty("xwikicontext", renderContext);

                setSession(null, renderContext);
                setTransaction(null, renderContext);

                XWikiRenderer renderer = this.engine.getRenderer("wiki");
                renderer.render(doc.getContent(), doc, doc, renderContext);

                linkReferences = (List<String>) renderContext.get("links");
            } catch (Exception e) {
                // If the rendering fails lets forget backlinks without errors
                linkReferences = Collections.emptyList();
            } finally {
                econtext.setProperty("xwikicontext", xcontext);
            }

            if (linkReferences != null) {
                Set<XWikiLink> links = new LinkedHashSet<>(linkReferences.size());
                for (String reference : linkReferences) {
                    // XWikiLink is the object declared in the Hibernate mapping
                    XWikiLink link = new XWikiLink();
                    link.setDocId(doc.getId());
                    link.setFullName(doc.getFullName());
                    link.setLink(reference);

                    links.add(link);
                }

                return links;
            }

            return Collections.emptySet();
        }

        return super.extractLinks(doc, xcontext);
    }

    /**
     * Allows to set the current session in the context This is set in beginTransaction
     *
     * @param session
     * @param context
     */
    private void setSession(Session session, XWikiContext context) {
        if (session == null) {
            context.remove("hibsession");
        } else {
            context.put("hibsession", session);
        }
    }

    /**
     * Allows to set the current transaction This is set in beginTransaction
     *
     * @param transaction
     * @param context
     */
    private void setTransaction(Transaction transaction, XWikiContext context) {
        if (transaction == null) {
            context.remove("hibtransaction");
        } else {
            context.put("hibtransaction", transaction);
        }
    }
}