summaryrefslogtreecommitdiff
path: root/java/src/IceGridGUI/Application/Root.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/IceGridGUI/Application/Root.java')
-rw-r--r--java/src/IceGridGUI/Application/Root.java1533
1 files changed, 1533 insertions, 0 deletions
diff --git a/java/src/IceGridGUI/Application/Root.java b/java/src/IceGridGUI/Application/Root.java
new file mode 100644
index 00000000000..ba8f7e6c675
--- /dev/null
+++ b/java/src/IceGridGUI/Application/Root.java
@@ -0,0 +1,1533 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceGridGUI.Application;
+
+import java.awt.Component;
+import java.awt.Cursor;
+
+import javax.swing.JOptionPane;
+import javax.swing.JPopupMenu;
+import javax.swing.JTree;
+import javax.swing.SwingUtilities;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreePath;
+
+import java.io.File;
+
+import java.util.Enumeration;
+
+import IceGrid.*;
+import IceGridGUI.*;
+
+public class Root extends ListTreeNode
+{
+ //
+ // Construct a normal, existing Application
+ //
+ public Root(Coordinator coordinator, ApplicationDescriptor desc, boolean live, File file)
+ throws UpdateFailedException
+ {
+ super(false, null, desc.name);
+ _coordinator = coordinator;
+ _traceSaveToRegistry = coordinator.traceSaveToRegistry();
+
+ _descriptor = desc;
+
+ _file = file;
+ _live = live;
+
+
+ init();
+ }
+
+ //
+ // Construct a new Application
+ //
+ public Root(Coordinator coordinator, ApplicationDescriptor desc)
+ {
+ super(true, null, desc.name);
+ _coordinator = coordinator;
+ _traceSaveToRegistry = coordinator.traceSaveToRegistry();
+ _descriptor = desc;
+
+ _file = null;
+ _live = false;
+
+ try
+ {
+ init();
+ }
+ catch(UpdateFailedException e)
+ {
+ //
+ // Impossible
+ //
+ assert false;
+ }
+ }
+
+ private void init()
+ throws UpdateFailedException
+ {
+ _resolver = new Utils.Resolver(_descriptor.variables);
+ _resolver.put("application", _descriptor.name);
+
+ _origVariables = _descriptor.variables;
+ _origDescription = _descriptor.description;
+ _origDistrib = (DistributionDescriptor)_descriptor.distrib.clone();
+
+ _propertySets = new PropertySets(this, _descriptor.propertySets);
+ _replicaGroups = new ReplicaGroups(this, _descriptor.replicaGroups);
+ _serviceTemplates = new ServiceTemplates(this, _descriptor.serviceTemplates);
+ _serverTemplates = new ServerTemplates(this, _descriptor.serverTemplates);
+ _nodes = new Nodes(this, _descriptor.nodes);
+
+ _children.add(_nodes);
+ _children.add(_propertySets);
+ _children.add(_replicaGroups);
+ _children.add(_serverTemplates);
+ _children.add(_serviceTemplates);
+
+ _tree = new JTree(this, true);
+ _treeModel = (DefaultTreeModel)_tree.getModel();
+
+ //
+ // Rebind "copy" and "paste"
+ //
+ javax.swing.ActionMap am = _tree.getActionMap();
+ am.put("copy", _coordinator.getActionsForMenu().get(COPY));
+ am.put("paste", _coordinator.getActionsForMenu().get(PASTE));
+ }
+
+ static public ApplicationDescriptor
+ copyDescriptor(ApplicationDescriptor ad)
+ {
+ ApplicationDescriptor copy = (ApplicationDescriptor)ad.clone();
+
+ copy.propertySets = PropertySets.copyDescriptors(copy.propertySets);
+
+ copy.replicaGroups = ReplicaGroups.copyDescriptors(copy.replicaGroups);
+
+ copy.serverTemplates = ServerTemplates.copyDescriptors(copy.serverTemplates);
+
+ copy.serviceTemplates = ServiceTemplates.copyDescriptors(copy.serviceTemplates);
+
+ copy.nodes = Nodes.copyDescriptors(copy.nodes);
+
+ copy.distrib = (DistributionDescriptor)copy.distrib.clone();
+ return copy;
+ }
+
+ public Editor getEditor()
+ {
+ if(_editor == null)
+ {
+ _editor = (ApplicationEditor)getEditor(ApplicationEditor.class, this);
+ }
+ _editor.show(this);
+ return _editor;
+ }
+
+ protected Editor createEditor()
+ {
+ return new ApplicationEditor();
+ }
+
+ public TreeNode findNodeLike(TreePath path, boolean exactMatch)
+ {
+ TreeNode result = null;
+ if(path == null)
+ {
+ return null;
+ }
+
+ for(int i = 0; i < path.getPathCount(); ++i)
+ {
+ TreeNode node = (TreeNode)path.getPathComponent(i);
+
+ if(result == null)
+ {
+ if(node.getId().equals(_id))
+ {
+ result = this;
+ }
+ else
+ {
+ return null;
+ }
+ }
+ else
+ {
+ TreeNode newNode = result.findChildLike(node);
+ if(newNode == null)
+ {
+ if(exactMatch)
+ {
+ return null;
+ }
+ else
+ {
+ return result;
+ }
+ }
+ else
+ {
+ result = newNode;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ //
+ // Check that this node is attached to the tree
+ //
+ public boolean hasNode(TreeNode node)
+ {
+ while(node != this)
+ {
+ TreeNode parent = (TreeNode)node.getParent();
+ if(parent == null || parent.getIndex(node) == -1)
+ {
+ return false;
+ }
+ else
+ {
+ node = parent;
+ }
+ }
+ return true;
+ }
+
+ public void setSelectedNode(TreeNode node)
+ {
+ _tree.setSelectionPath(node.getPath());
+ }
+
+ public TreeNode getSelectedNode()
+ {
+ TreePath path = _tree.getSelectionPath();
+ if(path == null)
+ {
+ return null;
+ }
+ else
+ {
+ return (TreeNode)path.getLastPathComponent();
+ }
+ }
+
+ public void selectServer(String nodeName, String serverId)
+ {
+ TreeNode target = _nodes;
+ if(target != null)
+ {
+ Node node = (Node)target.findChild(nodeName);
+ if(node != null)
+ {
+ target = node;
+ Server server = node.findServer(serverId);
+ if(server != null)
+ {
+ target = (TreeNode)server;
+ }
+ }
+ setSelectedNode(target);
+ }
+ }
+
+ public Component getTreeCellRendererComponent(
+ JTree tree,
+ Object value,
+ boolean sel,
+ boolean expanded,
+ boolean leaf,
+ int row,
+ boolean hasFocus)
+ {
+ if(_cellRenderer == null)
+ {
+ _cellRenderer = new DefaultTreeCellRenderer();
+ _cellRenderer.setOpenIcon(Utils.getIcon("/icons/16x16/application_open.png"));
+ _cellRenderer.setClosedIcon(Utils.getIcon("/icons/16x16/application_closed.png"));
+ }
+
+ return _cellRenderer.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
+ }
+
+ public boolean[] getAvailableActions()
+ {
+ boolean[] actions = new boolean[ACTION_COUNT];
+
+ actions[COPY] = true;
+ actions[DELETE] = true;
+
+ Object descriptor = _coordinator.getClipboard();
+ if(descriptor != null)
+ {
+ actions[PASTE] = descriptor instanceof ApplicationDescriptor;
+ }
+
+ actions[SHOW_VARS] = true;
+ actions[SUBSTITUTE_VARS] = true;
+ actions[NEW_NODE] = true;
+ actions[NEW_PROPERTY_SET] = true;
+ actions[NEW_REPLICA_GROUP] = true;
+ actions[NEW_TEMPLATE_SERVER] = true;
+ actions[NEW_TEMPLATE_SERVER_ICEBOX] = true;
+ actions[NEW_TEMPLATE_SERVICE] = true;
+
+ return actions;
+ }
+
+ public JPopupMenu getPopupMenu()
+ {
+ ApplicationActions actions = _coordinator.getActionsForPopup();
+ if(_popup == null)
+ {
+ _popup = new JPopupMenu();
+ _popup.add(actions.get(NEW_NODE));
+ _popup.add(actions.get(NEW_PROPERTY_SET));
+ _popup.add(actions.get(NEW_REPLICA_GROUP));
+ _popup.addSeparator();
+ _popup.add(actions.get(NEW_TEMPLATE_SERVER));
+ _popup.add(actions.get(NEW_TEMPLATE_SERVER_ICEBOX));
+ _popup.addSeparator();
+ _popup.add(actions.get(NEW_TEMPLATE_SERVICE));
+ }
+ actions.setTarget(this);
+ return _popup;
+ }
+
+ public void copy()
+ {
+ _coordinator.setClipboard(copyDescriptor(_descriptor));
+ _coordinator.getActionsForMenu().get(PASTE).setEnabled(true);
+ }
+
+ public void paste()
+ {
+ _coordinator.pasteApplication();
+ }
+
+ public void newNode()
+ {
+ _nodes.newNode();
+ }
+
+ public void newPropertySet()
+ {
+ _propertySets.newPropertySet();
+ }
+
+ public void newReplicaGroup()
+ {
+ _replicaGroups.newReplicaGroup();
+ }
+
+ public void newTemplateServer()
+ {
+ _serverTemplates.newTemplateServer();
+ }
+
+ public void newTemplateServerIceBox()
+ {
+ _serverTemplates.newTemplateServerIceBox();
+ }
+
+ public void newTemplateService()
+ {
+ _serviceTemplates.newTemplateService();
+ }
+
+ public void save()
+ {
+ if(_live)
+ {
+ saveToRegistry();
+ }
+ else if(_file != null)
+ {
+ File file = _coordinator.saveToFile(false, this, _file);
+ if(file != null)
+ {
+ _file = file;
+ commit();
+ _coordinator.getSaveAction().setEnabled(false);
+ _coordinator.getDiscardUpdatesAction().setEnabled(false);
+ }
+ }
+ else
+ {
+ assert false;
+ }
+ }
+
+ public void saveToRegistry()
+ {
+ //
+ // To be run in GUI thread when exclusive write access is acquired
+ //
+ Runnable runnable = new Runnable()
+ {
+ private void release()
+ {
+ _coordinator.releaseExclusiveWriteAccess();
+ _coordinator.getMainFrame().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+ }
+
+ private void handleFailure(String prefix, String title, String message)
+ {
+ release();
+
+ if(isSelected())
+ {
+ _coordinator.getSaveAction().setEnabled(isLive() && _coordinator.connectedToMaster() ||
+ hasFile());
+ _coordinator.getSaveToRegistryAction().setEnabled(true);
+ _coordinator.getDiscardUpdatesAction().setEnabled(true);
+ }
+
+ _coordinator.getStatusBar().setText(prefix + "failed!");
+
+ JOptionPane.showMessageDialog(
+ _coordinator.getMainFrame(),
+ message,
+ title,
+ JOptionPane.ERROR_MESSAGE);
+ }
+
+ public void run()
+ {
+ _coordinator.getMainFrame().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+ boolean asyncRelease = false;
+
+ try
+ {
+ if(_live && _canUseUpdateDescriptor)
+ {
+ ApplicationUpdateDescriptor updateDescriptor = createUpdateDescriptor();
+ if(updateDescriptor != null)
+ {
+ final String prefix = "Updating application '" + _id + "'...";
+ _coordinator.getStatusBar().setText(prefix);
+
+ AMI_Admin_updateApplication cb = new AMI_Admin_updateApplication()
+ {
+ public void ice_response()
+ {
+ if(_traceSaveToRegistry)
+ {
+ _coordinator.traceSaveToRegistry("updateApplication for application " +
+ _id + ": success");
+ }
+
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ commit();
+ release();
+ _coordinator.getStatusBar().setText(prefix + "done.");
+ }
+ });
+ }
+
+ public void ice_exception(final Ice.UserException e)
+ {
+ if(_traceSaveToRegistry)
+ {
+ _coordinator.traceSaveToRegistry("updateApplication for application " +
+ _id + ": failed");
+ }
+
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ _skipUpdates--;
+ handleFailure(prefix, "Update failed",
+ "IceGrid exception: " + e.toString());
+ }
+
+ });
+ }
+
+ public void ice_exception(final Ice.LocalException e)
+ {
+ if(_traceSaveToRegistry)
+ {
+ _coordinator.traceSaveToRegistry("updateApplication for application " +
+ _id + ": failed");
+ }
+
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ _skipUpdates--;
+ handleFailure(prefix, "Update failed",
+ "Communication exception: " + e.toString());
+ }
+ });
+ }
+
+ };
+
+ if(_traceSaveToRegistry)
+ {
+ _coordinator.traceSaveToRegistry("sending updateApplication for application " +
+ _id);
+ }
+
+ _coordinator.getAdmin().updateApplication_async(cb, updateDescriptor);
+ asyncRelease = true;
+
+ //
+ // If updateApplication fails, we know we can't get other updates
+ // since we have exclusive write access
+ //
+ _skipUpdates++;
+ }
+ else
+ {
+ final String prefix = "Application '" + _id + "' is already up-to-date";
+ _coordinator.getStatusBar().setText(prefix);
+ commit();
+ }
+ }
+ else
+ {
+ //
+ // Add or sync application
+ //
+ if(_coordinator.getLiveDeploymentRoot().getApplicationDescriptor(_id) == null)
+ {
+ assert _live == false;
+
+ final String prefix = "Adding application '" + _id + "'...";
+ _coordinator.getStatusBar().setText(prefix);
+
+ AMI_Admin_addApplication cb = new AMI_Admin_addApplication()
+ {
+ public void ice_response()
+ {
+ if(_traceSaveToRegistry)
+ {
+ _coordinator.traceSaveToRegistry("addApplication for application " +
+ _id + ": success");
+ }
+
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ commit();
+ liveReset();
+ _coordinator.addLiveApplication(Root.this);
+ release();
+ _coordinator.getStatusBar().setText(prefix + "done.");
+ }
+ });
+ }
+
+ public void ice_exception(final Ice.UserException e)
+ {
+ if(_traceSaveToRegistry)
+ {
+ _coordinator.traceSaveToRegistry("addApplication for application " +
+ _id + ": failed");
+ }
+
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ handleFailure(prefix, "Add failed",
+ "IceGrid exception: " + e.toString());
+ }
+
+ });
+ }
+
+ public void ice_exception(final Ice.LocalException e)
+ {
+ if(_traceSaveToRegistry)
+ {
+ _coordinator.traceSaveToRegistry("addApplication for application " +
+ _id + ": failed");
+ }
+
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ handleFailure(prefix, "Add failed",
+ "Communication exception: " + e.toString());
+ }
+ });
+ }
+
+ };
+
+ if(_traceSaveToRegistry)
+ {
+ _coordinator.traceSaveToRegistry("sending addApplication for application " + _id);
+ }
+
+ _coordinator.getAdmin().addApplication_async(cb, _descriptor);
+ asyncRelease = true;
+ }
+ else
+ {
+ final String prefix = "Synchronizing application '" + _id + "'...";
+ _coordinator.getStatusBar().setText(prefix);
+
+ AMI_Admin_syncApplication cb = new AMI_Admin_syncApplication()
+ {
+ public void ice_response()
+ {
+ if(_traceSaveToRegistry)
+ {
+ _coordinator.traceSaveToRegistry("syncApplication for application " +
+ _id + ": failed");
+ }
+
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ commit();
+ if(!_live)
+ {
+ //
+ // Make this tab live or close it if there is one already
+ // open
+ //
+ ApplicationPane app = _coordinator.getLiveApplication(_id);
+ if(app == null)
+ {
+ liveReset();
+ _coordinator.addLiveApplication(Root.this);
+ }
+ else
+ {
+ boolean selected = isSelected();
+ _coordinator.getMainPane().removeApplication(Root.this);
+ if(selected)
+ {
+ _coordinator.getMainPane()
+ .setSelectedComponent(app);
+ }
+ }
+ }
+
+ release();
+ _coordinator.getStatusBar().setText(prefix + "done.");
+ }
+ });
+ }
+
+ public void ice_exception(final Ice.UserException e)
+ {
+ if(_traceSaveToRegistry)
+ {
+ _coordinator.traceSaveToRegistry("syncApplication for application " +
+ _id + ": failed");
+ }
+
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ if(_live)
+ {
+ _skipUpdates--;
+ }
+
+ handleFailure(prefix, "Sync failed",
+ "IceGrid exception: " + e.toString());
+ }
+
+ });
+ }
+
+ public void ice_exception(final Ice.LocalException e)
+ {
+ if(_traceSaveToRegistry)
+ {
+ _coordinator.traceSaveToRegistry("syncApplication for application " +
+ _id + ": failed");
+ }
+
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ if(_live)
+ {
+ _skipUpdates--;
+ }
+
+ handleFailure(prefix, "Sync failed",
+ "Communication exception: " + e.toString());
+ }
+ });
+ }
+
+ };
+
+ if(_traceSaveToRegistry)
+ {
+ _coordinator.traceSaveToRegistry("sending syncApplication for application " + _id);
+ }
+
+ _coordinator.getAdmin().syncApplication_async(cb, _descriptor);
+ asyncRelease = true;
+ if(_live)
+ {
+ _skipUpdates++;
+ }
+ }
+ }
+ if(isSelected())
+ {
+ _coordinator.getSaveAction().setEnabled(false);
+ _coordinator.getSaveToRegistryAction().setEnabled(false);
+ _coordinator.getDiscardUpdatesAction().setEnabled(false);
+ }
+ }
+ catch(Ice.LocalException e)
+ {
+ if(_traceSaveToRegistry)
+ {
+ _coordinator.traceSaveToRegistry("Ice communications exception while saving application " +
+ _id);
+ }
+
+ JOptionPane.showMessageDialog(
+ _coordinator.getMainFrame(),
+ e.toString(),
+ "Communication Exception",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ finally
+ {
+ if(!asyncRelease)
+ {
+ _coordinator.getMainFrame().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+ _coordinator.releaseExclusiveWriteAccess();
+ }
+ }
+ }
+ };
+
+ try
+ {
+ _coordinator.acquireExclusiveWriteAccess(runnable);
+ }
+ catch(AccessDeniedException e)
+ {
+ _coordinator.accessDenied(e);
+ }
+ catch(Ice.LocalException e)
+ {
+ JOptionPane.showMessageDialog(
+ _coordinator.getMainFrame(),
+ e.toString(),
+ "Communication Exception",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+ public void saveToFile()
+ {
+ File file = _coordinator.saveToFile(true, this, _file);
+ if(file != null)
+ {
+ _file = file;
+ _live = false;
+
+ _coordinator.removeLiveApplication(_id);
+ _coordinator.getMainPane().resetIcon(this);
+
+ commit();
+ _coordinator.getSaveAction().setEnabled(false);
+ _coordinator.getDiscardUpdatesAction().setEnabled(false);
+ _coordinator.getSaveToRegistryAction().setEnabled(_coordinator.connectedToMaster());
+ }
+ }
+
+ public void discardUpdates()
+ {
+ ApplicationDescriptor desc = null;
+
+ if(_live)
+ {
+ desc = _coordinator.getLiveDeploymentRoot().getApplicationDescriptor(_id);
+ assert desc != null;
+ desc = IceGridGUI.Application.Root.copyDescriptor(desc);
+ }
+ else if(_file != null)
+ {
+ desc = _coordinator.parseFile(_file);
+ if(desc == null)
+ {
+ return;
+ }
+ }
+ else
+ {
+ assert false;
+ }
+
+ Root newRoot;
+
+ try
+ {
+ newRoot = new Root(_coordinator, desc, _live, _file);
+ }
+ catch(UpdateFailedException e)
+ {
+ JOptionPane.showMessageDialog(
+ _coordinator.getMainFrame(),
+ e.toString(),
+ "Bad Application Descriptor: Unable reload Application",
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ ApplicationPane app = _coordinator.getMainPane().findApplication(this);
+ assert app != null;
+ app.setRoot(newRoot);
+
+ TreeNode node = newRoot.findNodeLike(_tree.getSelectionPath(), false);
+ if(node == null)
+ {
+ newRoot.setSelectedNode(newRoot);
+ }
+ else
+ {
+ newRoot.setSelectedNode(node);
+ }
+ _coordinator.getCurrentTab().selected();
+ }
+
+ private void liveReset()
+ {
+ _live = true;
+ _skipUpdates = 0;
+ _file = null;
+ _coordinator.getMainPane().resetIcon(this);
+ }
+
+ private ApplicationUpdateDescriptor createUpdateDescriptor()
+ {
+ ApplicationUpdateDescriptor update = new ApplicationUpdateDescriptor();
+ update.name = _descriptor.name;
+ if(_editable.isModified())
+ {
+ //
+ // Diff description
+ //
+ if(!_descriptor.description.equals(_origDescription))
+ {
+ update.description = new IceGrid.BoxedString(_descriptor.description);
+ }
+
+ //
+ // Diff variables
+ //
+ update.variables = new java.util.TreeMap<String, String>(_descriptor.variables);
+ java.util.List<String> removeVariables = new java.util.LinkedList<String>();
+
+ for(java.util.Map.Entry<String, String> p : _origVariables.entrySet())
+ {
+ String key = p.getKey();
+ String newValue = update.variables.get(key);
+ if(newValue == null)
+ {
+ removeVariables.add(key);
+ }
+ else
+ {
+ String value = p.getValue();
+ if(newValue.equals(value))
+ {
+ update.variables.remove(key);
+ }
+ }
+ }
+ update.removeVariables = removeVariables.toArray(new String[0]);
+
+ //
+ // Diff distribution
+ //
+ if(!_descriptor.distrib.equals(_origDistrib))
+ {
+ update.distrib = new IceGrid.BoxedDistributionDescriptor(_descriptor.distrib);
+ }
+ }
+ else
+ {
+ update.variables = new java.util.TreeMap<String, String>();
+ update.removeVariables = new String[0];
+ }
+
+ //
+ // Property sets
+ //
+ update.removePropertySets = _propertySets.getEditable().removedElements(PropertySet.class);
+ update.propertySets = _propertySets.getUpdates();
+
+ //
+ // Replica Groups
+ //
+ update.removeReplicaGroups = _replicaGroups.getEditable().removedElements(ReplicaGroup.class);
+ update.replicaGroups = _replicaGroups.getUpdates();
+
+ //
+ // Server Templates
+ //
+ update.removeServerTemplates = _serverTemplates.getEditable().removedElements(ServerTemplate.class);
+ update.serverTemplates = _serverTemplates.getUpdates();
+
+ //
+ // Service Templates
+ //
+ update.removeServiceTemplates = _serviceTemplates.getEditable().removedElements(ServiceTemplate.class);
+ update.serviceTemplates =_serviceTemplates.getUpdates();
+
+ //
+ // Nodes
+ //
+ update.removeNodes = _nodes.getEditable().removedElements(Node.class);
+ update.nodes = _nodes.getUpdates();
+
+ //
+ // Return null if nothing changed
+ //
+ if(!_editable.isModified() &&
+ update.removePropertySets.length == 0 &&
+ update.propertySets.size() == 0 &&
+ update.removeReplicaGroups.length == 0 &&
+ update.replicaGroups.size() == 0 &&
+ update.removeServerTemplates.length == 0 &&
+ update.serverTemplates.size() == 0 &&
+ update.removeServiceTemplates.length == 0 &&
+ update.serviceTemplates.size() == 0 &&
+ update.removeNodes.length == 0 &&
+ update.nodes.size() == 0)
+ {
+ return null;
+ }
+ else
+ {
+ return update;
+ }
+ }
+
+ private void commit()
+ {
+ _updated = false;
+ _registryUpdatesEnabled = true;
+ _canUseUpdateDescriptor = true;
+
+ assert _concurrentUpdates.size() == 0;
+
+ _editable.commit();
+ _origVariables = _descriptor.variables;
+ _origDescription = _descriptor.description;
+ _origDistrib = (DistributionDescriptor)_descriptor.distrib.clone();
+
+ _nodes.commit();
+ _propertySets.commit();
+ _replicaGroups.commit();
+ _serverTemplates.commit();
+ _serviceTemplates.commit();
+ }
+
+ public boolean isEphemeral()
+ {
+ return false;
+ }
+
+ public void destroy()
+ {
+ if(!_live && _file == null)
+ {
+ _coordinator.getMainPane().removeApplication(this);
+ }
+ else if(_live)
+ {
+ int confirm = JOptionPane.showConfirmDialog(
+ _coordinator.getMainFrame(),
+ "You are about to remove application '" + _id + "' from the IceGrid registry. "
+ + "Do you want to proceed?",
+ "Remove Confirmation",
+ JOptionPane.YES_NO_OPTION);
+
+ if(confirm == JOptionPane.YES_OPTION)
+ {
+ _coordinator.removeApplicationFromRegistry(_id);
+ _discardMe = true;
+ }
+ }
+ else
+ {
+ assert _file != null;
+
+ int confirm = JOptionPane.showConfirmDialog(
+ _coordinator.getMainFrame(),
+ "You are about to remove application '" + _id + "' and its associated file. "
+ + "Do you want to proceed?",
+ "Remove Confirmation",
+ JOptionPane.YES_NO_OPTION);
+
+ if(confirm == JOptionPane.YES_OPTION)
+ {
+ if(_file.delete())
+ {
+ _coordinator.getMainPane().removeApplication(this);
+ }
+ }
+ }
+ }
+
+ public boolean update(ApplicationUpdateDescriptor desc)
+ {
+ assert _live == true;
+
+ if(_skipUpdates > 0)
+ {
+ _skipUpdates--;
+ return false;
+ }
+
+ if(!_registryUpdatesEnabled)
+ {
+ if(_updated)
+ {
+ _canUseUpdateDescriptor = false;
+ }
+ else
+ {
+ _concurrentUpdates.add(desc);
+ }
+ return false;
+ }
+
+ try
+ {
+ //
+ // Description
+ //
+ if(desc.description != null)
+ {
+ _descriptor.description = desc.description.value;
+ _origDescription = _descriptor.description;
+ }
+
+ //
+ // Variables
+ //
+ for(String name : desc.removeVariables)
+ {
+ _descriptor.variables.remove(name);
+ }
+ _descriptor.variables.putAll(desc.variables);
+
+ //
+ // Distrib
+ //
+ if(desc.distrib != null)
+ {
+ _descriptor.distrib = desc.distrib.value;
+ _origDistrib = (DistributionDescriptor)_descriptor.distrib.clone();
+ }
+
+ //
+ // Property Sets
+ //
+ for(String id : desc.removePropertySets)
+ {
+ _descriptor.propertySets.remove(id);
+ }
+ _descriptor.propertySets.putAll(desc.propertySets);
+ _propertySets.update(desc.propertySets, desc.removePropertySets);
+
+ //
+ // Replica groups
+ //
+ for(String id : desc.removeReplicaGroups)
+ {
+ _descriptor.replicaGroups.remove(id);
+ }
+ _descriptor.replicaGroups.addAll(desc.replicaGroups);
+ _replicaGroups.update(desc.replicaGroups, desc.removeReplicaGroups);
+
+ //
+ // Service templates
+ //
+ for(String id : desc.removeServiceTemplates)
+ {
+ _descriptor.serviceTemplates.remove(id);
+ }
+ _descriptor.serviceTemplates.putAll(desc.serviceTemplates);
+ _serviceTemplates.update(desc.serviceTemplates, desc.removeServiceTemplates);
+
+ //
+ // Server templates
+ //
+ for(String id : desc.removeServerTemplates)
+ {
+ _descriptor.serverTemplates.remove(id);
+ }
+ _descriptor.serverTemplates.putAll(desc.serverTemplates);
+ _serverTemplates.update(desc.serverTemplates, desc.removeServerTemplates, desc.serviceTemplates.keySet());
+
+ //
+ // Nodes
+ //
+ for(String id : desc.removeNodes)
+ {
+ _descriptor.nodes.remove(id);
+ }
+
+ //
+ // Updates also _descriptor.nodes
+ //
+ _nodes.update(desc.nodes, desc.removeNodes, desc.serverTemplates.keySet(), desc.serviceTemplates.keySet());
+ }
+ catch(UpdateFailedException e)
+ {
+ //
+ // Received invalid update from IceGrid registry: a bug!
+ //
+ assert false;
+ }
+
+ return true;
+ }
+
+ public JTree getTree()
+ {
+ return _tree;
+ }
+
+ public DefaultTreeModel getTreeModel()
+ {
+ return _treeModel;
+ }
+
+ public Coordinator getCoordinator()
+ {
+ return _coordinator;
+ }
+
+ public boolean isSelectionListenerEnabled()
+ {
+ return _selectionListenerEnabled;
+ }
+
+ public void enableSelectionListener()
+ {
+ _selectionListenerEnabled = true;
+ }
+
+ public void disableSelectionListener()
+ {
+ _selectionListenerEnabled = false;
+ }
+
+ public void cancelEdit()
+ {
+ if(!_updated)
+ {
+ _registryUpdatesEnabled = true;
+
+ //
+ // Apply now any delayed concurrent update
+ //
+ for(ApplicationUpdateDescriptor p : _concurrentUpdates)
+ {
+ boolean ok = update(p);
+ assert ok;
+ }
+ if(!_concurrentUpdates.isEmpty())
+ {
+ _applicationPane.refresh();
+ _concurrentUpdates.clear();
+ }
+
+ _coordinator.getSaveAction().setEnabled(false);
+ _coordinator.getDiscardUpdatesAction().setEnabled(false);
+ _coordinator.getSaveToRegistryAction().setEnabled(hasFile() && _coordinator.connectedToMaster());
+ }
+ }
+
+ public boolean kill()
+ {
+ _live = false;
+
+ if(_registryUpdatesEnabled || _discardMe)
+ {
+ return true;
+ }
+ else
+ {
+ _coordinator.getMainPane().resetIcon(this);
+ _coordinator.getCurrentTab().selected(); // only needed when 'this' corresponds to the current tab
+ return false;
+ }
+ }
+
+ public boolean isLive()
+ {
+ return _live;
+ }
+
+ public boolean hasFile()
+ {
+ return _file != null;
+ }
+
+ public boolean needsSaving()
+ {
+ return _updated || !_registryUpdatesEnabled;
+ }
+
+ public void setPane(ApplicationPane app)
+ {
+ _applicationPane = app;
+ }
+
+ public ApplicationPane getPane()
+ {
+ return _applicationPane;
+ }
+
+ Editor getEditor(Class c, TreeNode node)
+ {
+ Editor result = _editorMap.get(c);
+ if(result == null)
+ {
+ result = node.createEditor();
+ _editorMap.put(c, result);
+ }
+ return result;
+ }
+
+ Object getDescriptor()
+ {
+ return _descriptor;
+ }
+
+ ApplicationDescriptor saveDescriptor()
+ {
+ ApplicationDescriptor clone = (ApplicationDescriptor)_descriptor.clone();
+ clone.distrib = (IceGrid.DistributionDescriptor)clone.distrib.clone();
+ return clone;
+ }
+
+ void restoreDescriptor(ApplicationDescriptor clone)
+ {
+ _descriptor.name = clone.name;
+ _descriptor.variables = clone.variables;
+ _descriptor.distrib.icepatch = clone.distrib.icepatch;
+ _descriptor.distrib.directories = clone.distrib.directories;
+ _descriptor.description = clone.description;
+ }
+
+ public void write(XMLWriter writer)
+ throws java.io.IOException
+ {
+ writer.writeStartTag("icegrid");
+
+ java.util.List<String[]> attributes = new java.util.LinkedList<String[]>();
+ attributes.add(createAttribute("name", _id));
+
+ writer.writeStartTag("application", attributes);
+
+ if(_descriptor.description.length() > 0)
+ {
+ writer.writeElement("description", _descriptor.description);
+ }
+ writeVariables(writer, _descriptor.variables);
+ writeDistribution(writer, _descriptor.distrib);
+
+ _serviceTemplates.write(writer);
+ _serverTemplates.write(writer);
+ _replicaGroups.write(writer);
+ _propertySets.write(writer);
+ _nodes.write(writer);
+
+ writer.writeEndTag("application");
+ writer.writeEndTag("icegrid");
+ }
+
+ //
+ // Methods called by editors; see also cancelEdit() above
+ //
+ void disableRegistryUpdates()
+ {
+ if(_registryUpdatesEnabled)
+ {
+ _registryUpdatesEnabled = false;
+ _coordinator.getSaveAction().setEnabled(_live && _coordinator.connectedToMaster() || _file != null);
+ _coordinator.getDiscardUpdatesAction().setEnabled(_live || _file != null);
+ _coordinator.getSaveToRegistryAction().setEnabled(_coordinator.connectedToMaster());
+ }
+ }
+
+ void updated()
+ {
+ _updated = true;
+ disableRegistryUpdates(); // can be still enabled when updated() is called by destroy()
+
+ _concurrentUpdates.clear();
+ }
+
+ void rebuild()
+ throws UpdateFailedException
+ {
+ Utils.Resolver oldResolver = _resolver;
+ String oldId = _id;
+ _id = _descriptor.name;
+ _resolver = new Utils.Resolver(_descriptor.variables);
+ _resolver.put("application", _id);
+
+ try
+ {
+ _nodes.rebuild();
+ }
+ catch(UpdateFailedException e)
+ {
+ _id = oldId;
+ _resolver = oldResolver;
+ throw e;
+ }
+ }
+
+ //
+ // Called when a server-template is deleted, to remove all
+ // corresponding instances.
+ //
+ void removeServerInstances(String templateId)
+ {
+ _nodes.removeServerInstances(templateId);
+ }
+
+ //
+ // Called when a service-template is deleted, to remove all
+ // corresponding instances
+ //
+ void removeServiceInstances(String templateId)
+ {
+ _nodes.removeServiceInstances(templateId);
+ _serverTemplates.removeServiceInstances(templateId);
+ }
+
+ ServerTemplate findServerTemplate(String id)
+ {
+ return (ServerTemplate)_serverTemplates.findChild(id);
+ }
+
+ ServiceTemplate findServiceTemplate(String id)
+ {
+ return (ServiceTemplate)_serviceTemplates.findChild(id);
+ }
+
+ ReplicaGroup findReplicaGroup(String id)
+ {
+ return (ReplicaGroup)_replicaGroups.findChild(id);
+ }
+
+ Node findNode(String id)
+ {
+ return (Node)_nodes.findChild(id);
+ }
+
+ java.util.List<ServerInstance> findServerInstances(String template)
+ {
+ return _nodes.findServerInstances(template);
+ }
+
+ java.util.List<ServiceInstance> findServiceInstances(String template)
+ {
+ java.util.List<ServiceInstance> result = _serverTemplates.findServiceInstances(template);
+ result.addAll(_nodes.findServiceInstances(template));
+ return result;
+ }
+
+ TemplateDescriptor findServerTemplateDescriptor(String templateName)
+ {
+ return (TemplateDescriptor)_descriptor.serverTemplates.get(templateName);
+ }
+
+ TemplateDescriptor findServiceTemplateDescriptor(String templateName)
+ {
+ return (TemplateDescriptor)_descriptor.serviceTemplates.get(templateName);
+ }
+
+ ServerTemplates getServerTemplates()
+ {
+ return _serverTemplates;
+ }
+
+ ServiceTemplates getServiceTemplates()
+ {
+ return _serviceTemplates;
+ }
+
+ ReplicaGroups getReplicaGroups()
+ {
+ return _replicaGroups;
+ }
+
+ boolean pasteIceBox(IceBoxDescriptor ibd)
+ {
+ //
+ // During paste, check that all service instances refer to existing services,
+ // and remove any extra template parameters
+ //
+ for(ServiceInstanceDescriptor p : ibd.services)
+ {
+ if(p.template.length() > 0)
+ {
+ TemplateDescriptor td = findServiceTemplateDescriptor(p.template);
+
+ if(td == null)
+ {
+ JOptionPane.showMessageDialog(
+ _coordinator.getMainFrame(),
+ "Descriptor refers to undefined service template '" + p.template + "'",
+ "Cannot paste",
+ JOptionPane.ERROR_MESSAGE);
+ return false;
+ }
+
+ p.parameterValues.keySet().retainAll(td.parameters);
+ }
+ }
+ return true;
+ }
+
+ public Root getRoot()
+ {
+ return this;
+ }
+
+ Utils.Resolver getResolver()
+ {
+ return _resolver;
+ }
+
+ //
+ // Should only be used for reading
+ //
+ java.util.Map<String, String> getVariables()
+ {
+ return _descriptor.variables;
+ }
+
+ private boolean isSelected()
+ {
+ if(_coordinator.getCurrentTab() instanceof ApplicationPane)
+ {
+ return ((ApplicationPane)_coordinator.getCurrentTab()).getRoot() == Root.this;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ private final Coordinator _coordinator;
+ private final boolean _traceSaveToRegistry;
+
+ //
+ // 'this' is the root of the tree
+ //
+ private JTree _tree;
+ private DefaultTreeModel _treeModel;
+ private Utils.Resolver _resolver;
+
+ private boolean _live;
+
+ //
+ // null when this application is not tied to a file
+ //
+ private File _file;
+
+ private ApplicationDescriptor _descriptor;
+
+ //
+ // Keeps original version (as shallow copies) to be able to build
+ // ApplicationUpdateDescriptor. Only used when _live == true
+ //
+ private java.util.Map<String, String> _origVariables;
+ private String _origDescription;
+ private DistributionDescriptor _origDistrib;
+
+ //
+ // When this application (and children) is being updated, we
+ // no longer apply updates from the registry. Only meaningful when
+ // _live == true
+ //
+ private boolean _registryUpdatesEnabled = true;
+
+ private boolean _discardMe = false;
+
+ //
+ // True when any update was applied to this application
+ // (including children)
+ //
+ private boolean _updated = false;
+
+ //
+ // Updates saved when _updated == false and
+ // _registryUpdatesEnabled == false
+ //
+ private java.util.List<ApplicationUpdateDescriptor> _concurrentUpdates =
+ new java.util.LinkedList<ApplicationUpdateDescriptor>();
+
+ //
+ // When _live is true and _canUseUpdateDescriptor is true, we can
+ // save the updates using an ApplicationUpdateDescriptor
+ //
+ private boolean _canUseUpdateDescriptor = true;
+ //
+ // Updates to skip (because already applied locally)
+ //
+ private int _skipUpdates = 0;
+
+ private Nodes _nodes;
+ private PropertySets _propertySets;
+ private ReplicaGroups _replicaGroups;
+ private ServerTemplates _serverTemplates;
+ private ServiceTemplates _serviceTemplates;
+
+ private boolean _selectionListenerEnabled = true;
+
+ private ApplicationEditor _editor;
+
+ //
+ // Map editor-class to Editor object
+ //
+ private java.util.Map<Class, Editor> _editorMap = new java.util.HashMap<Class, Editor>();
+
+ private ApplicationPane _applicationPane;
+
+ static private DefaultTreeCellRenderer _cellRenderer;
+ static private JPopupMenu _popup;
+}