Author: adrianc
Date: Sat Oct 12 18:54:59 2013 New Revision: 1531577 URL: http://svn.apache.org/r1531577 Log: Refactored SecurityFactory implementation - use Java's ServiceLoader to discover Security implementations, instead of using configuration files. Removed: ofbiz/trunk/framework/security/config/security.xml Modified: ofbiz/trunk/framework/security/config/security.properties ofbiz/trunk/framework/security/src/org/ofbiz/security/Security.java ofbiz/trunk/framework/security/src/org/ofbiz/security/SecurityFactory.java Modified: ofbiz/trunk/framework/security/config/security.properties URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/security/config/security.properties?rev=1531577&r1=1531576&r2=1531577&view=diff ============================================================================== --- ofbiz/trunk/framework/security/config/security.properties (original) +++ ofbiz/trunk/framework/security/config/security.properties Sat Oct 12 18:54:59 2013 @@ -20,9 +20,6 @@ # OFBiz Security Settings #### -# -- define the default security context to be user -security.context=default - # -- define the password restrictions -- password.length.min=5 Modified: ofbiz/trunk/framework/security/src/org/ofbiz/security/Security.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/security/src/org/ofbiz/security/Security.java?rev=1531577&r1=1531576&r2=1531577&view=diff ============================================================================== --- ofbiz/trunk/framework/security/src/org/ofbiz/security/Security.java (original) +++ ofbiz/trunk/framework/security/src/org/ofbiz/security/Security.java Sat Oct 12 18:54:59 2013 @@ -28,6 +28,11 @@ import org.ofbiz.entity.GenericValue; /** * Security interface. This interface defines authorization-related methods. + * <p>Implementations must be thread-safe because the instance + * will be shared among multiple threads.</p> + * <p>Note that the API is changing. New versions might not reference a + * <code>Delegator</code>. Therefore, implementations requiring a <code>Delegator</code> + * reference should get one from the <code>GenericValue</code> method argument.</p> */ public interface Security { Modified: ofbiz/trunk/framework/security/src/org/ofbiz/security/SecurityFactory.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/security/src/org/ofbiz/security/SecurityFactory.java?rev=1531577&r1=1531576&r2=1531577&view=diff ============================================================================== --- ofbiz/trunk/framework/security/src/org/ofbiz/security/SecurityFactory.java (original) +++ ofbiz/trunk/framework/security/src/org/ofbiz/security/SecurityFactory.java Sat Oct 12 18:54:59 2013 @@ -18,111 +18,53 @@ *******************************************************************************/ package org.ofbiz.security; -import java.net.URL; -import java.util.concurrent.atomic.AtomicReference; +import java.util.Iterator; +import java.util.ServiceLoader; +import org.ofbiz.base.util.Assert; import org.ofbiz.base.util.Debug; -import org.ofbiz.base.util.UtilProperties; -import org.ofbiz.base.util.UtilURL; -import org.ofbiz.base.util.UtilXml; +import org.ofbiz.base.util.cache.UtilCache; import org.ofbiz.entity.Delegator; -import org.w3c.dom.Document; -import org.w3c.dom.Element; /** - * <code>SecurityFactory</code> - * - * This Factory class returns an instance of a security implementation. - * - * Setting the security implementation className is done in security.xml. - * If no customized security name is given, the default implementation will be used (OFBizSecurity) + * A <code>Security</code> factory. */ public final class SecurityFactory { public static final String module = SecurityFactory.class.getName(); - private static final String DEFAULT_SECURITY_CLASS_NAME = "org.ofbiz.security.OFBizSecurity"; - private static final String SECURITY_CONFIG_XML_FILENAME = "security.xml"; - private static final AtomicReference<SecurityInfo> configRef = new AtomicReference<SecurityInfo>(null); + // The default implementation stores a Delegator reference, so we will cache by delegator name. + // The goal is to remove Delegator references in the Security interface, then we can use a singleton + // and eliminate the cache. + private static final UtilCache<String, Security> authorizationCache = UtilCache.createUtilCache("security.AuthorizationCache"); /** - * Returns an instance of a Security implementation as defined in the security.xml by defined name - * in security.properties. + * Returns a <code>Security</code> instance. The method uses Java's + * <a href="http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html"><code>ServiceLoader</code></a> + * to get a <code>Security</code> instance. If no instance is found, a default implementation is used. + * The default implementation is based on/backed by the OFBiz entity engine. * - * @param delegator the generic delegator - * @return instance of security implementation (default: OFBizSecurity) + * @param delegator The delegator + * @return A <code>Security</code> instance */ @SuppressWarnings("deprecation") public static Security getInstance(Delegator delegator) throws SecurityConfigurationException { - Security security = null; - String securityClassName = DEFAULT_SECURITY_CLASS_NAME; - try { - SecurityInfo securityInfo = getSecurityInfo(); - securityClassName = securityInfo.className; - } catch (SecurityConfigurationException e) { - Debug.logError(e, "Exception thrown while getting security configuration, using default security class " + DEFAULT_SECURITY_CLASS_NAME, module); - } - try { - ClassLoader loader = Thread.currentThread().getContextClassLoader(); - Class<?> c = loader.loadClass(securityClassName); - security = (Security) c.newInstance(); - security.setDelegator(delegator); - } catch (ClassNotFoundException cnf) { - throw new SecurityConfigurationException("Cannot load security implementation class", cnf); - } catch (InstantiationException ie) { - throw new SecurityConfigurationException("Cannot get instance of the security implementation", ie); - } catch (IllegalAccessException iae) { - throw new SecurityConfigurationException(iae.getMessage(), iae); - } - if (Debug.verboseOn()) { - Debug.logVerbose("Security implementation created for delegator " + delegator.getDelegatorName(), module); - } - return security; - } - - private static SecurityInfo getSecurityInfo() throws SecurityConfigurationException { - SecurityInfo instance = configRef.get(); - if (instance == null) { - URL confUrl = UtilURL.fromResource(SECURITY_CONFIG_XML_FILENAME); - if (confUrl == null) { - throw new SecurityConfigurationException("Could not find the " + SECURITY_CONFIG_XML_FILENAME + " file"); - } - String securityName = UtilProperties.getPropertyValue("security.properties", "security.context"); - if (Debug.verboseOn()) { - Debug.logVerbose("Security implementation context name from security.properties: " + securityName, module); - } - Document document = null; - try { - document = UtilXml.readXmlDocument(confUrl, true, true); - } catch (Exception e) { - throw new SecurityConfigurationException("Exception thrown while reading " + SECURITY_CONFIG_XML_FILENAME + ": ", e); - } - Element securityElement = UtilXml.firstChildElement(document.getDocumentElement(), "security", "name", securityName); - if (securityElement == null) { - throw new SecurityConfigurationException("Could not find the <security> element in the " + SECURITY_CONFIG_XML_FILENAME + " file"); - } - instance = new SecurityInfo(securityElement); - if (configRef.compareAndSet(null, instance)) { - if (Debug.verboseOn()) { - Debug.logVerbose("Security configuration read from " + SECURITY_CONFIG_XML_FILENAME + ", using class " + instance.className, module); - } + Assert.notNull("delegator", delegator); + Security security = authorizationCache.get(delegator.getDelegatorName()); + if (security == null) { + Iterator<Security> iterator = ServiceLoader.load(Security.class).iterator(); + if (iterator.hasNext()) { + security = iterator.next(); } else { - instance = configRef.get(); + security = new OFBizSecurity(); } - } - return instance; - } - - private static final class SecurityInfo { - private final String name; - private final String className; - - private SecurityInfo(Element element) throws SecurityConfigurationException { - this.name = element.getAttribute("name"); - this.className = element.getAttribute("class"); - if (this.className.isEmpty()) { - throw new SecurityConfigurationException("<security> element class attribute is empty in the " + SECURITY_CONFIG_XML_FILENAME + " file"); + security.setDelegator(delegator); + security = authorizationCache.putIfAbsentAndGet(delegator.getDelegatorName(), security); + Debug.logInfo("Security implementation " + security.getClass().getName() + " created for delegator " + delegator.getDelegatorName(), module); + if (Debug.verboseOn()) { + Debug.logVerbose("Security implementation " + security.getClass().getName() + " created for delegator " + delegator.getDelegatorName(), module); } } + return security; } private SecurityFactory() {} |
Free forum by Nabble | Edit this page |