| /* |
| * 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; |
| } |
| } |