You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openaz.apache.org by pd...@apache.org on 2016/03/17 02:07:00 UTC

[21/23] incubator-openaz git commit: Ported original att source to openaz

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/a1d93100/openaz-xacml-pap-admin/src/META-INF/drop.sql
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/META-INF/drop.sql b/openaz-xacml-pap-admin/src/META-INF/drop.sql
new file mode 100644
index 0000000..8aee7ee
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/META-INF/drop.sql
@@ -0,0 +1,21 @@
+DROP TABLE IF EXISTS AttributeAssignment;
+DROP TABLE IF EXISTS ConstraintValues;
+DROP TABLE IF EXISTS ObadviceExpressions;
+DROP TABLE IF EXISTS Attribute;
+DROP TABLE IF EXISTS Category;
+DROP TABLE IF EXISTS ConstraintType;
+DROP VIEW IF EXISTS match_functions;
+DROP VIEW IF EXISTS higherorder_bag_functions;
+DROP VIEW IF EXISTS function_flattener;
+DROP TABLE IF EXISTS FunctionArguments;
+DROP TABLE IF EXISTS FunctionDefinition;
+DROP TABLE IF EXISTS Datatype;
+DROP TABLE IF EXISTS Obadvice;
+DROP TABLE IF EXISTS PIPConfigParams;
+DROP TABLE IF EXISTS PIPResolverParams;
+DROP TABLE IF EXISTS PIPResolver;
+DROP TABLE IF EXISTS PIPConfiguration;
+DROP TABLE IF EXISTS PIPType;
+DROP TABLE IF EXISTS PolicyAlgorithms;
+DROP TABLE IF EXISTS RuleAlgorithms;
+DROP TABLE IF EXISTS SEQUENCE;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/a1d93100/openaz-xacml-pap-admin/src/META-INF/empty.sql
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/META-INF/empty.sql b/openaz-xacml-pap-admin/src/META-INF/empty.sql
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/a1d93100/openaz-xacml-pap-admin/src/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/META-INF/persistence.xml b/openaz-xacml-pap-admin/src/META-INF/persistence.xml
new file mode 100644
index 0000000..79594a9
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/META-INF/persistence.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
+	<persistence-unit name="XACML-PAP-ADMIN">
+		<class>org.apache.openaz.xacml.admin.jpa.Attribute</class>
+		<class>org.apache.openaz.xacml.admin.jpa.AttributeAssignment</class>
+		<class>org.apache.openaz.xacml.admin.jpa.Category</class>
+		<class>org.apache.openaz.xacml.admin.jpa.ConstraintType</class>
+		<class>org.apache.openaz.xacml.admin.jpa.ConstraintValue</class>
+		<class>org.apache.openaz.xacml.admin.jpa.Datatype</class>
+		<class>org.apache.openaz.xacml.admin.jpa.Obadvice</class>
+		<class>org.apache.openaz.xacml.admin.jpa.ObadviceExpression</class>
+		<class>org.apache.openaz.xacml.admin.jpa.PolicyAlgorithms</class>
+		<class>org.apache.openaz.xacml.admin.jpa.RuleAlgorithms</class>
+		<class>org.apache.openaz.xacml.admin.jpa.FunctionArgument</class>
+		<class>org.apache.openaz.xacml.admin.jpa.FunctionDefinition</class>
+		<class>org.apache.openaz.xacml.admin.jpa.PIPConfigParam</class>
+		<class>org.apache.openaz.xacml.admin.jpa.PIPConfiguration</class>
+		<class>org.apache.openaz.xacml.admin.jpa.PIPResolver</class>
+		<class>org.apache.openaz.xacml.admin.jpa.PIPResolverParam</class>
+		<class>org.apache.openaz.xacml.admin.jpa.PIPType</class>
+		<properties>
+			<!-- 
+				The properties defined below are the default settings to be used when someone initially
+				wants to start working with the XACML-PAP-ADMIN web gui. They are not intended for production
+				use.
+				
+				They are setup to drop and create the tables and then load an initial set of data into the database
+				every time the application is deployed. So if you add anything to the dictionaries or PIP
+				configuration, they will get lost upon each deployment. It uses an H2 database engine configured
+				for a local file so you don't have to setup you're own SQL database environment to start.
+				
+				Instead of modifying this file directly, please refer to the xacml.admin.properties file for
+				customizing the application settings.
+				
+			 -->
+			<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
+			<property name="javax.persistence.schema-generation.create-source" value="metadata-then-script"/>
+			<property name="javax.persistence.schema-generation.create-script-source" value="META-INF/views.sql" />
+			<property name="javax.persistence.schema-generation.drop-source" value="script"/>
+			<property name="javax.persistence.schema-generation.drop-script-source" value="META-INF/drop.sql" />
+			<property name="javax.persistence.sql-load-script-source" value="META-INF/data.sql" />
+			
+			<!-- 
+			
+			These properties should be set in the xacml.admin.properties file, so they can be re-used by non-JPA
+			database functionality.
+			
+			<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
+			<property name="javax.persistence.jdbc.url" value="jdbc:h2:file:sql/xacml"/>
+			<property name="javax.persistence.jdbc.user" value="sa"/>
+			<property name="javax.persistence.jdbc.password" value=""/>
+			 -->
+		</properties>
+	</persistence-unit>
+</persistence>

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/a1d93100/openaz-xacml-pap-admin/src/META-INF/views.sql
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/META-INF/views.sql b/openaz-xacml-pap-admin/src/META-INF/views.sql
new file mode 100644
index 0000000..7c4a820
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/META-INF/views.sql
@@ -0,0 +1,6 @@
+
+CREATE VIEW match_functions AS SELECT D.ID AS id, D.SHORT_NAME AS shortname, D.XACML_ID AS xacmlid,	D.RETURN_DATATYPE AS return_datatype, D.IS_BAG_RETURN AS is_bag_return,	D.ARG_LB AS arg_lb,	D.ARG_UB AS arg_ub,	A1.IS_BAG AS arg1_isbag, A1.DATATYPE_ID AS arg1_datatype, A2.IS_BAG AS arg2_isbag,	A2.DATATYPE_ID AS arg2_datatype FROM (FunctionDefinition D left join FunctionArguments A1 on (A1.FUNCTION_ID = D.ID and A1.ARG_INDEX = 1) left join FunctionArguments A2 on (A2.FUNCTION_ID = D.ID and A2.ARG_INDEX = 2)) where (D.ARG_LB = 2 and D.ARG_UB = 2 and D.RETURN_DATATYPE = 18 and A1.IS_BAG = 0) order by D.SHORT_NAME;
+
+CREATE VIEW function_flattener AS SELECT D.ID AS id, D.SHORT_NAME AS shortname, D.RETURN_DATATYPE AS return_datatype, D.IS_BAG_RETURN AS is_bag_return, D.IS_HIGHER_ORDER AS is_higher_order, D.ARG_LB AS arg_lb, D.ARG_UB AS arg_ub, A1.IS_BAG AS arg1_isbag, A1.DATATYPE_ID AS arg1_datatype, A2.IS_BAG AS arg2_isbag, A2.DATATYPE_ID AS arg2_datatype, A3.IS_BAG AS arg3_isbag, A3.DATATYPE_ID AS arg3_datatype FROM (FunctionDefinition D left join FunctionArguments A1 ON (A1.FUNCTION_ID = D.ID and A1.ARG_INDEX = 1) left join FunctionArguments A2 ON (A2.FUNCTION_ID = D.ID and A2.ARG_INDEX = 2) LEFT JOIN FunctionArguments A3 ON (A3.FUNCTION_ID = D.ID and A3.ARG_INDEX = 3)) ORDER BY D.ID;
+
+CREATE VIEW higherorder_bag_functions AS SELECT * FROM function_flattener WHERE is_higher_order = 1 AND is_bag_return = 1 AND return_datatype=18 AND arg_lb=2 AND arg_ub=2 AND arg1_isbag = 1 AND (arg2_isbag = 1 OR arg2_isbag IS NULL);

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/a1d93100/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/PAPNotificationBroadcaster.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/PAPNotificationBroadcaster.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/PAPNotificationBroadcaster.java
new file mode 100644
index 0000000..b2deda7
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/PAPNotificationBroadcaster.java
@@ -0,0 +1,120 @@
+/*
+ *  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.openaz.xacml.admin;
+
+import java.io.Serializable;
+import java.util.LinkedList;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Handle Notifications from the PAP that the PDP Groups have been changed.
+ * We need a Server Push Broadcaster because there may be multiple Vaadin instances (i.e. Users) that need to be told when a change occurs.
+ * 
+ * Initially we only update the entire set of PDPGroups in one shot.
+ * 
+ * (Code copied from Book of Vaadin chapter on Server Push
+ * @author glenngriffin
+ *
+ */
+public class PAPNotificationBroadcaster implements Serializable {
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = -2539940306348821754L;
+
+
+	private static Log logger	= LogFactory.getLog(PAPNotificationBroadcaster.class);
+
+	
+    static ExecutorService executorService = Executors.newSingleThreadExecutor();
+
+    /**
+     * Interface used by all classes that need to be notified when PAP sends an update message.
+     * 
+     * @author glenngriffin
+     *
+     */
+    public interface PAPNotificationBroadcastListener {
+        void updateAllGroups();
+    }
+    
+    
+    
+    /*
+     * list of registered listeners
+     */
+    private static LinkedList<PAPNotificationBroadcastListener> listeners =
+        new LinkedList<PAPNotificationBroadcastListener>();
+    
+    /**
+     * Listener registers to hear about updates.
+     * @param listener
+     */
+    public static synchronized void register(
+    		PAPNotificationBroadcastListener listener) {
+        listeners.add(listener);
+    }
+    
+    
+    /**
+     * Listener is going away.
+     * 
+     * @param listener
+     */
+    public static synchronized void unregister(
+    		PAPNotificationBroadcastListener listener) {
+        listeners.remove(listener);
+    }
+    
+    
+    
+    /**
+     * Tell all listeners about an update.
+     * 
+     * @param message
+     */
+    public static synchronized void updateAllGroups() {
+        for (final PAPNotificationBroadcastListener listener: listeners) {
+  // Original code copied from example:
+  //          executorService.execute(new Runnable() {
+  //              @Override
+  //              public void run() {
+  // The problem with this is that the execute starts a new Thread, but the thing we are calling (the listener.updateAllGroups)
+  // happens in this case to ALSO create a new thread, and it locks up because the shared threadpool queue is already locked by this method.
+  // On application shutdown that left us with a blocked thread, so the process never goes away.
+  // Since the listener.updateAllGroups does ALL of its work inside a new Runnable thread, there should be no need for this method to also create a thread.
+  
+        	/*
+        	 * IMPORTANT:
+        	 * All listeners MUST either execute with no possibility of blocking
+        	 * OR must start their own threads to handle blocking and concurrent operations.
+        	 */
+        	if (logger.isDebugEnabled()) {
+        		logger.debug("updateAllGroups");
+        	}
+            listener.updateAllGroups();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/a1d93100/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlAdminAuthorization.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlAdminAuthorization.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlAdminAuthorization.java
new file mode 100644
index 0000000..2a065d5
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlAdminAuthorization.java
@@ -0,0 +1,178 @@
+/*
+ *  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.openaz.xacml.admin;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.openaz.xacml.std.annotations.XACMLRequest;
+import org.apache.openaz.xacml.std.annotations.RequestParser;
+import org.apache.openaz.xacml.std.annotations.XACMLSubject;
+import org.apache.openaz.xacml.std.annotations.XACMLAction;
+import org.apache.openaz.xacml.std.annotations.XACMLResource;
+import org.apache.openaz.xacml.api.DataTypeException;
+import org.apache.openaz.xacml.api.Decision;
+import org.apache.openaz.xacml.api.Request;
+import org.apache.openaz.xacml.api.Response;
+import org.apache.openaz.xacml.api.Result;
+import org.apache.openaz.xacml.api.pdp.PDPEngine;
+import org.apache.openaz.xacml.api.pdp.PDPEngineFactory;
+import org.apache.openaz.xacml.api.pdp.PDPException;
+import org.apache.openaz.xacml.util.FactoryException;
+
+public class XacmlAdminAuthorization {
+	private static Log logger	= LogFactory.getLog(XacmlAdminAuthorization.class);
+	
+	public enum AdminAction {
+		ACTION_ACCESS("access"),
+		ACTION_READ("read"),
+		ACTION_WRITE("write"),
+		ACTION_ADMIN("admin");
+		
+		String action;
+		AdminAction(String a) {
+			this.action = a;
+		}
+		public String toString() {
+			return this.action;
+		}
+	}
+	
+	public enum AdminResource {
+		RESOURCE_APPLICATION("application"),
+		RESOURCE_POLICY_WORKSPACE("workspace"),
+		RESOURCE_POLICY_EDITOR("editor"),
+		RESOURCE_DICTIONARIES("dictionaries"),
+		RESOURCE_PDP_ADMIN("pdp_admin"),
+		RESOURCE_PIP_ADMIN("pip_admin");
+		
+		String resource;
+		AdminResource(String r) {
+			this.resource = r;
+		}
+		public String toString() {
+			return this.resource;
+		}
+	}
+	
+	@XACMLRequest(ReturnPolicyIdList=true)
+	public class AuthorizationRequest {
+		
+		@XACMLSubject(includeInResults=true)
+		String	userID;
+		
+		@XACMLAction()
+		String	action;
+		
+		@XACMLResource()
+		String	resource;
+		
+		public AuthorizationRequest(String userId, String action, String resource) {
+			this.userID = userId;
+			this.action = action;
+			this.resource = resource;
+		}
+
+		public String getUserID() {
+			return userID;
+		}
+
+		public void setUserID(String userID) {
+			this.userID = userID;
+		}
+
+		public String getAction() {
+			return action;
+		}
+
+		public void setAction(String action) {
+			this.action = action;
+		}
+
+		public String getResource() {
+			return resource;
+		}
+
+		public void setResource(String resource) {
+			this.resource = resource;
+		}
+	}
+	
+	//
+	// The PDP Engine
+	//
+	protected PDPEngine pdpEngine;
+
+	public XacmlAdminAuthorization() {
+		PDPEngineFactory pdpEngineFactory	= null;
+		try {
+			pdpEngineFactory	= PDPEngineFactory.newInstance();
+			if (pdpEngineFactory == null) {
+				logger.error("Failed to create PDP Engine Factory");
+			}
+			this.pdpEngine = pdpEngineFactory.newEngine();
+		} catch (FactoryException e) {
+			logger.error("Exception create PDP Engine: " + e.getLocalizedMessage());
+		}
+	}
+	
+	public boolean	isAuthorized(String userid, AdminAction action, AdminResource resource) {
+		logger.info("authorize: " + userid + " to " + action + " with " + resource);
+		if (this.pdpEngine == null) {
+			logger.warn("no pdp engine available to authorize");
+			return false;
+		}
+		Request request;
+		try {
+			request = RequestParser.parseRequest(new AuthorizationRequest(userid, action.toString(), resource.toString()));
+		} catch (IllegalArgumentException | IllegalAccessException | DataTypeException e) {
+			logger.error("Failed to create request: " + e.getLocalizedMessage());
+			return false;
+		}
+		if (request == null) {
+			logger.error("Failed to parse request.");
+			return false;
+		}
+		logger.info("Request: " + request);
+		//
+		// Ask the engine
+		//
+		try {
+			Response response = this.pdpEngine.decide(request);
+			if (response == null) {
+				logger.error("Null response from PDP decide");
+			}
+			//
+			// Should only be one result
+			//
+			for (Result result : response.getResults()) {
+				Decision decision = result.getDecision();
+				logger.info("Decision: " + decision);
+				if (decision.equals(Decision.PERMIT)) {
+					return true;
+				}
+			}
+		} catch (PDPException e) {
+			logger.error("PDP Decide failed: " + e.getLocalizedMessage());
+		}
+		return false;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/a1d93100/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlAdminConsole.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlAdminConsole.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlAdminConsole.java
new file mode 100644
index 0000000..91e831b
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlAdminConsole.java
@@ -0,0 +1,253 @@
+/*
+ *  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.openaz.xacml.admin;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.openaz.xacml.admin.components.AttributeDictionary;
+import org.apache.openaz.xacml.admin.components.ObadviceDictionary;
+import org.apache.openaz.xacml.admin.components.PDPManagement;
+import org.apache.openaz.xacml.admin.components.PIPManagement;
+import org.apache.openaz.xacml.admin.components.PolicyWorkspace;
+import com.vaadin.annotations.AutoGenerated;
+import com.vaadin.navigator.View;
+import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
+import com.vaadin.server.ThemeResource;
+import com.vaadin.shared.ui.label.ContentMode;
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.CustomComponent;
+import com.vaadin.ui.Embedded;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.TabSheet;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.VerticalLayout;
+
+public class XacmlAdminConsole extends CustomComponent implements View {
+	private static final long serialVersionUID = 1L;
+	@AutoGenerated
+	private VerticalLayout mainLayout;
+	@AutoGenerated
+	private Label labelCopyright;
+	@AutoGenerated
+	private TabSheet tabSheet;
+	@AutoGenerated
+	private HorizontalLayout horizontalLayout_1;
+	@AutoGenerated
+	private Label labelWelcome;
+	@AutoGenerated
+	private Label caption;
+	@AutoGenerated
+	private Embedded embedded_1;
+
+	private static Log logger	= LogFactory.getLog(XacmlAdminConsole.class);
+	
+	private final PolicyWorkspace policyWorkspace;
+	private final AttributeDictionary attributeDictionary;
+	private final ObadviceDictionary obadvice;
+	private final PDPManagement pdp;
+	private final PIPManagement pip;
+//	private final UserManagement user;
+	
+	/**
+	 * The constructor should first build the main layout, set the
+	 * composition root and then do any custom initialization.
+	 *
+	 * The constructor will not be automatically regenerated by the
+	 * visual editor.
+	 */
+	public XacmlAdminConsole() {
+		buildMainLayout();
+		setCompositionRoot(mainLayout);
+		
+		if (logger.isDebugEnabled()) {
+			logger.debug("Creating tabs...");
+		}
+		
+		this.labelWelcome.setValue("Welcome " + ((XacmlAdminUI)UI.getCurrent()).getUserName());
+		this.labelCopyright.setContentMode(ContentMode.HTML);
+		
+		if (((XacmlAdminUI)UI.getCurrent()).isAuthorized( 
+				XacmlAdminAuthorization.AdminAction.ACTION_READ, 
+				XacmlAdminAuthorization.AdminResource.RESOURCE_POLICY_WORKSPACE)) {
+			this.policyWorkspace = new PolicyWorkspace();
+			this.tabSheet.addComponent(this.policyWorkspace);
+			this.tabSheet.getTab(this.policyWorkspace).setCaption("Policy Workspace");
+		} else {
+			this.policyWorkspace = null;
+		}
+		
+		if (((XacmlAdminUI)UI.getCurrent()).isAuthorized( 
+				XacmlAdminAuthorization.AdminAction.ACTION_READ, 
+				XacmlAdminAuthorization.AdminResource.RESOURCE_DICTIONARIES)) {
+			this.attributeDictionary = new AttributeDictionary();
+			this.tabSheet.addComponent(this.attributeDictionary);
+			this.tabSheet.getTab(this.attributeDictionary).setCaption("Attribute Dictionary");
+
+			this.obadvice = new ObadviceDictionary(); 
+			this.tabSheet.addComponent(this.obadvice);
+			this.tabSheet.getTab(this.obadvice).setCaption("Obligation/Advice Dictionary");
+		} else {
+			this.attributeDictionary = null;
+			this.obadvice = null;
+		}
+		if (((XacmlAdminUI)UI.getCurrent()).isAuthorized( 
+									XacmlAdminAuthorization.AdminAction.ACTION_READ, 
+									XacmlAdminAuthorization.AdminResource.RESOURCE_PDP_ADMIN)) {
+			this.pdp = new PDPManagement(((XacmlAdminUI)UI.getCurrent()).getPAPEngine());
+			this.tabSheet.addComponent(this.pdp);
+			this.tabSheet.getTab(this.pdp).setCaption("PDP Management");
+		} else {
+			this.pdp = null;
+		}
+		
+		if (((XacmlAdminUI)UI.getCurrent()).isAuthorized( 
+				XacmlAdminAuthorization.AdminAction.ACTION_READ, 
+				XacmlAdminAuthorization.AdminResource.RESOURCE_PIP_ADMIN)) {
+			this.pip = new PIPManagement();
+			this.tabSheet.addComponent(this.pip);
+			this.tabSheet.getTab(this.pip).setCaption("PIP Management");
+		} else {
+			this.pip = null;
+		}
+		/*
+		 * TODO  - figure out how to add this in
+		 *
+		if (((XacmlAdminUI)UI.getCurrent()).isAuthorized( 
+				XacmlAdminAuthorization.AdminAction.ACTION_READ, 
+				XacmlAdminAuthorization.AdminResource.RESOURCE_POLICY_WORKSPACE)) {
+			this.user = new UserManagement();
+			this.tabSheet.addComponent(this.user);
+			this.tabSheet.getTab(this.user).setCaption("User Management");
+		}
+		*/
+		
+		if (logger.isDebugEnabled()) {
+			logger.debug("Done creating tabs.");
+		}
+	}
+	
+	public void refreshAttributes() {
+		this.attributeDictionary.refreshContainer();
+	}
+	public void refreshObadvice() {
+		this.obadvice.refreshContainer();
+	}
+
+	public void refreshPIPConfiguration() {
+		this.pip.refreshContainer();
+	}
+
+	public void refreshPDPGroups() {
+		this.pdp.refreshContainer();
+	}
+
+	public TabSheet getTabSheet() { return tabSheet;}
+
+	@AutoGenerated
+	private VerticalLayout buildMainLayout() {
+		// common part: create layout
+		mainLayout = new VerticalLayout();
+		mainLayout.setImmediate(false);
+		mainLayout.setWidth("100%");
+		mainLayout.setHeight("100%");
+		mainLayout.setMargin(true);
+		
+		// top-level component properties
+		setWidth("100.0%");
+		setHeight("100.0%");
+		
+		// horizontalLayout_1
+		horizontalLayout_1 = buildHorizontalLayout_1();
+		mainLayout.addComponent(horizontalLayout_1);
+		
+		// tabSheet
+		tabSheet = new TabSheet();
+		tabSheet.setImmediate(false);
+		tabSheet.setWidth("100.0%");
+		tabSheet.setHeight("100.0%");
+		mainLayout.addComponent(tabSheet);
+		mainLayout.setExpandRatio(tabSheet, 1.0f);
+		
+		// labelCopyright
+		labelCopyright = new Label();
+		labelCopyright.setImmediate(false);
+		labelCopyright.setWidth("-1px");
+		labelCopyright.setHeight("40px");
+		labelCopyright
+				.setValue("<center>Copyright &copy; 2015 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.</center>");
+		mainLayout.addComponent(labelCopyright);
+		mainLayout.setComponentAlignment(labelCopyright, new Alignment(48));
+		
+		return mainLayout;
+	}
+
+	@AutoGenerated
+	private HorizontalLayout buildHorizontalLayout_1() {
+		// common part: create layout
+		horizontalLayout_1 = new HorizontalLayout();
+		horizontalLayout_1.setImmediate(false);
+		horizontalLayout_1.setWidth("100.0%");
+		horizontalLayout_1.setHeight("40px");
+		horizontalLayout_1.setMargin(false);
+		
+		// embedded_1
+		embedded_1 = new Embedded();
+		embedded_1.setImmediate(false);
+		embedded_1.setWidth("30px");
+		embedded_1.setHeight("30px");
+		embedded_1.setSource(new ThemeResource("img/att.png"));
+		embedded_1.setType(1);
+		embedded_1.setMimeType("image/png");
+		horizontalLayout_1.addComponent(embedded_1);
+		horizontalLayout_1.setComponentAlignment(embedded_1, new Alignment(33));
+		
+		// caption
+		caption = new Label();
+		caption.setImmediate(false);
+		caption.setWidth("-1px");
+		caption.setHeight("-1px");
+		caption.setValue("Apache OpenAZ Admin Console");
+		horizontalLayout_1.addComponent(caption);
+		horizontalLayout_1.setExpandRatio(caption, 1.0f);
+		horizontalLayout_1.setComponentAlignment(caption, new Alignment(33));
+		
+		// labelWelcome
+		labelWelcome = new Label();
+		labelWelcome.setImmediate(false);
+		labelWelcome.setWidth("-1px");
+		labelWelcome.setHeight("40px");
+		labelWelcome.setValue("Label");
+		horizontalLayout_1.addComponent(labelWelcome);
+		horizontalLayout_1.setComponentAlignment(labelWelcome,
+				new Alignment(34));
+		
+		return horizontalLayout_1;
+	}
+
+	@Override
+	public void enter(ViewChangeEvent event) {
+		//
+		// This needs to be implemented
+		//
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/a1d93100/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlAdminServlet.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlAdminServlet.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlAdminServlet.java
new file mode 100644
index 0000000..fa48543
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlAdminServlet.java
@@ -0,0 +1,97 @@
+/*
+ *  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.openaz.xacml.admin;
+
+import java.io.IOException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebInitParam;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.vaadin.annotations.Push;
+import com.vaadin.annotations.VaadinServletConfiguration;
+import com.vaadin.server.VaadinServlet;
+
+import org.apache.openaz.xacml.rest.XACMLRest;
+
+
+//
+// The Servlet underlying the Vaadin Servlet
+//
+@Push
+@WebServlet(
+		value = "/*",
+		description = "XACML Admin Console",
+		asyncSupported = true, 
+		loadOnStartup=1,
+		initParams = { 
+		@WebInitParam(name = "XACML_PROPERTIES_NAME", value = "xacml.admin.properties", description = "The location of the properties file holding configuration information.")
+})
+@VaadinServletConfiguration(productionMode = false, ui = XacmlAdminUI.class)
+public class XacmlAdminServlet extends VaadinServlet {
+	//
+	// All static declarations
+	//
+	private static Log logger	= LogFactory.getLog(XacmlAdminServlet.class); //NOPMD
+
+	@Override
+	public void init(ServletConfig servletConfig) throws ServletException {
+		super.init(servletConfig);
+		//
+		// Common initialization
+		//
+		XACMLRest.xacmlInit(servletConfig);
+
+		// Initialization
+		XacmlAdminUI.servletInit();
+	}
+	
+	@Override
+	public void destroy() {
+		XacmlAdminUI.servletDestroy();
+		super.destroy();
+	}
+	
+	/**
+	 * 
+	 * Called by:
+	 * 	- PAP to notify Vaadin GUIs that something has changed
+	 * 
+	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
+	 */
+	@Override
+	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+		// watch for notifications from the PAP
+		if (request.getMethod().equals("PUT") && request.getParameter("PAPNotification") != null) {
+			XacmlAdminUI.doPAPNotification(request, response);
+			return;
+		}
+
+		// not a PAP notification, so let Vaadin handle normally
+		super.service(request,response);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/a1d93100/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlAdminUI.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlAdminUI.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlAdminUI.java
new file mode 100644
index 0000000..e553749
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlAdminUI.java
@@ -0,0 +1,801 @@
+/*
+ *  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.openaz.xacml.admin;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.sql.SQLException;
+import java.util.Properties;
+import java.util.UUID;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.api.errors.InvalidRemoteException;
+import org.eclipse.jgit.api.errors.TransportException;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
+import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
+import org.eclipse.persistence.config.PersistenceUnitProperties;
+
+import org.apache.openaz.xacml.admin.XacmlAdminAuthorization.AdminAction;
+import org.apache.openaz.xacml.admin.XacmlAdminAuthorization.AdminResource;
+import org.apache.openaz.xacml.admin.converters.XacmlConverterFactory;
+import org.apache.openaz.xacml.admin.jpa.Attribute;
+import org.apache.openaz.xacml.admin.jpa.Category;
+import org.apache.openaz.xacml.admin.jpa.ConstraintType;
+import org.apache.openaz.xacml.admin.jpa.Datatype;
+import org.apache.openaz.xacml.admin.jpa.FunctionArgument;
+import org.apache.openaz.xacml.admin.jpa.FunctionDefinition;
+import org.apache.openaz.xacml.admin.jpa.Obadvice;
+import org.apache.openaz.xacml.admin.jpa.ObadviceExpression;
+import org.apache.openaz.xacml.admin.jpa.PIPConfiguration;
+import org.apache.openaz.xacml.admin.jpa.PIPResolver;
+import org.apache.openaz.xacml.admin.jpa.PIPType;
+import org.apache.openaz.xacml.admin.jpa.PolicyAlgorithms;
+import org.apache.openaz.xacml.admin.jpa.RuleAlgorithms;
+import org.apache.openaz.xacml.admin.model.MatchFunctionQueryDelegate;
+import org.apache.openaz.xacml.admin.util.RESTfulPAPEngine;
+import org.apache.openaz.xacml.api.XACML3;
+import org.apache.openaz.xacml.api.pap.PAPEngine;
+import org.apache.openaz.xacml.api.pap.PAPException;
+import org.apache.openaz.xacml.rest.XACMLRestProperties;
+import org.apache.openaz.xacml.util.XACMLProperties;
+import com.google.gwt.thirdparty.guava.common.base.Joiner;
+import com.google.gwt.thirdparty.guava.common.base.Splitter;
+import com.vaadin.addon.jpacontainer.JPAContainer;
+import com.vaadin.addon.jpacontainer.provider.CachingLocalEntityProvider;
+import com.vaadin.addon.jpacontainer.provider.CachingMutableLocalEntityProvider;
+import com.vaadin.annotations.Push;
+import com.vaadin.annotations.Theme;
+import com.vaadin.data.util.sqlcontainer.SQLContainer;
+import com.vaadin.data.util.sqlcontainer.connection.JDBCConnectionPool;
+import com.vaadin.data.util.sqlcontainer.query.FreeformQuery;
+import com.vaadin.navigator.Navigator;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.server.VaadinServletService;
+import com.vaadin.ui.UI;
+
+@Push
+@SuppressWarnings("serial")
+@Theme("xacml_pap_admin")
+public class XacmlAdminUI extends UI implements PAPNotificationBroadcaster.PAPNotificationBroadcastListener {
+	//
+	// All static declarations
+	//
+	public static final String PERSISTENCE_UNIT = "XACML-PAP-ADMIN";
+	private static Log logger	= LogFactory.getLog(XacmlAdminUI.class); //NOPMD
+	
+	/*
+	 * These objects are shared amongst sessions.
+	 */
+	private static Path repositoryPath;
+	private static Repository repository;
+	private static EntityManagerFactory emf;
+	private static JDBCConnectionPool pool;
+	
+	/*
+	 * These objects are created each session.
+	 */
+	private Path workspacePath;
+	private Path gitPath;
+	//
+	// Our Persistence Fields. For general use. NOTE: Be careful applying
+	// filters to these container objects. If one window applies a filter, then
+	// when another window uses the object, that filter will show up and cause confusion.
+	// If filters are needed within a window, then create another instance instead of
+	// using one of these pointers.
+	//
+	private EntityManager em;
+	private JPAContainer<Attribute> 			attributes;
+	private JPAContainer<ConstraintType> 		constraintTypes;
+	private JPAContainer<Obadvice> 				obadvice;
+	private JPAContainer<ObadviceExpression> 	obadviceExpressions;
+	private JPAContainer<Category> 				categories;
+	private JPAContainer<Datatype> 				datatypes;
+	private JPAContainer<PolicyAlgorithms> 		policyAlgorithms;
+	private JPAContainer<RuleAlgorithms> 		ruleAlgorithms;
+	private JPAContainer<PIPConfiguration>		pipConfigurations;
+	private JPAContainer<PIPResolver>			pipResolvers;
+	private JPAContainer<PIPType>				pipTypes;
+	private JPAContainer<FunctionDefinition>	functionDefinitions;
+	private JPAContainer<FunctionArgument>		functionArguments;
+	private SQLContainer matchFunctionContainer;
+	private SQLContainer higherorderBagContainer;
+	//
+	// Our authorization object
+	//
+	XacmlAdminAuthorization authorizer = new XacmlAdminAuthorization();
+	//
+	// The PAP Engine
+	//
+	private PAPEngine papEngine;
+	//
+	// GUI navigation
+	//
+	private Navigator navigator = null;
+	private XacmlAdminConsole console = null;
+	//
+	// Vaadin Init
+	//
+	@Override
+	protected void init(VaadinRequest request) {
+		//
+		// Set our title
+		//
+		this.getPage().setTitle("Apache OpenAZ Admin Console");
+		//
+		// Create our authorization object
+		//
+		this.authorizer = new XacmlAdminAuthorization();
+		//
+		// Is the user authorized to use the application?
+		//
+		if (this.authorizer.isAuthorized(this.getUserid(), 
+									XacmlAdminAuthorization.AdminAction.ACTION_ACCESS, 
+									XacmlAdminAuthorization.AdminResource.RESOURCE_APPLICATION) == false) {
+			logger.error("user " + this.getUserid() + " is not authorized.");
+			//
+			// Create a navigator to manage all our views
+			//
+			this.navigator = new Navigator(this, this);
+			//
+			// Redirect to an error page
+			//
+			this.navigator.addView(XacmlErrorHandler.VIEWNAME, new XacmlErrorHandler("User " + this.getUserid() + " is not authorized to access application", null));
+			this.navigator.navigateTo(XacmlErrorHandler.VIEWNAME);
+			return;
+		}
+		try {
+			//
+			// Initialize user's Git repository
+			//
+			this.workspacePath = Paths.get(XACMLProperties.getProperty(XACMLRestProperties.PROP_ADMIN_WORKSPACE), this.getUserid());
+			this.gitPath = XacmlAdminUI.initializeUserRepository(this.workspacePath, this.getUserid(), this.getUserEmail());
+		} catch (Exception e) {
+			logger.error("Git Setup failure", e);
+			//
+			// Create a navigator to manage all our views
+			//
+			this.navigator = new Navigator(this, this);
+			//
+			// Redirect to an error page
+			//
+			this.navigator.addView(XacmlErrorHandler.VIEWNAME, new XacmlErrorHandler(e.getMessage(), null));
+			this.navigator.navigateTo(XacmlErrorHandler.VIEWNAME);
+			return;
+		}
+		//
+		// Create a navigator to manage all our views
+		//
+		this.navigator = new Navigator(this, this);
+		//
+		// Set our converter factory
+		//
+		this.getSession().setConverterFactory(new XacmlConverterFactory());
+		//
+		// Initialize our data objects
+		//
+		try {
+			//
+			// Initialize JPA and SQL. Create our custom entity manager.
+			//
+			logger.info("Creating Persistence Entity Manager");
+			//
+			// Now create the entity manager. This is used throughout the application to create JPA
+			// containers of the entities located in the database.
+			//
+			this.em = XacmlAdminUI.emf.createEntityManager();
+			//
+			// Our Read-Only containers
+			//
+			logger.info("Creating JPA read-only containers");
+			this.constraintTypes = new JPAContainer<ConstraintType>(ConstraintType.class);
+			this.constraintTypes.setEntityProvider(new CachingLocalEntityProvider<ConstraintType>(ConstraintType.class, this.em));
+			
+			this.categories = new JPAContainer<Category>(Category.class);
+			this.categories.setEntityProvider(new CachingLocalEntityProvider<Category>(Category.class, this.em));
+
+			this.datatypes = new JPAContainer<Datatype>(Datatype.class);
+			this.datatypes.setEntityProvider(new CachingLocalEntityProvider<Datatype>(Datatype.class, this.em));
+			
+			this.policyAlgorithms = new JPAContainer<PolicyAlgorithms>(PolicyAlgorithms.class);
+			this.policyAlgorithms.setEntityProvider(new CachingLocalEntityProvider<PolicyAlgorithms>(PolicyAlgorithms.class, this.em));
+			
+			this.ruleAlgorithms = new JPAContainer<RuleAlgorithms>(RuleAlgorithms.class);
+			this.ruleAlgorithms.setEntityProvider(new CachingLocalEntityProvider<RuleAlgorithms>(RuleAlgorithms.class, this.em));
+			
+			this.pipTypes = new JPAContainer<PIPType>(PIPType.class);
+			this.pipTypes.setEntityProvider(new CachingLocalEntityProvider<PIPType>(PIPType.class, this.em));
+			
+			this.functionDefinitions = new JPAContainer<FunctionDefinition>(FunctionDefinition.class);
+			this.functionDefinitions.setEntityProvider(new CachingLocalEntityProvider<FunctionDefinition>(FunctionDefinition.class, this.em));
+
+			this.functionArguments = new JPAContainer<FunctionArgument>(FunctionArgument.class);
+			this.functionArguments.setEntityProvider(new CachingLocalEntityProvider<FunctionArgument>(FunctionArgument.class, this.em));
+			//
+			// Our writable containers. NOTE: The dictionaries have their own JPA instance since they can
+			// apply filters to their table views. If you update these, then refresh the dictionary containers
+			// by calling the appropriate refresh method defined in XacmlAdminUI.
+			//
+			logger.info("Creating JPA writable containers");
+			this.attributes = new JPAContainer<Attribute>(Attribute.class);
+			this.attributes.setEntityProvider(new CachingMutableLocalEntityProvider<Attribute>(Attribute.class, this.em));
+
+			this.obadvice = new JPAContainer<Obadvice>(Obadvice.class);
+			this.obadvice.setEntityProvider(new CachingMutableLocalEntityProvider<Obadvice>(Obadvice.class, this.em));
+
+			this.obadviceExpressions = new JPAContainer<ObadviceExpression>(ObadviceExpression.class);
+			this.obadviceExpressions.setEntityProvider(new CachingMutableLocalEntityProvider<ObadviceExpression>(ObadviceExpression.class, this.em));
+
+			this.pipConfigurations = new JPAContainer<PIPConfiguration>(PIPConfiguration.class);
+			this.pipConfigurations.setEntityProvider(new CachingMutableLocalEntityProvider<PIPConfiguration>(PIPConfiguration.class, this.em));
+			
+			this.pipResolvers = new JPAContainer<PIPResolver>(PIPResolver.class);
+			this.pipResolvers.setEntityProvider(new CachingMutableLocalEntityProvider<PIPResolver>(PIPResolver.class, this.em));
+			//
+			// Sort our persistence data
+			//
+			logger.info("Sorting containers");
+			this.categories.sort(new String[]{"xacmlId"}, new boolean[]{true});
+			this.datatypes.sort(new String[]{"xacmlId"}, new boolean[]{true});
+			this.policyAlgorithms.sort(new String[]{"xacmlId"}, new boolean[]{true});
+			this.ruleAlgorithms.sort(new String[]{"xacmlId"}, new boolean[]{true});
+			this.functionDefinitions.sort(new String[]{"xacmlid"}, new boolean[]{true});
+			//this.functionArguments.sort(new String[]{"datatypeBean"}, new boolean[]{true});
+			//
+			// Create our special query for MatchType functions. We need a custom
+			// QueryDelegate because these functions are accessible via a View (vs a Table).
+			// The basic FreeformQuery does not work with filters on a View (via Vaadin).
+			//
+			// TODO: Consider putting this into a couple of Map's. Doing so would speed up
+			// access. However, if we want to support custom functions, then there needs to
+			// be a way for those custom functions to get into the Map. This is why a database
+			// is being used to store ALL the functions, both standard and custom.
+			//
+			logger.info("Creating SQL Queries");
+			MatchFunctionQueryDelegate delegate = new MatchFunctionQueryDelegate();
+			FreeformQuery query = new FreeformQuery("SELECT * FROM match_functions", XacmlAdminUI.pool, new String[] {});
+			query.setDelegate(delegate);
+			this.matchFunctionContainer = new SQLContainer(query);
+			//
+			// Same for this one
+			//
+			delegate = new MatchFunctionQueryDelegate();
+			query = new FreeformQuery("SELECT * FROM higherorder_bag_functions", XacmlAdminUI.pool, new String[] {});
+			query.setDelegate(delegate);
+			this.higherorderBagContainer = new SQLContainer(query);
+			//
+			// Load our PAP engine
+			//
+			logger.info("Creating PAP engine");
+			String myRequestURL = VaadinServletService.getCurrentServletRequest().getRequestURL().toString();
+			try {
+				//
+				// Set the URL for the RESTful PAP Engine
+				//
+				papEngine = new RESTfulPAPEngine(myRequestURL);
+			} catch (PAPException e  ) {
+				logger.error("Failed to create PAP engine", e);
+			} catch (Exception e) {
+				logger.error("Failed to create PAP engine", e);
+			}
+			logger.info("done creating connections");
+		} catch(Exception e) {
+			//
+			// Redirect to an error page
+			//
+			logger.error(e);
+			e.printStackTrace();
+			this.navigator.addView("", new XacmlErrorHandler(e.getMessage(), null));
+			this.navigator.navigateTo("");
+			return;
+		}
+		logger.info("Creating main layout");
+		//
+		// Create our main component layout
+		//
+		this.console = new XacmlAdminConsole();
+		this.navigator.addView("", console);
+		this.navigator.setErrorView(new XacmlErrorHandler(null, null));
+		//
+		// Navigate to our view
+		//
+		this.navigator.navigateTo("");
+		//
+		// Register to receive PAP change notifications broadcasts
+		//
+		PAPNotificationBroadcaster.register(this);
+	}
+	
+	public static void servletInit() throws ServletException {
+		//
+		// Initialize GIT repository.
+		//
+		XacmlAdminUI.initializeGitRepository();
+		//
+		// Initialize Entity Factory
+		//
+		XacmlAdminUI.initializeEntityFactory();
+		//
+		// If we get here, then the configuration information
+		// seems ok.
+		//
+	}
+
+	public static void servletDestroy() {
+		if (XacmlAdminUI.repository != null) {
+			XacmlAdminUI.repository.close();
+		}
+	}
+	
+	/**
+	 * An Update Notification has arrived from the PAP.
+	 * Tell the Vaadin users to change their data.
+	 * 
+	 * @param request
+	 * @param response
+	 * @throws ServletException
+	 * @throws IOException
+	 */
+	public static void doPAPNotification(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+		try {
+			//
+			// Notify all user instances to update groups
+			//
+			PAPNotificationBroadcaster.updateAllGroups();
+		} catch (Exception e) {
+			logger.error("Unable to process PAP request: "+e, e);
+			response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+		}
+		response.setStatus(HttpServletResponse.SC_NO_CONTENT);
+	}
+
+	// Must unregister when the UI expires
+	@Override
+	public void detach() {
+		PAPNotificationBroadcaster.unregister(this);
+		super.detach();
+	}
+	
+	/**
+	 * This will initialize the JPA Entity Manager Factory. This will determine if
+	 * the database connection settings are correct.
+	 * 
+	 * @throws ServletException
+	 */
+	private static void initializeEntityFactory() throws ServletException {
+		logger.info("intializing Persistence Entity Factory");
+		//
+		// Pull custom persistence settings
+		//
+		Properties properties;
+		try {
+			properties = XACMLProperties.getProperties();
+		} catch (IOException e) {
+			throw new ServletException(e.getMessage(), e.getCause());
+		}
+		//
+		// Create the factory
+		//
+		emf = Persistence.createEntityManagerFactory(XacmlAdminUI.PERSISTENCE_UNIT, properties);
+		//
+		// Did it get created?
+		//
+		if (emf == null) {
+			throw new ServletException("Unable to create Entity Manager Factory");
+		}
+		//
+		// Create our JDBC connection pool
+		//
+		try {
+			logger.info("intializing JDBC Connection Pool");
+			XacmlAdminUI.pool = new XacmlJDBCConnectionPool(
+					properties.getProperty(PersistenceUnitProperties.JDBC_DRIVER),
+					properties.getProperty(PersistenceUnitProperties.JDBC_URL),
+					properties.getProperty(PersistenceUnitProperties.JDBC_USER),
+					properties.getProperty(PersistenceUnitProperties.JDBC_PASSWORD));
+		} catch (SQLException e) {
+			throw new ServletException(e.getMessage(), e.getCause());
+		}
+	}
+
+	private static void initializeGitRepository() throws ServletException {
+		XacmlAdminUI.repositoryPath = Paths.get(XACMLProperties.getProperty(XACMLRestProperties.PROP_ADMIN_REPOSITORY));
+		FileRepositoryBuilder builder = new FileRepositoryBuilder();
+		try {
+			XacmlAdminUI.repository = builder.setGitDir(XacmlAdminUI.repositoryPath.toFile()).readEnvironment().findGitDir().setBare().build();
+			if (Files.notExists(XacmlAdminUI.repositoryPath) || Files.notExists(Paths.get(XacmlAdminUI.repositoryPath.toString(), "HEAD"))) {
+				//
+				// Create it if it doesn't exist. As a bare repository
+				//
+				logger.info("Creating bare git repository: " + XacmlAdminUI.repositoryPath.toString());
+				XacmlAdminUI.repository.create();
+				//
+				// Add the magic file so remote works.
+				//
+				Path daemon = Paths.get(XacmlAdminUI.repositoryPath.toString(), "git-daemon-export-ok");
+				Files.createFile(daemon);					
+			}
+		} catch (IOException e) {
+			logger.error("Failed to build repository: " + repository, e);
+			throw new ServletException(e.getMessage(), e.getCause());
+		}
+		//
+		// Make sure the workspace directory is created
+		//
+		Path workspace = Paths.get(XACMLProperties.getProperty(XACMLRestProperties.PROP_ADMIN_WORKSPACE));
+		workspace = workspace.toAbsolutePath();
+		if (Files.notExists(workspace)) {
+			try {
+				Files.createDirectory(workspace);
+			} catch (IOException e) {
+				logger.error("Failed to build workspace: " + workspace, e);
+				throw new ServletException(e.getMessage(), e.getCause());
+			}
+		}
+		//
+		// Create the user workspace directory
+		//
+		workspace = Paths.get(workspace.toString(), "pe");
+		if (Files.notExists(workspace)) {
+			try {
+				Files.createDirectory(workspace);
+			} catch (IOException e) {
+				logger.error("Failed to create directory: " + workspace, e);
+				throw new ServletException(e.getMessage(), e.getCause());
+			}
+		}
+		//
+		// Get the path to where the repository is going to be
+		//
+		Path gitPath = Paths.get(workspace.toString(), XacmlAdminUI.repositoryPath.getFileName().toString());
+		if (Files.notExists(gitPath)) {
+			try {
+				Files.createDirectory(gitPath);
+			} catch (IOException e) {
+				logger.error("Failed to create directory: " + gitPath, e);
+				throw new ServletException(e.getMessage(), e.getCause());
+			}
+		}
+		//
+		// Initialize the domain structure
+		//
+		String base = null;
+		String domain = XacmlAdminUI.getDomain();
+		if (domain != null) {
+			for (String part : Splitter.on(':').trimResults().split(domain)) {
+				if (base == null) {
+					base = part;
+				}
+				Path subdir = Paths.get(gitPath.toString(), part);
+				if (Files.notExists(subdir)) {
+					try {
+						Files.createDirectory(subdir);
+						Files.createFile(Paths.get(subdir.toString(), ".svnignore"));
+					} catch (IOException e) {
+						logger.error("Failed to create: " + subdir, e);
+						throw new ServletException(e.getMessage(), e.getCause());
+					}
+				}
+			}
+		} else {
+			try {
+				Files.createFile(Paths.get(workspace.toString(), ".svnignore"));
+				base = ".svnignore";
+			} catch (IOException e) {
+				logger.error("Failed to create file", e);
+				throw new ServletException(e.getMessage(), e.getCause());
+			}
+		}
+		try {
+			//
+			// These are the sequence of commands that must be done initially to
+			// finish setting up the remote bare repository.
+			//
+			Git git = Git.init().setDirectory(gitPath.toFile()).setBare(false).call();
+			git.add().addFilepattern(base).call();
+			git.commit().setMessage("Initialize Bare Repository").call();
+			StoredConfig config = git.getRepository().getConfig();
+			config.setString("remote", "origin", "url", XacmlAdminUI.repositoryPath.toAbsolutePath().toString());
+			config.setString("remote", "origin", "fetch", "+refs/heads/*:refs/remotes/origin/*");
+			config.save();
+			git.push().setRemote("origin").add("master").call();
+			/*
+			 * This will not work unless git.push().setRemote("origin").add("master").call();
+			 * is called first. Otherwise it throws an exception. However, if the push() is
+			 * called then calling this function seems to add nothing.
+			 * 
+			git.branchCreate().setName("master")
+				.setUpstreamMode(SetupUpstreamMode.SET_UPSTREAM)
+				.setStartPoint("origin/master").setForce(true).call();
+			*/
+		} catch (GitAPIException | IOException e) {
+			logger.error(e);
+			throw new ServletException(e.getMessage(), e.getCause());
+		}
+	}
+
+	/**
+	 * Initializes a user's git repository.
+	 * 
+	 * 
+	 * @param workspacePath
+	 * @param userId
+	 * @param email
+	 * @return
+	 * @throws IOException
+	 * @throws InvalidRemoteException
+	 * @throws TransportException
+	 * @throws GitAPIException
+	 */
+	private static Path initializeUserRepository(Path workspacePath, String userId, URI email) throws IOException, InvalidRemoteException, TransportException, GitAPIException {
+		Path gitPath = null;
+		//
+		// Initialize the User's Git repository
+		//
+		if (Files.notExists(workspacePath)) {
+			logger.info("Creating user workspace: " + workspacePath.toAbsolutePath().toString());
+			//
+			// Create our user's directory
+			//
+			Files.createDirectory(workspacePath);
+		}
+		gitPath = Paths.get(workspacePath.toString(), XacmlAdminUI.repositoryPath.getFileName().toString());
+		if (Files.notExists(gitPath)) {
+			//
+			// It doesn't exist yet, so Clone it and check it out
+			//
+			logger.info("Cloning user git directory: " + gitPath.toAbsolutePath().toString());
+			Git.cloneRepository().setURI(XacmlAdminUI.repositoryPath.toUri().toString())
+							.setDirectory(gitPath.toFile())
+							.setNoCheckout(false)
+							.call();
+			//
+			// Set userid
+			//
+			Git git = Git.open(gitPath.toFile());
+			StoredConfig config = git.getRepository().getConfig();
+			config.setString("user", null, "name", userId);
+			if (email != null && email.getPath() != null) {
+				config.setString("user", null, "email", email.toString());
+			}
+			config.save();
+		}
+		return gitPath;
+	}
+
+
+	public static String	getDomain() {
+		return XACMLProperties.getProperty(XACMLRestProperties.PROP_ADMIN_DOMAIN, "urn");
+	}
+	
+	public static JDBCConnectionPool	getConnectionPool() {
+		return pool;
+	}
+	
+	public SQLContainer	getMatchFunctionContainer() {
+		return this.matchFunctionContainer;
+	}
+	
+	public SQLContainer getHigherOrderBagContainer() {
+		return this.higherorderBagContainer;
+	}
+	
+	public EntityManager getEntityManager() {
+		return this.em;
+	}
+	
+	public JPAContainer<Attribute>	getAttributes() {
+		return this.attributes;
+	}
+	
+	public void refreshAttributes() {
+		this.attributes.refresh();
+		this.console.refreshAttributes();
+	}
+
+	public JPAContainer<ConstraintType>	getConstraintTypes() {
+		return this.constraintTypes;
+	}
+	
+	public JPAContainer<Category>	getCategories() {
+		return this.categories;
+	}
+	
+	public JPAContainer<Datatype>	getDatatypes() {
+		return this.datatypes;
+	}
+
+	public JPAContainer<PolicyAlgorithms> getPolicyAlgorithms() {
+		return this.policyAlgorithms;
+	}
+	
+	public JPAContainer<RuleAlgorithms> getRuleAlgorithms() {
+		return this.ruleAlgorithms;
+	}
+
+	public JPAContainer<Obadvice> getObadvice() {
+		return this.obadvice;
+	}
+
+	public JPAContainer<ObadviceExpression> getObadviceExpressions() {
+		return this.obadviceExpressions;
+	}
+	
+	public void refreshObadvice() {
+		this.obadvice.refresh();
+		this.obadviceExpressions.refresh();
+		this.console.refreshObadvice();
+	}
+
+	public JPAContainer<FunctionDefinition>	getFunctionDefinitions() {
+		return this.functionDefinitions;
+	}
+	
+	public JPAContainer<FunctionArgument> getFunctionArguments() {
+		return this.functionArguments;
+	}
+	
+	public JPAContainer<PIPConfiguration> getPIPConfigurations() {
+		return this.pipConfigurations;
+	}
+	
+	public JPAContainer<PIPResolver>	getPIPResolvers() {
+		return this.pipResolvers;
+	}
+	
+	public JPAContainer<PIPType>	getPIPTypes() {
+		return this.pipTypes;
+	}
+
+	public void refreshPIPConfiguration() {
+		this.pipConfigurations.refresh();
+		this.console.refreshPIPConfiguration();
+	}
+	
+	public Category	getDefaultCategory() throws Exception {
+		for (Object id : categories.getItemIds()) {
+			Category cat = categories.getItem(id).getEntity();
+			if (cat.getIdentifer().equals(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT)) {
+				return cat;
+			}
+		}
+		throw new Exception("There is no default category.");
+	}
+	
+	public Datatype getDefaultDatatype() throws Exception {
+		for (Object id: this.datatypes.getItemIds()) {
+			Datatype dt = this.datatypes.getItem(id).getEntity();
+			if (dt.getIdentifer().equals(XACML3.ID_DATATYPE_STRING)) {
+				return dt;
+			}
+		}
+		throw new Exception("There is no default datatype.");
+	}
+	
+	public XacmlAdminAuthorization getAuthorizer() {
+		return this.authorizer;
+	}
+	
+	public boolean	isAuthorized(AdminAction action, AdminResource resource) {
+		return this.authorizer.isAuthorized(this.getUserid(), action, resource);
+	}
+	
+	public String	getUserid() {
+		Object id = this.getSession().getSession().getAttribute("xacml.rest.admin.user.id");
+		if (id == null) {
+			return XACMLProperties.getProperty("xacml.rest.admin.user.id", "guest");
+		}
+		String str = id.toString();
+		if (str == null || str.isEmpty()) {
+			return "guest";
+		}
+		return str;
+	}
+	
+	public String 	getUserName() {
+		Object id = this.getSession().getSession().getAttribute("xacml.rest.admin.user.name");
+		if (id == null) {
+			return XACMLProperties.getProperty("xacml.rest.admin.user.name", "guest");
+		}
+		String str = id.toString();
+		if (str == null || str.isEmpty()) {
+			return "guest";
+		}
+		return str;
+	}
+	
+	public URI		getUserEmail() {
+		Object id = this.getSession().getSession().getAttribute("xacml.rest.admin.user.email");
+		if (id == null) {
+			return URI.create(XACMLProperties.getProperty("xacml.rest.admin.user.email", "guest"));
+		}
+		String str = id.toString();
+		if (str == null || str.isEmpty()) {
+			return null;
+		}
+		return URI.create(str);
+	}
+	
+	public Path		getUserWorkspace() {
+		return this.workspacePath;
+	}
+	
+	public Path		getUserGitPath() {
+		return this.gitPath;
+	}
+	
+	public PAPEngine	getPAPEngine() {
+		return this.papEngine;
+	}
+	
+	public String	newPolicyID() {
+		return Joiner.on(':').skipNulls().join((XacmlAdminUI.getDomain().startsWith("urn") ? null : "urn"),
+												XacmlAdminUI.getDomain().replaceAll("[/\\\\.]", ":"), 
+												"xacml", "policy", "id", UUID.randomUUID());
+	}
+
+	public String	newRuleID() {
+		return Joiner.on(':').skipNulls().join((XacmlAdminUI.getDomain().startsWith("urn") ? null : "urn"),
+												XacmlAdminUI.getDomain().replaceAll("[/\\\\.]", ":"), 
+												"xacml", "rule", "id", UUID.randomUUID());
+	}
+	//
+	// PAPNotificationBroadcaster Interface implementation
+	//
+	/**
+	 * Got a notification that the PAP has changed the PDP data,
+	 * so update ALL PDPGroups.
+	 * This is called once for each Vaadin instance for each PAP change Notification.
+	 */
+	public void updateAllGroups() {
+		access(new Runnable() {
+			@Override
+			public void run() {
+				//
+				// locking is needed to avoid race conditions.
+				// Shows up as Exception: "A connector should not be marked as dirty while a response is being written."
+				//
+				getUI().getSession().lock();
+				try {
+					//
+					// Tell the console to refresh its PDP group information
+					//
+					console.refreshPDPGroups();
+				} finally {
+					getUI().getSession().unlock();
+				}
+			}
+		});
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/a1d93100/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlErrorHandler.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlErrorHandler.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlErrorHandler.java
new file mode 100644
index 0000000..dd014dd
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlErrorHandler.java
@@ -0,0 +1,106 @@
+/*
+ *  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.openaz.xacml.admin;
+
+import com.vaadin.annotations.AutoGenerated;
+import com.vaadin.navigator.View;
+import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.CustomComponent;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.VerticalLayout;
+
+public class XacmlErrorHandler extends CustomComponent implements View {
+	
+	@AutoGenerated
+	private VerticalLayout mainLayout;
+
+	@AutoGenerated
+	private Button buttonGo;
+
+	@AutoGenerated
+	private Label labelError;
+
+	public static String VIEWNAME="ErrorHandler.View";
+
+	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */
+
+	private static final long serialVersionUID = 1L;
+	/**
+	 * The constructor should first build the main layout, set the
+	 * composition root and then do any custom initialization.
+	 *
+	 * The constructor will not be automatically regenerated by the
+	 * visual editor.
+	 */
+	public XacmlErrorHandler(String message, String button) {
+		buildMainLayout();
+		setCompositionRoot(mainLayout);
+		this.labelError.setValue(message);
+		if (button != null) {
+			this.buttonGo.setCaption(button);
+		} else {
+			this.buttonGo.setVisible(false);
+		}
+	}
+
+	@Override
+	public void enter(ViewChangeEvent event) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@AutoGenerated
+	private VerticalLayout buildMainLayout() {
+		// common part: create layout
+		mainLayout = new VerticalLayout();
+		mainLayout.setImmediate(false);
+		mainLayout.setWidth("100%");
+		mainLayout.setHeight("-1px");
+		mainLayout.setMargin(true);
+		mainLayout.setSpacing(true);
+		
+		// top-level component properties
+		setWidth("100.0%");
+		setHeight("-1px");
+		
+		// labelError
+		labelError = new Label();
+		labelError.setImmediate(false);
+		labelError.setWidth("100.0%");
+		labelError.setHeight("80px");
+		labelError.setValue("This holds error messages.");
+		mainLayout.addComponent(labelError);
+		
+		// buttonGo
+		buttonGo = new Button();
+		buttonGo.setCaption("Ok");
+		buttonGo.setImmediate(true);
+		buttonGo.setWidth("-1px");
+		buttonGo.setHeight("-1px");
+		mainLayout.addComponent(buttonGo);
+		mainLayout.setComponentAlignment(buttonGo, new Alignment(48));
+		
+		return mainLayout;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/a1d93100/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlJDBCConnectionPool.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlJDBCConnectionPool.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlJDBCConnectionPool.java
new file mode 100644
index 0000000..a11707d
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/XacmlJDBCConnectionPool.java
@@ -0,0 +1,239 @@
+/*
+ *  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.openaz.xacml.admin;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.vaadin.data.util.sqlcontainer.connection.JDBCConnectionPool;
+
+public class XacmlJDBCConnectionPool implements JDBCConnectionPool {
+	private static final long serialVersionUID = 1L;
+	private static Log logger	= LogFactory.getLog(XacmlJDBCConnectionPool.class);
+
+    private int initialConnections = 5;
+    private int maxConnections = 300;
+
+    private String driverName;
+    private String connectionUri;
+    private String userName;
+    private String password;
+
+    private transient Set<Connection> availableConnections;
+    private transient Set<Connection> reservedConnections;
+
+    private boolean initialized;
+
+    public XacmlJDBCConnectionPool(String driverName, String connectionUri, String userName, String password) throws SQLException {
+        if (driverName == null) {
+            throw new IllegalArgumentException(
+                    "JDBC driver class name must be given.");
+        }
+        if (connectionUri == null) {
+            throw new IllegalArgumentException(
+                    "Database connection URI must be given.");
+        }
+        if (userName == null) {
+            throw new IllegalArgumentException(
+                    "Database username must be given.");
+        }
+        if (password == null) {
+            throw new IllegalArgumentException(
+                    "Database password must be given.");
+        }
+        this.driverName = driverName;
+        this.connectionUri = connectionUri;
+        this.userName = userName;
+        this.password = password;
+
+        /* Initialize JDBC driver */
+        try {
+            Class.forName(driverName).newInstance();
+        } catch (Exception ex) {
+            throw new RuntimeException("Specified JDBC Driver: " + driverName
+                    + " - initialization failed.", ex);
+        }
+    }
+
+    public XacmlJDBCConnectionPool(String driverName, String connectionUri,
+            String userName, String password, int initialConnections,
+            int maxConnections) throws SQLException {
+        this(driverName, connectionUri, userName, password);
+        this.initialConnections = initialConnections;
+        this.maxConnections = maxConnections;
+    }
+
+    private void initializeConnections() throws SQLException {
+        availableConnections = new HashSet<Connection>(initialConnections);
+        reservedConnections = new HashSet<Connection>(initialConnections);
+        for (int i = 0; i < initialConnections; i++) {
+            availableConnections.add(createConnection());
+        }
+        initialized = true;
+    }
+
+    @Override
+    public synchronized Connection reserveConnection() throws SQLException {
+        if (!initialized) {
+            initializeConnections();
+        }
+        Connection c = null;
+        do {
+	        if (availableConnections.isEmpty()) {
+	            if (reservedConnections.size() < maxConnections) {
+	            	logger.info("creating new connection");
+	                availableConnections.add(createConnection());
+	            } else {
+	                throw new SQLException("Connection limit has been reached.");
+	            }
+	        }
+	        //
+	        // Get first available
+	        //
+	        c = availableConnections.iterator().next();
+	        //
+	        // It is still valid?
+	        //
+	        if (!this.isValid(c)) {
+	        	try {
+	        		logger.warn("Removing invalid connection.");
+		        	//
+		        	// No close it
+		        	//
+	        		c.close();
+	        		//
+	        		// Remove from our list
+	        		//
+	        		this.availableConnections.remove(c);
+	        		//
+	        		// Try again
+	        		//
+	        		c = null;
+	        	} catch (SQLException e) { // NOPMD
+	        		// If removing the connection fails, ignore
+	        	}
+	        } else {
+	        	//
+	        	// Yes
+	        	//
+		        availableConnections.remove(c);
+	        	break;
+	        }
+        } while (c == null);
+        //
+        // Add it to our reserved list
+        //
+        reservedConnections.add(c);
+        return c;
+    }
+
+    @Override
+    public synchronized void releaseConnection(Connection conn) {
+        if (conn == null || !initialized) {
+            return;
+        }
+        /* Try to roll back if necessary */
+        try {
+            if (!conn.getAutoCommit()) {
+                conn.rollback();
+            }
+        } catch (SQLException e) {
+            /* Roll back failed, close and discard connection */
+            try {
+                conn.close();
+            } catch (SQLException e1) { // NOPMD
+                /* Nothing needs to be done */
+            }
+            reservedConnections.remove(conn);
+            return;
+        }
+        reservedConnections.remove(conn);
+        availableConnections.add(conn);
+    }
+
+    private Connection createConnection() throws SQLException {
+        Connection c = DriverManager.getConnection(connectionUri, userName,
+                password);
+        c.setAutoCommit(false);
+        if (driverName.toLowerCase().contains("mysql")) {
+            try {
+                Statement s = c.createStatement();
+                s.execute("SET SESSION sql_mode = 'ANSI'");
+                s.close();
+            } catch (Exception e) { // NOPMD
+                // Failed to set ansi mode; continue
+            }
+        }
+        return c;
+    }
+
+    @Override
+    public void destroy() {
+        for (Connection c : availableConnections) {
+            try {
+                c.close();
+            } catch (SQLException e) { // NOPMD
+                // No need to do anything
+            }
+        }
+        for (Connection c : reservedConnections) {
+            try {
+                c.close();
+            } catch (SQLException e) { // NOPMD
+                // No need to do anything
+            }
+        }
+
+    }
+
+    private void writeObject(java.io.ObjectOutputStream out) throws IOException {
+        initialized = false;
+        out.defaultWriteObject();
+    }
+
+	private final boolean isValid(final Connection con) throws SQLException {
+		final String bogusQuery = "SELECT 1";
+		
+		try (Statement st = con.createStatement(); ResultSet res = st.executeQuery(bogusQuery)) {
+			return true;
+		} catch (final SQLException sqlx) {
+			return false;
+		}
+	}
+
+	@Override
+	public String toString() {
+		return "XacmlJDBCConnectionPool [initialConnections="
+				+ initialConnections + ", maxConnections=" + maxConnections
+				+ ", driverName=" + driverName + ", connectionUri="
+				+ connectionUri + ", userName=" + userName + ", password="
+				+ password + ", initialized=" + initialized + "]";
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/a1d93100/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/components/AttributeDictionary.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/components/AttributeDictionary.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/components/AttributeDictionary.java
new file mode 100644
index 0000000..f0069a7
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/components/AttributeDictionary.java
@@ -0,0 +1,503 @@
+/*
+ *  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.openaz.xacml.admin.components;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.openaz.xacml.admin.XacmlAdminAuthorization;
+import org.apache.openaz.xacml.admin.XacmlAdminUI;
+import org.apache.openaz.xacml.admin.jpa.Attribute;
+import org.apache.openaz.xacml.admin.jpa.Category;
+import org.apache.openaz.xacml.admin.jpa.Datatype;
+import org.apache.openaz.xacml.admin.view.windows.AttributeEditorWindow;
+import com.vaadin.addon.jpacontainer.EntityItem;
+import com.vaadin.addon.jpacontainer.JPAContainer;
+import com.vaadin.addon.jpacontainer.provider.CachingLocalEntityProvider;
+import com.vaadin.addon.jpacontainer.provider.CachingMutableLocalEntityProvider;
+import com.vaadin.annotations.AutoGenerated;
+import com.vaadin.data.Container.Filter;
+import com.vaadin.data.Item;
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.data.Property.ValueChangeListener;
+import com.vaadin.data.util.filter.Compare;
+import com.vaadin.event.ItemClickEvent;
+import com.vaadin.event.ItemClickEvent.ItemClickListener;
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.AbstractSelect.ItemCaptionMode;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.ComboBox;
+import com.vaadin.ui.CustomComponent;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.Window.CloseEvent;
+import com.vaadin.ui.Window.CloseListener;
+
+public class AttributeDictionary extends CustomComponent {
+	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */
+
+	@AutoGenerated
+	private VerticalLayout mainLayout;
+	@AutoGenerated
+	private Table table;
+	@AutoGenerated
+	private HorizontalLayout horizontalLayoutToolbar;
+	@AutoGenerated
+	private ComboBox comboBoxFilterDatatype;
+	@AutoGenerated
+	private ComboBox comboBoxFilterCategory;
+	@AutoGenerated
+	private Button buttonClone;
+	@AutoGenerated
+	private Button buttonRemove;
+	@AutoGenerated
+	private Button buttonNew;
+	private static final long serialVersionUID = 4553719412188869190L;
+	private static final Log logger	= LogFactory.getLog(AttributeDictionary.class);
+	private static final Object[] visibleColumns = new Object[] { "xacmlId", "description", "categoryBean", "datatypeBean", "constraintType", "modifiedBy", "modifiedDate", "createdBy", "createdDate"};
+	private static final String[] columnHeaders = new String[] { "Attribute ID", "Description", "Category", "DataType", "Constraint", "Modified By", "Modified Date", "Created By", "Created Date"};
+	
+	private AttributeDictionary self = this;
+
+	private final JPAContainer<Attribute> attributes = new JPAContainer<Attribute>(Attribute.class);
+	private final JPAContainer<Category> categories = new JPAContainer<Category>(Category.class);
+	private final JPAContainer<Datatype> datatypes = new JPAContainer<Datatype>(Datatype.class);
+	
+	/**
+	 * The constructor should first build the main layout, set the
+	 * composition root and then do any custom initialization.
+	 *
+	 * The constructor will not be automatically regenerated by the
+	 * visual editor.
+	 */
+	public AttributeDictionary() {
+		buildMainLayout();
+		setCompositionRoot(mainLayout);
+		//
+		// Finish initializing the container
+		//
+		boolean isReadOnly;
+		if (((XacmlAdminUI)UI.getCurrent()).isAuthorized( 
+				XacmlAdminAuthorization.AdminAction.ACTION_WRITE, 
+				XacmlAdminAuthorization.AdminResource.RESOURCE_DICTIONARIES)) {
+			if (logger.isDebugEnabled()) {
+				logger.debug("write access");
+			}
+			//
+			// Make it mutable
+			//
+			isReadOnly = false;
+			this.attributes.setEntityProvider(new CachingMutableLocalEntityProvider<Attribute>(Attribute.class, ((XacmlAdminUI)UI.getCurrent()).getEntityManager()));
+		} else {
+			if (logger.isDebugEnabled()) {
+				logger.debug("read access");
+			}
+			//
+			// Make it read-only
+			//
+			isReadOnly = true;
+			this.attributes.setEntityProvider(new CachingLocalEntityProvider<Attribute>(Attribute.class, ((XacmlAdminUI)UI.getCurrent()).getEntityManager()));
+		}
+		this.categories.setEntityProvider(new CachingLocalEntityProvider<Category>(Category.class, ((XacmlAdminUI)UI.getCurrent()).getEntityManager()));
+		this.categories.sort(new String[]{"xacmlId"}, new boolean[]{true});
+		this.datatypes.setEntityProvider(new CachingLocalEntityProvider<Datatype>(Datatype.class, ((XacmlAdminUI)UI.getCurrent()).getEntityManager()));
+		this.datatypes.sort(new String[]{"xacmlId"}, new boolean[]{true});
+		//
+		// Initialize
+		//
+		this.initializeTable(isReadOnly);
+		this.initializeButtons(isReadOnly);
+		this.initializeCategoryComboFilter();
+		this.initializeDatatypeComboFilter();
+	}
+	
+	protected void initializeTable(boolean isReadOnly) {
+		//
+		// This is the data source
+		//
+		this.table.setContainerDataSource(this.attributes);
+		//
+		// Setup table
+		//
+		this.table.setVisibleColumns(visibleColumns);
+		this.table.setColumnHeaders(columnHeaders);
+		this.table.setImmediate(true);
+		this.table.setColumnCollapsingAllowed(true);
+		//
+		// Read only?
+		//
+		if (isReadOnly) {
+			if (logger.isDebugEnabled()) {
+				logger.debug("read only table");
+			}
+			return;
+		}
+		this.table.setSelectable(true);
+		//
+		// Respond to clicks
+		//
+		this.table.addItemClickListener(new ItemClickListener() {
+			private static final long serialVersionUID = 1L;
+			@Override
+			public void itemClick(ItemClickEvent event) {
+				if (event.isDoubleClick()) {
+					//
+					// Create our editor window
+					//
+					final AttributeEditorWindow attributeEditor = new AttributeEditorWindow(self.attributes.getItem(event.getItemId()));
+					attributeEditor.setCaption("Edit Attribute");
+					attributeEditor.setModal(true);
+					attributeEditor.center();
+					UI.getCurrent().addWindow(attributeEditor);
+				}
+			}
+		});
+		//
+		// Respond to selections
+		//
+		this.table.addValueChangeListener(new ValueChangeListener() {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void valueChange(ValueChangeEvent event) {
+				Object value = self.table.getValue();
+				if (value == null) {
+					self.buttonRemove.setEnabled(false);
+					self.buttonClone.setEnabled(false);
+				} else {
+					self.buttonRemove.setEnabled(true);
+					self.buttonClone.setEnabled(true);
+				}
+			}
+		});
+	}
+	
+	protected void initializeButtons(boolean isReadOnly) {
+		if (isReadOnly) {
+			this.buttonNew.setVisible(false);
+			this.buttonRemove.setVisible(false);
+			this.buttonClone.setVisible(false);
+			return;
+		}
+		this.buttonNew.addClickListener(new ClickListener() {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void buttonClick(ClickEvent event) {
+				AttributeDictionary.createNewAttributeWindow();
+			}
+			
+		});
+		
+		this.buttonRemove.setEnabled(false);
+		this.buttonRemove.addClickListener(new ClickListener() {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void buttonClick(ClickEvent event) {
+				//
+				// Get the selected item
+				//
+				Object id = self.table.getValue();
+				//
+				// Sanity check
+				//
+				if (id == null) {
+					return;
+				}
+				//
+				// Remove the attribute
+				//
+				self.attributes.removeItem(id);
+				//
+				// Unfortunately, removing the item does NOT result
+				// in a ValueChange event being generated. So we must
+				// trigger it ourselves.
+				//
+				self.table.select(self.table.getNullSelectionItemId());
+			}	
+		});
+		
+		this.buttonClone.setEnabled(false);
+		this.buttonClone.addClickListener(new ClickListener() {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void buttonClick(ClickEvent event) {
+				Object id = self.table.getValue();
+				if (id == null) {
+					return;
+				}
+				Item item = self.table.getItem(id);
+				if (item instanceof EntityItem) {
+					@SuppressWarnings("unchecked")
+					//
+					// Get the entity
+					//
+					EntityItem<Attribute> entityItem = (EntityItem<Attribute>) item;
+					//
+					// Clone it
+					//
+					Attribute newAttribute = new Attribute(entityItem.getEntity(), ((XacmlAdminUI)UI.getCurrent()).getUserid());
+					//
+					// Add it to the database
+					//
+					id = self.attributes.addEntity(newAttribute);
+					//
+					// Now select it
+					//
+					self.table.select(id);
+					//
+					// Refresh it to get the latest modified date
+					//
+					self.attributes.refreshItem(id);
+				}
+			}
+		});
+	}
+
+	protected void initializeCategoryComboFilter() {
+		//
+		// Set data source
+		//
+		this.comboBoxFilterCategory.setContainerDataSource(self.categories);
+		this.comboBoxFilterCategory.setItemCaptionMode(ItemCaptionMode.PROPERTY);
+		this.comboBoxFilterCategory.setItemCaptionPropertyId("xacmlId");
+		//
+		// Initialize GUI properties
+		//
+		this.comboBoxFilterCategory.setNullSelectionAllowed(true);
+		this.comboBoxFilterCategory.setImmediate(true);
+		//
+		// Respond to value changes
+		//
+		this.comboBoxFilterCategory.addValueChangeListener(new ValueChangeListener() {
+			private static final long serialVersionUID = 1L;
+			Filter currentFilter = null;
+
+			@Override
+			public void valueChange(ValueChangeEvent event) {
+				//
+				// Remove filter
+				//
+				if (currentFilter != null) {
+					self.attributes.removeContainerFilter(this.currentFilter);
+					this.currentFilter = null;
+				}
+				//
+				// Set the new one
+				//
+				Object id = self.comboBoxFilterCategory.getValue();
+				if (id == null) {
+					return;
+				}
+				Category cat = self.categories.getItem(id).getEntity();
+				this.currentFilter = new Compare.Equal("categoryBean", cat);
+				self.attributes.addContainerFilter(this.currentFilter);
+			}
+		});
+	}
+	
+	protected void initializeDatatypeComboFilter() {
+		//
+		// Set data source
+		//
+		this.comboBoxFilterDatatype.setContainerDataSource(self.datatypes);
+		this.comboBoxFilterDatatype.setItemCaptionMode(ItemCaptionMode.PROPERTY);
+		this.comboBoxFilterDatatype.setItemCaptionPropertyId("xacmlId");
+		//
+		// Initialize GUI properties
+		//
+		this.comboBoxFilterDatatype.setNullSelectionAllowed(true);
+		this.comboBoxFilterDatatype.setImmediate(true);
+		//
+		// Respond to value changes
+		//
+		this.comboBoxFilterDatatype.addValueChangeListener(new ValueChangeListener() {
+			private static final long serialVersionUID = 1L;
+			Filter currentFilter = null;
+
+			@Override
+			public void valueChange(ValueChangeEvent event) {
+				//
+				// Remove filter
+				//
+				if (currentFilter != null) {
+					self.attributes.removeContainerFilter(this.currentFilter);
+					this.currentFilter = null;
+				}
+				//
+				// Set the new one
+				//
+				Object id = self.comboBoxFilterDatatype.getValue();
+				if (id == null) {
+					return;
+				}
+				Datatype cat = self.datatypes.getItem(id).getEntity();
+				this.currentFilter = new Compare.Equal("datatypeBean", cat);
+				self.attributes.addContainerFilter(this.currentFilter);
+			}
+		});
+	}
+	
+	public void refreshContainer() {
+		this.attributes.refresh();
+		this.categories.refresh();
+		this.datatypes.refresh();
+	}
+	
+	public static void createNewAttributeWindow() {
+		//
+		// Create our new attribute
+		//
+		String domain = XacmlAdminUI.getDomain();
+		String userid = ((XacmlAdminUI)UI.getCurrent()).getUserid();
+		final Attribute newAttribute = new Attribute(domain, userid);
+		try {
+			newAttribute.setCategoryBean(((XacmlAdminUI)UI.getCurrent()).getDefaultCategory());
+			newAttribute.setDatatypeBean(((XacmlAdminUI)UI.getCurrent()).getDefaultDatatype());
+		} catch (Exception e) {
+			logger.error(e);
+			return;
+		}
+		//
+		// Create our editor window
+		//
+		final AttributeEditorWindow attributeEditor = new AttributeEditorWindow(((XacmlAdminUI)UI.getCurrent()).getAttributes().createEntityItem(newAttribute));
+		attributeEditor.setCaption("Add New Attribute");
+		attributeEditor.setModal(true);
+		attributeEditor.addCloseListener(new CloseListener() {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void windowClose(CloseEvent e) {
+				//
+				// Did the user hit save?
+				//
+				if (attributeEditor.isSaved()) {
+					//
+					// Add the new attribute
+					//
+					((XacmlAdminUI)UI.getCurrent()).getAttributes().addEntity(newAttribute);
+					((XacmlAdminUI)UI.getCurrent()).refreshAttributes();
+				}
+			}
+			
+		});
+		attributeEditor.center();
+		UI.getCurrent().addWindow(attributeEditor);
+	}
+
+	@AutoGenerated
+	private VerticalLayout buildMainLayout() {
+		// common part: create layout
+		mainLayout = new VerticalLayout();
+		mainLayout.setImmediate(false);
+		mainLayout.setWidth("-1px");
+		mainLayout.setHeight("-1px");
+		mainLayout.setMargin(true);
+		mainLayout.setSpacing(true);
+		
+		// top-level component properties
+		setWidth("-1px");
+		setHeight("-1px");
+		
+		// horizontalLayoutToolbar
+		horizontalLayoutToolbar = buildHorizontalLayoutToolbar();
+		mainLayout.addComponent(horizontalLayoutToolbar);
+		
+		// table
+		table = new Table();
+		table.setImmediate(false);
+		table.setWidth("100.0%");
+		table.setHeight("-1px");
+		mainLayout.addComponent(table);
+		
+		return mainLayout;
+	}
+
+	@AutoGenerated
+	private HorizontalLayout buildHorizontalLayoutToolbar() {
+		// common part: create layout
+		horizontalLayoutToolbar = new HorizontalLayout();
+		horizontalLayoutToolbar.setImmediate(false);
+		horizontalLayoutToolbar.setWidth("-1px");
+		horizontalLayoutToolbar.setHeight("-1px");
+		horizontalLayoutToolbar.setMargin(false);
+		horizontalLayoutToolbar.setSpacing(true);
+		
+		// buttonNew
+		buttonNew = new Button();
+		buttonNew.setCaption("New");
+		buttonNew.setImmediate(true);
+		buttonNew.setDescription("Create a new attribute");
+		buttonNew.setWidth("70px");
+		buttonNew.setHeight("-1px");
+		horizontalLayoutToolbar.addComponent(buttonNew);
+		horizontalLayoutToolbar.setComponentAlignment(buttonNew, new Alignment(
+				9));
+		
+		// buttonRemove
+		buttonRemove = new Button();
+		buttonRemove.setCaption("Remove");
+		buttonRemove.setImmediate(true);
+		buttonRemove.setDescription("Remove the selected attribute(s)");
+		buttonRemove.setWidth("-1px");
+		buttonRemove.setHeight("-1px");
+		horizontalLayoutToolbar.addComponent(buttonRemove);
+		horizontalLayoutToolbar.setComponentAlignment(buttonRemove,
+				new Alignment(9));
+		
+		// buttonClone
+		buttonClone = new Button();
+		buttonClone.setCaption("Clone");
+		buttonClone.setImmediate(true);
+		buttonClone.setDescription("Clone an attribute.");
+		buttonClone.setWidth("-1px");
+		buttonClone.setHeight("-1px");
+		horizontalLayoutToolbar.addComponent(buttonClone);
+		horizontalLayoutToolbar.setComponentAlignment(buttonClone,
+				new Alignment(9));
+		
+		// comboBoxFilterCategory
+		comboBoxFilterCategory = new ComboBox();
+		comboBoxFilterCategory.setCaption("Filter By Category");
+		comboBoxFilterCategory.setImmediate(false);
+		comboBoxFilterCategory.setWidth("-1px");
+		comboBoxFilterCategory.setHeight("-1px");
+		horizontalLayoutToolbar.addComponent(comboBoxFilterCategory);
+		
+		// comboBoxFilterDatatype
+		comboBoxFilterDatatype = new ComboBox();
+		comboBoxFilterDatatype.setCaption("Filter By Data Type");
+		comboBoxFilterDatatype.setImmediate(false);
+		comboBoxFilterDatatype.setWidth("-1px");
+		comboBoxFilterDatatype.setHeight("-1px");
+		horizontalLayoutToolbar.addComponent(comboBoxFilterDatatype);
+		
+		return horizontalLayoutToolbar;
+	}
+
+}