| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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.cocoon.generation; |
| |
| import java.io.IOException; |
| import java.util.Map; |
| |
| import org.apache.avalon.framework.parameters.Parameters; |
| import org.apache.cocoon.ProcessingException; |
| import org.apache.cocoon.xml.XMLUtils; |
| import org.apache.cocoon.components.source.InspectableSource; |
| import org.apache.cocoon.components.source.LockableSource; |
| import org.apache.cocoon.components.source.RestrictableSource; |
| import org.apache.cocoon.components.source.VersionableSource; |
| import org.apache.cocoon.components.source.helpers.GroupSourcePermission; |
| import org.apache.cocoon.components.source.helpers.PrincipalSourcePermission; |
| import org.apache.cocoon.components.source.helpers.SourceLock; |
| import org.apache.cocoon.components.source.helpers.SourcePermission; |
| import org.apache.cocoon.components.source.helpers.SourceProperty; |
| import org.apache.cocoon.environment.SourceResolver; |
| import org.apache.excalibur.source.SourceException; |
| import org.apache.excalibur.source.TraversableSource; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.helpers.AttributesImpl; |
| |
| /** |
| * This Generator augments the output of the TraversableGenerator. |
| * <p> |
| * It adds: |
| * <ul> |
| * <li>version information if the Source implements VersionableSource.</li> |
| * <li>locking information if the Source implements Lockablesource.</li> |
| * <li>permission information if the Source implements RestrictableSource.</li> |
| * <li>and describes its SourceProperties if the Source implements InspectableSource.</li> |
| * </ul> |
| * </p> |
| * <p> |
| * Sitemap parameters that can be specified to control processing are: |
| * <ul> |
| * <li><code>version</code> (<code>true</code>) |
| * whether to generate versioning information.</li> |
| * <li><code>locking</code> (<code>true</code>) |
| * whether to generate locking information.</li> |
| * <li><code>permission</code> (<code>true</code>) |
| * whether to generate permission information.</li> |
| * <li><code>properties</code> (<code>true</code>) |
| * whether to generate source property information.</li> |
| * </ul> |
| * </p> |
| * |
| * @author <a href="mailto:stephan@apache.org">Stephan Michels</a> |
| * @author <a href="mailto:unico@hippo.nl">Unico Hommes</a> |
| * @version $Id$ |
| */ |
| public class TraversableSourceDescriptionGenerator extends TraversableGenerator { |
| |
| protected static final String MIME_TYPE_ATTR_NAME = "mimeType"; |
| |
| private static final String REVISION_ATTR_NAME = "revision"; |
| private static final String REVISIONBRANCH_ATTR_NAME = "branch"; |
| |
| private static final String PROPERTIES_NODE_NAME = "properties"; |
| private static final String PROPERTIES_NODE_QNAME = PREFIX + ":" + PROPERTIES_NODE_NAME; |
| |
| private static final String PERMISSIONS_NODE_NAME = "permissions"; |
| private static final String PERMISSIONS_NODE_QNAME = PREFIX + ":" + PERMISSIONS_NODE_NAME; |
| private static final String PERMISSION_NODE_NAME = "permission"; |
| private static final String PERMISSION_NODE_QNAME = PREFIX + ":" + PERMISSION_NODE_NAME; |
| |
| private static final String LOCKS_NODE_NAME = "locks"; |
| private static final String LOCKS_NODE_QNAME = PREFIX + ":" + LOCKS_NODE_NAME; |
| private static final String LOCK_NODE_NAME = "lock"; |
| private static final String LOCK_NODE_QNAME = PREFIX + ":" + LOCK_NODE_NAME; |
| |
| private static final String PRINCIPAL_ATTR_NAME = "principal"; |
| private static final String GROUP_ATTR_NAME = "group"; |
| private static final String PRIVILEGE_ATTR_NAME = "privilege"; |
| private static final String INHERITABLE_ATTR_NAME = "inheritable"; |
| private static final String NEGATIVE_ATTR_NAME = "negative"; |
| |
| private static final String TYPE_ATTR_NAME = "type"; |
| private static final String EXPIRATION_ATTR_NAME = "expiration"; |
| private static final String EXCLUSIVE_ATTR_NAME = "exclusive"; |
| |
| |
| /** Include properties into the description */ |
| private boolean properties = true; |
| |
| /** Include permissions into the description */ |
| private boolean permissions = true; |
| |
| /** Include locks into the description */ |
| private boolean locks = true; |
| |
| /** Include version into the description */ |
| private boolean version = true; |
| |
| |
| /** |
| * Set the <code>SourceResolver</code>, objectModel <code>Map</code>, |
| * the source and sitemap <code>Parameters</code> used to process the request. |
| * |
| * @param resolver Source Resolver |
| * @param objectModel Object model. |
| * @param location Location of the source. |
| * @param parameters Parameters for the generator. |
| */ |
| public void setup(SourceResolver resolver, Map objectModel, |
| String location, |
| Parameters parameters) |
| throws ProcessingException, SAXException, IOException { |
| |
| super.setup(resolver, objectModel, location, parameters); |
| |
| this.properties = parameters.getParameterAsBoolean("properties", true); |
| super.cacheKeyParList.add(String.valueOf(String.valueOf(this.properties))); |
| |
| this.permissions = parameters.getParameterAsBoolean("permissions", true); |
| super.cacheKeyParList.add(String.valueOf(this.permissions)); |
| |
| this.locks = parameters.getParameterAsBoolean("locks", true); |
| super.cacheKeyParList.add(String.valueOf(this.locks)); |
| |
| this.version = parameters.getParameterAsBoolean("version", true); |
| super.cacheKeyParList.add(String.valueOf(this.version)); |
| |
| if (getLogger().isDebugEnabled()) { |
| getLogger().debug("properties: " + this.properties); |
| getLogger().debug("permissions: " + this.permissions); |
| getLogger().debug("locks: " + this.locks); |
| getLogger().debug("version: " + this.version); |
| } |
| } |
| |
| /** |
| * Augments source nodes with additional information. |
| * |
| * @param source the Source to describe. |
| */ |
| protected final void addContent(TraversableSource source) |
| throws SAXException, ProcessingException { |
| |
| super.addContent(source); |
| try { |
| if (this.properties && (source instanceof InspectableSource)) { |
| pushSourceProperties((InspectableSource) source); |
| } |
| if (this.permissions && (source instanceof RestrictableSource)) { |
| pushSourcePermissions((RestrictableSource) source); |
| } |
| if (this.locks && (source instanceof LockableSource)) { |
| pushSourceLocks((LockableSource) source); |
| } |
| } catch (SourceException e) { |
| throw new ProcessingException(e); |
| } |
| |
| } |
| |
| /** |
| * Augments source node elements with additional attributes describing the Source. |
| * The additional attributes are a <code>mimeType</code> attribute, |
| * and iff the Source is an instance of VersionableSource and the generator |
| * is configured to output versioning information two attributes: |
| * <code>revision</code> and <code>branch</code>. |
| * |
| * @param source the Source to describe. |
| */ |
| protected void setNodeAttributes(TraversableSource source) throws SAXException, ProcessingException { |
| super.setNodeAttributes(source); |
| if (!source.isCollection()) { |
| String mimeType = source.getMimeType(); |
| if (mimeType != null) { |
| attributes.addAttribute("", MIME_TYPE_ATTR_NAME, MIME_TYPE_ATTR_NAME, |
| "CDATA", source.getMimeType()); |
| } |
| } |
| if (this.version && source instanceof VersionableSource) { |
| try { |
| VersionableSource versionablesource = (VersionableSource) source; |
| if (versionablesource.isVersioned()) { |
| if ((versionablesource.getSourceRevision()!=null) && |
| (versionablesource.getSourceRevision().length()>0)) { |
| attributes.addAttribute("", |
| REVISION_ATTR_NAME, |
| REVISION_ATTR_NAME, "CDATA", |
| versionablesource.getSourceRevision()); |
| } |
| |
| if ((versionablesource.getSourceRevisionBranch()!=null) && |
| (versionablesource.getSourceRevisionBranch().length()> |
| 0)) { |
| attributes.addAttribute("", |
| REVISIONBRANCH_ATTR_NAME, |
| REVISIONBRANCH_ATTR_NAME, |
| "CDATA", |
| versionablesource.getSourceRevisionBranch()); |
| } |
| } |
| } catch (SourceException e) { |
| throw new ProcessingException(e); |
| } |
| } |
| } |
| |
| /** |
| * Push a XML description about all properties, which |
| * the source owns. |
| * |
| * @param source the Source to describe. |
| */ |
| private void pushSourceProperties(InspectableSource source) |
| throws SAXException, SourceException { |
| |
| SourceProperty[] properties = source.getSourceProperties(); |
| if (properties != null && properties.length > 0) { |
| this.contentHandler.startElement(URI, PROPERTIES_NODE_NAME, |
| PROPERTIES_NODE_QNAME, XMLUtils.EMPTY_ATTRIBUTES); |
| for (int i = 0; i < properties.length; i++) { |
| SourceProperty property = properties[i]; |
| property.toSAX(this.contentHandler); |
| } |
| this.contentHandler.endElement(URI, PROPERTIES_NODE_NAME, |
| PROPERTIES_NODE_QNAME); |
| } |
| } |
| |
| |
| /** |
| * Push a XML description of all permissions of a source. |
| * |
| * @param source the Source to describe. |
| */ |
| private void pushSourcePermissions(RestrictableSource source) |
| throws SAXException, SourceException { |
| SourcePermission[] permissions = source.getSourcePermissions(); |
| |
| if (permissions != null && permissions.length > 0) { |
| this.contentHandler.startElement(URI, |
| PERMISSIONS_NODE_NAME, |
| PERMISSIONS_NODE_QNAME, |
| XMLUtils.EMPTY_ATTRIBUTES); |
| |
| for (int i = 0; i < permissions.length; i++) { |
| AttributesImpl attributes = new AttributesImpl(); |
| |
| if (permissions[i] instanceof PrincipalSourcePermission) { |
| attributes.addAttribute("", PRINCIPAL_ATTR_NAME, |
| PRINCIPAL_ATTR_NAME, "CDATA", |
| ((PrincipalSourcePermission) permissions[i]).getPrincipal()); |
| } else if (permissions[i] instanceof GroupSourcePermission) { |
| attributes.addAttribute("", GROUP_ATTR_NAME, |
| GROUP_ATTR_NAME, "CDATA", |
| ((GroupSourcePermission) permissions[i]).getGroup()); |
| } |
| |
| attributes.addAttribute("", PRIVILEGE_ATTR_NAME, |
| PRIVILEGE_ATTR_NAME, "CDATA", |
| permissions[i].getPrivilege()); |
| attributes.addAttribute("", INHERITABLE_ATTR_NAME, |
| INHERITABLE_ATTR_NAME, "CDATA", |
| String.valueOf(permissions[i].isInheritable())); |
| attributes.addAttribute("", NEGATIVE_ATTR_NAME, |
| NEGATIVE_ATTR_NAME, "CDATA", |
| String.valueOf(permissions[i].isNegative())); |
| |
| this.contentHandler.startElement(URI, |
| PERMISSION_NODE_NAME, |
| PERMISSION_NODE_QNAME, |
| attributes); |
| this.contentHandler.endElement(URI, |
| PERMISSION_NODE_NAME, |
| PERMISSION_NODE_QNAME); |
| } |
| |
| this.contentHandler.endElement(URI, PERMISSIONS_NODE_NAME, |
| PERMISSIONS_NODE_QNAME); |
| } |
| } |
| |
| /** |
| * Push a XML description about all locks of a source. |
| * |
| * @param source the Source to describe. |
| */ |
| public void pushSourceLocks(LockableSource source) |
| throws SAXException, SourceException { |
| SourceLock[] locks = source.getSourceLocks(); |
| |
| if (locks != null && locks.length > 0) { |
| this.contentHandler.startElement(URI, LOCKS_NODE_NAME, |
| LOCKS_NODE_QNAME, |
| XMLUtils.EMPTY_ATTRIBUTES); |
| |
| for (int i = 0; locks.length > 0; i++) { |
| SourceLock lock = locks[i]; |
| |
| AttributesImpl attributes = new AttributesImpl(); |
| attributes.addAttribute("", PRINCIPAL_ATTR_NAME, |
| PRINCIPAL_ATTR_NAME, "CDATA", |
| lock.getSubject()); |
| attributes.addAttribute("", TYPE_ATTR_NAME, TYPE_ATTR_NAME, |
| "CDATA", lock.getType()); |
| attributes.addAttribute("", EXPIRATION_ATTR_NAME, |
| EXPIRATION_ATTR_NAME, "CDATA", |
| lock.getExpiration().toString()); |
| attributes.addAttribute("", INHERITABLE_ATTR_NAME, |
| INHERITABLE_ATTR_NAME, "CDATA", |
| String.valueOf(lock.isInheritable())); |
| attributes.addAttribute("", EXCLUSIVE_ATTR_NAME, |
| EXCLUSIVE_ATTR_NAME, "CDATA", |
| String.valueOf(lock.isExclusive())); |
| |
| this.contentHandler.startElement(URI, LOCK_NODE_NAME, |
| LOCK_NODE_QNAME, attributes); |
| this.contentHandler.endElement(URI, LOCK_NODE_NAME, |
| LOCK_NODE_QNAME); |
| } |
| |
| this.contentHandler.endElement(URI, LOCKS_NODE_NAME, |
| LOCKS_NODE_QNAME); |
| } |
| } |
| |
| } |