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 2006/11/09 18:16:16 UTC
svn commit: r472981 - in /lenya/trunk/src:
java/org/apache/lenya/cms/cocoon/transformation/
java/org/apache/lenya/util/ modules-core/linking/
modules-core/linking/config/ modules-core/linking/config/cocoon-xconf/
modules-core/linking/java/ modules-core...
Author: andreas
Date: Thu Nov 9 09:16:14 2006
New Revision: 472981
URL: http://svn.apache.org/viewvc?view=rev&rev=472981
Log:
Add linking module, use lenya-document link syntax in BXE
Added:
lenya/trunk/src/java/org/apache/lenya/util/Query.java
lenya/trunk/src/modules-core/linking/
lenya/trunk/src/modules-core/linking/config/
lenya/trunk/src/modules-core/linking/config/cocoon-xconf/
lenya/trunk/src/modules-core/linking/config/cocoon-xconf/linkresolver.xconf
lenya/trunk/src/modules-core/linking/config/cocoon-xconf/sourcefactory.xconf
lenya/trunk/src/modules-core/linking/java/
lenya/trunk/src/modules-core/linking/java/src/
lenya/trunk/src/modules-core/linking/java/src/org/
lenya/trunk/src/modules-core/linking/java/src/org/apache/
lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/
lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/
lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/cocoon/
lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/cocoon/source/
lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/cocoon/source/DocumentSourceFactory.java
lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/cocoon/transformation/
lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/cocoon/transformation/LinkRewritingTransformer.java
lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/linking/
lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/linking/LinkResolver.java
lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/linking/LinkResolverImpl.java
lenya/trunk/src/modules-core/linking/module.xml
Removed:
lenya/trunk/src/java/org/apache/lenya/cms/cocoon/transformation/LinkRewritingTransformer.java
Modified:
lenya/trunk/src/modules/bxe/resources/javascript/insertLink.js
lenya/trunk/src/modules/bxe/xslt/link.xsl
lenya/trunk/src/modules/sitetree/resources/javascript/navtree.js
lenya/trunk/src/modules/xhtml/sitemap.xmap
Added: lenya/trunk/src/java/org/apache/lenya/util/Query.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/java/org/apache/lenya/util/Query.java?view=auto&rev=472981
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/util/Query.java (added)
+++ lenya/trunk/src/java/org/apache/lenya/util/Query.java Thu Nov 9 09:16:14 2006
@@ -0,0 +1,100 @@
+/*
+ * Copyright 1999-2005 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.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>
+ * Utility class to analyze a query string of the form
+ * <code>key1=value1&key2=value2&...</code>.
+ * </p>
+ * <p>
+ * Invalid parts (not a valid key-value-pair) are omitted.
+ * </p>
+ */
+public class Query {
+
+ protected static final String PAIR_DELIMITER = "&";
+ protected static final String KEY_VALUE_DELIMITER = "=";
+ private String string;
+ private String pairDelimiter;
+ private String keyValueDelimiter;
+
+ /**
+ * Creates a query object with default values for the pair and key-value
+ * delimiters.
+ *
+ * @param string The query string.
+ */
+ public Query(String string) {
+ this(string, PAIR_DELIMITER, KEY_VALUE_DELIMITER);
+ }
+
+ /**
+ * Creates a query object.
+ * @param string The string.
+ * @param pairDelimiter The delimiter between key-value pairs.
+ * @param keyValueDelimiter The delimiter between key and value.
+ */
+ public Query(String string, String pairDelimiter, String keyValueDelimiter) {
+ this.string = string;
+ this.pairDelimiter = pairDelimiter;
+ this.keyValueDelimiter = keyValueDelimiter;
+ }
+
+ private Map key2value;
+
+ protected void analyze() {
+ if (this.key2value == null) {
+ this.key2value = new HashMap();
+ String[] pairs = this.string.split(getPairDelimiter());
+ for (int i = 0; i < pairs.length; i++) {
+ String[] keyAndValue = pairs[i].split(getKeyValueDelimiter());
+ if (keyAndValue.length == 2) {
+ final String key = keyAndValue[0];
+ final String value = keyAndValue[1];
+ this.key2value.put(key, value);
+ }
+ }
+ }
+ }
+
+ public String getValue(String key) {
+ analyze();
+ return (String) this.key2value.get(key);
+ }
+
+ public String getValue(String key, String defaultValue) {
+ String value = getValue(key);
+ if (value == null) {
+ return defaultValue;
+ } else {
+ return value;
+ }
+ }
+
+ public String getKeyValueDelimiter() {
+ return keyValueDelimiter;
+ }
+
+ public String getPairDelimiter() {
+ return pairDelimiter;
+ }
+
+}
Added: lenya/trunk/src/modules-core/linking/config/cocoon-xconf/linkresolver.xconf
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules-core/linking/config/cocoon-xconf/linkresolver.xconf?view=auto&rev=472981
==============================================================================
--- lenya/trunk/src/modules-core/linking/config/cocoon-xconf/linkresolver.xconf (added)
+++ lenya/trunk/src/modules-core/linking/config/cocoon-xconf/linkresolver.xconf Thu Nov 9 09:16:14 2006
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<!--
+ 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.
+-->
+
+<!-- $Id:$ -->
+
+<xconf xpath="/cocoon" unless="/cocoon/component[@role = 'org.apache.lenya.cms.linking.LinkResolver']">
+
+ <component logger="" role="org.apache.lenya.cms.linking.LinkResolver"
+ class="org.apache.lenya.cms.linking.LinkResolverImpl"/>
+
+</xconf>
Added: lenya/trunk/src/modules-core/linking/config/cocoon-xconf/sourcefactory.xconf
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules-core/linking/config/cocoon-xconf/sourcefactory.xconf?view=auto&rev=472981
==============================================================================
--- lenya/trunk/src/modules-core/linking/config/cocoon-xconf/sourcefactory.xconf (added)
+++ lenya/trunk/src/modules-core/linking/config/cocoon-xconf/sourcefactory.xconf Thu Nov 9 09:16:14 2006
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<!--
+ 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.
+-->
+
+<!-- $Id:$ -->
+
+<xconf xpath="/cocoon/source-factories" unless="/cocoon/source-factories/component-instance[@name = 'lenya-document']">
+
+ <component-instance logger="" name="lenya-document"
+ class="org.apache.lenya.cms.cocoon.source.DocumentSourceFactory"/>
+
+</xconf>
Added: lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/cocoon/source/DocumentSourceFactory.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/cocoon/source/DocumentSourceFactory.java?view=auto&rev=472981
==============================================================================
--- lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/cocoon/source/DocumentSourceFactory.java (added)
+++ lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/cocoon/source/DocumentSourceFactory.java Thu Nov 9 09:16:14 2006
@@ -0,0 +1,177 @@
+/*
+ * Copyright 1999-2005 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.cocoon.source;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Map;
+
+import org.apache.avalon.framework.configuration.Configurable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+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.avalon.framework.thread.ThreadSafe;
+import org.apache.cocoon.components.ContextHelper;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Request;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceException;
+import org.apache.excalibur.source.SourceFactory;
+import org.apache.excalibur.source.SourceResolver;
+import org.apache.lenya.cms.linking.LinkResolver;
+import org.apache.lenya.cms.publication.Document;
+import org.apache.lenya.cms.publication.DocumentException;
+import org.apache.lenya.cms.publication.DocumentFactory;
+import org.apache.lenya.cms.publication.DocumentUtil;
+import org.apache.lenya.cms.repository.RepositoryUtil;
+import org.apache.lenya.cms.repository.Session;
+import org.apache.lenya.util.Query;
+import org.apache.lenya.util.ServletHelper;
+
+/**
+ * <p>
+ * This source factory allows to access documents using their
+ * </p>
+ * <ul>
+ * <li>publication ID</li>
+ * <li>area</li>
+ * <li>UUID</li>
+ * <li>language</li>
+ * <li>revision number</li>
+ * </ul>
+ * <p>
+ * Additional parameters:
+ * </p>
+ * <ul>
+ * <li><strong>format</strong> - the resource type format</li>
+ * </ul>
+ * <p>
+ * All of these parameters are optional and default to the attributes of the
+ * document which contains the link.
+ * </p>
+ * <p>
+ * Syntax (square brackets denote optional parts):
+ * </p>
+ * <code>lenya-document:<uuid>[,lang=...][,area=...][,rev=...][,pub=...]</code>
+ */
+public class DocumentSourceFactory extends AbstractLogEnabled implements SourceFactory, ThreadSafe,
+ Contextualizable, Serviceable, Configurable {
+
+ public static final String SCHEME = "lenya-document";
+
+ private Context context;
+ private ServiceManager manager;
+
+ /**
+ * Used for resolving the object model.
+ *
+ * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
+ */
+ public void contextualize(Context context) throws ContextException {
+ this.context = context;
+ }
+
+ /**
+ * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
+ */
+ public void service(ServiceManager manager) throws ServiceException {
+ this.manager = manager;
+ }
+
+ /**
+ * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
+ */
+ public void configure(Configuration configuration) throws ConfigurationException {
+ }
+
+ /**
+ * @see org.apache.excalibur.source.SourceFactory#getSource(java.lang.String,
+ * java.util.Map)
+ */
+ public Source getSource(String location, Map parameters) throws MalformedURLException,
+ IOException, SourceException {
+
+ Map objectModel = ContextHelper.getObjectModel(this.context);
+ Request request = ObjectModelHelper.getRequest(objectModel);
+
+ String[] uriAndQuery = location.split("\\?");
+
+ String linkUri = uriAndQuery[0];
+ String queryString = null;
+ if (uriAndQuery.length > 1) {
+ queryString = uriAndQuery[1];
+ }
+
+ LinkResolver resolver = null;
+ try {
+ resolver = (LinkResolver) this.manager.lookup(LinkResolver.ROLE);
+ DocumentFactory factory = DocumentUtil.getDocumentFactory(this.manager, request);
+ String webappUrl = ServletHelper.getWebappURI(request);
+ Document currentDoc = factory.getFromURL(webappUrl);
+
+ Document doc = resolver.resolve(currentDoc, linkUri);
+
+ String format = null;
+ if (queryString != null) {
+ Query query = new Query(queryString);
+ format = query.getValue("format");
+ }
+ if (format != null) {
+ return getFormatSource(doc, format);
+ } else {
+ String lenyaURL = doc.getSourceURI();
+ Session session = RepositoryUtil.getSession(this.manager, request);
+ return new RepositorySource(manager, lenyaURL, session, getLogger());
+ }
+
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ protected Source getFormatSource(Document doc, String format) throws DocumentException,
+ ServiceException, IOException {
+ String formatBaseUri = doc.getResourceType().getFormatURI(format);
+ String formatUri = formatBaseUri + "/" + doc.getPublication().getId() + "/" + doc.getArea()
+ + "/" + doc.getUUID() + "/" + doc.getLanguage();
+
+ SourceResolver resolver = null;
+ try {
+ resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
+ return resolver.resolveURI(formatUri);
+ } finally {
+ if (resolver != null) {
+ this.manager.release(resolver);
+ }
+ }
+ }
+
+ /**
+ * @see org.apache.excalibur.source.SourceFactory#release(org.apache.excalibur.source.Source)
+ */
+ public void release(Source source) {
+ // Source will be released by delegated source factory.
+ }
+
+}
Added: lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/cocoon/transformation/LinkRewritingTransformer.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/cocoon/transformation/LinkRewritingTransformer.java?view=auto&rev=472981
==============================================================================
--- lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/cocoon/transformation/LinkRewritingTransformer.java (added)
+++ lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/cocoon/transformation/LinkRewritingTransformer.java Thu Nov 9 09:16:14 2006
@@ -0,0 +1,434 @@
+/*
+ * 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.cocoon.transformation;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.avalon.framework.activity.Disposable;
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceSelector;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Request;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.cocoon.transformation.AbstractSAXTransformer;
+import org.apache.lenya.ac.AccessControlException;
+import org.apache.lenya.ac.AccessController;
+import org.apache.lenya.ac.AccessControllerResolver;
+import org.apache.lenya.ac.AccreditableManager;
+import org.apache.lenya.ac.Policy;
+import org.apache.lenya.ac.PolicyManager;
+import org.apache.lenya.cms.linking.LinkResolver;
+import org.apache.lenya.cms.publication.Document;
+import org.apache.lenya.cms.publication.DocumentFactory;
+import org.apache.lenya.cms.publication.DocumentUtil;
+import org.apache.lenya.cms.publication.Proxy;
+import org.apache.lenya.cms.publication.Publication;
+import org.apache.lenya.cms.repository.RepositoryUtil;
+import org.apache.lenya.cms.repository.Session;
+import org.apache.lenya.util.ServletHelper;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * <p>
+ * Link rewriting transformer.
+ * </p>
+ *
+ * <p>
+ * This transformer is applied to an XHMTL document. It processes
+ * <code><xhtml:a href="..."></code> attributes of the following form:
+ * </p>
+ * <p>
+ * <code>/{publication-id}/{area}{document-url}</code>
+ * </p>
+ * <p>
+ * These links are rewritten using the following rules:
+ * </p>
+ * <ul>
+ * <li>The area is replaced by the current area (obtained from the page envelope).</li>
+ * <li>A URL prefix is added depending on the proxy configuration of the publication.</li>
+ * <li>If the target document does not exist and is in the authoring area, the href attribute is
+ * removed and a class="brokenlink" attribute is added to the <code><a/></code> element</li>
+ * <li>If the target document does not exist and is in the live area, the <code><a/></code>
+ * element is removed to disable the link.</li>
+ * </ul>
+ *
+ * $Id: LinkRewritingTransformer.java,v 1.7 2004/03/16 11:12:16 gregor
+ */
+public class LinkRewritingTransformer extends AbstractSAXTransformer implements Disposable {
+
+ protected static final String BROKEN_ATTRIB = "class";
+ protected static final String BROKEN_VALUE = "brokenlink";
+
+ private boolean ignoreAElement = false;
+ private ServiceSelector serviceSelector;
+ private PolicyManager policyManager;
+ private AccessControllerResolver acResolver;
+ private AccreditableManager accreditableManager;
+
+ private Document currentDocument;
+
+ private DocumentFactory factory;
+ private LinkResolver linkResolver;
+
+ /**
+ * @see org.apache.cocoon.sitemap.SitemapModelComponent#setup(org.apache.cocoon.environment.SourceResolver,
+ * java.util.Map, java.lang.String, org.apache.avalon.framework.parameters.Parameters)
+ */
+ public void setup(SourceResolver _resolver, Map _objectModel, String _source,
+ Parameters _parameters) throws ProcessingException, SAXException, IOException {
+ super.setup(_resolver, _objectModel, _source, _parameters);
+
+ Request _request = ObjectModelHelper.getRequest(_objectModel);
+
+ try {
+ Session session = RepositoryUtil.getSession(this.manager, _request);
+ this.factory = DocumentUtil.createDocumentFactory(this.manager, session);
+ String url = ServletHelper.getWebappURI(_request);
+ this.currentDocument = this.factory.getFromURL(url);
+ } catch (final Exception e1) {
+ throw new ProcessingException(e1);
+ }
+
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("Setting up transformer");
+ getLogger().debug(" Processed version: [" + getCurrentDocument() + "]");
+ }
+
+ this.serviceSelector = null;
+ this.acResolver = null;
+ this.policyManager = null;
+ this.linkResolver = null;
+
+ try {
+ this.serviceSelector = (ServiceSelector) this.manager.lookup(AccessControllerResolver.ROLE
+ + "Selector");
+ this.acResolver = (AccessControllerResolver) this.serviceSelector.select(AccessControllerResolver.DEFAULT_RESOLVER);
+
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug(" Resolved AC resolver [" + this.acResolver + "]");
+ }
+ String webappUrl = ServletHelper.getWebappURI(_request);
+ AccessController accessController = this.acResolver.resolveAccessController(webappUrl);
+ this.accreditableManager = accessController.getAccreditableManager();
+ this.policyManager = accessController.getPolicyManager();
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug(" Using policy manager [" + this.policyManager + "]");
+ }
+ this.linkResolver = (LinkResolver) this.manager.lookup(LinkResolver.ROLE);
+ } catch (final ServiceException e) {
+ throw new ProcessingException(e);
+ } catch (final AccessControlException e) {
+ throw new ProcessingException(e);
+ }
+ }
+
+ /**
+ * Returns the currently processed document.
+ * @return A document.
+ */
+ protected Document getCurrentDocument() {
+ return this.currentDocument;
+ }
+
+ /**
+ * The local name of the HTML <a> href attribute.
+ */
+ public static final String ATTRIBUTE_HREF = "href";
+
+ private String indent = "";
+
+ /**
+ * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String,
+ * java.lang.String, org.xml.sax.Attributes)
+ */
+ public void startElement(String uri, String name, String qname, Attributes attrs)
+ throws SAXException {
+
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug(this.indent + "<" + qname + "> (ignoreAElement = "
+ + this.ignoreAElement + ")");
+ this.indent += " ";
+ }
+
+ AttributesImpl newAttrs = null;
+ if (lookingAtAElement(name)) {
+
+ this.ignoreAElement = false;
+
+ String href = attrs.getValue(ATTRIBUTE_HREF);
+ if (href != null) {
+
+ Publication publication = getCurrentDocument().getPublication();
+
+ try {
+ newAttrs = new AttributesImpl(attrs);
+
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug(this.indent + "href URL: [" + href + "]");
+ }
+
+ if (href.startsWith("lenya-document:")) {
+
+ String anchor = null;
+ String url = null;
+
+ int anchorIndex = href.indexOf("#");
+ if (anchorIndex > -1) {
+ url = href.substring(0, anchorIndex);
+ anchor = href.substring(anchorIndex + 1);
+ } else {
+ url = href;
+ }
+
+ String[] linkUriAndQuery = url.split("\\?");
+ String linkUri = linkUriAndQuery[0];
+ String queryString = null;
+ if (linkUriAndQuery.length > 1) {
+ queryString = linkUriAndQuery[1];
+ }
+ Document targetDocument = this.linkResolver.resolve(getCurrentDocument(), linkUri);
+ String extension = targetDocument.getExtension();
+ if (extension.length() > 0) {
+ extension = "." + extension;
+ }
+ rewriteLink(newAttrs,
+ targetDocument,
+ anchor,
+ queryString,
+ extension);
+ }
+ else if (href.startsWith("/" + publication.getId())) {
+
+ final String webappUrlWithQueryString = href;
+ String webappUrlWithAnchor;
+
+ String queryString = null;
+ int queryStringIndex = webappUrlWithQueryString.indexOf("?");
+ if (queryStringIndex > -1) {
+ webappUrlWithAnchor = webappUrlWithQueryString.substring(0,
+ queryStringIndex);
+ queryString = webappUrlWithQueryString.substring(queryStringIndex + 1);
+ } else {
+ webappUrlWithAnchor = webappUrlWithQueryString;
+ }
+
+ String anchor = null;
+ String webappUrl = null;
+
+ int anchorIndex = webappUrlWithAnchor.indexOf("#");
+ if (anchorIndex > -1) {
+ webappUrl = webappUrlWithAnchor.substring(0, anchorIndex);
+ anchor = webappUrlWithAnchor.substring(anchorIndex + 1);
+ } else {
+ webappUrl = webappUrlWithAnchor;
+ }
+
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug(this.indent + "webapp URL: [" + webappUrl + "]");
+ getLogger().debug(this.indent + "anchor: [" + anchor + "]");
+ }
+ if (this.factory.isDocument(webappUrl)) {
+
+ Document targetDocument = this.factory.getFromURL(webappUrl);
+
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug(this.indent + "Resolved target document: ["
+ + targetDocument + "]");
+ }
+
+ targetDocument = this.factory.get(publication,
+ getCurrentDocument().getArea(),
+ targetDocument.getUUID(),
+ targetDocument.getLanguage());
+
+ if (targetDocument.hasLink()) {
+ String extension = "";
+ int lastDotIndex = webappUrl.lastIndexOf(".");
+ if (lastDotIndex > -1) {
+ extension = webappUrl.substring(lastDotIndex);
+ }
+ rewriteLink(newAttrs,
+ targetDocument,
+ anchor,
+ queryString,
+ extension);
+ } else if (getCurrentDocument().getArea()
+ .equals(Publication.AUTHORING_AREA)) {
+ markBrokenLink(newAttrs, href);
+ } else {
+ this.ignoreAElement = true;
+ }
+ }
+ }
+ } catch (final Exception e) {
+ getLogger().error("startElement failed: ", e);
+ throw new SAXException(e);
+ }
+ }
+
+ }
+
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug(this.indent + "ignoreAElement: " + this.ignoreAElement);
+ }
+
+ if (!(lookingAtAElement(name) && this.ignoreAElement)) {
+ if (newAttrs != null) {
+ attrs = newAttrs;
+ }
+ super.startElement(uri, name, qname, attrs);
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug(this.indent + "<" + qname + "> sent");
+ }
+ }
+ }
+
+ /**
+ * Marks a <code><a/></code> element as broken and removes href attribute.
+ *
+ * @param newAttrs The new attributes.
+ * @throws AccessControlException when something went wrong.
+ */
+ protected void markBrokenLink(AttributesImpl newAttrs, String brokenHref)
+ throws AccessControlException {
+ if (newAttrs.getIndex(BROKEN_ATTRIB) > -1)
+ newAttrs.removeAttribute(newAttrs.getIndex(BROKEN_ATTRIB));
+ if (newAttrs.getIndex("title") > -1)
+ newAttrs.removeAttribute(newAttrs.getIndex("title"));
+ if (newAttrs.getIndex("href") > -1)
+ newAttrs.setAttribute(newAttrs.getIndex("href"), "", "href", "href", "CDATA", "");
+ String warning = "Broken Link: " + brokenHref;
+ newAttrs.addAttribute("", "title", "title", "CDATA", warning);
+ newAttrs.addAttribute("", BROKEN_ATTRIB, BROKEN_ATTRIB, "CDATA", BROKEN_VALUE);
+ }
+
+ /**
+ * Rewrites a link.
+ *
+ * @param newAttrs The new attributes.
+ * @param targetDocument The target document.
+ * @param anchor The anchor (the string after the # character in the URL).
+ * @param queryString The query string without question mark.
+ * @param extension The extension to use.
+ * @throws AccessControlException when something went wrong.
+ */
+ protected void rewriteLink(AttributesImpl newAttrs, Document targetDocument, String anchor,
+ String queryString, String extension) throws AccessControlException {
+
+ String webappUrl = targetDocument.getCanonicalWebappURL();
+ Policy policy = this.policyManager.getPolicy(this.accreditableManager, webappUrl);
+
+ Proxy proxy = targetDocument.getPublication().getProxy(targetDocument,
+ policy.isSSLProtected());
+
+ String rewrittenURL;
+ if (proxy == null) {
+ rewrittenURL = this.request.getContextPath() + webappUrl;
+ } else {
+ rewrittenURL = proxy.getURL(targetDocument);
+ }
+
+ int lastDotIndex = rewrittenURL.lastIndexOf(".");
+ if (lastDotIndex > -1) {
+ rewrittenURL = rewrittenURL.substring(0, lastDotIndex) + extension;
+ }
+
+ if (anchor != null) {
+ rewrittenURL += "#" + anchor;
+ }
+
+ if (queryString != null) {
+ rewrittenURL += "?" + queryString;
+ }
+
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug(this.indent + "SSL protection: [" + policy.isSSLProtected() + "]");
+ getLogger().debug(this.indent + "Resolved proxy: [" + proxy + "]");
+ getLogger().debug(this.indent + "Rewriting URL to: [" + rewrittenURL + "]");
+ }
+
+ setHrefAttribute(newAttrs, rewrittenURL);
+ }
+
+ /**
+ * Sets the value of the href attribute.
+ *
+ * @param attr The attributes.
+ * @param value The value.
+ * @throws IllegalArgumentException if the href attribute is not contained in this attributes.
+ */
+ protected void setHrefAttribute(AttributesImpl attr, String value) {
+ int position = attr.getIndex(ATTRIBUTE_HREF);
+ if (position == -1) {
+ throw new IllegalArgumentException("The href attribute is not available!");
+ }
+ attr.setValue(position, value);
+ }
+
+ /**
+ * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String,
+ * java.lang.String)
+ */
+ public void endElement(String uri, String name, String qname) throws SAXException {
+ if (getLogger().isDebugEnabled()) {
+ this.indent = this.indent.substring(2);
+ getLogger().debug(this.indent + "</" + qname + ">");
+ }
+ if (lookingAtAElement(name) && this.ignoreAElement) {
+ this.ignoreAElement = false;
+ } else {
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug(this.indent + "</" + qname + "> sent");
+ }
+ super.endElement(uri, name, qname);
+ }
+ }
+
+ private boolean lookingAtAElement(String name) {
+ return name.equals("a");
+ }
+
+ /**
+ * @see org.apache.avalon.framework.activity.Disposable#dispose()
+ */
+ public void dispose() {
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("Disposing transformer");
+ }
+ if (this.serviceSelector != null) {
+ if (this.acResolver != null) {
+ this.serviceSelector.release(this.acResolver);
+ }
+ this.manager.release(this.serviceSelector);
+ }
+ if (this.linkResolver != null) {
+ this.manager.release(this.linkResolver);
+ }
+ }
+
+ /**
+ * @see org.apache.avalon.excalibur.pool.Recyclable#recycle()
+ */
+ public void recycle() {
+ this.ignoreAElement = false;
+ }
+}
\ No newline at end of file
Added: lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/linking/LinkResolver.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/linking/LinkResolver.java?view=auto&rev=472981
==============================================================================
--- lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/linking/LinkResolver.java (added)
+++ lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/linking/LinkResolver.java Thu Nov 9 09:16:14 2006
@@ -0,0 +1,39 @@
+/*
+ * 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.linking;
+
+import java.net.MalformedURLException;
+
+import org.apache.lenya.cms.publication.Document;
+
+/**
+ * Resolve a link from a document to another document.
+ */
+public interface LinkResolver {
+
+ String ROLE = LinkResolver.class.getName();
+
+ /**
+ * Resolve a link.
+ * @param currentDocument The document which contains the link.
+ * @param linkUri The link URI.
+ * @return A document or <code>null</code> if the target document does not exist.
+ * @throws MalformedURLException if the URI is invalid.
+ */
+ Document resolve(Document currentDocument, String linkUri) throws MalformedURLException;
+
+}
Added: lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/linking/LinkResolverImpl.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/linking/LinkResolverImpl.java?view=auto&rev=472981
==============================================================================
--- lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/linking/LinkResolverImpl.java (added)
+++ lenya/trunk/src/modules-core/linking/java/src/org/apache/lenya/cms/linking/LinkResolverImpl.java Thu Nov 9 09:16:14 2006
@@ -0,0 +1,71 @@
+/*
+ * 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.linking;
+
+import java.net.MalformedURLException;
+
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.lenya.cms.publication.Document;
+import org.apache.lenya.cms.publication.Publication;
+import org.apache.lenya.cms.publication.PublicationException;
+import org.apache.lenya.util.Query;
+
+public class LinkResolverImpl extends AbstractLogEnabled implements LinkResolver {
+
+ public static final String ROLE = LinkResolverImpl.class.getName();
+ protected static final String PAIR_DELIMITER = ",";
+ protected static final String KEY_VALUE_DELIMITER = "=";
+
+ public Document resolve(Document currentDoc, String linkUri) throws MalformedURLException {
+
+ String[] schemeAndPath = linkUri.split(":");
+ String path = schemeAndPath[1];
+
+ String pubId;
+ String uuid;
+ String area;
+ String language;
+
+ if (path.indexOf(PAIR_DELIMITER) > -1) {
+ int firstDelimiterIndex = path.indexOf(PAIR_DELIMITER);
+ uuid = path.substring(0, firstDelimiterIndex);
+ String pathQueryString = path.substring(firstDelimiterIndex + 1);
+ Query query = new Query(pathQueryString, PAIR_DELIMITER, KEY_VALUE_DELIMITER);
+ pubId = query.getValue("pub", currentDoc.getPublication().getId());
+ area = query.getValue("area", currentDoc.getArea());
+ language = query.getValue("lang", currentDoc.getLanguage());
+ } else {
+ uuid = path;
+ pubId = currentDoc.getPublication().getId();
+ area = currentDoc.getArea();
+ language = currentDoc.getLanguage();
+ }
+
+ if (uuid.length() == 0) {
+ uuid = currentDoc.getUUID();
+ }
+
+ try {
+ Publication pub = currentDoc.getFactory().getPublication(pubId);
+ Document doc = pub.getArea(area).getDocument(uuid, language);
+ return doc;
+ } catch (PublicationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
Added: lenya/trunk/src/modules-core/linking/module.xml
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules-core/linking/module.xml?view=auto&rev=472981
==============================================================================
--- lenya/trunk/src/modules-core/linking/module.xml (added)
+++ lenya/trunk/src/modules-core/linking/module.xml Thu Nov 9 09:16:14 2006
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 1999-2005 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.
+-->
+
+<!-- $Id: publication.xml 374687 2006-02-03 15:24:55Z michi $ -->
+
+<module xmlns="http://apache.org/lenya/module/1.0">
+ <id>org.apache.lenya.modules.linking</id>
+ <published>false</published>
+ <package>org.apache.lenya.modules</package>
+ <version>0.1-dev</version>
+ <name>Linking</name>
+ <lenya-version>@lenya.version@</lenya-version>
+ <description>Components to handle internal links.</description>
+</module>
Modified: lenya/trunk/src/modules/bxe/resources/javascript/insertLink.js
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/bxe/resources/javascript/insertLink.js?view=diff&rev=472981&r1=472980&r2=472981
==============================================================================
--- lenya/trunk/src/modules/bxe/resources/javascript/insertLink.js (original)
+++ lenya/trunk/src/modules/bxe/resources/javascript/insertLink.js Thu Nov 9 09:16:14 2006
@@ -12,9 +12,9 @@
window.close();
}
-function setLink(src) {
- url = src;
- document.forms["link"].url.value = url;
+function setLink(uuid) {
+ var language = CHOSEN_LANGUAGE;
+ document.forms["link"].url.value = "lenya-document:" + uuid + ",lang=" + language;
}
function insertText() {
@@ -34,7 +34,7 @@
LinkTree.prototype = new NavTree;
LinkTree.prototype.handleItemClick = function(item, event) {
- setLink(item.href);
+ setLink(item.uuid);
}
function buildTree() {
Modified: lenya/trunk/src/modules/bxe/xslt/link.xsl
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/bxe/xslt/link.xsl?view=diff&rev=472981&r1=472980&r2=472981
==============================================================================
--- lenya/trunk/src/modules/bxe/xslt/link.xsl (original)
+++ lenya/trunk/src/modules/bxe/xslt/link.xsl Thu Nov 9 09:16:14 2006
@@ -95,19 +95,15 @@
<td colspan="2"> </td>
</tr>
<tr>
- <td class="lenya-form-caption">URL:</td>
+ <td class="lenya-form-caption"><i18n:text>URL</i18n:text>:</td>
<td>
- <input class="lenya-form-element"
- type="text"
- name="url"/>
+ <input class="lenya-form-element" type="text" name="url"/>
</td>
</tr>
<tr>
- <td class="lenya-form-caption">Title:</td>
+ <td class="lenya-form-caption"><i18n:text>Title</i18n:text>:</td>
<td>
- <input class="lenya-form-element"
- type="text"
- name="title"/>
+ <input class="lenya-form-element" type="text" name="title"/>
</td>
</tr>
<tr>
Modified: lenya/trunk/src/modules/sitetree/resources/javascript/navtree.js
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/sitetree/resources/javascript/navtree.js?view=diff&rev=472981&r1=472980&r2=472981
==============================================================================
--- lenya/trunk/src/modules/sitetree/resources/javascript/navtree.js (original)
+++ lenya/trunk/src/modules/sitetree/resources/javascript/navtree.js Thu Nov 9 09:16:14 2006
@@ -23,6 +23,7 @@
this.parent = parent;
this.items = {};
this.isfolder = false;
+ this.uuid = '';
this.href = '';
this.label = '';
this.area = '';
@@ -42,6 +43,7 @@
newItem.isfolder = isNodeFolder(node);
newItem.area = this.area;
newItem.path = node.getAttribute('basic-url');
+ newItem.uuid = node.getAttribute('uuid');
newItem.isprotected = isNodeProtected(node);
newItem.href = node.getAttribute('href');
newItem.label = getLabel(node);
Modified: lenya/trunk/src/modules/xhtml/sitemap.xmap
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/xhtml/sitemap.xmap?view=diff&rev=472981&r1=472980&r2=472981
==============================================================================
--- lenya/trunk/src/modules/xhtml/sitemap.xmap (original)
+++ lenya/trunk/src/modules/xhtml/sitemap.xmap Thu Nov 9 09:16:14 2006
@@ -92,7 +92,7 @@
<!-- parametrized doctype matcher -->
<!-- pattern="{rendertype}" -->
<map:match pattern="*.xml">
- <map:generate src="lenyadoc:/{page-envelope:document-language}/{page-envelope:document-id}"/>
+ <map:generate src="lenya-document:{page-envelope:document-uuid},lang={page-envelope:document-language}"/>
<map:transform src="fallback://lenya/modules/xhtml/xslt/xhtml2xhtml.xsl">
<map:parameter name="rendertype" value="{request-param:rendertype}"/>
<map:parameter name="nodeid" value="{page-envelope:document-name}"/>
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@lenya.apache.org
For additional commands, e-mail: commits-help@lenya.apache.org