| | |
| | | /** |
| | | * The mask used to display the number of ACIs or not. |
| | | */ |
| | | public final static int DISPLAY_ACI_COUNT = 0x01; |
| | | private static final int DISPLAY_ACI_COUNT = 0x01; |
| | | |
| | | /** |
| | | * The list of attributes that are used to sort the entries (if the sorting |
| | | * option is used). |
| | | */ |
| | | public static final String[] SORT_ATTRIBUTES = {"cn", "givenname", "o", "ou", |
| | | "sn", "uid"}; |
| | | private static final String[] SORT_ATTRIBUTES = |
| | | { "cn", "givenname", "o", "ou", "sn", "uid" }; |
| | | |
| | | /** |
| | | * This is a key value. It is used to specify that the attribute that should |
| | | * be used to display the entry is the RDN attribute. |
| | | */ |
| | | public static final String RDN_ATTRIBUTE = "rdn attribute"; |
| | | private static final String RDN_ATTRIBUTE = "rdn attribute"; |
| | | |
| | | /** |
| | | * The filter used to retrieve all the entries. |
| | |
| | | public static final String ALL_OBJECTS_FILTER = |
| | | "(|(objectClass=*)(objectClass=ldapsubentry))"; |
| | | |
| | | private JTree tree; |
| | | private DefaultTreeModel treeModel; |
| | | private RootNode rootNode; |
| | | private final JTree tree; |
| | | private final DefaultTreeModel treeModel; |
| | | private final RootNode rootNode; |
| | | private int displayFlags; |
| | | private String displayAttribute; |
| | | private boolean showAttributeName; |
| | | private final boolean showAttributeName; |
| | | private InitialLdapContext ctxConfiguration; |
| | | private InitialLdapContext ctxUserData; |
| | | private boolean followReferrals; |
| | |
| | | private NumSubordinateHacker numSubordinateHacker; |
| | | private int queueTotalSize; |
| | | private int maxChildren = 0; |
| | | private Collection<BrowserEventListener> listeners = |
| | | private final Collection<BrowserEventListener> listeners = |
| | | new ArrayList<BrowserEventListener>(); |
| | | private LDAPConnectionPool connectionPool; |
| | | private IconPool iconPool; |
| | | private final LDAPConnectionPool connectionPool; |
| | | private final IconPool iconPool; |
| | | |
| | | private NodeSearcherQueue refreshQueue; |
| | | private final NodeSearcherQueue refreshQueue; |
| | | |
| | | private String filter; |
| | | |
| | |
| | | tree.addTreeExpansionListener(this); |
| | | tree.setCellRenderer(new BrowserCellRenderer()); |
| | | displayFlags = DISPLAY_ACI_COUNT; |
| | | showAttributeName = false; |
| | | displayAttribute = RDN_ATTRIBUTE; |
| | | followReferrals = false; |
| | | sorted = false; |
| | |
| | | } |
| | | |
| | | /** |
| | | * Tells wether the given suffix is in the tree or not. |
| | | * Tells whether the given suffix is in the tree or not. |
| | | * @param suffixDn the DN of the suffix to be analyzed. |
| | | * @return <CODE>true</CODE> if the provided String is the DN of a suffix |
| | | * and <CODE>false</CODE> otherwise. |
| | | * @throws IllegalArgumentException if a node with the given dn exists but |
| | | * is not a suffix node. |
| | | */ |
| | | public boolean hasSuffix(String suffixDn) |
| | | throws IllegalArgumentException |
| | | public boolean hasSuffix(String suffixDn) throws IllegalArgumentException |
| | | { |
| | | return (findSuffixNode(suffixDn, rootNode) != null); |
| | | return findSuffixNode(suffixDn, rootNode) != null; |
| | | } |
| | | |
| | | /** |
| | |
| | | return new TreePath(treeModel.getPathToRoot(newNode)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Remove the suffix from this controller. |
| | | * The controller updates the JTree and returns the TreePath |
| | | * of the parent node. |
| | | * @param suffixDn the DN of the suffix to be removed. |
| | | * @return the TreePath of the parent node of the removed node. |
| | | */ |
| | | public TreePath removeSuffix(String suffixDn) { |
| | | TreePath result = null; |
| | | BasicNode node = findSuffixNode(suffixDn, rootNode); |
| | | TreeNode parentNode = node.getParent(); |
| | | /* If the parent is null... the node is no longer in the tree */ |
| | | if (parentNode != null) { |
| | | removeOneNode(node); |
| | | result = new TreePath(treeModel.getPathToRoot(parentNode)); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Remove all the suffixes. |
| | | * The controller removes all the nodes from the JTree except the root. |
| | |
| | | } |
| | | |
| | | /** |
| | | * Says wether to show the attribute name or not. |
| | | * This routine collapses the JTree and invokes startRefresh(). |
| | | * @param showAttributeName whether to show the attribute name or not. |
| | | */ |
| | | public void showAttributeName(boolean showAttributeName) { |
| | | this.showAttributeName = showAttributeName; |
| | | stopRefresh(); |
| | | removeAllChildNodes(rootNode, true /* Keep suffixes */); |
| | | startRefresh(null); |
| | | } |
| | | |
| | | /** |
| | | * Says wether we are showing the attribute name or not. |
| | | * @return <CODE>true</CODE> if we are showing the attribute name and |
| | | * <CODE>false</CODE> otherwise. |
| | |
| | | listeners.add(l); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Remove a BrowserEventListener from this controller. |
| | | * @param l the listener to be removed. |
| | | */ |
| | | public void removeBrowserEventListener(BrowserEventListener l) { |
| | | listeners.remove(l); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Notify this controller that an entry has been added. |
| | | * The controller adds a new node in the JTree and starts refreshing this new |
| | |
| | | * @return the tree path associated with the parent of the deleted node. |
| | | */ |
| | | public TreePath notifyEntryDeleted(BrowserNodeInfo nodeInfo) { |
| | | TreePath result = null; |
| | | BasicNode node = nodeInfo.getNode(); |
| | | if (node == rootNode) { |
| | | throw new IllegalArgumentException("Root node cannot be removed"); |
| | | } |
| | | TreeNode parentNode = node.getParent(); |
| | | |
| | | /* If the parent is null... the node is no longer in the tree */ |
| | | final TreeNode parentNode = node.getParent(); |
| | | if (parentNode != null) { |
| | | removeOneNode(node); |
| | | result = new TreePath(treeModel.getPathToRoot(parentNode)); |
| | | return new TreePath(treeModel.getPathToRoot(parentNode)); |
| | | } |
| | | return result; |
| | | return null; |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * Notify this controller that a child entry has changed. |
| | | * The controller has to refresh the corresponding node and (if necessary) |
| | | * itself. |
| | | * @param nodeInfo the parent of the node that changed. |
| | | * @param dn the DN of the entry that changed. |
| | | */ |
| | | public void notifyChildEntryChanged(BrowserNodeInfo nodeInfo, String dn) { |
| | | BasicNode node = nodeInfo.getNode(); |
| | | startRefreshNode(node, null, true); |
| | | } |
| | | |
| | | /** |
| | | * Notify this controller that a child entry has been added. |
| | | * The controller has to refresh the corresponding node and (if necessary) |
| | | * itself. |
| | | * @param nodeInfo the parent of the node that was added. |
| | | * @param dn the DN of the entry that was added. |
| | | */ |
| | | public void notifyChildEntryAdded(BrowserNodeInfo nodeInfo, String dn) { |
| | | BasicNode node = nodeInfo.getNode(); |
| | | startRefreshNode(node, null, true); |
| | | } |
| | | |
| | | /** |
| | | * Notify this controller that a child entry has been deleted. |
| | | * The controller has to refresh the corresponding node and (if necessary) |
| | | * itself. |
| | | * @param nodeInfo the parent of the node that was deleted. |
| | | * @param dn the DN of the entry that was deleted. |
| | | */ |
| | | public void notifyChildEntryDeleted(BrowserNodeInfo nodeInfo, String dn) { |
| | | BasicNode node = nodeInfo.getNode(); |
| | | if (node.getParent() != null) { |
| | | startRefreshNode((BasicNode) node.getParent(), null, true); |
| | | } else { |
| | | startRefreshNode(node, null, true); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Notify this controller that authentication data have changed in the |
| | | * connection pool. |
| | | */ |
| | | @Override |
| | | public void notifyAuthDataChanged() { |
| | | notifyAuthDataChanged(null); |
| | | } |
| | |
| | | * url. |
| | | * @param url the URL of the connection that changed. |
| | | */ |
| | | public void notifyAuthDataChanged(LDAPURL url) { |
| | | private void notifyAuthDataChanged(LDAPURL url) { |
| | | // TODO: temporary implementation |
| | | // we should refresh only nodes : |
| | | // - whose URL matches 'url' |
| | |
| | | |
| | | /** |
| | | * Start a refresh from the specified node. |
| | | * If some refresh are on-going on descendent nodes, they are stopped. |
| | | * If some refresh are on-going on descendant nodes, they are stopped. |
| | | * If nodeInfo is null, refresh is started from the root. |
| | | * @param nodeInfo the node to be refreshed. |
| | | */ |
| | |
| | | startRefreshNode(node, null, true); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Equivalent to startRefresh(null). |
| | | */ |
| | | public void startRefresh() { |
| | | startRefresh(null); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Stop the current refreshing. |
| | | * Nodes being expanded are collapsed. |
| | | */ |
| | | public void stopRefresh() { |
| | | private void stopRefresh() { |
| | | stopRefreshNode(rootNode); |
| | | // TODO: refresh must be stopped in a clean state. |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Shutdown the controller : all the backgroup threads are stopped. |
| | | * After this call, the controller is no longer usable. |
| | | */ |
| | | public void shutDown() { |
| | | tree.removeTreeExpansionListener(this); |
| | | refreshQueue.shutdown(); |
| | | connectionPool.flush(); |
| | | } |
| | | |
| | | /** |
| | | * Start refreshing the whole tree from the specified node. |
| | | * We queue a refresh which: |
| | |
| | | * @param localEntry the local entry corresponding to the node. |
| | | * @param recursive whether the refresh must be executed recursively or not. |
| | | */ |
| | | void startRefreshNode(BasicNode node, SearchResult localEntry, |
| | | private void startRefreshNode(BasicNode node, SearchResult localEntry, |
| | | boolean recursive) { |
| | | if (node == rootNode) { |
| | | // For the root node, readBaseEntry is meaningless. |
| | |
| | | // The task does not *see* suffixes. |
| | | // So we need to propagate the refresh on |
| | | // the sub-suffixes if any. |
| | | if (recursive && (node instanceof SuffixNode)) { |
| | | if (recursive && node instanceof SuffixNode) { |
| | | Enumeration<?> e = node.children(); |
| | | while (e.hasMoreElements()) { |
| | | BasicNode child = (BasicNode)e.nextElement(); |
| | |
| | | * root node. |
| | | * @param node the node where the refresh must stop. |
| | | */ |
| | | void stopRefreshNode(BasicNode node) { |
| | | private void stopRefreshNode(BasicNode node) { |
| | | if (node == rootNode) { |
| | | refreshQueue.cancelAll(); |
| | | } |
| | |
| | | * Call startRefreshNode() on each referral node accessible from parentNode. |
| | | * @param parentNode the parent node. |
| | | */ |
| | | void startRefreshReferralNodes(BasicNode parentNode) { |
| | | private void startRefreshReferralNodes(BasicNode parentNode) { |
| | | Enumeration<?> e = parentNode.children(); |
| | | while (e.hasMoreElements()) { |
| | | BasicNode child = (BasicNode)e.nextElement(); |
| | | if ((child.getReferral() != null) || (child.getRemoteUrl() != null)) { |
| | | if (child.getReferral() != null || child.getRemoteUrl() != null) { |
| | | startRefreshNode(child, null, true); |
| | | } |
| | | else { |
| | |
| | | * @param parentNode the parent node. |
| | | * @param keepSuffixes whether the suffixes should be kept or not. |
| | | */ |
| | | void removeAllChildNodes(BasicNode parentNode, boolean keepSuffixes) { |
| | | private void removeAllChildNodes(BasicNode parentNode, boolean keepSuffixes) { |
| | | for (int i = parentNode.getChildCount() - 1; i >= 0; i--) { |
| | | BasicNode child = (BasicNode)parentNode.getChildAt(i); |
| | | if ((child instanceof SuffixNode) && keepSuffixes) { |
| | | if (child instanceof SuffixNode && keepSuffixes) { |
| | | removeAllChildNodes(child, true); |
| | | child.setRefreshNeededOnExpansion(true); |
| | | } |
| | |
| | | * if it needs it (to search the children for instance). |
| | | * @param event the tree expansion event. |
| | | */ |
| | | @Override |
| | | public void treeExpanded(TreeExpansionEvent event) { |
| | | if (!automaticallyExpandedNode) |
| | | { |
| | |
| | | * tasks on it are canceled. |
| | | * @param event the tree collapse event. |
| | | */ |
| | | @Override |
| | | public void treeCollapsed(TreeExpansionEvent event) { |
| | | Object node = event.getPath().getLastPathComponent(); |
| | | if (!(node instanceof RootNode)) { |
| | |
| | | * @throws NamingException if there is an error retrieving the connection. |
| | | * @return the LDAP connection to reading the base entry of a node. |
| | | */ |
| | | InitialLdapContext findConnectionForLocalEntry(BasicNode node, |
| | | boolean isConfigurationNode) |
| | | throws NamingException { |
| | | InitialLdapContext result; |
| | | private InitialLdapContext findConnectionForLocalEntry(BasicNode node, |
| | | boolean isConfigurationNode) throws NamingException |
| | | { |
| | | if (node == rootNode) { |
| | | result = ctxConfiguration; |
| | | return ctxConfiguration; |
| | | } |
| | | else { |
| | | BasicNode parent = (BasicNode)node.getParent(); |
| | | if ((parent != null) && (parent != rootNode)) |
| | | { |
| | | result = findConnectionForDisplayedEntry(parent, isConfigurationNode); |
| | | } |
| | | else |
| | | { |
| | | if (isConfigurationNode) |
| | | { |
| | | result = ctxConfiguration; |
| | | } |
| | | else |
| | | { |
| | | result = ctxUserData; |
| | | } |
| | | } |
| | | |
| | | final BasicNode parent = (BasicNode) node.getParent(); |
| | | if (parent != null && parent != rootNode) |
| | | { |
| | | return findConnectionForDisplayedEntry(parent, isConfigurationNode); |
| | | } |
| | | return result; |
| | | return isConfigurationNode ? ctxConfiguration : ctxUserData; |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public boolean isConfigurationNode(BasicNode node) |
| | | { |
| | | boolean isConfigurationNode = false; |
| | | if (node instanceof SuffixNode) |
| | | { |
| | | String dn = node.getDN(); |
| | |
| | | Utilities.areDnsEqual(dn, ConfigConstants.DN_BACKUP_ROOT) || |
| | | Utilities.areDnsEqual(dn, ServerConstants.DN_EXTERNAL_CHANGELOG_ROOT)) |
| | | { |
| | | isConfigurationNode = true; |
| | | return true; |
| | | } |
| | | } |
| | | else if (node instanceof RootNode) |
| | | { |
| | | isConfigurationNode = true; |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | |
| | | return isConfigurationNode(parentNode); |
| | | } |
| | | |
| | | return isConfigurationNode; |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | |
| | | * @return the LDAP connection to search the displayed entry. |
| | | * @throws NamingException if there is an error retrieving the connection. |
| | | */ |
| | | InitialLdapContext findConnectionForDisplayedEntry(BasicNode node, |
| | | boolean isConfigurationNode) |
| | | throws NamingException { |
| | | InitialLdapContext result; |
| | | if (followReferrals && (node.getRemoteUrl() != null)) |
| | | private InitialLdapContext findConnectionForDisplayedEntry(BasicNode node, |
| | | boolean isConfigurationNode) throws NamingException { |
| | | if (followReferrals && node.getRemoteUrl() != null) |
| | | { |
| | | result = connectionPool.getConnection(node.getRemoteUrl()); |
| | | return connectionPool.getConnection(node.getRemoteUrl()); |
| | | } |
| | | else { |
| | | result = findConnectionForLocalEntry(node, isConfigurationNode); |
| | | } |
| | | return result; |
| | | return findConnectionForLocalEntry(node, isConfigurationNode); |
| | | } |
| | | |
| | | |
| | |
| | | * @param ctx the connection to be released. |
| | | */ |
| | | void releaseLDAPConnection(InitialLdapContext ctx) { |
| | | if ((ctx != this.ctxConfiguration) && |
| | | (ctx != this.ctxUserData)) |
| | | if (ctx != this.ctxConfiguration && ctx != this.ctxUserData) |
| | | { |
| | | // Thus it comes from the connection pool |
| | | connectionPool.releaseConnection(ctx); |
| | |
| | | * @return the local entry URL for a given node. |
| | | */ |
| | | LDAPURL findUrlForLocalEntry(BasicNode node) { |
| | | LDAPURL result; |
| | | if (node == rootNode) { |
| | | result = LDAPConnectionPool.makeLDAPUrl(ctxConfiguration, ""); |
| | | return LDAPConnectionPool.makeLDAPUrl(ctxConfiguration, ""); |
| | | } |
| | | else { |
| | | BasicNode parent = (BasicNode)node.getParent(); |
| | | if (parent != null) { |
| | | LDAPURL parentUrl = findUrlForDisplayedEntry(parent); |
| | | result = LDAPConnectionPool.makeLDAPUrl(parentUrl, node.getDN()); |
| | | } else { |
| | | result = LDAPConnectionPool.makeLDAPUrl(ctxConfiguration, node.getDN()); |
| | | } |
| | | final BasicNode parent = (BasicNode) node.getParent(); |
| | | if (parent != null) |
| | | { |
| | | final LDAPURL parentUrl = findUrlForDisplayedEntry(parent); |
| | | return LDAPConnectionPool.makeLDAPUrl(parentUrl, node.getDN()); |
| | | } |
| | | return result; |
| | | return LDAPConnectionPool.makeLDAPUrl(ctxConfiguration, node.getDN()); |
| | | } |
| | | |
| | | |
| | |
| | | * @param node the node. |
| | | * @return the displayed entry URL for a given node. |
| | | */ |
| | | LDAPURL findUrlForDisplayedEntry(BasicNode node) { |
| | | LDAPURL result; |
| | | if (followReferrals && (node.getRemoteUrl() != null)) { |
| | | result = node.getRemoteUrl(); |
| | | private LDAPURL findUrlForDisplayedEntry(BasicNode node) |
| | | { |
| | | if (followReferrals && node.getRemoteUrl() != null) { |
| | | return node.getRemoteUrl(); |
| | | } |
| | | else { |
| | | result = findUrlForLocalEntry(node); |
| | | } |
| | | return result; |
| | | return findUrlForLocalEntry(node); |
| | | } |
| | | |
| | | |
| | |
| | | * @return the DN to use for searching children of a given node. |
| | | */ |
| | | String findBaseDNForChildEntries(BasicNode node) { |
| | | String result; |
| | | |
| | | if (followReferrals && (node.getRemoteUrl() != null)) { |
| | | result = node.getRemoteUrl().getRawBaseDN(); |
| | | if (followReferrals && node.getRemoteUrl() != null) { |
| | | return node.getRemoteUrl().getRawBaseDN(); |
| | | } |
| | | else { |
| | | result = node.getDN(); |
| | | } |
| | | return result; |
| | | return node.getDN(); |
| | | } |
| | | |
| | | |
| | |
| | | * @return <CODE>true</CODE> if the node displays a remote entry and |
| | | * <CODE>false</CODE> otherwise. |
| | | */ |
| | | boolean isDisplayedEntryRemote(BasicNode node) { |
| | | boolean result = false; |
| | | private boolean isDisplayedEntryRemote(BasicNode node) { |
| | | if (followReferrals) { |
| | | if (node == rootNode) { |
| | | result = false; |
| | | return false; |
| | | } |
| | | else if (node.getRemoteUrl() != null) { |
| | | result = true; |
| | | if (node.getRemoteUrl() != null) { |
| | | return true; |
| | | } |
| | | else { |
| | | BasicNode parent = (BasicNode)node.getParent(); |
| | | if (parent != null) { |
| | | result = isDisplayedEntryRemote(parent); |
| | | } |
| | | final BasicNode parent = (BasicNode)node.getParent(); |
| | | if (parent != null) { |
| | | return isDisplayedEntryRemote(parent); |
| | | } |
| | | } |
| | | |
| | | return result; |
| | | return false; |
| | | } |
| | | |
| | | |
| | |
| | | if ((displayFlags & DISPLAY_ACI_COUNT) != 0) { |
| | | v.add("aci"); |
| | | } |
| | | if (!displayAttribute.equals(RDN_ATTRIBUTE)) { |
| | | if (!RDN_ATTRIBUTE.equals(displayAttribute)) { |
| | | v.add(displayAttribute); |
| | | } |
| | | |
| | | String[] result = new String[v.size()]; |
| | | v.toArray(result); |
| | | return result; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns the list of attributes for the green search. |
| | | * @return the list of attributes for the green search. |
| | | */ |
| | | String[] getAttrsForGreenSearch() { |
| | | if (!displayAttribute.equals(RDN_ATTRIBUTE)) { |
| | | return new String[] { |
| | | "aci", |
| | | displayAttribute}; |
| | | } else { |
| | | return new String[] { |
| | | "aci" |
| | | }; |
| | | } |
| | | return v.toArray(new String[v.size()]); |
| | | } |
| | | |
| | | /** |
| | |
| | | * @return the list of attributes for the black search. |
| | | */ |
| | | String[] getAttrsForBlackSearch() { |
| | | if (!displayAttribute.equals(RDN_ATTRIBUTE)) { |
| | | if (!RDN_ATTRIBUTE.equals(displayAttribute)) { |
| | | return new String[] { |
| | | "objectClass", |
| | | "numsubordinates", |
| | |
| | | * Returns the request controls to search user data. |
| | | * @return the request controls to search user data. |
| | | */ |
| | | Control[] getRequestControls() |
| | | private Control[] getRequestControls() |
| | | { |
| | | Control ctls[]; |
| | | if (followReferrals) |
| | |
| | | * Returns the request controls to search configuration data. |
| | | * @return the request controls to search configuration data. |
| | | */ |
| | | Control[] getConfigurationRequestControls() |
| | | private Control[] getConfigurationRequestControls() |
| | | { |
| | | return getRequestControls(); |
| | | } |
| | |
| | | // tree. |
| | | // Except when it's due a to referral resolution: we keep the node |
| | | // in order the user can fix the referral. |
| | | if (isNameNotFoundException(task.getException()) && |
| | | (oldState != NodeRefresher.State.SOLVING_REFERRAL)) { |
| | | if (isNameNotFoundException(task.getException()) |
| | | && oldState != NodeRefresher.State.SOLVING_REFERRAL) { |
| | | removeOneNode(node); |
| | | } |
| | | else { |
| | |
| | | nodeChanged = updateNodeRendering(node, task.getDisplayedEntry()); |
| | | } |
| | | } |
| | | else if ((newState == NodeRefresher.State.CANCELLED) && |
| | | (newState == NodeRefresher.State.INTERRUPTED)) { |
| | | else if (newState == NodeRefresher.State.CANCELLED |
| | | && newState == NodeRefresher.State.INTERRUPTED) { |
| | | |
| | | // Let's collapse task.getNode() |
| | | tree.collapsePath(new TreePath(treeModel.getPathToRoot(node))); |
| | |
| | | } |
| | | else { |
| | | |
| | | if ((oldState != NodeRefresher.State.SEARCHING_CHILDREN) && |
| | | (newState == NodeRefresher.State.SEARCHING_CHILDREN)) { |
| | | if (oldState != NodeRefresher.State.SEARCHING_CHILDREN |
| | | && newState == NodeRefresher.State.SEARCHING_CHILDREN) { |
| | | // The children search is going to start |
| | | if (canDoDifferentialUpdate(task)) { |
| | | Enumeration<?> e = node.children(); |
| | |
| | | } |
| | | } |
| | | |
| | | if (newState == NodeRefresher.State.FINISHED) { |
| | | if (node.getError() != null) { |
| | | node.setError(null); |
| | | nodeChanged = updateNodeRendering(node, task.getDisplayedEntry()); |
| | | } |
| | | if (newState == NodeRefresher.State.FINISHED && node.getError() != null) { |
| | | node.setError(null); |
| | | nodeChanged = updateNodeRendering(node, task.getDisplayedEntry()); |
| | | } |
| | | } |
| | | |
| | |
| | | treeModel.nodeChanged(task.getNode()); |
| | | } |
| | | |
| | | if (node.isLeaf() && (node.getChildCount() >= 1)) { |
| | | if (node.isLeaf() && node.getChildCount() >= 1) { |
| | | throw new RuntimeException("Inconsistent node: " + node.getDN()); |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | |
| | | final NodeRefresher.State oldState, |
| | | final NodeRefresher.State newState) |
| | | throws InterruptedException { |
| | | |
| | | Runnable r = new Runnable() { |
| | | @Override |
| | | public void run() { |
| | | try { |
| | | refreshTaskDidProgress(task, oldState, newState); |
| | |
| | | child = new BasicNode(entry.getName()); |
| | | parent.insert(child, index); |
| | | updateNodeRendering(child, entry); |
| | | insertIndex.add(new Integer(index)); |
| | | insertIndex.add(Integer.valueOf(index)); |
| | | // System.out.println("Inserted " + child.getDN() + " at " + index); |
| | | } |
| | | else { // Else we update the existing one |
| | | child = (BasicNode)parent.getChildAt(index); |
| | | if (updateNodeRendering(child, entry)) { |
| | | changedIndex.add(new Integer(index)); |
| | | changedIndex.add(Integer.valueOf(index)); |
| | | } |
| | | // The node is no longer obsolete |
| | | child.setObsolete(false); |
| | |
| | | |
| | | // NUMSUBORDINATE HACK |
| | | // Let's see if child has subordinates or not. |
| | | // Thanks to slapd, we cannot always trust the |
| | | // numSubOrdinates attribute. If the child entry's DN |
| | | // is found in the hacker's list, then we ignore |
| | | // Thanks to slapd, we cannot always trust the numSubOrdinates attribute. |
| | | // If the child entry's DN is found in the hacker's list, then we ignore |
| | | // the numSubordinate attribute... :(( |
| | | boolean hasNoSubOrdinates; |
| | | if (!child.hasSubOrdinates() && dontTrust) { |
| | | LDAPURL childUrl = findUrlForDisplayedEntry(child); |
| | | if (numSubordinateHacker.contains(childUrl)) { |
| | | // The numSubOrdinates we have is unreliable. |
| | | // child may potentially have subordinates. |
| | | hasNoSubOrdinates = false; |
| | | // System.out.println("numSubordinates of " + childUrl + |
| | | // " is not reliable"); |
| | | } |
| | | else { |
| | | // We can trust this 0 value |
| | | hasNoSubOrdinates = true; |
| | | } |
| | | hasNoSubOrdinates = !numSubordinateHacker.contains(childUrl); |
| | | } |
| | | else { |
| | | hasNoSubOrdinates = !child.hasSubOrdinates(); |
| | |
| | | |
| | | |
| | | // Propagate the refresh |
| | | // Note: logically we should unconditionaly call: |
| | | // Note: logically we should unconditionally call: |
| | | // startRefreshNode(child, false, true); |
| | | // |
| | | // However doing that saturates refreshQueue |
| | |
| | | // node had children (in the tree). In this case |
| | | // we force the refresh. See bug 5015115 |
| | | // |
| | | if (!hasNoSubOrdinates || |
| | | (child.getReferral() != null) || |
| | | (child.getChildCount() > 0)) { |
| | | if (!hasNoSubOrdinates |
| | | || child.getReferral() != null |
| | | || child.getChildCount() > 0) { |
| | | startRefreshNode(child, entry, true); |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * Tells wheter a differential update can be made in the provided task. |
| | | * Tells whether a differential update can be made in the provided task. |
| | | * @param task the task. |
| | | * @return <CODE>true</CODE> if a differential update can be made and |
| | | * <CODE>false</CODE> otherwise. |
| | | */ |
| | | private boolean canDoDifferentialUpdate(NodeRefresher task) { |
| | | return ( |
| | | (task.getNode().getChildCount() >= 1) && |
| | | (task.getNode().getNumSubOrdinates() <= 100) |
| | | ); |
| | | return task.getNode().getChildCount() >= 1 |
| | | && task.getNode().getNumSubOrdinates() <= 100; |
| | | } |
| | | |
| | | |
| | |
| | | if (entry != null) { |
| | | // Get the numsubordinates |
| | | node.setNumSubOrdinates(getNumSubOrdinates(entry)); |
| | | if (node.getNumSubOrdinates() > 0) |
| | | { |
| | | node.setHasSubOrdinates(true); |
| | | } |
| | | else |
| | | { |
| | | // Calculate based also in the hasSubordinates attribute |
| | | node.setHasSubOrdinates(getHasSubOrdinates(entry)); |
| | | } |
| | | node.setHasSubOrdinates( |
| | | node.getNumSubOrdinates() > 0 || getHasSubOrdinates(entry)); |
| | | node.setReferral(getReferral(entry)); |
| | | Set<String> ocValues = ConnectionUtils.getValues(entry, "objectClass"); |
| | | if (ocValues != null) { |
| | | String[] array = new String[ocValues.size()]; |
| | | ocValues.toArray(array); |
| | | node.setObjectClassValues(array); |
| | | node.setObjectClassValues(ocValues.toArray(new String[ocValues.size()])); |
| | | } |
| | | } |
| | | // Get the aci count |
| | | int aciCount; |
| | | |
| | | if (((displayFlags & DISPLAY_ACI_COUNT) != 0) && (entry != null)) { |
| | | Set<String> aciValues = ConnectionUtils.getValues(entry, "aci"); |
| | | if (aciValues != null) { |
| | | aciCount = aciValues.size(); |
| | | } |
| | | else { |
| | | aciCount = 0; |
| | | } |
| | | } |
| | | else { |
| | | aciCount = 0; |
| | | } |
| | | |
| | | // Select the icon according the objectClass,... |
| | | int modifiers = 0; |
| | | if (node.isLeaf() && !node.hasSubOrdinates()) { |
| | | modifiers |= IconPool.MODIFIER_LEAF; |
| | | } |
| | | if (node.getReferral() != null) { |
| | | modifiers |= IconPool.MODIFIER_REFERRAL; |
| | | } |
| | | if (node.getError() != null) { |
| | | if (node.getError().getException() != null) |
| | | { |
| | | LOG.log(Level.SEVERE, "node has error: "+node.getError().getException(), |
| | | node.getError().getException()); |
| | | } |
| | | modifiers |= IconPool.MODIFIER_ERROR; |
| | | } |
| | | SortedSet<String> objectClasses = new TreeSet<String>(); |
| | | if (entry != null) { |
| | | Set<String> ocs = ConnectionUtils.getValues(entry, "objectClass"); |
| | | if (ocs != null) |
| | | { |
| | | objectClasses.addAll(ocs); |
| | | } |
| | | } |
| | | Icon newIcon; |
| | | if (node instanceof SuffixNode) |
| | | { |
| | | newIcon = iconPool.getSuffixIcon(); |
| | | } |
| | | else |
| | | { |
| | | newIcon = iconPool.getIcon(objectClasses, modifiers); |
| | | } |
| | | int aciCount = getAciCount(entry); |
| | | Icon newIcon = getNewIcon(node, entry); |
| | | |
| | | // Construct the icon text according the dn, the aci count... |
| | | StringBuilder sb2 = new StringBuilder(); |
| | | if (aciCount >= 1) { |
| | | sb2.append(String.valueOf(aciCount)); |
| | | if (aciCount == 1) { |
| | | sb2.append(" aci"); |
| | | } |
| | | else { |
| | | sb2.append(" acis"); |
| | | sb2.append(aciCount); |
| | | sb2.append(" aci"); |
| | | if (aciCount != 1) { |
| | | sb2.append("s"); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | } else { |
| | | boolean useRdn = true; |
| | | if (!displayAttribute.equals(RDN_ATTRIBUTE) && |
| | | (entry != null)) { |
| | | if (!RDN_ATTRIBUTE.equals(displayAttribute) && entry != null) { |
| | | String value = ConnectionUtils.getFirstValue(entry,displayAttribute); |
| | | if (value != null) { |
| | | if (showAttributeName) { |
| | |
| | | useRdn = false; |
| | | } |
| | | } |
| | | |
| | | if (useRdn) { |
| | | String rdn; |
| | | if (followReferrals && (node.getRemoteUrl() != null)) { |
| | | if (followReferrals && node.getRemoteUrl() != null) { |
| | | if (showAttributeName) { |
| | | rdn = node.getRemoteRDNWithAttributeName(); |
| | | } else { |
| | |
| | | } |
| | | |
| | | // Determine if the rendering needs to be updated |
| | | boolean changed = ( |
| | | (node.getIcon() != newIcon) || |
| | | (node.getDisplayName() != newDisplayName) || |
| | | (node.getFontStyle() != newStyle) |
| | | ); |
| | | boolean changed = |
| | | node.getIcon() != newIcon |
| | | || node.getDisplayName() != newDisplayName |
| | | || node.getFontStyle() != newStyle; |
| | | if (changed) { |
| | | node.setIcon(newIcon); |
| | | node.setDisplayName(newDisplayName); |
| | | node.setFontStyle(newStyle); |
| | | } |
| | | |
| | | |
| | | return changed; |
| | | } |
| | | |
| | | private int getAciCount(SearchResult entry) throws NamingException |
| | | { |
| | | if ((displayFlags & DISPLAY_ACI_COUNT) != 0 && entry != null) { |
| | | Set<String> aciValues = ConnectionUtils.getValues(entry, "aci"); |
| | | if (aciValues != null) { |
| | | return aciValues.size(); |
| | | } |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | private Icon getNewIcon(BasicNode node, SearchResult entry) |
| | | throws NamingException |
| | | { |
| | | // Select the icon according the objectClass,... |
| | | int modifiers = 0; |
| | | if (node.isLeaf() && !node.hasSubOrdinates()) { |
| | | modifiers |= IconPool.MODIFIER_LEAF; |
| | | } |
| | | if (node.getReferral() != null) { |
| | | modifiers |= IconPool.MODIFIER_REFERRAL; |
| | | } |
| | | if (node.getError() != null) { |
| | | final Exception ex = node.getError().getException(); |
| | | if (ex != null) |
| | | { |
| | | LOG.log(Level.SEVERE, "node has error: " + ex, ex); |
| | | } |
| | | modifiers |= IconPool.MODIFIER_ERROR; |
| | | } |
| | | |
| | | SortedSet<String> objectClasses = new TreeSet<String>(); |
| | | if (entry != null) { |
| | | Set<String> ocs = ConnectionUtils.getValues(entry, "objectClass"); |
| | | if (ocs != null) |
| | | { |
| | | objectClasses.addAll(ocs); |
| | | } |
| | | } |
| | | |
| | | if (node instanceof SuffixNode) |
| | | { |
| | | return iconPool.getSuffixIcon(); |
| | | } |
| | | return iconPool.getIcon(objectClasses, modifiers); |
| | | } |
| | | |
| | | /** |
| | | * Find a child node matching a given DN. |
| | |
| | | public int findChildNode(BasicNode parent, String childDn) { |
| | | int childCount = parent.getChildCount(); |
| | | int i = 0; |
| | | while ((i < childCount) && |
| | | !childDn.equals(((BasicNode)parent.getChildAt(i)).getDN())) { |
| | | while (i < childCount |
| | | && !childDn.equals(((BasicNode)parent.getChildAt(i)).getDN())) { |
| | | i++; |
| | | } |
| | | if (i >= childCount) { // Not found |
| | | i = -(childCount + 1); |
| | | } |
| | | |
| | | return i; |
| | | } |
| | | |
| | |
| | | newSize = newSize - 1; |
| | | } |
| | | if (newSize != queueTotalSize) { |
| | | if ((queueTotalSize == 0) && (newSize >= 1)) { |
| | | if (queueTotalSize == 0 && newSize >= 1) { |
| | | fireEvent(BrowserEvent.Type.UPDATE_START); |
| | | } |
| | | else if ((queueTotalSize >= 1) && (newSize == 0)) { |
| | | else if (queueTotalSize >= 1 && newSize == 0) { |
| | | fireEvent(BrowserEvent.Type.UPDATE_END); |
| | | } |
| | | queueTotalSize = newSize; |
| | |
| | | * @throws IllegalArgumentException if a node with the given dn exists but |
| | | * is not a suffix node. |
| | | */ |
| | | SuffixNode findSuffixNode(String suffixDn, SuffixNode suffixNode) |
| | | throws IllegalArgumentException |
| | | private SuffixNode findSuffixNode(String suffixDn, SuffixNode suffixNode) |
| | | throws IllegalArgumentException |
| | | { |
| | | SuffixNode result; |
| | | |
| | | if (Utilities.areDnsEqual(suffixNode.getDN(), suffixDn)) { |
| | | result = suffixNode; |
| | | } |
| | | else { |
| | | int childCount = suffixNode.getChildCount(); |
| | | if (childCount == 0) { |
| | | result = null; |
| | | } |
| | | else { |
| | | BasicNode child; |
| | | int i = 0; |
| | | boolean found = false; |
| | | do { |
| | | child = (BasicNode)suffixNode.getChildAt(i) ; |
| | | if (Utilities.areDnsEqual(child.getDN(), suffixDn)) { |
| | | found = true; |
| | | } |
| | | i++; |
| | | } |
| | | while ((i < childCount) && !found); |
| | | if (!found) { |
| | | result = null; |
| | | } |
| | | else if (child instanceof SuffixNode) { |
| | | result = (SuffixNode)child; |
| | | } |
| | | else { |
| | | // A node matches suffixDn however it's not a suffix node. |
| | | // There's a bug in the caller. |
| | | throw new IllegalArgumentException(suffixDn +" is not a suffix node"); |
| | | } |
| | | } |
| | | return suffixNode; |
| | | } |
| | | |
| | | return result; |
| | | int childCount = suffixNode.getChildCount(); |
| | | if (childCount == 0) |
| | | { |
| | | return null; |
| | | } |
| | | BasicNode child; |
| | | int i = 0; |
| | | boolean found = false; |
| | | do |
| | | { |
| | | child = (BasicNode) suffixNode.getChildAt(i); |
| | | if (Utilities.areDnsEqual(child.getDN(), suffixDn)) |
| | | { |
| | | found = true; |
| | | } |
| | | i++; |
| | | } |
| | | while (i < childCount && !found); |
| | | |
| | | if (!found) |
| | | { |
| | | return null; |
| | | } |
| | | if (child instanceof SuffixNode) |
| | | { |
| | | return (SuffixNode) child; |
| | | } |
| | | |
| | | // A node matches suffixDn however it's not a suffix node. |
| | | // There's a bug in the caller. |
| | | throw new IllegalArgumentException(suffixDn + " is not a suffix node"); |
| | | } |
| | | |
| | | |
| | |
| | | * NameNotFoundException. |
| | | */ |
| | | private boolean isNameNotFoundException(Object x) { |
| | | boolean result; |
| | | if ((x != null) && (x instanceof NameNotFoundException)) |
| | | { |
| | | result = true; |
| | | } |
| | | else { |
| | | result = false; |
| | | } |
| | | return result; |
| | | return x instanceof NameNotFoundException; |
| | | } |
| | | |
| | | |
| | |
| | | * If numsubordinates is not present, returns 0. |
| | | * @param entry the entry to analyze. |
| | | * @throws NamingException if an error occurs. |
| | | * @return the value of the numsubordinate attribute. 0 if the attribute |
| | | * @return the value of the numsubordinates attribute. 0 if the attribute |
| | | * could not be found. |
| | | */ |
| | | public static int getNumSubOrdinates(SearchResult entry) |
| | | throws NamingException |
| | | private static int getNumSubOrdinates(SearchResult entry) throws NamingException |
| | | { |
| | | int result; |
| | | |
| | | String v = ConnectionUtils.getFirstValue(entry, "numsubordinates"); |
| | | if (v == null) { |
| | | result = 0; |
| | | } |
| | | else { |
| | | try { |
| | | result = Integer.parseInt(v); |
| | | } |
| | | catch(NumberFormatException x) { |
| | | result = 0; |
| | | } |
| | | } |
| | | |
| | | return result; |
| | | return toInt(ConnectionUtils.getFirstValue(entry, "numsubordinates")); |
| | | } |
| | | |
| | | /** |
| | |
| | | public static boolean getHasSubOrdinates(SearchResult entry) |
| | | throws NamingException |
| | | { |
| | | boolean result; |
| | | |
| | | String v = ConnectionUtils.getFirstValue(entry, "hassubordinates"); |
| | | if (v == null) { |
| | | result = getNumSubOrdinates(entry) > 0; |
| | | if (v != null) { |
| | | return "true".equalsIgnoreCase(v); |
| | | } |
| | | else { |
| | | result = "true".equalsIgnoreCase(v); |
| | | } |
| | | |
| | | return result; |
| | | return getNumSubOrdinates(entry) > 0; |
| | | } |
| | | |
| | | /** |
| | | * Get the value of the numsubordinates attribute. |
| | | * If numsubordinates is not present, returns 0. |
| | | * @param entry the entry to analyze. |
| | | * @return the value of the numsubordinate attribute. 0 if the attribute |
| | | * @return the value of the numsubordinates attribute. 0 if the attribute |
| | | * could not be found. |
| | | */ |
| | | public static int getNumSubOrdinates(CustomSearchResult entry) |
| | | private static int getNumSubOrdinates(CustomSearchResult entry) |
| | | { |
| | | int result; |
| | | |
| | | List<Object> vs = entry.getAttributeValues("numsubordinates"); |
| | | String v = null; |
| | | if (vs != null && !vs.isEmpty()) |
| | | { |
| | | v = vs.get(0).toString(); |
| | | } |
| | | if (v == null) { |
| | | result = 0; |
| | | } |
| | | else { |
| | | try { |
| | | result = Integer.parseInt(v); |
| | | } |
| | | catch(NumberFormatException x) { |
| | | result = 0; |
| | | } |
| | | } |
| | | return toInt(v); |
| | | } |
| | | |
| | | return result; |
| | | |
| | | private static int toInt(String v) |
| | | { |
| | | if (v == null) |
| | | { |
| | | return 0; |
| | | } |
| | | try |
| | | { |
| | | return Integer.parseInt(v); |
| | | } |
| | | catch (NumberFormatException x) |
| | | { |
| | | return 0; |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public static boolean getHasSubOrdinates(CustomSearchResult entry) |
| | | { |
| | | boolean result; |
| | | |
| | | List<Object> vs = entry.getAttributeValues("hassubordinates"); |
| | | String v = null; |
| | | if (vs != null && !vs.isEmpty()) |
| | | { |
| | | v = vs.get(0).toString(); |
| | | } |
| | | if (v == null) { |
| | | result = getNumSubOrdinates(entry) > 0; |
| | | if (v != null) |
| | | { |
| | | return "true".equalsIgnoreCase(v); |
| | | } |
| | | else { |
| | | result = "true".equalsIgnoreCase(v); |
| | | } |
| | | |
| | | return result; |
| | | return getNumSubOrdinates(entry) > 0; |
| | | } |
| | | |
| | | |
| | |
| | | { |
| | | for (String value : values) |
| | | { |
| | | boolean isReferral = value.equalsIgnoreCase("referral"); |
| | | boolean isReferral = "referral".equalsIgnoreCase(value); |
| | | if (isReferral) |
| | | { |
| | | Set<String> refValues = ConnectionUtils.getValues(entry, "ref"); |
| | |
| | | * @param v the Collection of Integer objects. |
| | | * @return an array of int from a Collection of Integer objects. |
| | | */ |
| | | static int[] intArrayFromCollection(Collection<Integer> v) { |
| | | private static int[] intArrayFromCollection(Collection<Integer> v) { |
| | | int[] result = new int[v.size()]; |
| | | int i = 0; |
| | | for (Integer value : v) |
| | |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * Returns an array of SearchResult from a Collection of SearchResult objects. |
| | | * @param v the Collection of SearchResult objects. |
| | | * @return an array of SearchResult from a Collection of SearchResult objects. |
| | | */ |
| | | static SearchResult[] entryArrayFromCollection(Collection<SearchResult> v) { |
| | | SearchResult[] result = new SearchResult[v.size()]; |
| | | v.toArray(result); |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * Returns an array of BasicNode from a Collection of BasicNode objects. |
| | | * @param v the Collection of BasicNode objects. |
| | | * @return an array of BasicNode from a Collection of BasicNode objects. |
| | | */ |
| | | static BasicNode[] nodeArrayFromCollection(Collection<BasicNode> v) { |
| | | BasicNode[] result = new BasicNode[v.size()]; |
| | | v.toArray(result); |
| | | return result; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * For debugging purpose: allows to switch easily |
| | |
| | | * @param r the runnable to be invoked. |
| | | * @throws InterruptedException if there is an error invoking SwingUtilities. |
| | | */ |
| | | static void swingInvoke(Runnable r) |
| | | throws InterruptedException { |
| | | private static void swingInvoke(Runnable r) throws InterruptedException { |
| | | try { |
| | | SwingUtilities.invokeAndWait(r); |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * The default implementaion of the BrowserNodeInfo interface. |
| | | * The default implementation of the BrowserNodeInfo interface. |
| | | */ |
| | | class BrowserNodeInfoImpl implements BrowserNodeInfo |
| | | private class BrowserNodeInfoImpl implements BrowserNodeInfo |
| | | { |
| | | BasicNode node; |
| | | LDAPURL url; |
| | | boolean isRemote; |
| | | boolean isSuffix; |
| | | boolean isRootNode; |
| | | String[] referral; |
| | | int numSubOrdinates; |
| | | boolean hasSubOrdinates; |
| | | int errorType; |
| | | Exception errorException; |
| | | Object errorArg; |
| | | String[] objectClassValues; |
| | | String toString; |
| | | private BasicNode node; |
| | | private LDAPURL url; |
| | | private boolean isRemote; |
| | | private boolean isSuffix; |
| | | private boolean isRootNode; |
| | | private String[] referral; |
| | | private int numSubOrdinates; |
| | | private boolean hasSubOrdinates; |
| | | private int errorType; |
| | | private Exception errorException; |
| | | private Object errorArg; |
| | | private String[] objectClassValues; |
| | | private String toString; |
| | | |
| | | /** |
| | | * The constructor of this object. |
| | |
| | | * Returns the node associated with this object. |
| | | * @return the node associated with this object. |
| | | */ |
| | | @Override |
| | | public BasicNode getNode() { |
| | | return node; |
| | | } |
| | |
| | | * Returns the LDAP URL associated with this object. |
| | | * @return the LDAP URL associated with this object. |
| | | */ |
| | | @Override |
| | | public LDAPURL getURL() { |
| | | return url; |
| | | } |
| | |
| | | * @return <CODE>true</CODE> if this is a root node and <CODE>false</CODE> |
| | | * otherwise. |
| | | */ |
| | | @Override |
| | | public boolean isRootNode() { |
| | | return isRootNode; |
| | | } |
| | |
| | | * @return <CODE>true</CODE> if this is a suffix node and <CODE>false</CODE> |
| | | * otherwise. |
| | | */ |
| | | @Override |
| | | public boolean isSuffix() { |
| | | return isSuffix; |
| | | } |
| | |
| | | * @return <CODE>true</CODE> if this is a remote node and <CODE>false</CODE> |
| | | * otherwise. |
| | | */ |
| | | @Override |
| | | public boolean isRemote() { |
| | | return isRemote; |
| | | } |
| | |
| | | * Returns the list of referral associated with this node. |
| | | * @return the list of referral associated with this node. |
| | | */ |
| | | @Override |
| | | public String[] getReferral() { |
| | | return referral; |
| | | } |
| | |
| | | * @return the number of subordinates of the entry associated with this |
| | | * node. |
| | | */ |
| | | @Override |
| | | public int getNumSubOrdinates() { |
| | | return numSubOrdinates; |
| | | } |
| | |
| | | * @return {@code true} if the entry has subordinates and {@code false} |
| | | * otherwise. |
| | | */ |
| | | @Override |
| | | public boolean hasSubOrdinates() { |
| | | return hasSubOrdinates; |
| | | } |
| | |
| | | * @return the error type associated we got when refreshing the node. |
| | | * <CODE>null</CODE> if no error was found. |
| | | */ |
| | | @Override |
| | | public int getErrorType() { |
| | | return errorType; |
| | | } |
| | |
| | | * @return the exception associated we got when refreshing the node. |
| | | * <CODE>null</CODE> if no exception was found. |
| | | */ |
| | | @Override |
| | | public Exception getErrorException() { |
| | | return errorException; |
| | | } |
| | |
| | | * @return the error argument associated we got when refreshing the node. |
| | | * <CODE>null</CODE> if no error argument was found. |
| | | */ |
| | | @Override |
| | | public Object getErrorArg() { |
| | | return errorArg; |
| | | } |
| | |
| | | * Return the tree path associated with the node in the tree. |
| | | * @return the tree path associated with the node in the tree. |
| | | */ |
| | | @Override |
| | | public TreePath getTreePath() { |
| | | return new TreePath(treeModel.getPathToRoot(node)); |
| | | } |
| | |
| | | * Returns the object class values of the entry associated with the node. |
| | | * @return the object class values of the entry associated with the node. |
| | | */ |
| | | @Override |
| | | public String[] getObjectClassValues() { |
| | | return objectClassValues; |
| | | } |
| | |
| | | * Returns a String representation of the object. |
| | | * @return a String representation of the object. |
| | | */ |
| | | @Override |
| | | public String toString() { |
| | | return toString; |
| | | } |
| | |
| | | * @return <CODE>true</CODE> if the node info represents the same node as |
| | | * this and <CODE>false</CODE> otherwise. |
| | | */ |
| | | @Override |
| | | public boolean representsSameNode(BrowserNodeInfo node) { |
| | | boolean representsSameNode = false; |
| | | if (node != null) { |
| | | representsSameNode = node.getNode() == node; |
| | | return node.getNode() == node; |
| | | } |
| | | return representsSameNode; |
| | | return false; |
| | | } |
| | | } |
| | | |