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:06:57 UTC

[18/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/main/java/org/apache/openaz/xacml/admin/components/PolicyWorkspace.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/components/PolicyWorkspace.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/components/PolicyWorkspace.java
new file mode 100644
index 0000000..8e006d1
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/components/PolicyWorkspace.java
@@ -0,0 +1,1640 @@
+/*
+ *  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 java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Collection;
+import java.util.Iterator;
+
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicySetType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
+
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
+import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.Status;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.dircache.DirCache;
+import org.eclipse.jgit.dircache.DirCacheEntry;
+import org.eclipse.jgit.errors.NoWorkTreeException;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.transport.PushResult;
+import org.vaadin.dialogs.ConfirmDialog;
+import org.vaadin.dialogs.ConfirmDialog.ContentMode;
+
+import org.apache.openaz.xacml.admin.XacmlAdminAuthorization;
+import org.apache.openaz.xacml.admin.XacmlAdminUI;
+import org.apache.openaz.xacml.admin.model.GitRepositoryContainer;
+import org.apache.openaz.xacml.admin.util.AdminNotification;
+import org.apache.openaz.xacml.admin.util.OnDemandFileDownloader;
+import org.apache.openaz.xacml.admin.util.OnDemandFileDownloader.OnDemandStreamResource;
+import org.apache.openaz.xacml.admin.util.XACMLPolicyImporter;
+import org.apache.openaz.xacml.admin.view.windows.GitPushWindow;
+import org.apache.openaz.xacml.admin.view.windows.GitSynchronizeWindow;
+import org.apache.openaz.xacml.admin.view.windows.PolicyNameEditorWindow;
+import org.apache.openaz.xacml.admin.view.windows.PolicyUploadWindow;
+import org.apache.openaz.xacml.admin.view.windows.RenamePolicyFileWindow;
+import org.apache.openaz.xacml.admin.view.windows.SubDomainEditorWindow;
+import org.apache.openaz.xacml.std.pap.StdPDPPolicy;
+import org.apache.openaz.xacml.util.XACMLPolicyScanner;
+import org.apache.openaz.xacml.util.XACMLPolicyScanner.CallbackResult;
+import org.apache.openaz.xacml.util.XACMLPolicyWriter;
+import com.vaadin.annotations.AutoGenerated;
+import com.vaadin.data.Item;
+import com.vaadin.event.Action;
+import com.vaadin.event.Action.Handler;
+import com.vaadin.event.ItemClickEvent;
+import com.vaadin.event.ItemClickEvent.ItemClickListener;
+import com.vaadin.event.ShortcutAction.KeyCode;
+import com.vaadin.event.Transferable;
+import com.vaadin.event.dd.DragAndDropEvent;
+import com.vaadin.event.dd.DropHandler;
+import com.vaadin.event.dd.acceptcriteria.AcceptAll;
+import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
+import com.vaadin.ui.AbstractSelect.AbstractSelectTargetDetails;
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.CustomComponent;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.HorizontalSplitPanel;
+import com.vaadin.ui.Notification;
+import com.vaadin.ui.TabSheet;
+import com.vaadin.ui.TabSheet.CloseHandler;
+import com.vaadin.ui.TabSheet.Tab;
+import com.vaadin.ui.Table.TableDragMode;
+import com.vaadin.ui.Table.TableTransferable;
+import com.vaadin.ui.TreeTable;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.Window.CloseEvent;
+import com.vaadin.ui.Window.CloseListener;
+
+/**
+ * The class represents Policy Editor in Policy Authoring Tool
+ */
+public class PolicyWorkspace extends CustomComponent implements DropHandler, OnDemandStreamResource {
+	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */
+
+	@AutoGenerated
+	private VerticalLayout mainLayout;
+
+	@AutoGenerated
+	private HorizontalSplitPanel horizontalSplitPanel;
+
+	@AutoGenerated
+	private VerticalLayout verticalLayoutRightPanel;
+
+	@AutoGenerated
+	private TabSheet tabSheet;
+
+	@AutoGenerated
+	private HorizontalLayout horizontalLayoutRightToolbar;
+
+	@AutoGenerated
+	private Button buttonRight;
+
+	@AutoGenerated
+	private VerticalLayout verticalLayoutLeftPanel;
+
+	@AutoGenerated
+	private TreeTable treeWorkspace;
+
+	@AutoGenerated
+	private HorizontalLayout horizontalLayoutLeftToolbar;
+
+	@AutoGenerated
+	private Button buttonLeft;
+
+	@AutoGenerated
+	private HorizontalLayout horizontalLayoutLeftToolbarLeft;
+
+	@AutoGenerated
+	private Button buttonExport;
+
+	@AutoGenerated
+	private Button buttonSynchronize;
+
+	private static final long serialVersionUID = 1L;
+	private static final Log logger	= LogFactory.getLog(PolicyWorkspace.class);
+	private final PolicyWorkspace self = this;
+	private final OnDemandFileDownloader downloader = new OnDemandFileDownloader(this);
+	
+	private GitRepositoryContainer treeContainer;
+	
+	private static final Action EXPORT_REPOSITORY = 	new Action ("Export Repository");
+	private static final Action SYNCHRONIZE_REPOSITORY =new Action ("Synchronize");
+	private static final Action PUSH_CHANGES = 			new Action ("Push Changes");
+	private static final Action CREATE_SUBDOMAIN = 		new Action("Create Sub Domain");
+	private static final Action RENAME_SUBDOMAIN = 		new Action("Rename Sub Domain");
+	private static final Action CREATE_NEWPOLICY =		new Action ("Create New Policy");
+	private static final Action RENAME_POLICY =			new Action ("Rename Policy");
+	private static final Action IMPORT_POLICY = 		new Action ("Import Policy");
+	private static final Action DELETE_SUBDOMAIN = 		new Action ("Delete Sub Domain");
+	private static final Action CLONE_POLICY = 			new Action ("Clone Policy");
+	private static final Action VIEW_POLICY = 			new Action ("View Policy");
+	private static final Action EDIT_POLICY = 			new Action ("Edit Policy");
+	private static final Action EXPORT_POLICY = 		new Action ("Export Policy");
+	private static final Action DELETE_POLICY = 		new Action ("Delete Policy");
+	
+	public static final String VIEWNAME = PolicyWorkspace.class.getCanonicalName();
+	
+	/**
+	 * 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 PolicyWorkspace() {
+		buildMainLayout();
+		setCompositionRoot(mainLayout);
+		//
+		// Initialize GUI
+		//
+		this.initializeTree();
+		this.initializeButtons();
+	}
+	
+	protected void initializeButtons() {
+		buttonLeft.addClickListener(new ClickListener() {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void buttonClick(ClickEvent event) {
+				if (horizontalSplitPanel.getSplitPosition() == 100.0)
+					horizontalSplitPanel.setSplitPosition(36, Unit.PERCENTAGE);
+				else
+					horizontalSplitPanel.setSplitPosition(0);
+			}
+		});
+		buttonRight.addClickListener(new ClickListener() {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void buttonClick(ClickEvent event) {
+				if (horizontalSplitPanel.getSplitPosition() == 0.0)
+					horizontalSplitPanel.setSplitPosition(36, Unit.PERCENTAGE);
+				else
+					horizontalSplitPanel.setSplitPosition(100, Unit.PERCENTAGE);
+			}
+		});
+		//
+		// Check user write-access
+		//
+		if (((XacmlAdminUI)UI.getCurrent()).isAuthorized( 
+				XacmlAdminAuthorization.AdminAction.ACTION_WRITE, 
+				XacmlAdminAuthorization.AdminResource.RESOURCE_POLICY_WORKSPACE)) {
+			this.buttonSynchronize.addClickListener(new ClickListener() {
+				private static final long serialVersionUID = 1L;
+	
+				@Override
+				public void buttonClick(ClickEvent event) {
+					self.synchronizeRepository();
+				}			
+			});
+		} else {
+			logger.info("user not authorized to write, removing synchronize button.");
+			this.buttonSynchronize.setVisible(false);
+		}
+		//
+		// The export button is attached to dynamic downloader
+		//
+		downloader.extend(this.buttonExport);
+	}
+	
+	protected void initializeTree() {
+		//
+		// This is where the user's Git repository is located
+		//
+		final Path gitPath = ((XacmlAdminUI)UI.getCurrent()).getUserGitPath();
+		//
+		// Create our Git file system container
+		//
+		this.treeContainer = new GitRepositoryContainer(gitPath, gitPath.toFile());
+		//
+		// Create our own filter to filter out File extensions and
+		// also the Git directory.
+		//
+		this.treeContainer.setFilter(new FilenameFilter() {
+
+			@Override
+			public boolean accept(File dir, String name) {
+				//
+				// We don't want any of the hidden files
+				//
+				if (name.startsWith(".git") || name.equals(".DS_Store")) {
+					return false;
+				}
+				//
+				// We definitely want xml files
+				//
+				if (name.endsWith(".xml")) {
+					return true;
+				}
+				//
+				// We should test if its a directory, we want those
+				// included.
+				//
+				Path path = Paths.get(dir.getAbsolutePath(), name);
+				if (Files.isDirectory(path)) {
+					return true;
+				}
+				logger.warn("Filtering out: " + path.toString());
+				return false;
+			}
+			
+		});
+		//
+		// Set TreeTables datasource as our git container
+		//
+		this.treeWorkspace.setContainerDataSource(this.treeContainer);
+		//
+		// Setup other properties etc.
+		//
+		this.treeWorkspace.setItemIconPropertyId("Icon");
+		this.treeWorkspace.setVisibleColumns(new Object[]{"Name", "Version", "Size", "Last Modified", "Status"});
+		this.treeWorkspace.setSizeFull();
+		this.treeWorkspace.setSelectable(true);
+		this.treeWorkspace.setEditable(false);
+		//
+		// Expand the first couple of directories
+		//
+		for (Object id : this.treeWorkspace.getItemIds()) {
+			this.treeWorkspace.setCollapsed(id, false);
+			for (Object child : this.treeWorkspace.getChildren(id)) {
+				this.treeWorkspace.setCollapsed(child, false);
+			}
+		}
+		//
+		// Respond to table selections
+		//
+		/*
+		this.treeWorkspace.addValueChangeListener(new ValueChangeListener() {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void valueChange(ValueChangeEvent event) {
+				File selection = (File) self.treeWorkspace.getValue();
+				if (selection != null) {
+					self.buttonImport.setEnabled(selection.isDirectory());
+					self.buttonExport.setEnabled(selection.isFile());
+				} else {
+					
+				}
+			}
+			
+		});
+		*/
+		this.treeWorkspace.addItemClickListener(new ItemClickListener() {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void itemClick(ItemClickEvent event) {
+				if (event.isDoubleClick() && 
+					event.getItemId() instanceof File &&
+					((File) event.getItemId()).isFile()) {
+					self.openPolicyTab((File) event.getItemId(), true);
+				}				
+			}
+		});
+		//
+		// Setup our action handlers
+		//
+		this.treeWorkspace.addActionHandler(new Handler() {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public Action[] getActions(Object target, Object sender) {
+				if (target == null) {
+					//
+					// Nothing is selected, they right-clicked empty space
+					//
+					return new Action[] {SYNCHRONIZE_REPOSITORY, EXPORT_REPOSITORY, CREATE_SUBDOMAIN};
+				}
+				if (! (target instanceof File)) {
+					return null;
+				}
+				if (((File)target).isDirectory()) {
+					//
+					// Selected a directory
+					//
+					return new Action[] {CREATE_SUBDOMAIN, RENAME_SUBDOMAIN, DELETE_SUBDOMAIN, CREATE_NEWPOLICY, IMPORT_POLICY, PUSH_CHANGES};
+				}
+				if (((File)target).isFile()) {
+					//
+					// Selected a policy file
+					//
+					return new Action[] {VIEW_POLICY, EDIT_POLICY, CLONE_POLICY, EXPORT_POLICY, RENAME_POLICY, DELETE_POLICY, PUSH_CHANGES};
+				}
+				return null;
+			}
+
+			@Override
+			public void handleAction(Action action, Object sender, Object target) {
+				if (action == SYNCHRONIZE_REPOSITORY) {
+					self.synchronizeRepository();
+					return;
+				}
+				if (action == EXPORT_REPOSITORY) {
+					self.exportRepository();
+					return;
+				}
+				if (action == PUSH_CHANGES) {
+					self.pushChanges((File) target);
+					return;
+				}
+				if (action == CREATE_SUBDOMAIN) {
+					self.editSubDomain((File) target, null);
+					return;
+				}
+				if (action == RENAME_SUBDOMAIN) {
+					self.editSubDomain((File) self.treeWorkspace.getParent(target), ((File)target).getName());
+					return;
+				}
+				if (action == CREATE_NEWPOLICY) {
+					self.createPolicy((File) target);
+					return;
+				}
+				if (action == RENAME_POLICY) {
+					self.renamePolicy((File) target);
+					return;
+					
+				}
+				if (action == IMPORT_POLICY) {
+					self.importPolicy((File) target);
+					return;
+				}
+				if (action == DELETE_SUBDOMAIN) {
+					self.deleteSubDomain((File) target);
+					return;
+				}
+				if (action == CLONE_POLICY) {
+					self.clonePolicy((File) target);
+					return;
+				}
+				if (action == VIEW_POLICY) {
+					self.openPolicyTab((File) target, true);
+					return;
+				}
+				if (action == EDIT_POLICY) {
+					self.openPolicyTab((File) target, false);
+					return;
+				}
+				if (action == EXPORT_POLICY) {
+					return;
+
+				}
+				if (action == DELETE_POLICY) {
+					self.deletePolicy((File) target);
+					return;
+				}
+			}
+		});
+		//
+		// Set the drop handler
+		//
+		this.treeWorkspace.setDragMode(TableDragMode.ROW);
+		this.treeWorkspace.setDropHandler(this);
+		//
+		// Detect when a tab closes and remove it from the
+		// tab sheet.
+		//
+		this.tabSheet.setCloseHandler(new CloseHandler() {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void onTabClose(TabSheet tabsheet, Component tabContent) {
+				logger.info("tabsheet closing: " + tabsheet.getCaption());
+				tabsheet.removeTab(tabsheet.getTab(tabContent));
+			}
+			
+		});
+	}
+
+	protected void	editSubDomain(final File parent, final String subdomain) {
+		final SubDomainEditorWindow editor = new SubDomainEditorWindow(null);
+		editor.setCaption((subdomain == null ? "Create New SubDomain" : "Edit SubDomain"));
+		editor.setCloseShortcut(KeyCode.ESCAPE);
+		editor.setModal(true);
+		editor.addCloseListener(new CloseListener() {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void windowClose(CloseEvent event) {
+				//
+				// Did the user save it
+				//
+				if (editor.isSaved() == false) {
+					return;
+				}
+				String newSubDomain = editor.getSubDomain();
+				if (newSubDomain == null) {
+					logger.warn("Shouldn't have a null subdomain if the user clicked save button");
+					return;
+				}
+				//
+				// New subdomain?
+				//
+				if (subdomain == null) {
+					//
+					// Create new one
+					//
+					Path createDir;
+					if (parent == null) {
+						//
+						// New Root domain
+						//
+						createDir = Paths.get(((XacmlAdminUI)UI.getCurrent()).getUserGitPath().toAbsolutePath().toString(), newSubDomain);
+					} else {
+						//
+						// New subdomain
+						//
+						createDir = Paths.get(parent.getAbsolutePath(), newSubDomain);
+					}
+					try {
+						//
+						// Does the new subdomain exist?
+						//
+						Path newDir;
+						if (Files.exists(createDir)) {
+							//
+							// It already exists
+							//
+							newDir = createDir;
+						} else {
+							//
+							// Create it
+							//
+							newDir = Files.createDirectory(createDir);
+							//
+							// Create empty .gitignore file
+							//
+							Files.createFile(Paths.get(newDir.toString(), ".gitignore"));
+						}
+						//
+						// Setup the TreeTable
+						//
+						File file = newDir.toFile();
+						if (parent == null) {
+							Item item = self.treeWorkspace.addItem(file);
+							if (item != null) {
+								self.treeWorkspace.setCollapsed(file, false);
+								self.treeWorkspace.select(file);
+							}
+						} else {
+							Item item = self.treeWorkspace.addItem(file);
+							if (item != null) {
+								self.treeWorkspace.setParent(file, parent);
+								self.treeWorkspace.setCollapsed(parent, false);
+								self.treeWorkspace.select(file);
+							}
+						}
+					} catch (IOException e) {
+						logger.error("Failed to create subdomain: " + createDir.toString(), e);
+					}
+				} else {
+					//
+					// Get our paths
+					//
+					Path oldDir = Paths.get(parent.getAbsolutePath(), subdomain);
+					Path newDir = Paths.get(parent.getAbsolutePath(), newSubDomain);
+					try {
+						//
+						// Rename the subdomain
+						//
+						Files.move(oldDir, newDir);
+						//
+						// Add to the TreeTable
+						//
+						File newFile = newDir.toFile();
+						File oldFile = oldDir.toFile();
+						Item item = self.treeWorkspace.addItem(newFile);
+						if (item != null) {
+							self.treeWorkspace.setChildrenAllowed(newFile, true);
+							//
+							// Make sure its parent is the same as the old one, unless they
+							// renamed the top-level.
+							//
+							Object parent = self.treeWorkspace.getParent(oldFile);
+							if (parent != null) {
+								self.treeWorkspace.setParent(newFile, parent);
+							}
+							//
+							// Make any children of the old subdomain now children
+							// of the new subdomain.
+							//
+							Collection<?> children = self.treeWorkspace.getChildren(oldFile);
+							Iterator<?> iter = children.iterator();
+							while (iter.hasNext()) {
+								Object child = iter.next();
+								self.treeWorkspace.setParent(child, newFile);
+							}
+							//
+							// Finally remove the old subdomain
+							//
+							self.treeWorkspace.removeItem(oldFile);
+						}
+					} catch (IOException e) {
+						logger.error("Failed to rename subdomain: " + oldDir.toString() + " to: " + newDir.toString(), e);
+					}
+				}
+			}
+		});
+		editor.center();
+		UI.getCurrent().addWindow(editor);
+	}
+	
+	protected void	deleteSubDomain(final File subdomain) {
+		String message = "Are you sure you want to delete subdomain\n" + subdomain.getName() + "\nThis will remove <B>ALL</B> of its subdomains and policy files.";
+		ConfirmDialog dialog = ConfirmDialog.getFactory().create("Confirm SubDomain Deletion", message, "Delete", "Cancel");
+		dialog.setContentMode(ContentMode.HTML);
+		dialog.show(getUI(), new ConfirmDialog.Listener() {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void onClose(ConfirmDialog dialog) {
+				if (dialog.isConfirmed()) {
+					//
+					// Iterate the subdomain
+					//
+					try {
+						Files.walkFileTree(Paths.get(subdomain.getAbsolutePath()), new SimpleFileVisitor<Path>() {
+							@Override
+							public FileVisitResult visitFile(Path deleteFile, BasicFileAttributes attrs)
+									throws IOException {
+								try {
+									boolean removeFromTree = deleteFile.getFileName().toString().endsWith(".xml");
+									Files.delete(deleteFile);									
+									if (removeFromTree) {
+										self.treeWorkspace.removeItem(deleteFile.toFile());
+									}
+									if (logger.isDebugEnabled()) {
+										logger.debug("Deleted file: " + deleteFile.toString());
+									}
+								} catch (IOException e) {
+									logger.error("Failed to delete file: " + deleteFile.toString(), e);
+									return FileVisitResult.TERMINATE;
+								}
+								return super.visitFile(deleteFile, attrs);
+							}
+
+							@Override
+							public FileVisitResult postVisitDirectory(Path dir, IOException exc)
+									throws IOException {
+								try {
+									Files.delete(dir);									
+									self.treeWorkspace.removeItem(dir.toFile());
+									if (logger.isDebugEnabled()) {
+										logger.debug("Deleted dir: " + dir.toString());
+									}
+								} catch (IOException e) {
+									logger.error("Failed to delete directory: " + dir.toString(), e);
+									return FileVisitResult.TERMINATE;
+								}
+								return super.postVisitDirectory(dir, exc);
+							}
+							
+						});
+					} catch (IOException e) {
+						logger.error("Failed to walk subdomain: " + subdomain.getAbsolutePath(), e);
+					}
+				}
+			}
+			
+		}, true);
+		
+	}
+	
+	protected void	createPolicy(final File parentDirectory) {
+		//
+		// Construct our parameters
+		//
+		Path parent = Paths.get(parentDirectory.getAbsolutePath());
+		Path newFile = this.getNextFilename(parent, "Policy");
+		//
+		// Run the window
+		//
+		this.runPolicyWindow("Create New Policy", parent, newFile, null, null);
+	}
+	
+	protected void	renamePolicy(final File policy) {
+		//
+		// Run the rename window
+		//
+		final RenamePolicyFileWindow window = new RenamePolicyFileWindow(policy.getName());
+		window.setCaption("Rename Policy");
+		window.setModal(true);
+		window.addCloseListener(new CloseListener() {
+			private static final long serialVersionUID = 1L;
+			
+			@Override
+			public void windowClose(CloseEvent event) {
+				String newFilename = window.getNewFilename();
+				if (newFilename == null) {
+					//
+					// User cancelled
+					//
+					return;
+				}
+				Path newPolicy = Paths.get(policy.getParent(), newFilename);
+				if (Files.exists(newPolicy)) {
+					Notification.show("Cannot rename to an existing file", Notification.Type.ERROR_MESSAGE);
+					return;
+				}
+				try {
+					if (policy.renameTo(newPolicy.toFile()) == false) {
+						throw new Exception("No known error, rename failed");
+					}
+					self.treeContainer.updateItem(newPolicy.getParent().toFile());
+				} catch (Exception e) {
+					Notification.show("Failed to rename file: " + e.getLocalizedMessage());
+				}
+			}
+		});
+		window.center();
+		UI.getCurrent().addWindow(window);
+	}
+	
+	protected void	clonePolicy(final File policy) {
+		//
+		// Figure out a new name for the cloned policy
+		//
+		Path policyClone = Paths.get(policy.getAbsolutePath());
+		Path newFile = this.getNextFilename(policyClone.getParent(), policy.getName());
+		if (newFile == null) {
+			return;
+		}
+		//
+		// Scan the policy in, replace policy ID's and rule ID's
+		//
+		Object policyData = new XACMLPolicyScanner(policyClone, new XACMLPolicyScanner.SimpleCallback() {
+
+			@Override
+			public CallbackResult onPreVisitRule(PolicyType parent, RuleType rule) {
+				rule.setRuleId(((XacmlAdminUI)getUI()).newRuleID());
+				return CallbackResult.CONTINUE;
+			}
+			
+			@Override
+			public CallbackResult onPreVisitPolicySet(PolicySetType parent, PolicySetType policySet) {
+				policySet.setPolicySetId(((XacmlAdminUI)getUI()).newPolicyID());
+				policySet.setVersion("1");
+				return CallbackResult.CONTINUE;
+			}
+			
+			@Override
+			public CallbackResult onPreVisitPolicy(PolicySetType parent, PolicyType policy) {
+				policy.setPolicyId(((XacmlAdminUI)getUI()).newPolicyID());
+				policy.setVersion("1");
+				return CallbackResult.CONTINUE;
+			}
+			
+		}).scan();
+		//
+		// Run the window
+		//
+		this.runPolicyWindow("Clone Policy", newFile.getParent(), newFile.getFileName(), policyData, null);
+	}
+	
+	protected void	runPolicyWindow(String caption, final Path parentPath, final Path policyPath, final Object policyData, final Path oldPolicyFile) {
+		//
+		// Create our editor window
+		//
+		final PolicyNameEditorWindow editor = new PolicyNameEditorWindow((policyPath != null ? policyPath.getFileName().toString() : null), 
+															policyData, 
+															((XacmlAdminUI)getUI()).getPolicyAlgorithms(),
+															((XacmlAdminUI)getUI()).getRuleAlgorithms());
+		editor.setCaption(caption);
+		editor.setCloseShortcut(KeyCode.ESCAPE);
+		editor.setModal(true);
+		editor.addCloseListener(new CloseListener() {
+			private static final long serialVersionUID = 1L;
+			
+			@Override
+			public void windowClose(CloseEvent event) {
+				//
+				// Did the user hit save button or esc?
+				//
+				if (editor.isSaved() == false) {
+					return;
+				}
+				final Object data = editor.getPolicyData();
+				String filename = editor.getPolicyFilename();
+				if (filename == null || data == null) {
+					logger.warn("Editor said is was saved but filename/data is null.");
+					return;
+				}
+				//
+				// Determine new path
+				//
+				final Path newPolicyPath = Paths.get(parentPath.toString(), filename);
+				//
+				// Is it ok to overwrite the new file?
+				//
+				try {
+					//
+					// Handle if we are not replacing an old file and we are overwriting
+					// an existing file.
+					//
+					if (self.isOverwritingAPolicy(newPolicyPath, oldPolicyFile) == false && Files.exists(newPolicyPath)) {
+						//
+						// Confirm they wanted to do this, and figure out
+						// new version number.
+						//
+						String message = "You are overwriting a file: " + newPolicyPath.getFileName().toString();
+						ConfirmDialog dialog = ConfirmDialog.getFactory().create("Confirm Policy File Overwriting", message, "Overwrite", "Cancel");
+						dialog.setData(false);
+						dialog.setContentMode(ContentMode.HTML);
+						dialog.setModal(true);
+						dialog.show(getUI(), new ConfirmDialog.Listener() {
+							private static final long serialVersionUID = 1L;
+
+							@Override
+							public void onClose(ConfirmDialog dialog) {
+								if (dialog.isConfirmed()) {
+									//
+									// Yep the user wants to overwrite it
+									//
+									self.savePolicy(newPolicyPath, data, oldPolicyFile);
+									//
+									// Open it for editing
+									//
+									self.openPolicyTab(newPolicyPath.toFile(), false);
+								}
+							}
+							
+						}, true);
+						//
+						// Exit out of this thread
+						//
+						return;
+					}
+				} catch (Exception e) {
+					logger.error(e);
+					return;
+				}
+				//
+				// Save it off
+				//
+				self.savePolicy(newPolicyPath, data, oldPolicyFile);
+				//
+				// Open it for editing
+				//
+				self.openPolicyTab(newPolicyPath.toFile(), false);
+			}
+		});
+		editor.center();
+		UI.getCurrent().addWindow(editor);
+	}
+
+	protected Path	getNextFilename(Path parent, String filename) {
+		filename = FilenameUtils.removeExtension(filename);
+		Path newFile = null;
+		int i = 0;
+		while (true) {
+			newFile = Paths.get(parent.toString(), String.format("%s(%02d)", filename, i++) + ".xml");
+			if (Files.notExists(newFile)) {
+				return newFile;
+			}
+			if (i == 100) {
+				logger.error("Could not construct a new name for cloned policy.");
+				return null;
+			}
+		}
+		
+	}
+	
+	protected boolean isOverwritingAPolicy(Path newPolicyPath, Path oldPolicyPath) throws Exception {
+		//
+		// Check to see if we were editing an existing file. Then check if the
+		// new file actually exists. Then check if we are overwriting the original old file
+		//
+		if (oldPolicyPath != null && Files.exists(newPolicyPath) && Files.isSameFile(newPolicyPath, oldPolicyPath)) {
+			//
+			// Yes its the same, overwriting it is expected.
+			//
+			logger.info("isOverwritingAPolicy");
+			return true;
+		}
+		return false;
+	}
+
+	protected void	savePolicy(final Path newPolicyPath, final Object policyData, Path oldPolicyPath) {
+		//
+		// Are they overwriting another policy?
+		//
+		String version = "1.0";
+		boolean delete = false;
+		if (oldPolicyPath != null) {
+			//
+			// This policy name was being edited. Is it still the same?
+			//
+			try {
+				delete = true;
+				if (Files.exists(newPolicyPath) && Files.isSameFile(newPolicyPath, oldPolicyPath)) {
+					delete = false;
+				}
+			} catch (Exception e) {
+				logger.error("Could not determine if same file", e);
+				return;
+			}
+			logger.info("Deleting old file: " + delete);
+		}
+		//
+		// Are we now overwriting another file?
+		//
+		if (Files.exists(newPolicyPath)) {
+			//
+			// Yes
+			//
+			logger.info("Overwriting file");
+			//
+			// Overwrite is happening. Bump the version (IF WE CAN)
+			//
+//TODO - What if user wants to change something other than the last number?  For example, changing 1.5.23 to 2.0.0.
+//TODO	  We need a mechanism that allows the user to specify the new policy version (disallowing backtracking) if they desire
+//TODO	  and get that new number (if any) passed down to here.  This code then becomes the "then" branch of "If new version has been specified..."
+			try {
+				int[] versionArray = StdPDPPolicy.versionStringToArray(XACMLPolicyScanner.getVersion(newPolicyPath));
+				// increment the right-most digit
+				versionArray[versionArray.length - 1]++;
+				version = StdPDPPolicy.versionArrayToString(versionArray);
+			} catch (NumberFormatException | IOException e) {
+				try {
+					logger.warn("Previous version '" + XACMLPolicyScanner.getVersion(newPolicyPath) + "' not a series of itegers");
+				} catch (IOException e1) {
+					logger.error("could not get previous version");
+				}
+//TODO - This may not be wise since the intent is to increase the version number.  Perhaps we should abort this an go back to the user?
+				version = "1.0";
+			}
+			if (policyData instanceof PolicySetType) {
+				((PolicySetType) policyData).setVersion(version);
+			} else if (policyData instanceof PolicyType) {
+				((PolicyType) policyData).setVersion(version);
+			}
+		} else {
+			//
+			// Nope, a completely new file
+			//
+			logger.info("New file");
+		}
+		//
+		// Is the root a PolicySet or Policy?
+		//
+		Path finalPolicyPath;
+		if (policyData instanceof PolicySetType) {
+			//
+			// Write it out
+			//
+			finalPolicyPath = XACMLPolicyWriter.writePolicyFile(newPolicyPath, (PolicySetType) policyData);
+		} else if (policyData instanceof PolicyType) {
+			//
+			// Write it out
+			//
+			finalPolicyPath = XACMLPolicyWriter.writePolicyFile(newPolicyPath, (PolicyType) policyData);
+		} else {
+			logger.error("Unknown data type sent back.");
+			return;
+		}
+		//
+		// Did it get written?
+		//
+		if (finalPolicyPath == null || ! Files.exists(finalPolicyPath)) {
+			logger.error("Failed to write policy file.");
+			return;
+		}
+		//
+		// Add it into our tree
+		//
+		this.addPolicyFileToTree(finalPolicyPath.getParent().toFile(), finalPolicyPath.toFile());
+		//
+		// Do we need to delete the old file?
+		//
+		if (oldPolicyPath != null && delete) {
+			try {
+				Files.delete(oldPolicyPath);
+			} catch (Exception e) {
+				logger.error("Failed to delete old policy", e);
+			}
+			if (self.treeWorkspace.removeItem(oldPolicyPath.toFile()) == false) {
+				logger.warn("Failed to remove old policy path");
+			}
+		}
+	}	
+
+	protected void	deletePolicy(final File policy) {
+		String message = "Are you sure you want to delete policy: " + policy.getName();
+		ConfirmDialog dialog = ConfirmDialog.getFactory().create("Confirm Policy File Deletion", message, "Delete", "Cancel");
+		dialog.setContentMode(ContentMode.HTML);
+		dialog.show(getUI(), new ConfirmDialog.Listener() {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void onClose(ConfirmDialog dialog) {
+				if (dialog.isConfirmed() && policy.delete()) {
+					self.treeWorkspace.removeItem(policy);
+					if (logger.isDebugEnabled()) {
+						logger.debug("Deleted file: " + policy.toString());
+					}
+				}
+			}
+			
+		}, true);
+		
+	}
+
+	protected void	importPolicy(final File domain) {
+		//
+		// Get the current domain
+		//
+		if (! domain.isDirectory()) {
+			logger.error("Table must have a directory selected to import the file.");
+			return;
+		}
+		//
+		// Create the upload window
+		//
+		final PolicyUploadWindow upload = new PolicyUploadWindow(Paths.get(domain.toURI()));
+		upload.setCaption("Import Xacml 3.0 Policy File");
+		upload.setCloseShortcut(KeyCode.ESCAPE);
+		upload.setModal(true);
+		upload.addCloseListener(new CloseListener() {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public void windowClose(CloseEvent e) {
+				//
+				// Was it successful?
+				//
+				Path newFile = upload.getUploadedFile();
+				if (newFile == null) {
+					return;
+				}
+				//
+				// Add it
+				//
+				self.addPolicyFileToTree(domain, newFile.toFile());
+				//
+				// Are we importing anything in the policy file?
+				//
+				boolean importAttributes = upload.importAttributes();
+				boolean importObligations = upload.importObligations();
+				boolean importAdvice = upload.importAdvice();
+				if (importAttributes || importObligations || importAdvice) {
+					//
+					// Create our importer
+					//
+					XACMLPolicyImporter importer = new XACMLPolicyImporter();
+					importer.setImportAttributes(importAttributes);
+					importer.setImportObligations(importObligations);
+					importer.setImportAdvice(importAdvice);		
+					importer.setIgnoreStandardAttributes(upload.ignoreStandard());
+					//
+					// Yes load and scan the policy
+					//
+					new XACMLPolicyScanner(newFile, importer).scan();
+				}
+			}
+		});
+		upload.center();
+		UI.getCurrent().addWindow(upload);
+	}
+	
+	protected	void	addPolicyFileToTree(File domain, File file) {
+		//
+		// Add it into our tree
+		//
+		if (this.treeWorkspace.addItem(file) != null) {
+			//
+			// Make sure it has the right parent
+			//
+			this.treeWorkspace.setParent(file, domain);
+			//
+			// Select our new policy
+			//
+			self.treeWorkspace.select(file);
+		} else {
+			logger.error("Failed to add policy to workspace tree");
+		}
+	}
+	
+	/*
+	protected void	publishPolicy(final File policy) {
+		//
+		// Get its ID
+		//
+		Item item = this.treeContainer.getItem(policy);
+		if (item == null) {
+			logger.error("Failed to get the item");
+			return;
+		}
+		Object policyData = item.getItemProperty("Data");
+		if (policyData == null) {
+			logger.error("Failed to get item data property.");
+			return;
+		}
+		String fullId = XACMLPolicyScanner.getID(policyData);
+		String version = XACMLPolicyScanner.getVersion(policyData);
+		if (fullId == null || version == null) {
+			logger.error("Failed to get policy Id");
+			return;
+		}
+		List<String> ids = Lists.newArrayList(Splitter.on(':').split(fullId));
+		if (ids.isEmpty()) {
+			logger.error("Couldn't parse policy Id");
+			return;
+		}
+		final String id = ids.get(ids.size() - 1) + "." + version;
+		//
+		// Is there only one group?
+		//
+		PAPEngine engine = ((XacmlAdminUI)getUI()).getPAPEngine();
+		Set<PDPGroup> groups;
+		PDPGroup defaultGroup;
+		try {
+			groups = engine.getPDPGroups();
+		} catch (PAPException e) {
+			String message = "Unable to retrieve Groups from server: " + e;
+			logger.error(message, e);
+			throw new RuntimeException(message);
+		}
+		try {
+			defaultGroup = engine.getDefaultGroup();
+		} catch (PAPException e) {
+			String message = "Unable to retrieve Default Group from server: " + e;
+			logger.error(message, e);
+			throw new RuntimeException(message);
+		}
+		if (groups.size() == 1) {
+			this.doPublish(id, policy, defaultGroup);
+			return;
+		}
+		//
+		// Have user select a group
+		//
+		final SelectPDPGroupWindow window = new SelectPDPGroupWindow(groups, "Select PDP Group to publish in");
+		window.setCaption("Select PDP Group");
+		window.setCloseShortcut(KeyCode.ESCAPE);
+		window.setModal(true);
+		window.addCloseListener(new CloseListener() {
+			private static final long serialVersionUID = 1L;
+			
+			@Override
+			public void windowClose(CloseEvent event) {
+				PDPGroup group = window.selectedGroup();
+				if (group != null) {
+					self.doPublish(id, policy, group);
+				}
+			}
+		});
+		window.center();
+		UI.getCurrent().addWindow(window);
+
+	}
+	
+	protected void	doPublish(String id, File policy, PDPGroup group) {
+		//
+		// The policy status must be up-to-date
+		//
+		// TODO
+		
+		//
+		// TODO - get list of referenced policies and publish
+		// them first.
+		//
+		
+		//
+		// Publish the policy
+		//
+		
+		PAPEngine engine = ((XacmlAdminUI)getUI()).getPAPEngine();
+		try (InputStream is = new FileInputStream(policy)) {
+			engine.publishPolicy(id, policy.getName(), true, is, group);
+		} catch (PAPException | IOException e) {
+			logger.error("Failed to publish policy: ", e);
+		}
+	}
+	*/
+	
+	protected void	pushChanges(final File target) {
+		try {
+			//
+			// Grab our working repository
+			//
+    		Path repoPath = ((XacmlAdminUI)getUI()).getUserGitPath();
+			final Git git = Git.open(repoPath.toFile());
+			//
+			// Get our status
+			//
+			final String base;
+			Status status;
+			if (target == null) {
+				base = ".";
+			} else {
+				Path relativePath = repoPath.relativize(Paths.get(target.getPath()));
+				base = relativePath.toString();
+			}
+			if (logger.isDebugEnabled()) {
+				logger.debug("Status on base: " + base);
+			}
+			status = git.status().addPath(base).call();
+			//
+			// Check if its clean
+			//
+			if (status.isClean()) {
+				//
+				// Its clean
+				//
+				AdminNotification.warn(target.getName() + " is clean!");
+				return;
+			}
+			//
+			// Create the window
+			//
+			final GitPushWindow window = new GitPushWindow(git, target, status);
+			window.setCaption("Push Changes");
+			window.setModal(true);
+			window.addCloseListener(new CloseListener() {
+				private static final long serialVersionUID = 1L;
+
+				@Override
+				public void windowClose(CloseEvent e) {
+					if (window.isSaved() == false) {
+						return;
+					}
+					try {
+						//
+						// Needs to be added first
+						//
+						DirCache cache = git.add().addFilepattern(base).call();
+						for (int i = 0; i < cache.getEntryCount(); i++) {
+							DirCacheEntry entry = cache.getEntry(i);
+							if (logger.isDebugEnabled()) {
+								logger.debug("Entry: " + entry);
+							}
+						}
+						//
+						// Next they need to be committed
+						//
+						RevCommit rev = git.commit().setMessage(window.getComment()).call();
+						if (logger.isDebugEnabled()) {
+							logger.debug("RevCommit: " + rev);
+						}
+						//
+						// Now we can push changes to the Git repository
+						//
+						Iterable<PushResult> results = git.push().call();
+						for (PushResult result : results) {
+							logger.info(result);
+						}
+						//
+						// Have the container fire an item set change notification
+						//
+						self.treeContainer.updateItem(target);
+					} catch (NoWorkTreeException | GitAPIException e1) {
+						logger.error(e);
+						AdminNotification.error("Exception occurred while trying to push: " + e1);
+					}
+				}
+				
+			});
+			window.center();
+			UI.getCurrent().addWindow(window);
+		} catch (IOException | GitAPIException e) {
+			logger.error(e);
+			AdminNotification.error("Exception occurred while trying to get status: " + e);
+		}
+	}
+	
+	protected void synchronizeRepository() {
+		final GitSynchronizeWindow window = new GitSynchronizeWindow();
+		window.setCaption("Synchronize with server repository?");
+		window.setModal(true);
+		window.center();
+		UI.getCurrent().addWindow(window);
+	}
+	
+	protected void exportRepository() {
+		this.buttonExport.click();
+	}
+	
+	@Override
+	public String getFilename() {
+		return "Repository.tgz";
+	}
+
+	@Override
+	public InputStream getStream() {
+		//
+		// Grab our working repository
+		//
+		final Path repoPath = ((XacmlAdminUI)getUI()).getUserGitPath();
+		Path workspacePath = ((XacmlAdminUI)getUI()).getUserWorkspace();
+		final Path tarFile = Paths.get(workspacePath.toString(), "Repository.tgz");
+		
+		try (OutputStream os = Files.newOutputStream(tarFile)) {
+			try (GzipCompressorOutputStream gzOut = new GzipCompressorOutputStream(os)) {
+				try (TarArchiveOutputStream tarOut = new TarArchiveOutputStream(gzOut)) {
+					
+					tarOut.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
+					
+					Files.walkFileTree(repoPath, new SimpleFileVisitor<Path>() {
+
+						@Override
+						public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
+							if (dir.getFileName().toString().startsWith(".git")) {
+								return FileVisitResult.SKIP_SUBTREE;
+							}
+							Path relative = repoPath.relativize(dir);
+							if (relative.toString().isEmpty()) {
+								return super.preVisitDirectory(dir, attrs);
+							}
+							TarArchiveEntry entry = new TarArchiveEntry(relative.toFile());
+							tarOut.putArchiveEntry(entry);
+							tarOut.closeArchiveEntry();
+							return super.preVisitDirectory(dir, attrs);
+						}
+
+						@Override
+						public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+							if (file.getFileName().toString().endsWith(".xml") == false) {
+								return super.visitFile(file, attrs);
+							}
+							Path relative = repoPath.relativize(file);
+							TarArchiveEntry entry = new TarArchiveEntry(relative.toFile());
+							entry.setSize(Files.size(file));
+							tarOut.putArchiveEntry(entry);
+							try {
+								IOUtils.copy(Files.newInputStream(file), tarOut);
+							} catch (IOException e) {
+								logger.error(e);
+							}
+							tarOut.closeArchiveEntry();
+							return super.visitFile(file, attrs);
+						}
+						
+					});
+					tarOut.finish();
+				}				
+			}
+		} catch (IOException e) {
+			logger.error(e);
+		}
+		try {
+			return Files.newInputStream(tarFile);
+		} catch (IOException e) {
+			logger.error(e);
+		}
+		return null;
+	}
+
+	protected void openPolicyTab(File policy, boolean readOnly) {
+		//
+		// Sanity check
+		//
+		assert policy != null;
+		assert policy.isFile();
+		if (policy == null || ! policy.isFile()) {
+			throw new IllegalArgumentException("You must specify a file.");
+		}
+		Status status;
+		Path relativePath;
+		String base;
+		try {
+			//
+			// Grab our working repository
+			//
+			Path repoPath = ((XacmlAdminUI)getUI()).getUserGitPath();
+			final Git git = Git.open(repoPath.toFile());
+			//
+			// Get our status
+			//
+			relativePath = repoPath.relativize(Paths.get(policy.getPath()));
+			base = relativePath.toString();
+			if (logger.isDebugEnabled()) {
+				logger.debug("Status on base: " + base);
+			}
+			status = git.status().addPath(base).call();
+		} catch (NoWorkTreeException | IOException | GitAPIException e) {
+			logger.error("Failed to get status on " + policy + " " + e);
+			AdminNotification.error("Could not get Git status on the file.");
+			return;
+		}
+		//
+		// Check if its clean
+		//
+		if (status.isClean() == false) {
+			//
+			// Check if its conflicting
+			//
+			for (String conflict : status.getConflicting()) {
+				if (conflict.equals(base)) {
+					//
+					// Yes - we won't be able to edit it
+					//
+					AdminNotification.error("Policy has conflicts with master, please synchronize the repository.");
+					return;
+				}
+			}
+		}
+		//
+		// Check to see if there already is a tab open
+		//
+		Iterator<Component> iter = self.tabSheet.iterator();
+		while (iter.hasNext()) {
+			Component c = iter.next();
+			if (c instanceof PolicyEditor) {
+				Object data = ((PolicyEditor) c).getData();
+				if (data != null && data instanceof File && ((File)data).equals(policy)) {
+					self.tabSheet.setSelectedTab(c);
+					return;
+				}
+			}
+		}
+		//
+		// No tab is open, create a new one
+		//
+		PolicyEditor editor = null;
+		try {
+			editor = new PolicyEditor(policy, this.treeContainer, readOnly);
+		} catch (IOException e) {
+			logger.error("Failed to open policy");
+			editor = null;
+		}
+		if (editor != null) {
+			editor.setWidth("100%");
+			Tab tab = self.tabSheet.addTab(editor);
+			editor.setTab(tab);
+			tab.setClosable(true);
+			
+			self.tabSheet.setSelectedTab(editor);
+		} else {
+			AdminNotification.error("The Policy File is not a Xacml 3.0 policy.");
+		}
+	}
+
+	@Override
+	public void drop(DragAndDropEvent event) {
+		Transferable t = event.getTransferable();
+		Component source = t.getSourceComponent();
+		if (source != this.treeWorkspace) {
+			assert false;
+			throw new IllegalArgumentException();
+		}
+		TableTransferable tt = (TableTransferable) t;
+		File sourceFile = (File) tt.getItemId();
+		
+		AbstractSelectTargetDetails target = (AbstractSelectTargetDetails)event.getTargetDetails();
+		File targetFile = (File) target.getItemIdOver();
+		
+		if (sourceFile.isFile() && targetFile != null && targetFile.isDirectory()) {
+			//
+			// Construct destination filename
+			//
+			Path dest = targetFile.toPath().resolve(sourceFile.getName());
+			//
+			// Check if the target domain exists
+			//
+			if (Files.exists(dest)) {
+				//
+				// Prompt the user
+				//
+				Notification.show("A policy file with that name already exists in that directory.", Notification.Type.ERROR_MESSAGE);
+			} else {
+				//
+				// Go ahead and rename it
+				//
+				this.renamePolicyFile(sourceFile, dest.toFile(), targetFile);
+			}
+		}
+	}
+	
+	protected void renamePolicyFile(File sourceFile, File dest, File parent) {
+		try {
+			if (sourceFile.renameTo(dest)) {
+				this.treeContainer.setParent(sourceFile, parent);
+				this.treeContainer.updateItem(parent);
+			}
+		} catch (Exception e) {
+			String error = "Failed to rename " + sourceFile + " to: " + dest + System.lineSeparator() + e.getLocalizedMessage();
+			logger.error(error);
+			AdminNotification.error(error);
+		}
+	}
+
+	@Override
+	public AcceptCriterion getAcceptCriterion() {
+        return AcceptAll.get();
+	}
+	
+	@AutoGenerated
+	private VerticalLayout buildMainLayout() {
+		// common part: create layout
+		mainLayout = new VerticalLayout();
+		mainLayout.setImmediate(false);
+		mainLayout.setWidth("100%");
+		mainLayout.setHeight("100%");
+		mainLayout.setMargin(false);
+		
+		// top-level component properties
+		setWidth("100.0%");
+		setHeight("100.0%");
+		
+		// horizontalSplitPanel
+		horizontalSplitPanel = buildHorizontalSplitPanel();
+		mainLayout.addComponent(horizontalSplitPanel);
+		mainLayout.setExpandRatio(horizontalSplitPanel, 1.0f);
+		
+		return mainLayout;
+	}
+
+	@AutoGenerated
+	private HorizontalSplitPanel buildHorizontalSplitPanel() {
+		// common part: create layout
+		horizontalSplitPanel = new HorizontalSplitPanel();
+		horizontalSplitPanel.setImmediate(false);
+		horizontalSplitPanel.setWidth("100.0%");
+		horizontalSplitPanel.setHeight("100.0%");
+		
+		// verticalLayoutLeftPanel
+		verticalLayoutLeftPanel = buildVerticalLayoutLeftPanel();
+		horizontalSplitPanel.addComponent(verticalLayoutLeftPanel);
+		
+		// verticalLayoutRightPanel
+		verticalLayoutRightPanel = buildVerticalLayoutRightPanel();
+		horizontalSplitPanel.addComponent(verticalLayoutRightPanel);
+		
+		return horizontalSplitPanel;
+	}
+
+	@AutoGenerated
+	private VerticalLayout buildVerticalLayoutLeftPanel() {
+		// common part: create layout
+		verticalLayoutLeftPanel = new VerticalLayout();
+		verticalLayoutLeftPanel.setImmediate(false);
+		verticalLayoutLeftPanel.setWidth("100.0%");
+		verticalLayoutLeftPanel.setHeight("100.0%");
+		verticalLayoutLeftPanel.setMargin(true);
+		verticalLayoutLeftPanel.setSpacing(true);
+		
+		// horizontalLayoutLeftToolbar
+		horizontalLayoutLeftToolbar = buildHorizontalLayoutLeftToolbar();
+		verticalLayoutLeftPanel.addComponent(horizontalLayoutLeftToolbar);
+		
+		// treeWorkspace
+		treeWorkspace = new TreeTable();
+		treeWorkspace.setImmediate(true);
+		treeWorkspace.setWidth("100.0%");
+		treeWorkspace.setHeight("100.0%");
+		verticalLayoutLeftPanel.addComponent(treeWorkspace);
+		verticalLayoutLeftPanel.setExpandRatio(treeWorkspace, 1.0f);
+		
+		return verticalLayoutLeftPanel;
+	}
+
+	@AutoGenerated
+	private HorizontalLayout buildHorizontalLayoutLeftToolbar() {
+		// common part: create layout
+		horizontalLayoutLeftToolbar = new HorizontalLayout();
+		horizontalLayoutLeftToolbar.setImmediate(false);
+		horizontalLayoutLeftToolbar.setWidth("100.0%");
+		horizontalLayoutLeftToolbar.setHeight("-1px");
+		horizontalLayoutLeftToolbar.setMargin(false);
+		horizontalLayoutLeftToolbar.setSpacing(true);
+		
+		// horizontalLayoutLeftToolbarLeft
+		horizontalLayoutLeftToolbarLeft = buildHorizontalLayoutLeftToolbarLeft();
+		horizontalLayoutLeftToolbar
+				.addComponent(horizontalLayoutLeftToolbarLeft);
+		
+		// buttonLeft
+		buttonLeft = new Button();
+		buttonLeft.setCaption("<<");
+		buttonLeft.setImmediate(true);
+		buttonLeft.setDescription("Minimize left panel.");
+		buttonLeft.setWidth("-1px");
+		buttonLeft.setHeight("-1px");
+		horizontalLayoutLeftToolbar.addComponent(buttonLeft);
+		horizontalLayoutLeftToolbar.setComponentAlignment(buttonLeft,
+				new Alignment(34));
+		
+		return horizontalLayoutLeftToolbar;
+	}
+
+	@AutoGenerated
+	private HorizontalLayout buildHorizontalLayoutLeftToolbarLeft() {
+		// common part: create layout
+		horizontalLayoutLeftToolbarLeft = new HorizontalLayout();
+		horizontalLayoutLeftToolbarLeft.setImmediate(false);
+		horizontalLayoutLeftToolbarLeft.setWidth("-1px");
+		horizontalLayoutLeftToolbarLeft.setHeight("-1px");
+		horizontalLayoutLeftToolbarLeft.setMargin(false);
+		horizontalLayoutLeftToolbarLeft.setSpacing(true);
+		
+		// buttonSynchronize
+		buttonSynchronize = new Button();
+		buttonSynchronize.setCaption("Synchronize Repository");
+		buttonSynchronize.setImmediate(true);
+		buttonSynchronize
+				.setDescription("Synchronize local repository with main branch.");
+		buttonSynchronize.setWidth("-1px");
+		buttonSynchronize.setHeight("-1px");
+		horizontalLayoutLeftToolbarLeft.addComponent(buttonSynchronize);
+		
+		// buttonExport
+		buttonExport = new Button();
+		buttonExport.setCaption("Export Workspace");
+		buttonExport.setImmediate(true);
+		buttonExport.setDescription("Export your workspace to your local drive.");
+		buttonExport.setWidth("-1px");
+		buttonExport.setHeight("-1px");
+		horizontalLayoutLeftToolbarLeft.addComponent(buttonExport);
+		
+		return horizontalLayoutLeftToolbarLeft;
+	}
+
+	@AutoGenerated
+	private VerticalLayout buildVerticalLayoutRightPanel() {
+		// common part: create layout
+		verticalLayoutRightPanel = new VerticalLayout();
+		verticalLayoutRightPanel.setImmediate(false);
+		verticalLayoutRightPanel.setWidth("100.0%");
+		verticalLayoutRightPanel.setHeight("-1px");
+		verticalLayoutRightPanel.setMargin(true);
+		verticalLayoutRightPanel.setSpacing(true);
+		
+		// horizontalLayoutRightToolbar
+		horizontalLayoutRightToolbar = buildHorizontalLayoutRightToolbar();
+		verticalLayoutRightPanel.addComponent(horizontalLayoutRightToolbar);
+		
+		// tabSheet
+		tabSheet = new TabSheet();
+		tabSheet.setImmediate(true);
+		tabSheet.setWidth("100.0%");
+		tabSheet.setHeight("-1px");
+		verticalLayoutRightPanel.addComponent(tabSheet);
+		verticalLayoutRightPanel.setExpandRatio(tabSheet, 1.0f);
+		
+		return verticalLayoutRightPanel;
+	}
+
+	@AutoGenerated
+	private HorizontalLayout buildHorizontalLayoutRightToolbar() {
+		// common part: create layout
+		horizontalLayoutRightToolbar = new HorizontalLayout();
+		horizontalLayoutRightToolbar.setImmediate(false);
+		horizontalLayoutRightToolbar.setWidth("100.0%");
+		horizontalLayoutRightToolbar.setHeight("-1px");
+		horizontalLayoutRightToolbar.setMargin(false);
+		horizontalLayoutRightToolbar.setSpacing(true);
+		
+		// buttonRight
+		buttonRight = new Button();
+		buttonRight.setCaption(">>");
+		buttonRight.setImmediate(true);
+		buttonRight.setDescription("Restore left panel.");
+		buttonRight.setWidth("-1px");
+		buttonRight.setHeight("-1px");
+		horizontalLayoutRightToolbar.addComponent(buttonRight);
+		
+		return horizontalLayoutRightToolbar;
+	}
+}

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/Simulator.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/components/Simulator.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/components/Simulator.java
new file mode 100644
index 0000000..c554568
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/components/Simulator.java
@@ -0,0 +1,69 @@
+/*
+ *  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 com.vaadin.annotations.AutoGenerated;
+import com.vaadin.annotations.Theme;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.ui.AbsoluteLayout;
+import com.vaadin.ui.CustomComponent;
+import com.vaadin.ui.UI;
+
+public class Simulator extends CustomComponent {
+
+	@AutoGenerated
+	private AbsoluteLayout mainLayout;
+
+	private static final long serialVersionUID = 1L;
+
+	@Theme("xacml_pap_admin")
+	public static class SimulatorUI extends UI {
+		private static final long serialVersionUID = 1L;
+
+		@Override
+		protected void init(VaadinRequest request) {
+			// TODO Auto-generated method stub
+
+		}
+
+	}
+	
+	/**
+	 * 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 Simulator() {
+		buildMainLayout();
+		setCompositionRoot(mainLayout);
+
+		// TODO add user code here
+	}
+
+	@AutoGenerated
+	private void buildMainLayout() {
+		// the main layout and components will be created here
+		mainLayout = new AbsoluteLayout();
+	}
+
+}

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/UserManagement.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/components/UserManagement.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/components/UserManagement.java
new file mode 100644
index 0000000..a883dec
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/components/UserManagement.java
@@ -0,0 +1,114 @@
+/*
+ *  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 com.vaadin.annotations.AutoGenerated;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.CustomComponent;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.VerticalLayout;
+
+public class UserManagement extends CustomComponent {
+	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */
+
+	@AutoGenerated
+	private VerticalLayout mainLayout;
+	@AutoGenerated
+	private Table tableUsers;
+	@AutoGenerated
+	private HorizontalLayout horizontalLayoutToolbar;
+	@AutoGenerated
+	private Button buttonRemove;
+	@AutoGenerated
+	private Button buttonAdd;
+	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 UserManagement() {
+		buildMainLayout();
+		setCompositionRoot(mainLayout);
+
+		// TODO add user code here
+	}
+
+	@AutoGenerated
+	private VerticalLayout buildMainLayout() {
+		// common part: create layout
+		mainLayout = new VerticalLayout();
+		mainLayout.setImmediate(false);
+		mainLayout.setWidth("100%");
+		mainLayout.setHeight("-1px");
+		mainLayout.setMargin(false);
+		
+		// top-level component properties
+		setWidth("100.0%");
+		setHeight("-1px");
+		
+		// horizontalLayoutToolbar
+		horizontalLayoutToolbar = buildHorizontalLayoutToolbar();
+		mainLayout.addComponent(horizontalLayoutToolbar);
+		
+		// tableUsers
+		tableUsers = new Table();
+		tableUsers.setImmediate(false);
+		tableUsers.setWidth("100.0%");
+		tableUsers.setHeight("-1px");
+		mainLayout.addComponent(tableUsers);
+		
+		return mainLayout;
+	}
+
+	@AutoGenerated
+	private HorizontalLayout buildHorizontalLayoutToolbar() {
+		// common part: create layout
+		horizontalLayoutToolbar = new HorizontalLayout();
+		horizontalLayoutToolbar.setImmediate(false);
+		horizontalLayoutToolbar.setWidth("-1px");
+		horizontalLayoutToolbar.setHeight("-1px");
+		horizontalLayoutToolbar.setMargin(true);
+		horizontalLayoutToolbar.setSpacing(true);
+		
+		// buttonAdd
+		buttonAdd = new Button();
+		buttonAdd.setCaption("Add User");
+		buttonAdd.setImmediate(false);
+		buttonAdd.setWidth("-1px");
+		buttonAdd.setHeight("-1px");
+		horizontalLayoutToolbar.addComponent(buttonAdd);
+		
+		// buttonRemove
+		buttonRemove = new Button();
+		buttonRemove.setCaption("Remove User");
+		buttonRemove.setImmediate(false);
+		buttonRemove.setWidth("-1px");
+		buttonRemove.setHeight("-1px");
+		horizontalLayoutToolbar.addComponent(buttonRemove);
+		
+		return horizontalLayoutToolbar;
+	}
+
+}

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/package-info.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/components/package-info.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/components/package-info.java
new file mode 100644
index 0000000..947702e
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/components/package-info.java
@@ -0,0 +1,28 @@
+/*
+ *  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.
+ *
+ */
+
+/**
+ * 
+ */
+/**
+ * @author pameladragosh
+ *
+ */
+package org.apache.openaz.xacml.admin.components;

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/a1d93100/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/CategoryConverter.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/CategoryConverter.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/CategoryConverter.java
new file mode 100644
index 0000000..4229a4e
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/CategoryConverter.java
@@ -0,0 +1,71 @@
+/*
+ *  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.converters;
+
+import java.util.Locale;
+
+import org.apache.openaz.xacml.admin.jpa.Category;
+import org.apache.openaz.xacml.api.Identifier;
+import com.vaadin.data.util.converter.Converter;
+
+public class CategoryConverter implements Converter<Object, Category> {
+	private static final long serialVersionUID = 1L;
+
+	@Override
+	public Category convertToModel(Object value,
+			Class<? extends Category> targetType, Locale locale)
+			throws Converter.ConversionException {
+		Category category = new Category();
+		if (value == null) {
+			return category;
+		}
+		if (value instanceof Identifier) {
+			category.setXacmlId(((Identifier)value).stringValue());
+		} else {
+			category.setXacmlId(value.toString());
+		}
+		return category;
+	}
+
+	@Override
+	public Object convertToPresentation(Category value,
+			Class<? extends Object> targetType, Locale locale)
+			throws Converter.ConversionException {
+		if (targetType.getName().equals(String.class.getName())) {
+			return value.getXacmlId();
+		}
+		if (targetType.getName().equals(Identifier.class.getName())) {
+			return value.getIdentifer();
+		}
+		return value.getIdentifer();
+	}
+
+	@Override
+	public Class<Category> getModelType() {
+		return Category.class;
+	}
+
+	@Override
+	public Class<Object> getPresentationType() {
+		return Object.class;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/a1d93100/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/ConstraintTypeConverter.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/ConstraintTypeConverter.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/ConstraintTypeConverter.java
new file mode 100644
index 0000000..c6705ca
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/ConstraintTypeConverter.java
@@ -0,0 +1,79 @@
+/*
+ *  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.converters;
+
+import java.util.Locale;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.openaz.xacml.admin.jpa.ConstraintType;
+import com.vaadin.data.util.converter.Converter;
+
+public class ConstraintTypeConverter  implements Converter<Object, ConstraintType> {
+	private static final long serialVersionUID = 1L;
+	private static final Log logger	= LogFactory.getLog(ConstraintTypeConverter.class);
+
+	@Override
+	public ConstraintType convertToModel(Object value,
+			Class<? extends ConstraintType> targetType, Locale locale)
+			throws Converter.ConversionException {
+		if (logger.isTraceEnabled()) {
+			logger.trace("convertToModel:" + value + " target " + targetType);
+		}
+		ConstraintType constraintValue = new ConstraintType();
+		if (value == null) {
+			return constraintValue;
+		}
+		// PLD TODO??
+		return constraintValue;
+	}
+
+	@Override
+	public Object convertToPresentation(ConstraintType value,
+			Class<? extends Object> targetType, Locale locale)
+			throws Converter.ConversionException {
+		if (logger.isTraceEnabled()) {
+			logger.trace("convertToPresentation:" + value + " target " + targetType);
+		}
+		if (value == null) {
+			return null;
+		}
+		if (targetType.isAssignableFrom(String.class)) {
+			return value.getConstraintType();
+		}
+		if (targetType.isInstance(Integer.class)) {
+			return value.getId();
+		}
+		return null;
+	}
+
+	@Override
+	public Class<ConstraintType> getModelType() {
+		return ConstraintType.class;
+	}
+
+	@Override
+	public Class<Object> getPresentationType() {
+		return Object.class;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/a1d93100/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/ConstraintValueConverter.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/ConstraintValueConverter.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/ConstraintValueConverter.java
new file mode 100644
index 0000000..03c76be
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/ConstraintValueConverter.java
@@ -0,0 +1,73 @@
+/*
+ *  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.converters;
+
+import java.util.Locale;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.openaz.xacml.admin.jpa.ConstraintValue;
+import com.vaadin.data.util.converter.Converter;
+
+public class ConstraintValueConverter implements Converter<Object, ConstraintValue> {
+	private static final long serialVersionUID = 1L;
+	private static final Log logger	= LogFactory.getLog(ConstraintValueConverter.class);
+	
+	@Override
+	public ConstraintValue convertToModel(Object value,
+			Class<? extends ConstraintValue> targetType, Locale locale)
+			throws Converter.ConversionException {
+		if (logger.isTraceEnabled()) {
+			logger.trace("convertToModel:" + value + " target " + targetType);
+		}
+		ConstraintValue newValue = new ConstraintValue();
+		if (value == null) {
+			return newValue;
+		}
+		// PLD TODO?
+		return newValue;
+	}
+
+	@Override
+	public Object convertToPresentation(ConstraintValue value,
+			Class<? extends Object> targetType, Locale locale)
+			throws Converter.ConversionException {
+		if (logger.isTraceEnabled()) {
+			logger.trace("convertToPresentation:" + value + " target " + targetType);
+		}
+		if (value == null) {
+			return null;
+		}
+		return value.getProperty();
+	}
+
+	@Override
+	public Class<ConstraintValue> getModelType() {
+		return ConstraintValue.class;
+	}
+
+	@Override
+	public Class<Object> getPresentationType() {
+		return Object.class;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/a1d93100/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/DatatypeConverter.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/DatatypeConverter.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/DatatypeConverter.java
new file mode 100644
index 0000000..8817428
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/DatatypeConverter.java
@@ -0,0 +1,76 @@
+/*
+ *  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.converters;
+
+import java.util.Locale;
+
+import org.apache.openaz.xacml.admin.jpa.Datatype;
+import org.apache.openaz.xacml.api.Identifier;
+import com.vaadin.data.util.converter.Converter;
+
+public class DatatypeConverter implements Converter<Object, Datatype> {
+	private static final long serialVersionUID = 1L;
+
+	@Override
+	public Datatype convertToModel(Object value,
+			Class<? extends Datatype> targetType, Locale locale)
+			throws Converter.ConversionException {
+		Datatype datatype = new Datatype();
+		if (value == null) {
+			return datatype;
+		}
+		if (value instanceof Identifier) {
+			datatype.setXacmlId(((Identifier)value).stringValue());
+		} else {
+			datatype.setXacmlId(value.toString());
+		}
+		return datatype;
+	}
+
+	@Override
+	public Object convertToPresentation(Datatype value,
+			Class<? extends Object> targetType, Locale locale)
+			throws Converter.ConversionException {
+		if (value == null) {
+			return null;
+		}
+		if (targetType.isInstance(String.class) ||
+			targetType.getName().equals(String.class.getName())) {
+			return value.getXacmlId();
+		}
+		if (targetType.isInstance(Identifier.class) ||
+			targetType.getName().equals(Identifier.class.getName())) {
+			return value.getIdentifer();
+		}
+		return value.getIdentifer();
+	}
+
+	@Override
+	public Class<Datatype> getModelType() {
+		return Datatype.class;
+	}
+
+	@Override
+	public Class<Object> getPresentationType() {
+		return Object.class;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/a1d93100/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/IdentifierConverter.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/IdentifierConverter.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/IdentifierConverter.java
new file mode 100644
index 0000000..07b810d
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/IdentifierConverter.java
@@ -0,0 +1,61 @@
+/*
+ *  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.converters;
+
+import java.util.Locale;
+
+import org.apache.openaz.xacml.api.Identifier;
+import org.apache.openaz.xacml.std.IdentifierImpl;
+import com.vaadin.data.util.converter.Converter;
+
+
+public class IdentifierConverter implements Converter<Object, Identifier> {
+	private static final long serialVersionUID = 1L;
+
+	@Override
+	public Identifier convertToModel(Object value,
+			Class<? extends Identifier> targetType, Locale locale)
+			throws Converter.ConversionException {
+		return new IdentifierImpl(value.toString());
+	}
+
+	@Override
+	public Object convertToPresentation(Identifier value,
+			Class<? extends Object> targetType, Locale locale)
+			throws Converter.ConversionException {
+		if (targetType.isInstance(String.class) ||
+			targetType.getName().equals(String.class.getName())) {
+			return value.stringValue();
+		}
+		return null;
+	}
+
+	@Override
+	public Class<Identifier> getModelType() {
+		return Identifier.class;
+	}
+
+	@Override
+	public Class<Object> getPresentationType() {
+		return Object.class;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/a1d93100/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/XacmlConverterFactory.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/XacmlConverterFactory.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/XacmlConverterFactory.java
new file mode 100644
index 0000000..32fb8bf
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/converters/XacmlConverterFactory.java
@@ -0,0 +1,83 @@
+/*
+ *  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.converters;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.openaz.xacml.admin.jpa.Category;
+import org.apache.openaz.xacml.admin.jpa.ConstraintType;
+import org.apache.openaz.xacml.admin.jpa.ConstraintValue;
+import org.apache.openaz.xacml.admin.jpa.Datatype;
+import org.apache.openaz.xacml.api.Identifier;
+import com.vaadin.data.util.converter.Converter;
+import com.vaadin.data.util.converter.DefaultConverterFactory;
+
+public class XacmlConverterFactory extends DefaultConverterFactory {
+	private static final long serialVersionUID = 1L;
+	private static final Log logger	= LogFactory.getLog(XacmlConverterFactory.class);
+	
+    @SuppressWarnings("unchecked")
+	@Override
+    public <PRESENTATION, MODEL> Converter<PRESENTATION, MODEL>
+            createConverter(Class<PRESENTATION> presentationType,
+                            Class<MODEL> modelType) {
+    	if (logger.isTraceEnabled()) {
+    		logger.trace("createConverter: " + presentationType + " from model " + modelType);
+    	}
+    	//
+        // Handle one particular type conversion for Categories
+    	//
+        if (Category.class == modelType) {
+            return (Converter<PRESENTATION, MODEL>) new CategoryConverter();
+        }
+        //
+        // Handle one particular type conversion for Datatypes
+        //
+        if (Datatype.class == modelType) {
+            return (Converter<PRESENTATION, MODEL>) new DatatypeConverter();
+        }
+        //
+        // Handle one particular type conversion for ConstraintType
+        //
+        if (ConstraintType.class == modelType) {
+        	return (Converter<PRESENTATION, MODEL>) new ConstraintTypeConverter();
+        }
+        //
+        // Handle one particular type conversion for ConstraintType
+        //
+        if (ConstraintValue.class == modelType) {
+        	return (Converter<PRESENTATION, MODEL>) new ConstraintValueConverter();
+        }
+        //
+        // Handle one particular type conversion for Identifiers
+        //
+        if (Identifier.class == modelType) {
+        	return (Converter<PRESENTATION, MODEL>) new IdentifierConverter();
+        }
+        //
+        // Default to the supertype
+        //
+        return super.createConverter(presentationType,
+                                     modelType);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/a1d93100/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/jpa/Attribute.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/jpa/Attribute.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/jpa/Attribute.java
new file mode 100644
index 0000000..84ec82a
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/jpa/Attribute.java
@@ -0,0 +1,327 @@
+/*
+ *  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.jpa;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.persistence.Transient;
+
+import org.apache.openaz.xacml.api.Identifier;
+import org.apache.openaz.xacml.std.IdentifierImpl;
+
+
+/**
+ * The persistent class for the Attribute database table.
+ * 
+ */
+@Entity
+@Table(name="Attribute")
+@NamedQuery(name="Attribute.findAll", query="SELECT a FROM Attribute a")
+public class Attribute implements Serializable {
+	private static final long serialVersionUID = 1L;
+	
+	public static String	ATTRIBUTE_DESIGNATOR = "Attribute Designator";
+	public static String	ATTRIBUTE_SELECTOR = "Attribute Selector";
+
+	@Id
+	@GeneratedValue(strategy = GenerationType.AUTO)
+	@Column(name="id")
+	private int id;
+
+	//bi-directional many-to-one association to Category
+	@ManyToOne
+	@JoinColumn(name="constraint_type", nullable=true)
+	private ConstraintType constraintType;
+
+	@Column(name="created_by", nullable=false, length=255)
+	private String createdBy = "guest";
+
+	@Temporal(TemporalType.TIMESTAMP)
+	@Column(name="created_date", updatable=false)
+	private Date createdDate;
+
+	@Column(name="description", nullable=true, length=2048)
+	private String description;
+
+	@Column(name="modified_by", nullable=false, length=255)
+	private String modifiedBy = "guest";
+
+	@Temporal(TemporalType.TIMESTAMP)
+	@Column(name="modified_date", nullable=false)
+	private Date modifiedDate;
+
+	@Column(name="xacml_id", nullable=false)
+	private String xacmlId = "urn";
+
+	//bi-directional many-to-one association to ConstraintValue
+	@OneToMany(mappedBy="attribute", orphanRemoval=true, cascade=CascadeType.REMOVE)
+	private Set<ConstraintValue> constraintValues = new HashSet<ConstraintValue>();
+
+	//bi-directional many-to-one association to Category
+	@ManyToOne
+	@JoinColumn(name="category")
+	private Category categoryBean;
+
+	//bi-directional many-to-one association to Datatype
+	@ManyToOne
+	@JoinColumn(name="datatype")
+	private Datatype datatypeBean;
+
+	@Column(name="is_designator", nullable=false)
+	private char isDesignator = '1';
+
+	@Column(name="selector_path", nullable=true, length=2048)
+	private String selectorPath;
+	
+	@Transient
+	private String issuer = null;
+	
+	@Transient
+	private boolean mustBePresent = false;
+
+	public Attribute() {
+	}
+	
+	public Attribute(String domain) {
+		this.xacmlId = domain;
+	}
+	
+	public Attribute(String domain, String user) {
+		this(domain);
+		this.createdBy = user;
+		this.modifiedBy = user;
+	}
+	public Attribute(Attribute copy, String user) {
+		this(copy.getXacmlId() + ":(0)", user);
+		this.constraintType = copy.getConstraintType();
+		this.categoryBean = copy.getCategoryBean();
+		this.datatypeBean = copy.getDatatypeBean();
+		this.description = copy.getDescription();
+		for (ConstraintValue value : copy.getConstraintValues()) {
+			ConstraintValue newValue = new ConstraintValue(value);
+			newValue.setAttribute(this);
+			this.addConstraintValue(newValue);
+		}
+	}
+
+	@PrePersist
+	public void	prePersist() {
+		Date date = new Date();
+		this.createdDate = date;
+		this.modifiedDate = date;
+	}
+	
+	@PreUpdate
+	public void preUpdate() {
+		this.modifiedDate = new Date();
+	}
+
+	public int getId() {
+		return this.id;
+	}
+
+	public void setId(int id) {
+		this.id = id;
+	}
+
+	public ConstraintType getConstraintType() {
+		return this.constraintType;
+	}
+
+	public void setConstraintType(ConstraintType constraintType) {
+		this.constraintType = constraintType;
+	}
+
+	public String getCreatedBy() {
+		return this.createdBy;
+	}
+
+	public void setCreatedBy(String createdBy) {
+		this.createdBy = createdBy;
+	}
+
+	public Date getCreatedDate() {
+		return this.createdDate;
+	}
+
+	public void setCreatedDate(Date createdDate) {
+		this.createdDate = createdDate;
+	}
+
+	public String getDescription() {
+		return this.description;
+	}
+
+	public void setDescription(String description) {
+		this.description = description;
+	}
+
+	public String getModifiedBy() {
+		return this.modifiedBy;
+	}
+
+	public void setModifiedBy(String modifiedBy) {
+		this.modifiedBy = modifiedBy;
+	}
+
+	public Date getModifiedDate() {
+		return this.modifiedDate;
+	}
+
+	public void setModifiedDate(Date modifiedDate) {
+		this.modifiedDate = modifiedDate;
+	}
+
+	public String getXacmlId() {
+		return this.xacmlId;
+	}
+	
+	@Transient
+	public Identifier getXacmlIdentifier() {
+		return new IdentifierImpl(this.xacmlId);
+	}
+
+	public void setXacmlId(String xacmlId) {
+		this.xacmlId = xacmlId;
+	}
+
+	public Set<ConstraintValue> getConstraintValues() {
+		return this.constraintValues;
+	}
+
+	public void setConstraintValues(Set<ConstraintValue> constraintValues) {
+		for (ConstraintValue value : this.constraintValues) {
+			value.setAttribute(this);
+		}
+		this.constraintValues = constraintValues;
+	}
+
+	public ConstraintValue addConstraintValue(ConstraintValue constraintValue) {
+		if (this.constraintValues == null) {
+			this.constraintValues = new HashSet<ConstraintValue>();
+		}
+		this.constraintValues.add(constraintValue);
+		constraintValue.setAttribute(this);
+
+		return constraintValue;
+	}
+
+	public ConstraintValue removeConstraintValue(ConstraintValue constraintValue) {
+		this.constraintValues.remove(constraintValue);
+		constraintValue.setAttribute(null);
+
+		return constraintValue;
+	}
+	
+	public void removeAllConstraintValues() {
+		if (this.constraintValues == null) {
+			return;
+		}
+		for (ConstraintValue value : this.constraintValues) {
+			value.setAttribute(null);
+		}
+		this.constraintValues.clear();
+	}
+
+	public Category getCategoryBean() {
+		return this.categoryBean;
+	}
+
+	public void setCategoryBean(Category categoryBean) {
+		this.categoryBean = categoryBean;
+	}
+
+	public Datatype getDatatypeBean() {
+		return this.datatypeBean;
+	}
+
+	public void setDatatypeBean(Datatype datatypeBean) {
+		this.datatypeBean = datatypeBean;
+	}
+
+	public char getIsDesignator() {
+		return this.isDesignator;
+	}
+	
+	public void setIsDesignator(char is) {
+		this.isDesignator = is;
+	}
+	
+	public String getSelectorPath() {
+		return this.selectorPath;
+	}
+	
+	public void setSelectorPath(String path) {
+		this.selectorPath = path;
+	}
+	
+	@Transient
+	public String getIssuer() {
+		return issuer;
+	}
+
+	@Transient
+	public void setIssuer(String issuer) {
+		this.issuer = issuer;
+	}
+
+	@Transient
+	public boolean isMustBePresent() {
+		return mustBePresent;
+	}
+
+	@Transient
+	public void setMustBePresent(boolean mustBePresent) {
+		this.mustBePresent = mustBePresent;
+	}
+
+	@Transient
+	public boolean isDesignator() {
+		return this.isDesignator == '1';
+	}
+	
+	@Transient
+	public void setIsDesignator(boolean is) {
+		if (is) {
+			this.isDesignator = '1';
+		} else {
+			this.isDesignator = '0';
+		}
+	}
+}