Index: java/org/apache/catalina/realm/LocalStrings.properties =================================================================== --- java/org/apache/catalina/realm/LocalStrings.properties (revision 1516983) +++ java/org/apache/catalina/realm/LocalStrings.properties (working copy) @@ -57,6 +57,10 @@ jndiRealm.close=Exception closing directory server connection jndiRealm.exception=Exception performing authentication jndiRealm.open=Exception opening directory server connection +mappingRealm.fileNotExists=Realm mapping file {0} does not exist. No security role will be available +mappingRealm.loadFailed=Could not Realm mapping file {0} +mappingRealm.loadOK=Loaded Realm mapping file {0} +mappingRealm.translated=Translated application security role [{0}] to realm security role [{1}] memoryRealm.authenticateFailure=Username {0} NOT successfully authenticated memoryRealm.authenticateSuccess=Username {0} successfully authenticated memoryRealm.loadExist=Memory database file {0} cannot be read Index: java/org/apache/catalina/realm/MappingRealm.java =================================================================== --- java/org/apache/catalina/realm/MappingRealm.java (revision 0) +++ java/org/apache/catalina/realm/MappingRealm.java (working copy) @@ -0,0 +1,192 @@ +/* + * 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.catalina.realm; + +import java.security.Principal; +import java.util.ArrayList; +import java.util.Properties; +import java.util.LinkedList; +import java.util.List; +import java.io.IOException; +import java.io.File; +import java.io.FileInputStream; + +import org.apache.catalina.Globals; +import org.apache.catalina.Wrapper; +import org.apache.catalina.LifecycleException; +import org.apache.catalina.Realm; +import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; + +/** + */ + +public class MappingRealm extends CombinedRealm { + + private static final Log log = LogFactory.getLog(MappingRealm.class); + + + // ----------------------------------------------------- Instance Variables + + /** + * Internal security role translation + */ + protected Properties mapping = null; + + /** + * Filename to load translation from + * Format is application-security-role=inner-realm-security-role + */ + protected String pathname = "conf/mapping.properties"; + + /** + * Descriptive information about this Realm implementation. + */ + protected static final String info = + "org.apache.catalina.realm.MappingRealm/1.0"; + + /** + * Descriptive information about this Realm implementation. + */ + protected static final String name = "MappingRealm"; + + /** + * Return descriptive information about this Realm implementation and + * the corresponding version number, in the format + * <description>/<version>. + */ + @Override + public String getInfo() { + + return info; + + } + + /** + * Return a short name for this Realm implementation. + */ + @Override + protected String getName() { + + return (name); + + } + + // ---------------------------------------------------------- Realm Methods + + /** + * Return true if the specified Principal has the specified + * security role, within the context of this Realm; otherwise return + * false. This method can be overridden by Realm + * implementations, but the default is adequate when an instance of + * GenericPrincipal is used to represent authenticated + * Principals from this Realm. + * + * @param principal Principal for whom the role is to be checked + * @param role Security role to be checked + */ + @Override + public boolean hasRole(Wrapper wrapper, Principal principal, String role) { + + // Copied from GenericPrincipal + if("*".equals(role)) { // Special 2.4 role meaning everyone + return true; + } + if (role == null) { + return (false); + } + + String mappedRole = mapping.getProperty(role); + + if((mappedRole != null) && super.hasRole(wrapper, principal, mappedRole)) { + if (log.isDebugEnabled()) { + log.debug(sm.getString("mappingRealm.translated", role, mappedRole)); + } + return true; + } else { + return false; + } + } + + + // ------------------------------------------------------ Lifecycle Methods + + + /** + * Prepare for the beginning of active use of the public methods of this + * component and implement the requirements of + * {@link org.apache.catalina.util.LifecycleBase#startInternal()}. + * + * @exception LifecycleException if this component detects a fatal error + * that prevents this component from being used + */ + @Override + protected void startInternal() throws LifecycleException { + + mapping = new Properties(); + + File file = new File(pathname); + if (!file.isAbsolute()) { + file = new File(System.getProperty(Globals.CATALINA_BASE_PROP), + pathname); + } + if (file.exists()) { + FileInputStream fis = null; + try { + fis = new FileInputStream(file); + mapping.load(fis); + log.info(sm.getString("mappingRealm.loadOK", pathname)); + } catch (IOException ioe) { + log.error(sm.getString("mappingRealm.loadFailed", pathname)); + } finally { + if (fis != null) { + try { + fis.close(); + } catch (IOException ioe) { + // Ignore + } + } + } + } else { + log.warn(sm.getString("mappingRealm.fileNotExists", pathname)); + } + + super.startInternal(); + } + + + /** + * Gracefully terminate the active use of the public methods of this + * component and implement the requirements of + * {@link org.apache.catalina.util.LifecycleBase#stopInternal()}. + * + * @exception LifecycleException if this component detects a fatal error + * that needs to be reported + */ + @Override + protected void stopInternal() throws LifecycleException { + + // Perform normal superclass finalization + super.stopInternal(); + + // Release mapping + mapping = null; + + } +} +