alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Glassfish example source code file (PolicyConfigurationImpl.java)

This example Glassfish source code file (PolicyConfigurationImpl.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Glassfish tags/keywords

context_id, file, file, io, jacc, log, logging, object, object, permission, permissions, policy, policy, policycontextexception, reflection, runtimeexception, security, string, string, util

The Glassfish PolicyConfigurationImpl.java source code

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package com.sun.enterprise.security.provider;

import javax.security.jacc.*;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import java.util.Map;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.lang.reflect.Constructor;

import java.security.*;
import javax.security.auth.Subject;
import java.io.File;
import java.io.FileReader;

import java.util.logging.*;
import sun.security.provider.PolicyParser;
import sun.security.provider.PolicyParser.GrantEntry;
import sun.security.provider.PolicyParser.PermissionEntry;
import sun.security.provider.PolicyParser.PrincipalEntry;
import com.sun.logging.LogDomains;
import com.sun.enterprise.util.LocalStringManagerImpl;

import com.sun.enterprise.deployment.interfaces.SecurityRoleMapper;
import com.sun.enterprise.deployment.interfaces.SecurityRoleMapperFactory;
import com.sun.enterprise.security.SecurityRoleMapperFactoryGen;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;

/** 
 * Implementation of Jacc PolicyConfiguration Interface
 * @author Harpreet Singh (harpreet.singh@sun.com)
 * @author Ron Monzillo
 */
public class PolicyConfigurationImpl implements PolicyConfiguration {

    private static Logger logger = 
	Logger.getLogger(LogDomains.SECURITY_LOGGER);

    private static LocalStringManagerImpl localStrings =
	new LocalStringManagerImpl(PolicyConfigurationImpl.class);

    //package access
    String CONTEXT_ID = null;

    // Excluded permissions
    private Permissions excludedPermissions = null;
    // Unchecked permissions
    private Permissions uncheckedPermissions = null;
    // permissions mapped to roles.
    private HashMap rolePermissionsTable = null;

    //private /*TODO: static */ SecurityRoleMapperFactory factory = SecurityRoleMapperFactoryGen.getSecurityRoleMapperFactory();

    private static String policySuffix = ".policy";
 
    private static String PROVIDER_URL = "policy.url.";

    private static final Class[] permissionParams = { String.class, String.class};

    // These are the 3 possible states that this object can be in.
    public static final int OPEN_STATE = 0;
    public static final int INSERVICE_STATE = 2;
    public static final int DELETED_STATE = 3;

    // new instances are created in the open state.
    protected int state = OPEN_STATE;

    private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(true);
    private Lock rLock = rwLock.readLock();
    private Lock wLock = rwLock.writeLock();

    // this bit is used to optimize commit processing
    private boolean writeOnCommit = true;

    // this bit is used to optimize refresh processing
    private boolean wasRefreshed = false;
    
    private Policy policy = null;
    private String policyUrlValue = null;

    // policy file mod times 
    private long[] lastModTimes = new long[2];
    private final  Object refreshLock = new Object();
    private  String repository = null;
    private  Permission setPolicyPermission = null;
    private  PolicyConfigurationFactoryImpl fact=null;
    
    protected PolicyConfigurationImpl(String contextId, PolicyConfigurationFactoryImpl fact){
	CONTEXT_ID = contextId;
        this.fact = fact;
        repository = fact.getRepository();
	// initialize(open,remove,!fromFile)
//        initializeRepository();
	initialize(true,true,false);
    }

    /**
     * @param applicationPolicyDirectory, need to have absolute path
     * @param open, then mark state as open
     * @param remove, then remove any existing policy statements
     */
    protected PolicyConfigurationImpl
	(File applicationPolicyDirectory, boolean open, boolean remove, PolicyConfigurationFactoryImpl fact) {

        this.fact = fact;
	CONTEXT_ID = applicationPolicyDirectory.getParentFile().getName() +
                '/' + applicationPolicyDirectory.getName();

        repository = fact.getRepository();
        //initializeRepository();
	String name = getPolicyFileName(true);
	File f = new File(name);
	if (!f.exists()) {
            String defMsg="Unable to open Policy file: "+name;
            String msg= localStrings.getLocalString("pc.file_not_found",defMsg,new Object []{ name});
	    logger.log(Level.SEVERE,msg);
	    throw new RuntimeException(defMsg);
	}

	// initialize(open,remove,fromFile)
	initialize(open,remove,true);
    }

   /**
    * This method returns this object's policy context identifier.
    * @return this object's policy context identifier.
    *
    * @throws java.lang.SecurityException
    * if called by an AccessControlContext that has not been
    * granted the "setPolicy" SecurityPermission.
    *
    * @throws javax.security.jacc.PolicyContextException
    * if the implementation throws a checked exception that has not been
    * accounted for by the getContextID method signature. The exception thrown
    * by the implementation class will be encapsulated (during construction)
    * in the thrown PolicyContextException.
    */
    public String getContextID() throws PolicyContextException {
	checkSetPolicyPermission();
	return this.CONTEXT_ID;
    }

   /**
    * Used to add permissions to a named role in this PolicyConfiguration.
    * If the named Role does not exist in the PolicyConfiguration, it is
    * created as a result of the call to this function.
    * <P>
    * It is the job of the Policy provider to ensure that all the permissions
    * added to a role are granted to principals "mapped to the role".
    * <P>
    * @param roleName the name of the Role to which the permissions are
    * to be added.
    * <P>
    * @param permissions the collection of permissions to be added
    * to the role. The collection may be either a homogenous or
    * heterogenous collection.
    *
    * @throws java.lang.SecurityException
    * if called by an AccessControlContext that has not been
    * granted the "setPolicy" SecurityPermission.
    *
    * @throws java.lang.UnsupportedOperationException
    * if the state of the policy context whose interface is this
    * PolicyConfiguration Object is "deleted" or "inService" when this
    * method is called.
    *
    * @throws javax.security.jacc.PolicyContextException
    * if the implementation throws a checked exception that has not been
    * accounted for by the addToRole method signature. The exception thrown
    * by the implementation class will be encapsulated (during construction)
    * in the thrown PolicyContextException.
    */
    public void addToRole(String roleName, PermissionCollection permissions)
	throws PolicyContextException
    {
        assertStateIsOpen();

	assert roleName != null;
	assert permissions != null;
	
	if (roleName != null && permissions != null) {
	    checkSetPolicyPermission();
	    for(Enumeration e = permissions.elements(); e.hasMoreElements();) {
		this.getRolePermissions(roleName).add((Permission)e.nextElement());
		writeOnCommit = true;
	    }
	}
    }
    
   /**
    * Used to add a single permission to a named role in this
    * PolicyConfiguration.
    * If the named Role does not exist in the PolicyConfiguration, it is
    * created as a result of the call to this function.
    * <P>
    * It is the job of the Policy provider to ensure that all the permissions
    * added to a role are granted to principals "mapped to the role".
    * <P>
    * @param roleName the name of the Role to which the permission is
    * to be added.
    * <P>
    * @param permission the permission to be added
    * to the role.
    *
    * @throws java.lang.SecurityException
    * if called by an AccessControlContext that has not been
    * granted the "setPolicy" SecurityPermission.
    *
    * @throws java.lang.UnsupportedOperationException
    * if the state of the policy context whose interface is this
    * PolicyConfiguration Object is "deleted" or "inService" when this
    * method is called.
    *
    * @throws javax.security.jacc.PolicyContextException
    * if the implementation throws a checked exception that has not been
    * accounted for by the addToRole method signature. The exception thrown
    * by the implementation class will be encapsulated (during construction)
    * in the thrown PolicyContextException.
    */
    public void addToRole(String roleName, Permission permission)
	throws PolicyContextException {

        assertStateIsOpen();

	assert permission != null;
	assert roleName != null;
	
	if (roleName != null && permission != null) {
	    checkSetPolicyPermission();
	    this.getRolePermissions(roleName).add(permission);
	    writeOnCommit = true;
	}
    }
	
   /**
    * Used to add unchecked policy statements to this PolicyConfiguration.
    * <P>
    * @param permissions the collection of permissions to be added
    * as unchecked policy statements. The collection may be either
    * a homogenous or heterogenous collection.
    *
    * @throws java.lang.SecurityException
    * if called by an AccessControlContext that has not been
    * granted the "setPolicy" SecurityPermission.
    *
    * @throws java.lang.UnsupportedOperationException
    * if the state of the policy context whose interface is this
    * PolicyConfiguration Object is "deleted" or "inService" when this
    * method is called.
    *
    * @throws javax.security.jacc.PolicyContextException
    * if the implementation throws a checked exception that has not been
    * accounted for by the addToUncheckedPolicy method signature.
    * The exception thrown
    * by the implementation class will be encapsulated (during construction)
    * in the thrown PolicyContextException.
    */
    public void addToUncheckedPolicy(PermissionCollection permissions)
	throws PolicyContextException {	

        assertStateIsOpen();

	assert permissions != null;
	
	if (permissions != null) {
	    checkSetPolicyPermission();
	    for(Enumeration e = permissions.elements(); e.hasMoreElements();){
		this.getUncheckedPermissions().add((Permission) e.nextElement());
		writeOnCommit = true;
	    }
	}
    }

   /**
    * Used to add a single unchecked policy statement to this
    * PolicyConfiguration.
    * <P>
    * @param permission the permission to be added
    * to the unchecked policy statements.
    *
    * @throws java.lang.SecurityException
    * if called by an AccessControlContext that has not been
    * granted the "setPolicy" SecurityPermission.
    *
    * @throws java.lang.UnsupportedOperationException
    * if the state of the policy context whose interface is this
    * PolicyConfiguration Object is "deleted" or "inService" when this
    * method is called.
    *
    * @throws javax.security.jacc.PolicyContextException
    * if the implementation throws a checked exception that has not been
    * accounted for by the addToUncheckedPolicy method signature.
    * The exception thrown
    * by the implementation class will be encapsulated (during construction)
    * in the thrown PolicyContextException.
    */
    public void addToUncheckedPolicy(Permission permission)
	throws PolicyContextException{
	
        assertStateIsOpen();

	assert permission != null;

	if (permission != null) {
	    checkSetPolicyPermission();
	    this.getUncheckedPermissions().add(permission);
	    writeOnCommit = true;
	}
    }

   /**
    * Used to add excluded policy statements to this PolicyConfiguration.
    * <P>
    * @param permissions the collection of permissions to be added
    * to the excluded policy statements. The collection may be either
    * a homogenous or heterogenous collection.
    *
    * @throws java.lang.SecurityException
    * if called by an AccessControlContext that has not been
    * granted the "setPolicy" SecurityPermission.
    *
    * @throws java.lang.UnsupportedOperationException
    * if the state of the policy context whose interface is this
    * PolicyConfiguration Object is "deleted" or "inService" when this
    * method is called.
    *
    * @throws javax.security.jacc.PolicyContextException
    * if the implementation throws a checked exception that has not been
    * accounted for by the addToExcludedPolicy method signature.
    * The exception thrown
    * by the implementation class will be encapsulated (during construction)
    * in the thrown PolicyContextException.
    */
    public void addToExcludedPolicy(PermissionCollection permissions)
	throws PolicyContextException {

        assertStateIsOpen();

	assert permissions != null;

	if (permissions != null) {
	    checkSetPolicyPermission();
	    for(Enumeration e = permissions.elements(); e.hasMoreElements();){
		this.getExcludedPermissions().add((Permission) e.nextElement());
		writeOnCommit = true;
	    }
	}
    }

   /**
    * Used to add a single excluded policy statement to this
    * PolicyConfiguration.
    * <P>
    * @param permission the permission to be added
    * to the excluded policy statements. 
    *
    * @throws java.lang.SecurityException
    * if called by an AccessControlContext that has not been
    * granted the "setPolicy" SecurityPermission.
    *
    * @throws java.lang.UnsupportedOperationException
    * if the state of the policy context whose interface is this
    * PolicyConfiguration Object is "deleted" or "inService" when this
    * method is called.
    *
    * @throws javax.security.jacc.PolicyContextException
    * if the implementation throws a checked exception that has not been
    * accounted for by the addToExcludedPolicy method signature.
    * The exception thrown
    * by the implementation class will be encapsulated (during construction)
    * in the thrown PolicyContextException.
    */
    public void addToExcludedPolicy(Permission permission)
	throws PolicyContextException{

        assertStateIsOpen();

	assert permission != null;

	if (permission != null) {
	    checkSetPolicyPermission();
	    this.getExcludedPermissions().add(permission);
	    writeOnCommit = true;
	}
    }

   /**
    * Used to remove a role and all its permissions from this
    * PolicyConfiguration.
    * <P>
    * @param roleName the name of the role to remove from this 
    * PolicyConfiguration. If the value of the roleName parameter is "*"
    * and no role with name "*" exists in this PolicyConfiguration,
    * then all roles must be removed from this PolicyConfiguration.
    *
    * @throws java.lang.SecurityException
    * if called by an AccessControlContext that has not been
    * granted the "setPolicy" SecurityPermission.
    *
    * @throws java.lang.UnsupportedOperationException
    * if the state of the policy context whose interface is this
    * PolicyConfiguration Object is "deleted" or "inService" when this
    * method is called.
    *
    * @throws javax.security.jacc.PolicyContextException
    * if the implementation throws a checked exception that has not been
    * accounted for by the removeRole method signature. The exception thrown
    * by the implementation class will be encapsulated (during construction)
    * in the thrown PolicyContextException.
    */
    public void removeRole(String roleName)
	throws PolicyContextException{

        assertStateIsOpen();

	assert roleName != null;

	if(roleName != null && rolePermissionsTable != null) {
	    checkSetPolicyPermission();
	    if (rolePermissionsTable.remove(roleName) != null) {
		if (rolePermissionsTable.isEmpty()) {
		    rolePermissionsTable = null;
		}
		writeOnCommit = true;
	    } else if (roleName.equals("*")) {
		boolean wasEmpty = rolePermissionsTable.isEmpty();
		if (!wasEmpty) {
		     rolePermissionsTable.clear();
		}
		rolePermissionsTable = null;
		if (!wasEmpty) {
		    writeOnCommit = true;
		}
	    }
	}
    }

   /**
    * Used to remove any unchecked policy statements from this 
    * PolicyConfiguration.
    *
    * @throws java.lang.SecurityException
    * if called by an AccessControlContext that has not been
    * granted the "setPolicy" SecurityPermission.
    *
    * @throws java.lang.UnsupportedOperationException
    * if the state of the policy context whose interface is this
    * PolicyConfiguration Object is "deleted" or "inService" when this
    * method is called.
    *
    * @throws javax.security.jacc.PolicyContextException
    * if the implementation throws a checked exception that has not been
    * accounted for by the removeUncheckedPolicy method signature.
    * The exception thrown
    * by the implementation class will be encapsulated (during construction)
    * in the thrown PolicyContextException.
    */
    public void removeUncheckedPolicy()
	throws PolicyContextException{

        assertStateIsOpen();

	checkSetPolicyPermission();	

	if (uncheckedPermissions != null) {
	    uncheckedPermissions = null;
	    writeOnCommit = true;
	}
    }

   /**
    * Used to remove any excluded policy statements from this
    * PolicyConfiguration.
    *
    * @throws java.lang.SecurityException
    * if called by an AccessControlContext that has not been
    * granted the "setPolicy" SecurityPermission.
    *
    * @throws java.lang.UnsupportedOperationException
    * if the state of the policy context whose interface is this
    * PolicyConfiguration Object is "deleted" or "inService" when this
    * method is called.
    *
    * @throws javax.security.jacc.PolicyContextException
    * if the implementation throws a checked exception that has not been
    * accounted for by the removeExcludedPolicy method signature.
    * The exception thrown
    * by the implementation class will be encapsulated (during construction)
    * in the thrown PolicyContextException.
    */
    public void removeExcludedPolicy()
        throws PolicyContextException{

        assertStateIsOpen();

	checkSetPolicyPermission();

	if (excludedPermissions != null) {
	    excludedPermissions = null;
	    writeOnCommit = true;
	}
    } 

   /**
    * This method is used to set to "inService" the state of the policy context
    * whose interface is this PolicyConfiguration Object. Only those policy
    * contexts whose state is "inService" will be included in the policy
    * contexts processed by the Policy.refresh method. A policy context whose
    * state is "inService" may be returned to the "open" state by calling the 
    * getPolicyConfiguration method of the PolicyConfiguration factory
    * with the policy context identifier of the policy context.
    * <P>
    * When the state of a policy context is "inService", calling any method
    * other than commit, delete, getContextID, or inService on its
    * PolicyConfiguration Object will cause an UnsupportedOperationException
    * to be thrown.
    *
    * @throws java.lang.SecurityException
    * if called by an AccessControlContext that has not been
    * granted the "setPolicy" SecurityPermission.
    *
    * @throws java.lang.UnsupportedOperationException
    * if the state of the policy context whose interface is this
    * PolicyConfiguration Object is "deleted" when this
    * method is called.
    *
    * @throws javax.security.jacc.PolicyContextException
    * if the implementation throws a checked exception that has not been
    * accounted for by the commit method signature. The exception thrown
    * by the implementation class will be encapsulated (during construction)
    * in the thrown PolicyContextException.
    */
    public void commit() throws PolicyContextException{

	synchronized(refreshLock) {
	    if(stateIs(DELETED_STATE)){
                String defMsg="Cannot perform Operation on a deleted PolicyConfiguration";
                String msg=localStrings.getLocalString("pc.invalid_op_for_state_delete",defMsg);
		logger.log(Level.WARNING,msg);
		throw new UnsupportedOperationException(defMsg);

	    } else {
            
		try {

		    checkSetPolicyPermission();

		    if (stateIs(OPEN_STATE)) {

			generatePermissions();

			setState(INSERVICE_STATE);
		    }
		} catch(Exception e){
                    String defMsg="commit fail for contextod "+CONTEXT_ID;
                    String msg=localStrings.getLocalString("pc.commit_failure",defMsg,new Object[]{CONTEXT_ID,e});
		    logger.log(Level.SEVERE,msg);
		    throw new PolicyContextException(e);
		}
		if (logger.isLoggable(Level.FINE)){
		    logger.fine("JACC Policy Provider: PC.commit "+CONTEXT_ID);
		}
	    }
	    
	}
    }

   /**
    * Creates a relationship between this configuration and another
    * such that they share the same principal-to-role mappings.
    * PolicyConfigurations are linked to apply a common principal-to-role
    * mapping to multiple seperately manageable PolicyConfigurations,
    * as is required when an application is composed of multiple
    * modules.
    * <P>
    * Note that the policy statements which comprise a role, or comprise
    * the excluded or unchecked policy collections in a PolicyConfiguration
    * are unaffected by the configuration being linked to another.
    * <P>
    * @param link a reference to a different PolicyConfiguration than this
    * PolicyConfiguration.
    * <P>
    * The relationship formed by this method is symetric, transitive
    * and idempotent. If the argument PolicyConfiguration does not have a
    * different Policy context identifier than this PolicyConfiguration
    * no relationship is formed, and an exception, as described below, is
    * thrown.
    *
    * @throws java.lang.SecurityException
    * if called by an AccessControlContext that has not been
    * granted the "setPolicy" SecurityPermission.
    *
    * @throws java.lang.UnsupportedOperationException
    * if the state of the policy context whose interface is this
    * PolicyConfiguration Object is "deleted" or "inService" when this
    * method is called.
    *
    * @throws java.lang.IllegalArgumentException
    * if called with an argument PolicyConfiguration whose Policy context
    * is equivalent to that of this PolicyConfiguration.
    *
    * @throws javax.security.jacc.PolicyContextException
    * if the implementation throws a checked exception that has not been
    * accounted for by the linkConfiguration method signature. The exception
    * thrown
    * by the implementation class will be encapsulated (during construction)
    * in the thrown PolicyContextException.
    */
    public void linkConfiguration(PolicyConfiguration link) throws PolicyContextException {

        assertStateIsOpen();

	String linkId = link.getContextID();
	if (this.CONTEXT_ID == linkId) {
            String defMsg="Operation attempted to link PolicyConfiguration to itself.";
            String msg=localStrings.getLocalString("pc.unsupported_link_operation",defMsg);
	    logger.log(Level.WARNING,msg);
	    throw new IllegalArgumentException(defMsg);
	}

	checkSetPolicyPermission();

	updateLinkTable(linkId);

    }

   /**
    * Causes all policy statements to be deleted from this PolicyConfiguration
    * and sets its internal state such that calling any method, other than
    * delete, getContextID, or inService on the PolicyConfiguration will 
    * be rejected and cause an UnsupportedOperationException to be thrown.
    * <P>
    * This operation has no affect on any linked PolicyConfigurations
    * other than removing any links involving the deleted PolicyConfiguration.
    *
    * @throws java.lang.SecurityException
    * if called by an AccessControlContext that has not been
    * granted the "setPolicy" SecurityPermission.
    *
    * @throws javax.security.jacc.PolicyContextException
    * if the implementation throws a checked exception that has not been
    * accounted for by the delete method signature. The exception thrown
    * by the implementation class will be encapsulated (during construction)
    * in the thrown PolicyContextException.
    */
    public void delete() throws PolicyContextException
    {
	checkSetPolicyPermission();
	synchronized(refreshLock) {
	    try {
		removePolicy();
	    } finally {
		setState(DELETED_STATE);
	    }
	}
    }

   /**
    * This method is used to determine if the policy context whose interface is
    * this PolicyConfiguration Object is in the "inService" state.
    *
    * @return true if the state of the associated policy context is
    * "inService"; false otherwise.
    *
    * @throws java.lang.SecurityException
    * if called by an AccessControlContext that has not been
    * granted the "setPolicy" SecurityPermission.
    *
    * @throws javax.security.jacc.PolicyContextException
    * if the implementation throws a checked exception that has not been
    * accounted for by the inService method signature. The exception thrown
    * by the implementation class will be encapsulated (during construction)
    * in the thrown PolicyContextException.
    */
    public boolean inService() throws PolicyContextException{
	checkSetPolicyPermission();	
	boolean rvalue = stateIs(INSERVICE_STATE);
        
        if (logger.isLoggable(Level.FINE)) {
             logger.fine("JACC Policy Provider: inService: " +
                        (rvalue ? "true " : "false ") +
                        CONTEXT_ID);
        }
        
        return rvalue;
    }

    // The following methods are implementation specific

    protected  void checkSetPolicyPermission() {
	SecurityManager sm = System.getSecurityManager();
	if (sm != null) {
	    if (setPolicyPermission == null) {
		setPolicyPermission = new java.security.SecurityPermission("setPolicy");
	    }
	    sm.checkPermission(setPolicyPermission);
	}
    }

    // get the policy object
    protected java.security.Policy getPolicy(){
	if (stateIs(INSERVICE_STATE)) {
	    return this.policy;
	} 
	if (logger.isLoggable(Level.FINEST)) {
	    logger.finest("JACC Policy Provider: getPolicy ("+CONTEXT_ID+") is NOT in service");
	}
	return null;
    }

    // get the policy object
    protected Permissions getExcludedPolicy(){
	return stateIs(INSERVICE_STATE) ? this.excludedPermissions : null;
    }

    // called by PolicyWrapper to refresh context specific policy object.
    protected void refresh(boolean force){

	synchronized(refreshLock){
	    if (stateIs(INSERVICE_STATE) && 
		(wasRefreshed == false || force || filesChanged())) {

		// find open policy.url
		int i = 0;
		String value = null;
		String urlKey = null;
		while (true) {
		    urlKey = PROVIDER_URL+(++i);
		    value = java.security.Security.getProperty(urlKey);
		    if (value == null || value.equals("")) {
			break;
		    }
		}

		try {
		    java.security.Security.setProperty(urlKey,policyUrlValue);

		    if (fileChanged(false)) {
			excludedPermissions = loadExcludedPolicy();
		    }

		    // capture time before load, to ensure that we
		    // have a time that precedes load
		    captureFileTime(true);

		    if (policy == null) {
			policy = getNewPolicy();
		    } else {
			policy.refresh();
			if (logger.isLoggable(Level.FINE)){
			    logger.fine("JACC Policy Provider: Called Policy.refresh on contextId: "+CONTEXT_ID+" policyUrlValue was "+policyUrlValue);
			}
		    }
		    wasRefreshed = true;
		} finally {
		    // can't setProperty back to null, workaround is to 
		    // use empty string
		    java.security.Security.setProperty(urlKey,"");
		}
	    }
	}
    }

    private java.security.Policy getNewPolicy() {
	Object wrapper = java.security.Policy.getPolicy();
	if (wrapper != null && wrapper instanceof BasePolicyWrapper) {
	    return ((BasePolicyWrapper) wrapper).getNewPolicy();
	} else {
	    return new sun.security.provider.PolicyFile();
	} 
    }

    private void captureFileTime(boolean granted) {
	String name = getPolicyFileName(granted);
	File f = new File(name);
	lastModTimes[(int) (granted ? 1 : 0)] = f.lastModified();
    }

    private boolean _fileChanged(boolean granted, File f) {
	return !(lastModTimes[(int) (granted ? 1 : 0)] == f.lastModified());
    }
    
    private boolean fileChanged(boolean granted) {
	String name = getPolicyFileName(granted);
	File f = new File(name);
        return _fileChanged(granted,f);
    }

    private boolean filesChanged() {
	return (fileChanged(true) || fileChanged(false));
    }
    
    /** 
     * tests if policy file has arrived (via synchronization system).
     * if File exists, also checks last modified time, in case file was
     * not deleted on transition out of inservice state. Called when context 
     * is not inService to determine if it was needs to be transitioned
     * because of file distribution.
     * @param granted selects granted or excluded policy file
     * @return true if new file has arrived.
     */
    private boolean fileArrived(boolean granted) {
	String name = getPolicyFileName(granted);
	File f = new File(name);
	boolean rvalue = ( f.exists() && _fileChanged(granted,f) );

        if (logger.isLoggable(Level.FINE)){
            logger.fine("JACC Policy Provider: file arrival check" +
                    " type: " + (granted? "granted " : "excluded ") +
                    " arrived: " + rvalue +
		    " exists: " + f.exists() +
		    " lastModified: " + f.lastModified() + 
		    " storedTime: " + lastModTimes[(int) (granted ? 1 : 0)] +
                    " state: " + (this.state == OPEN_STATE ? "open " : "deleted ") +
                    CONTEXT_ID);
        }

	return rvalue;
    }

    // initilaize the internal data structures.
    // if open, then mark state as open
    // if remove, then remove any existing policy statements
    // if fromFile (and not remove), then mark state as in service,
    //      and not requiring write on commit
    // if fromFile (and remove), then remove and mark state as open
    protected void initialize(boolean open, boolean remove, boolean fromFile) {
	synchronized(refreshLock) {
	    String name = getPolicyFileName(true);
	    if (open || remove) {
		setState(OPEN_STATE);
	    } else {
		setState(INSERVICE_STATE);
	    }
	    try {
		if (remove) {
		    removePolicy();
		}

		policyUrlValue = 
		    sun.net.www.ParseUtil.fileToEncodedURL(new File(name)).toString();
		if (fromFile && !remove) {
                    uncheckedPermissions = null;
                    rolePermissionsTable = null;
		    excludedPermissions = loadExcludedPolicy();
                    initLinkTable();
                    captureFileTime(true);
		    writeOnCommit = false;
		}
		wasRefreshed = false;
	    } catch (java.net.MalformedURLException mue) {
                String defMsg="Unable to convert Policy file Name to URL: "+name;
                String msg=localStrings.getLocalString("pc.file_to_url",defMsg, new Object[]{name,mue});
		logger.log(Level.SEVERE,msg);
		throw new RuntimeException(defMsg);
	    }
	}
    }

    private String getPolicyFileName(boolean granted) {
      return granted ?
	  getContextDirectoryName()+File.separator+"granted"+policySuffix :
	  getContextDirectoryName()+File.separator+"excluded"+policySuffix;
    }

    private String getContextDirectoryName() {
	if (repository == null) {
	    throw new RuntimeException("JACC Policy provider: repository not initialized");
	}
	return fact.getContextDirectoryName(CONTEXT_ID);
    }

    

    // remove the directory used ot hold the context's policy files
    private void removePolicyContextDirectory(){
	String directoryName = getContextDirectoryName();
	File f = new File(directoryName);
	if(f.exists()){

            // WORKAROUND: due to existence of timestamp file in given directory
            // for SE/EE synchronization
            File[] files = f.listFiles();
            if (files != null && files.length > 0) {
                for (int i = 0; i < files.length; i++) {
                    files[i].delete();
                }
             }
             //WORKAROUND: End 

	    if (!f.delete()) {
                String defMsg = "Failure removing policy context directory: "+directoryName;
                String msg=localStrings.getLocalString("pc.file_delete_error", defMsg);
		logger.log(Level.SEVERE,msg);
		throw new RuntimeException(defMsg);
	    } else if(logger.isLoggable(Level.FINE)){
		logger.fine("JACC Policy Provider: Policy context directory removed: "+directoryName);
	    }

            File appDir = f.getParentFile();
            // WORKAROUND: due to existence of timestamp file in given directory
            // for SE/EE synchronization
            File[] fs = appDir.listFiles();
            if (fs != null && fs.length > 0) {
                boolean hasDir = false;
                for (int i = 0; i < fs.length; i++) {
                    if (fs[i].isDirectory()) {
                        hasDir = true;
                        break;
                    }
                }
                if (!hasDir) {
                    for (int i = 0; i < fs.length; i++) {
                        fs[i].delete();
                    }
                }
            }
            //WORKAROUND: End 

            File[] moduleDirs = appDir.listFiles();
            if (moduleDirs == null || moduleDirs.length == 0) {
                if (!appDir.delete()) {
                    String defMsg = "Failure removing policy context directory: " + appDir;
                    String msg = localStrings.getLocalString("pc.file_delete_error", defMsg);
		    logger.log(Level.SEVERE,msg);
		    throw new RuntimeException(defMsg);
                }
            }
	}
    }

    // remove the external (file) policy statements.
    private void removePolicyFile(boolean granted){
	String fileName = getPolicyFileName(granted);
	File f = new File(fileName);
	if(f.exists()){
	    if (!f.delete()) {
                String defMsg = "Failure removing policy file: "+fileName; 
                String msg=localStrings.getLocalString("pc.file_delete_error", defMsg,new Object []{ fileName} );
		logger.log(Level.SEVERE,msg);
		throw new RuntimeException(defMsg);
	    } else if(logger.isLoggable(Level.FINE)){
		logger.fine("JACC Policy Provider: Policy file removed: "+fileName);
	    }
	}
    }

    // remove the internal and external (file) policy statements.
    private void removePolicy(){
	excludedPermissions = null;
	uncheckedPermissions = null;
	rolePermissionsTable = null;
	removePolicyFile(true);
	removePolicyFile(false);
	removePolicyContextDirectory();
	initLinkTable();
	policy = null;
	writeOnCommit = true;
    }

    private void initLinkTable() {

	synchronized(refreshLock) {
	    // get the linkSet corresponding to this context.
	    Set linkSet = (Set) fact.getLinkTable().get(CONTEXT_ID);
	    // remobe this context id from the linkSet (which may be shared
	    // with other contexts), and unmap the linkSet form this context.
	    if (linkSet != null) {
		linkSet.remove(CONTEXT_ID);
		fact.getLinkTable().remove(CONTEXT_ID);
	    }

	    // create a new linkSet with onlythis context id, and put it in the table.
	    linkSet = new HashSet();
	    linkSet.add(CONTEXT_ID);
	    fact.getLinkTable().put(CONTEXT_ID,linkSet);
	}
    }

    private void updateLinkTable(String otherId) {

	synchronized(refreshLock) {

	    // get the linkSet corresponding to this context
	    Set linkSet = (Set) fact.getLinkTable().get(CONTEXT_ID);
	    // get the linkSet corresponding to the context being linked to this
	    Set otherLinkSet = (Set) fact.getLinkTable().get(otherId);

	    if (otherLinkSet == null) {
                String defMsg="Linked policy configuration ("+otherId+") does not exist";
                //String msg = localStrings.getLocalString("pc.invalid_link_target",defMsg, new Object []{otherId});
		logger.log(Level.SEVERE,"pc.invalid_link_target",otherId);
		throw new RuntimeException(defMsg);
	    } else {
		Iterator it = otherLinkSet.iterator();
		// for each context (id) linked to the context being linked to this
		while (it.hasNext()) {
		    String id = (String) it.next();
		    //add the id to this linkSet
		    linkSet.add(id);
		    //replace the linkset mapped to all the contexts being linked
		    //to this context, with this linkset.
		    fact.getLinkTable().put(id,linkSet);
		}
	    }
	}
    }

    private void setState(int stateValue) {
	wLock.lock();
	try {
	    this.state = stateValue;
	} finally {
	    wLock.unlock();
	}
    }

    
    private boolean _stateIs(int stateValue) {
	rLock.lock();
	try {
	    return (this.state == stateValue);
	} finally {
	    rLock.unlock();
	}
    }
    
     /**
     * checks if PolicyContex is in agrument state.
     * Detects implicpit state changes resulting from
     * distribution of policy files by synchronization
     * system.
     * @param stateValue state the context is tested for
     * @return true if in state.
     */
    private boolean stateIs(int stateValue) {
	boolean inState = _stateIs(stateValue);
	if (stateValue == INSERVICE_STATE && !inState) {
	    if (fileArrived(true) || fileArrived(false)) {
                
                if (logger.isLoggable(Level.FINE)){
                    logger.fine("JACC Policy Provider: file arrived transition to inService: " +
                        " state: " + (this.state == OPEN_STATE ? "open " : "deleted ") +
                        CONTEXT_ID);
                }
                
		// initialize(!open,!remove,fromFile)               
                initialize(false,false,true);
	    }
	    inState = _stateIs(INSERVICE_STATE);
	} 
              
	return inState;
    }


    private void assertStateIsOpen() {
      
        if (!stateIs(OPEN_STATE)){
            String defMsg="Operation invoked on closed or deleted PolicyConfiguration.";
            String msg = localStrings.getLocalString("pc.op_requires_state_open",defMsg); 
	    logger.log(Level.WARNING, msg);
	    throw new UnsupportedOperationException(defMsg);
	}
    }

 

    private Permissions getUncheckedPermissions() {
	if (uncheckedPermissions == null) {
	    uncheckedPermissions = new Permissions();
	}
	return uncheckedPermissions;
    }

    private Permissions getExcludedPermissions() {
	if (excludedPermissions == null) {
	    excludedPermissions = new Permissions();
	}
	return excludedPermissions;
    }

    private Permissions getRolePermissions(String roleName) {
	if (rolePermissionsTable == null) rolePermissionsTable = new HashMap();
	Permissions rolePermissions = (Permissions) rolePermissionsTable.get(roleName);
	if (rolePermissions == null) {
	    rolePermissions = new Permissions();
	    rolePermissionsTable.put(roleName,rolePermissions);
	}
	return rolePermissions;
    }

    // This method workarounds a bug in PolicyParser.write(...).
    private String escapeName(String name) {
        return (name != null && name.indexOf('"') > 0) ?
                name.replaceAll("\"", "\\\\\"") : name;
    }
    
    private void generatePermissions() 

	throws java.io.FileNotFoundException, java.io.IOException {

	// optimization - return if the rules have not changed

	if (!writeOnCommit) return;

	// otherwise proceed to write policy file

	Map roleToSubjectMap = null;
        SecurityRoleMapperFactory factory=SecurityRoleMapperFactoryGen.getSecurityRoleMapperFactory();
	if (rolePermissionsTable != null) {
	    // Make sure a role to subject map has been defined for the Policy Context
	    if (factory != null) {
                // the rolemapper is stored against the
                // appname, for a web app get the appname for this contextid
                SecurityRoleMapper srm = factory.getRoleMapper(CONTEXT_ID);
		if (srm != null) {
		    roleToSubjectMap = srm.getRoleToSubjectMapping();
		}
		if (roleToSubjectMap != null) {
		    // make sure all liked PC's have the same roleToSubjectMap
		    Set linkSet = (Set) fact.getLinkTable().get(CONTEXT_ID);
		    if (linkSet != null) {
			Iterator it = linkSet.iterator();
			while (it.hasNext()) {
			    String contextId = (String)it.next();
			    if (!CONTEXT_ID.equals(contextId)) {
				SecurityRoleMapper otherSrm = factory.getRoleMapper(contextId);
				Map otherRoleToSubjectMap = null;

				if (otherSrm != null) {
				    otherRoleToSubjectMap = otherSrm.getRoleToSubjectMapping();
				}
				
				if (otherRoleToSubjectMap != roleToSubjectMap) {
                                    String defMsg="Linked policy contexts have different roleToSubjectMaps ("+CONTEXT_ID+")<->("+contextId+")";
                                    String msg=localStrings.getLocalString("pc.linked_with_different_role_maps",defMsg,new Object []{CONTEXT_ID,contextId});
				    logger.log(Level.SEVERE,msg); 
				    throw new RuntimeException(defMsg);
				}
			    }
			}
		    }
		}
	    }
	}

	if (roleToSubjectMap == null && rolePermissionsTable != null) {
            String defMsg="This application has no role mapper factory defined";
            String msg=localStrings.getLocalString("pc.role_map_not_defined_at_commit",defMsg,new Object []{CONTEXT_ID});
	    logger.log(Level.SEVERE,msg);
	    throw new RuntimeException
		(localStrings.getLocalString
		 ("enterprise.deployment.deployment.norolemapperfactorydefine",defMsg));
	}

	PolicyParser parser = new PolicyParser(false);

	// load unchecked grants in parser
	if (uncheckedPermissions != null) {
	    Enumeration pEnum = uncheckedPermissions.elements();
	    if (pEnum.hasMoreElements()) {
		GrantEntry grant = new GrantEntry();
		while (pEnum.hasMoreElements()) {
		    Permission p = (Permission) pEnum.nextElement();
		    PermissionEntry entry = 
			new PermissionEntry(p.getClass().getName(),
					    p.getName(),p.getActions());
		    grant.add(entry);
		}
		parser.add(grant);
	    }
	}

	// load role based grants in parser
	if (rolePermissionsTable != null) {
	    Iterator roleIt = rolePermissionsTable.keySet().iterator();
	    while (roleIt.hasNext()) {
		boolean withPrincipals = false;
		String roleName = (String) roleIt.next();
		Permissions rolePerms = getRolePermissions(roleName);
		Subject rolePrincipals = (Subject) roleToSubjectMap.get(roleName);
		if (rolePrincipals != null) {
		    Iterator pit = rolePrincipals.getPrincipals().iterator();
		    while (pit.hasNext()){
			Principal prin = (Principal) pit.next();
			assert prin instanceof java.security.Principal;
			if (prin instanceof java.security.Principal) {
			    withPrincipals = true;
			    PrincipalEntry prinEntry = 
				new PrincipalEntry(prin.getClass().getName(),
						   escapeName(prin.getName()));
			    GrantEntry grant = new GrantEntry();
			    grant.principals.add(prinEntry);
			    Enumeration pEnum = rolePerms.elements();
			    while (pEnum.hasMoreElements()) {
				Permission perm = (Permission) pEnum.nextElement();
				PermissionEntry permEntry = 
				    new PermissionEntry(perm.getClass().getName(),
							perm.getName(),
							perm.getActions());
				grant.add(permEntry);
			    }
			    parser.add(grant);
			}
			else {
                            String msg = localStrings.getLocalString("pc.non_principal_mapped_to_role",
                                         "non principal mapped to role "+roleName,new Object[]{prin,roleName});
			    logger.log(Level.WARNING,msg);
			}
		    }
		} 
		if (!withPrincipals) {
                    String msg = localStrings.getLocalString("pc.no_principals_mapped_to_role",
                                  "no principals mapped to role "+roleName, new Object []{ roleName});
		    logger.log(Level.WARNING,msg);
		}
	    }
	}

	writeOnCommit = createPolicyFile(true,parser,writeOnCommit);

	// load excluded perms in excluded parser
	if (excludedPermissions != null) {

	    PolicyParser excludedParser = new PolicyParser(false);

	    Enumeration pEnum = excludedPermissions.elements();
	    if (pEnum.hasMoreElements()) {
		GrantEntry grant = new GrantEntry();
		while (pEnum.hasMoreElements()) {
		    Permission p = (Permission) pEnum.nextElement();
		    PermissionEntry entry = 
			new PermissionEntry(p.getClass().getName(),
					    p.getName(),p.getActions());
		    grant.add(entry);
		}
		excludedParser.add(grant);
	    }

	    writeOnCommit = createPolicyFile(false,excludedParser,writeOnCommit);
	} 

	if (!writeOnCommit) wasRefreshed = false;
    }

    private void createPolicyContextDirectory() {

	String contextDirectoryName = getContextDirectoryName();
	File d = new File(contextDirectoryName);
	if (d.exists()) {
	    if(!d.isDirectory()) {
                String defMsg="unable to create policy context directory";
                String msg=localStrings.getLocalString("pc.unable_to_create_context_directory",
                      defMsg,new Object []{contextDirectoryName});
		logger.log(Level.SEVERE,msg);
		throw new RuntimeException(defMsg);
	    } 
	} else {
	    d.mkdirs();
	}
    }

    // returns false if write succeeds. otherwise returns input woc (i.e. writeOnCommit)
    private boolean createPolicyFile
	(boolean granted, PolicyParser parser, boolean woc) throws java.io.IOException {

	boolean result = woc;
	createPolicyContextDirectory();
	removePolicyFile(granted);
	String name = getPolicyFileName(granted);
	OutputStreamWriter writer = null;
	try {
	    if(logger.isLoggable (Level.FINE)){
		logger.fine("JACC Policy Provider: Writing grant statements to policy file: "+name);
	    }
	    writer = new OutputStreamWriter(new FileOutputStream(name), "UTF-8");
	    parser.write(writer);
	    result = false;
	} catch(java.io.FileNotFoundException fnfe) {
            String msg=localStrings.getLocalString("pc.file_error","file not found "+name,
                  new Object []{name, fnfe});
	    logger.log(Level.SEVERE,msg);
	    throw fnfe;
	} catch(java.io.IOException ioe){
            String msg=localStrings.getLocalString("pc.file_write_error","file IO error on file "+name,
                  new Object []{name,ioe});
	    logger.log(Level.SEVERE,msg);
	    throw ioe;
	} finally {
	    if (writer != null) {
		try {
		    writer.close();
		    captureFileTime(granted);
		} catch (Exception e) {
                    String defMsg="Unable to close Policy file: "+name;
                    String msg=localStrings.getLocalString("pc.file_close_error",defMsg,new Object []{name,e}); 
		    logger.log(Level.SEVERE,msg);
		    throw new RuntimeException(defMsg);
		}
	    }
	}
	return result;
    }

    private Permission loadPermission(String className,String name,String actions){
	Class clazz = null;
	Permission permission = null;
	try{
	    clazz = Class.forName(className);
	    Constructor c = clazz.getConstructor(permissionParams);
	    permission = (Permission) c.newInstance(new Object[] { name, actions });	
	} catch(Exception e){
            String defMsg="PolicyConfiguration error loading permission";
            String msg=localStrings.getLocalString("pc.permission_load_error",defMsg,
                       new Object []{className, e});
	    logger.log(Level.SEVERE,msg);
	    throw new RuntimeException(defMsg,e);
	}
	return permission;
    }

    private Permissions loadExcludedPolicy() {
	Permissions result = null;
	String name = getPolicyFileName(false);
	FileReader reader = null;
	PolicyParser parser = new PolicyParser(false);
	try {
	    captureFileTime(false);
	    reader = new FileReader(name);
	    parser.read(reader);
	} catch (java.io.FileNotFoundException fnf) {
	    //Just means there is no excluded Policy file, which
	    // is the typical case
	    parser = null;
	} catch (java.io.IOException ioe) {
            String defMsg="Error reading Policy file: "+name;
            String msg=localStrings.getLocalString("pc.file_read_error",defMsg,
                       new Object []{name, ioe});
	    logger.log(Level.SEVERE,msg);
	    throw new RuntimeException(defMsg);
	} catch ( sun.security.provider.PolicyParser.ParsingException pe) {
            String defMsg="Unable to parse Policy file: "+name;
            String msg=localStrings.getLocalString("pc.policy_parsing_exception",defMsg,
                       new Object []{name,pe});
	    logger.log(Level.SEVERE,msg);
	    throw new RuntimeException(defMsg);
	} finally {
	    if (reader != null) {
		try {
		    reader.close();
		} catch (Exception e) {
                    String defMsg="Unable to close Policy file: "+name;
                    String msg=localStrings.getLocalString("pc.file_close_error",defMsg,
                                new Object []{name,e});
		    logger.log(Level.SEVERE,msg);
		    throw new RuntimeException(defMsg);
		}
	    }
	}

	if (parser != null) {
	    Enumeration grants = parser.grantElements();
	    while (grants.hasMoreElements()) {
		GrantEntry grant = (GrantEntry) grants.nextElement();
		if (grant.codeBase != null || grant.signedBy != null || 
		    grant.principals.size() != 0) {
                        String msg=localStrings.getLocalString("pc.excluded_grant_context_ignored",
                                   "ignore excluded grant context", new Object []{grant});
		    logger.log(Level.WARNING,msg);
		} else {
		    Enumeration perms = grant.permissionEntries.elements();
		    while (perms.hasMoreElements()) {
			PermissionEntry entry = (PermissionEntry) perms.nextElement();
			Permission p = 
			    loadPermission(entry.permission,entry.name,entry.action);
			if (result == null) {
			    result = new Permissions();
			}
			result.add(p);
		    }
		}
	    }
	}

	return result;
    }

}





Other Glassfish examples (source code examples)

Here is a short list of links related to this Glassfish PolicyConfigurationImpl.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.