blob: 2a80900d62ac51f19e310a881795e64c2544d0fb [file] [log] [blame]
/*
* 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$ */
package org.apache.lenya.cms.ac;
import java.io.File;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
import org.apache.excalibur.source.Source;
import org.apache.excalibur.source.SourceResolver;
import org.apache.excalibur.source.SourceUtil;
import org.apache.lenya.ac.AccessControlException;
import org.apache.lenya.ac.AccessController;
import org.apache.lenya.ac.impl.AbstractAccessControllerResolver;
import org.apache.lenya.cms.publication.Publication;
import org.apache.lenya.cms.publication.PublicationUtil;
import org.apache.lenya.cms.publication.URLInformation;
/**
* Resolves the access controller according to the <code>ac.xconf</code> file of a publication.
*/
public class PublicationAccessControllerResolver extends AbstractAccessControllerResolver implements
Initializable {
protected static final String CONFIGURATION_FILE = "config/ac/ac.xconf".replace('/',
File.separatorChar);
protected static final String TYPE_ATTRIBUTE = "type";
/**
* This implementation uses the publication ID in combination with the context path as cache
* key.
* @see org.apache.lenya.ac.impl.AbstractAccessControllerResolver#generateCacheKey(java.lang.String,
* org.apache.excalibur.source.SourceResolver)
*/
protected Object generateCacheKey(String webappUrl, SourceResolver resolver)
throws AccessControlException {
URLInformation info = new URLInformation(webappUrl);
String publicationId = info.getPublicationId();
if (getLogger().isDebugEnabled()) {
getLogger().debug("Using first URL step (might be publication ID) as cache key: ["
+ publicationId + "]");
}
return super.generateCacheKey(publicationId, resolver);
}
/**
* @see org.apache.lenya.ac.impl.AbstractAccessControllerResolver#doResolveAccessController(java.lang.String)
*/
public AccessController doResolveAccessController(String webappUrl)
throws AccessControlException {
getLogger().debug("Resolving controller for URL [" + webappUrl + "]");
AccessController controller = null;
Publication publication = getPublication(webappUrl);
if (publication != null) {
String publicationUrl = webappUrl.substring(("/" + publication.getId()).length());
controller = resolveAccessController(publication, publicationUrl);
}
return controller;
}
/**
* Returns the publication for the webapp URL or null if the URL is not included in a
* publication.
* @param webappUrl The webapp URL.
* @return A publication.
* @throws AccessControlException when something went wrong.
*/
protected Publication getPublication(String webappUrl) throws AccessControlException {
Publication publication = null;
assert webappUrl.startsWith("/");
// remove leading slash
String url = webappUrl.substring(1);
if (url.length() > 0) {
URLInformation info = new URLInformation(webappUrl);
String publicationId = info.getPublicationId();
try {
publication = PublicationUtil.getPublicationFromUrl(this.manager, webappUrl);
} catch (Exception e) {
throw new AccessControlException(e);
}
if (publication.exists()) {
getLogger().debug("Publication [" + publicationId + "] exists.");
} else {
getLogger().debug("Publication [" + publicationId + "] does not exist.");
publication = null;
}
}
return publication;
}
/**
* Returns the servlet context.
* @return A file.
*/
protected File getContext() {
return this.context;
}
private File context;
/**
* Resolves an access controller for a certain URL within a publication.
* @param publication The publication.
* @param url The url within the publication.
* @return An access controller.
* @throws AccessControlException when something went wrong.
*/
public AccessController resolveAccessController(Publication publication, String url)
throws AccessControlException {
assert publication != null;
AccessController accessController = null;
File configurationFile = new File(publication.getDirectory(), CONFIGURATION_FILE);
if (configurationFile.isFile()) {
try {
Configuration configuration = new DefaultConfigurationBuilder().buildFromFile(configurationFile);
String type = configuration.getAttribute(TYPE_ATTRIBUTE);
accessController = (AccessController) getManager().lookup(AccessController.ROLE
+ "/" + type);
if (accessController instanceof Configurable) {
((Configurable) accessController).configure(configuration);
}
} catch (Exception e) {
throw new AccessControlException(e);
}
}
return accessController;
}
/**
* @see org.apache.avalon.framework.activity.Initializable#initialize()
*/
public void initialize() throws Exception {
SourceResolver resolver = null;
Source contextSource = null;
File contextDir;
try {
resolver = (SourceResolver) getManager().lookup(SourceResolver.ROLE);
contextSource = resolver.resolveURI("context:///");
contextDir = SourceUtil.getFile(contextSource);
if (contextDir == null || !contextDir.isDirectory()) {
throw new AccessControlException("The servlet context is not a directory!");
}
} finally {
if (resolver != null) {
if (contextSource != null) {
resolver.release(contextSource);
}
getManager().release(resolver);
}
}
this.context = contextDir;
}
}