You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lenya.apache.org by an...@apache.org on 2005/02/17 18:54:19 UTC

svn commit: r154172 - in lenya/trunk/src/java/org/apache/lenya/cms: publication/DocumentType.java publication/DocumentTypeBuilder.java site/usecases/LinkRewriter.java site/usecases/LinkRewriterImpl.java

Author: andreas
Date: Thu Feb 17 09:54:16 2005
New Revision: 154172

URL: http://svn.apache.org/viewcvs?view=rev&rev=154172
Log:
added initial version of LinkRewriter

Added:
    lenya/trunk/src/java/org/apache/lenya/cms/site/usecases/LinkRewriter.java
    lenya/trunk/src/java/org/apache/lenya/cms/site/usecases/LinkRewriterImpl.java
Modified:
    lenya/trunk/src/java/org/apache/lenya/cms/publication/DocumentType.java
    lenya/trunk/src/java/org/apache/lenya/cms/publication/DocumentTypeBuilder.java

Modified: lenya/trunk/src/java/org/apache/lenya/cms/publication/DocumentType.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/publication/DocumentType.java?view=diff&r1=154171&r2=154172
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/publication/DocumentType.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/publication/DocumentType.java Thu Feb 17 09:54:16 2005
@@ -112,4 +112,23 @@
     public String toString() {
         return getName();
     }
+
+    private String[] linkAttributeXPaths = { };
+
+    /**
+     * Returns an array of XPaths representing attributes to be rewritten
+     * when a document URL has changed.
+     * @return An array of strings.
+     */
+    public String[] getLinkAttributeXPaths() {
+        return this.linkAttributeXPaths;
+    }
+    
+    /**
+     * Sets the link attribute XPath values.
+     * @param xPaths An array of strings.
+     */
+    public void setLinkAttributeXPaths(String[] xPaths) {
+        this.linkAttributeXPaths = xPaths;
+    }
 }

Modified: lenya/trunk/src/java/org/apache/lenya/cms/publication/DocumentTypeBuilder.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/publication/DocumentTypeBuilder.java?view=diff&r1=154171&r2=154172
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/publication/DocumentTypeBuilder.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/publication/DocumentTypeBuilder.java Thu Feb 17 09:54:16 2005
@@ -21,6 +21,8 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
@@ -71,6 +73,14 @@
      * <code>WORKFLOW_ELEMENT</code> The workflow element
      */
     public static final String WORKFLOW_ELEMENT = "workflow";
+    /**
+     * <code>ELEMENT_REWRITE_ATTRIBUTE</code> The link-attribute element.
+     */
+    public static final String ELEMENT_REWRITE_ATTRIBUTE = "link-attribute";
+    /**
+     * <code>ATTRIBUTE_XPATH</code> The xpath attribute.
+     */
+    public static final String ATTRIBUTE_XPATH = "xpath";
 
     /**
      * Builds a document type for a given name.
@@ -123,6 +133,16 @@
                 String workflowFileName = workflowConf.getAttribute(SRC_ATTRIBUTE);
                 type.setWorkflowFileName(workflowFileName);
             }
+            
+            Configuration[] rewriteAttributeConfigs = doctypeConf.getChildren(ELEMENT_REWRITE_ATTRIBUTE);
+            List xPaths = new ArrayList();
+            for (int i = 0; i < rewriteAttributeConfigs.length; i++) {
+                String xPath = rewriteAttributeConfigs[i].getAttribute(ATTRIBUTE_XPATH);
+                xPaths.add(xPath);
+            }
+            String[] xPathArray = (String[]) xPaths.toArray(new String[xPaths.size()]);
+            type.setLinkAttributeXPaths(xPathArray);
+            
         } catch (final ConfigurationException e) {
             throw new DocumentTypeBuildException(e);
         } catch (final SAXException e) {

Added: lenya/trunk/src/java/org/apache/lenya/cms/site/usecases/LinkRewriter.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/site/usecases/LinkRewriter.java?view=auto&rev=154172
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/site/usecases/LinkRewriter.java (added)
+++ lenya/trunk/src/java/org/apache/lenya/cms/site/usecases/LinkRewriter.java Thu Feb 17 09:54:16 2005
@@ -0,0 +1,37 @@
+/*
+ * Copyright  1999-2004 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.lenya.cms.site.usecases;
+
+import org.apache.lenya.cms.publication.Document;
+
+/**
+ * Rewrite the links in a publication. This is used after renaming / moving a
+ * document.
+ * 
+ * @version $Id:$
+ */
+public interface LinkRewriter {
+
+    /**
+     * Rewrites the links to a document and all its descendants, including all
+     * language versions.
+     * @param originalTargetDocument The original target document.
+     * @param newTargetDocument The new target document.
+     */
+    void rewriteLinks(Document originalTargetDocument, Document newTargetDocument);
+
+}
\ No newline at end of file

Added: lenya/trunk/src/java/org/apache/lenya/cms/site/usecases/LinkRewriterImpl.java
URL: http://svn.apache.org/viewcvs/lenya/trunk/src/java/org/apache/lenya/cms/site/usecases/LinkRewriterImpl.java?view=auto&rev=154172
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/site/usecases/LinkRewriterImpl.java (added)
+++ lenya/trunk/src/java/org/apache/lenya/cms/site/usecases/LinkRewriterImpl.java Thu Feb 17 09:54:16 2005
@@ -0,0 +1,238 @@
+/*
+ * Copyright  1999-2004 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.lenya.cms.site.usecases;
+
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.Map;
+
+import org.apache.avalon.framework.context.Context;
+import org.apache.avalon.framework.context.ContextException;
+import org.apache.avalon.framework.context.Contextualizable;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.cocoon.components.ContextHelper;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Request;
+import org.apache.excalibur.source.ModifiableSource;
+import org.apache.excalibur.source.SourceResolver;
+import org.apache.lenya.cms.publication.Document;
+import org.apache.lenya.cms.publication.DocumentBuilder;
+import org.apache.lenya.cms.publication.DocumentFactory;
+import org.apache.lenya.cms.publication.DocumentIdentityMap;
+import org.apache.lenya.cms.publication.DocumentType;
+import org.apache.lenya.cms.publication.DocumentTypeResolver;
+import org.apache.lenya.cms.publication.Publication;
+import org.apache.lenya.cms.site.SiteException;
+import org.apache.lenya.cms.site.SiteManager;
+import org.apache.lenya.xml.DocumentHelper;
+import org.apache.xpath.XPathAPI;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Rewrite the links in a publication. This is used after renaming / moving a
+ * document.
+ * 
+ * @version $Id:$
+ */
+public class LinkRewriterImpl extends AbstractLogEnabled implements LinkRewriter, Serviceable,
+        Contextualizable {
+
+    /**
+     * Ctor.
+     */
+    public LinkRewriterImpl() {
+    }
+
+    /**
+     * @see org.apache.lenya.cms.site.usecases.LinkRewriter#rewriteLinks(org.apache.lenya.cms.publication.Document,
+     *      org.apache.lenya.cms.publication.Document)
+     */
+    public void rewriteLinks(Document originalTargetDocument, Document newTargetDocument) {
+
+        Publication publication = originalTargetDocument.getPublication();
+        String area = originalTargetDocument.getArea();
+        DocumentIdentityMap identityMap = originalTargetDocument.getIdentityMap();
+
+        SiteManager siteManager;
+        Document[] documents; 
+        try {
+            siteManager = publication.getSiteManager(identityMap);
+            documents = siteManager.getDocuments(area);
+        } catch (SiteException e) {
+            throw new RuntimeException(e);
+        }
+
+        DocumentFactory docFactory = identityMap.getFactory();
+
+        DocumentTypeResolver doctypeResolver = null;
+        SourceResolver sourceResolver = null;
+
+        Request request = ObjectModelHelper.getRequest(this.objectModel);
+        String contextPath = request.getContextPath();
+
+        try {
+            for (int documentIndex = 0; documentIndex < documents.length; documentIndex++) {
+
+                doctypeResolver = (DocumentTypeResolver) manager.lookup(DocumentTypeResolver.ROLE);
+                sourceResolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
+
+                Document examinedDocument = documents[documentIndex];
+                if (examinedDocument.exists()) {
+
+                    if (getLogger().isDebugEnabled()) {
+                        getLogger().debug("Rewriting links in document [" + examinedDocument + "]");
+                    }
+
+                    boolean linksRewritten = false;
+
+                    DocumentType doctype = doctypeResolver.resolve(examinedDocument);
+                    String[] xPaths = doctype.getLinkAttributeXPaths();
+                    ModifiableSource source = null;
+
+                    try {
+
+                        source = (ModifiableSource) sourceResolver.resolveURI(examinedDocument
+                                .getSourceURI());
+                        org.w3c.dom.Document xmlDocument = DocumentHelper.readDocument(source
+                                .getInputStream());
+
+                        for (int xPathIndex = 0; xPathIndex < xPaths.length; xPathIndex++) {
+                            NodeList nodes = XPathAPI.selectNodeList(xmlDocument,
+                                    xPaths[xPathIndex]);
+                            for (int nodeIndex = 0; nodeIndex < nodes.getLength(); nodeIndex++) {
+                                Node node = nodes.item(nodeIndex);
+                                if (node.getNodeType() != Node.ATTRIBUTE_NODE) {
+                                    throw new RuntimeException("The XPath [" + xPaths[xPathIndex]
+                                            + "] may only match attribute nodes!");
+                                }
+                                Attr attribute = (Attr) node;
+                                final String url = attribute.getValue();
+
+                                if (url.startsWith(contextPath + "/" + publication.getId())) {
+                                    final String webappUrl = url.substring(contextPath.length());
+
+                                    if (docFactory.isDocument(webappUrl)) {
+                                        Document targetDocument = docFactory.getFromURL(webappUrl);
+
+                                        if (matches(targetDocument, originalTargetDocument)) {
+                                            String newTargetUrl = getNewTargetURL(targetDocument,
+                                                    originalTargetDocument,
+                                                    newTargetDocument);
+                                            attribute.setValue(contextPath + newTargetUrl);
+                                            linksRewritten = true;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+
+                        if (linksRewritten) {
+                            OutputStream oStream = source.getOutputStream();
+                            Writer writer = new OutputStreamWriter(oStream);
+                            DocumentHelper.writeDocument(xmlDocument, writer);
+                            if (oStream != null) {
+                                oStream.flush();
+                                try {
+                                    oStream.close();
+                                } catch (Throwable t) {
+                                    if (getLogger().isDebugEnabled()) {
+                                        getLogger().debug("Exception closing output stream: ", t);
+                                    }
+                                    throw new RuntimeException("Could not write document: ", t);
+                                }
+                            }
+                        }
+
+                    } finally {
+                        if (source != null) {
+                            sourceResolver.release(source);
+                        }
+                    }
+
+                }
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        } finally {
+            if (doctypeResolver != null) {
+                this.manager.release(doctypeResolver);
+            }
+        }
+    }
+
+    /**
+     * Checks if targetDocument refers to originalTargetDocument, to one of its
+     * language versions, to one of its descendants, or to a language version of
+     * one of the descendants.
+     * @param targetDocument The target document.
+     * @param originalTargetDocument The original target document.
+     * @return A boolean value.
+     */
+    protected boolean matches(Document targetDocument, Document originalTargetDocument) {
+        String matchString = originalTargetDocument.getId() + "/";
+        String testString = targetDocument.getId() + "/";
+        return testString.startsWith(matchString);
+    }
+
+    /**
+     * Rewrites a document.
+     * @param targetDocument The target document to rewrite.
+     * @param originalTargetDocument The original target document.
+     * @param newTargetDocument The new target document.
+     * @return A string.
+     */
+    protected String getNewTargetURL(Document targetDocument, Document originalTargetDocument,
+            Document newTargetDocument) {
+        String originalId = originalTargetDocument.getId();
+        String targetId = targetDocument.getId();
+        String childString = targetId.substring(originalId.length());
+
+        DocumentBuilder builder = targetDocument.getPublication().getDocumentBuilder();
+        String newTargetUrl = builder.buildCanonicalUrl(newTargetDocument.getPublication(),
+                newTargetDocument.getArea(),
+                newTargetDocument.getId() + childString,
+                targetDocument.getLanguage());
+
+        return newTargetUrl;
+    }
+
+    private ServiceManager manager;
+
+    /**
+     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
+     */
+    public void service(ServiceManager manager) throws ServiceException {
+        this.manager = manager;
+    }
+
+    private Map objectModel;
+
+    /**
+     * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
+     */
+    public void contextualize(Context context) throws ContextException {
+        this.objectModel = ContextHelper.getObjectModel(context);
+
+    }
+
+}
\ No newline at end of file



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@lenya.apache.org
For additional commands, e-mail: commits-help@lenya.apache.org