Skip to content

Commit

Permalink
Add wrapping constructors to factories for jakartaee#156
Browse files Browse the repository at this point in the history
Update API, spec text and TCK.

Signed-off-by: Arjan Tijms <arjan.tijms@omnifish.ee>
  • Loading branch information
arjantijms committed Mar 29, 2024
1 parent 81f9684 commit abb81f6
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 112 deletions.
Expand Up @@ -26,8 +26,8 @@
* Provider.
*
* <p>
* Implementation classes must have a public no argument constructor that may be used to create an operational instance
* of the factory implementation class.
* Usage: extend this class and push the implementation being wrapped to the constructor and use {@link #getWrapped} to
* access the instance being wrapped.
*
* @see Permission
* @see PolicyConfiguration
Expand All @@ -43,6 +43,8 @@ public abstract class PolicyConfigurationFactory {

private static volatile PolicyConfigurationFactory policyConfigurationFactory;

private PolicyConfigurationFactory wrapped;

/**
* This static method uses a system property to find and instantiate (via a public constructor) a provider specific
* factory implementation class.
Expand Down Expand Up @@ -148,6 +150,30 @@ public static PolicyConfigurationFactory get() {
}
}

/**
* Default constructor for if no wrapping is needed
*/
public PolicyConfigurationFactory() {
}

/**
* If this factory has been decorated, the implementation doing the decorating should push the implementation being
* wrapped to this constructor. The {@link #getWrapped()} will then return the implementation being wrapped.
*
* @param wrapped The implementation being wrapped.
*/
public PolicyConfigurationFactory(PolicyConfigurationFactory wrapped) {
this.wrapped = wrapped;
}

/**
* If this factory has been decorated, the implementation doing the decorating may override this method to provide
* access to the implementation being wrapped.
*/
public PolicyConfigurationFactory getWrapped() {
return wrapped;
}

/**
* This method is used to obtain an instance of the provider specific class that implements the PolicyConfiguration
* interface that corresponds to the identified policy context within the provider. The methods of the
Expand Down
26 changes: 26 additions & 0 deletions api/src/main/java/jakarta/security/jacc/PolicyFactory.java
Expand Up @@ -32,6 +32,8 @@ public abstract class PolicyFactory {

private static volatile PolicyFactory policyFactory;

private PolicyFactory wrapped;

/**
* Get the system-wide PolicyFactory implementation.
*
Expand Down Expand Up @@ -87,6 +89,30 @@ public static synchronized void setPolicyFactory(PolicyFactory policyFactory) {
PolicyFactory.policyFactory = policyFactory;
}

/**
* Default constructor for if no wrapping is needed
*/
public PolicyFactory() {
}

/**
* If this factory has been decorated, the implementation doing the decorating should push the implementation being
* wrapped to this constructor. The {@link #getWrapped()} will then return the implementation being wrapped.
*
* @param wrapped The implementation being wrapped.
*/
public PolicyFactory(PolicyFactory wrapped) {
this.wrapped = wrapped;
}

/**
* If this factory has been decorated, the implementation doing the decorating may override this method to provide
* access to the implementation being wrapped.
*/
public PolicyFactory getWrapped() {
return wrapped;
}

/**
* This method is used to obtain an instance of the provider specific class that implements the {@link Policy}
* interface that corresponds to policy context within the provider. The policy context is identified by
Expand Down
10 changes: 7 additions & 3 deletions spec/src/main/asciidoc/chapters/2_provider-configuration.adoc
Expand Up @@ -28,10 +28,14 @@ although for most common uses this should not be needed.
Replacement is done via the `jakarta.security.jacc.PolicyConfigurationFactory` abstract factory class. A
default static method, `getPolicyConfigurationFactory` is provided that uses the system property
`jakarta.security.jacc.PolicyConfigurationFactory.provider` to locate a concrete implementation. The
application server can alternatively set a custom `PolicyConfigurationFactory` using the
container can alternatively set a custom `PolicyConfigurationFactory` using the
`setPolicyConfigurationFactory` method. In that case the `PolicyConfigurationFactory` implementation
can come from an application server specific configuration, or in case of the Servlet Container
from the context property `jakarta.security.jacc.PolicyConfigurationFactory.provider`.
can come from a container specific configuration, or in case of the Servlet Container
from the context property `jakarta.security.jacc.PolicyConfigurationFactory.provider`. If the
`PolicyConfigurationFactory` has a public constructor with one argument of type `PolicyConfigurationFactory`,
then the container should call this constructor with as argument the `PolicyConfigurationFactory` instance
that is being replaced. This allows a replacement `PolicyConfigurationFactory` to wrap the existing one
and selectively provide extra functionality.

From this factory class a concrete implementation of the Policy Configuration of type
`jakarta.security.jacc.PolicyConfiguration` can be obtained using the method `getPolicyConfiguration`.
Expand Down
Expand Up @@ -26,7 +26,6 @@

import static java.util.logging.Level.FINER;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.SEVERE;

import ee.jakarta.tck.authorization.util.logging.server.TSLogger;
import jakarta.security.jacc.PolicyConfiguration;
Expand All @@ -45,17 +44,12 @@ public class TSPolicyConfigurationFactoryImpl extends PolicyConfigurationFactory

private static String FACTORY_NAME = "vendor.jakarta.security.jacc.PolicyConfigurationFactory.provider";

private static PolicyConfigurationFactory policyConfigurationFactory;

public TSPolicyConfigurationFactoryImpl() throws PolicyContextException {
try {
policyConfigurationFactory = TSPolicyConfigurationFactoryImpl.getPolicyConfigurationFactory();
} catch (PolicyContextException pce) {
if (logger != null) {
logger.severe("Failed to get PolicyConfigurationFactory");
}

throw new PolicyContextException(pce);
public TSPolicyConfigurationFactoryImpl(PolicyConfigurationFactory policyConfigurationFactory) {
super(policyConfigurationFactory);
logger.log(INFO, "PolicyConfigurationFactory instantiated");
if (policyConfigurationFactory.getClass().getName().equals(FACTORY_NAME)) {
logger.log(INFO, "policyConfigurationFactory equals expected vendor PolicyConfigurationFactory");
}
}

Expand Down Expand Up @@ -109,55 +103,6 @@ public PolicyConfiguration getPolicyConfiguration(String contextId, boolean remo
return policyConfiguration;
}

/**
* This static method uses a system property to find and instantiate (via a public constructor) a provider specific
* factory implementation class. The name of the provider specific factory implementation class is obtained from the
* value of the system property,
* <P>
* <code><Pre>
* vendor.jakarta.security.jacc.PolicyConfigurationFactory.provider
* </Pre></code>
* <P>
*
* @return the singleton instance of the provider specific PolicyConfigurationFactory implementation class.
*
* @throws SecurityException when called by an AccessControlContext that has not been granted the "getPolicy"
* SecurityPermission.
*
* @throws PolicyContextException when the class named by the system property could not be found including because the
* value of the system property has not been set.
*/

public static PolicyConfigurationFactory getPolicyConfigurationFactory() throws PolicyContextException {
if (policyConfigurationFactory != null) {
return policyConfigurationFactory;
}

String classname = System.getProperty(FACTORY_NAME);
if (classname == null) {
logger.severe("factory.name.notset");
throw new PolicyContextException("PolicyConfigurationFactory name not set!");
}

try {
policyConfigurationFactory = (PolicyConfigurationFactory)
TSPolicyConfigurationFactoryImpl.class
.getClassLoader()
.loadClass(classname)
.getDeclaredConstructor()
.newInstance();

if (policyConfigurationFactory != null) {
logger.log(INFO, "PolicyConfigurationFactory instantiated");
}
} catch (Exception e) {
logger.log(SEVERE, "factory.instantiation.error", e);
throw new PolicyContextException(e);
}

return policyConfigurationFactory;
}

/**
* This method determines if the identified policy context exists with state "inService" in the Policy provider
* associated with the factory.
Expand All @@ -182,15 +127,15 @@ public boolean inService(String contextId) throws PolicyContextException {
logger.log(INFO, "PolicyConfigurationFactory.inService() invoked");
logger.log(FINER, "PolicyConfiguration.inService() invoked for context id = " + contextId);

return policyConfigurationFactory.inService(contextId);
return getWrapped().inService(contextId);
}

public PolicyConfiguration getPolicyConfiguration(String contextID) {
if (logger.isLoggable(FINER)) {
logger.entering("PolicyConfigurationFactoryImpl", "getPolicyConfiguration(String)");
}

PolicyConfiguration policyConfiguration = policyConfigurationFactory.getPolicyConfiguration(contextID);
PolicyConfiguration policyConfiguration = getWrapped().getPolicyConfiguration(contextID);
logger.log(INFO, "PolicyConfigurationFactory.getPolicyConfiguration(String) invoked");

return policyConfiguration;
Expand All @@ -202,7 +147,7 @@ public PolicyConfiguration getPolicyConfiguration() {
}

String contextId = PolicyContext.getContextID();
PolicyConfiguration policyConfiguration = policyConfigurationFactory.getPolicyConfiguration(contextId);
PolicyConfiguration policyConfiguration = getWrapped().getPolicyConfiguration(contextId);
logger.log(INFO, "PolicyConfigurationFactory.getPolicyConfiguration(String) invoked");
logger.log(FINER, "Getting PolicyConfiguration object with id = " + contextId);

Expand Down

0 comments on commit abb81f6

Please sign in to comment.