📄 contextnode.java
字号:
/*------------------------------------------------------------------------------Name: ContextNode.javaProject: xmlBlaster.orgCopyright: xmlBlaster.org, see xmlBlaster-LICENSE file------------------------------------------------------------------------------*/package org.xmlBlaster.util.context;import org.xmlBlaster.util.Global;import org.xmlBlaster.util.StringPairTokenizer;import org.xmlBlaster.util.def.Constants;import java.lang.ref.WeakReference;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.logging.Logger;import javax.management.ObjectName;/** * This represents one node in the administrative hierarchy, and is a linked * list to its parent and its childs. * * @author xmlBlaster@marcelruff.info * @see <a href="http://www.xmlBlaster.org/xmlBlaster/doc/requirements/admin.commands.html">The admin.commands requirement</a> */public final class ContextNode{ private static Logger log = Logger.getLogger(ContextNode.class.getName()); /** Name for logging output */ public final static String SEP = "/"; public final static String ROOT_MARKER_TAG = SEP+"xmlBlaster"; /** Use to mark a cluster node name */ public final static String CLUSTER_MARKER_TAG = "node"; /** Use to mark a client */ public final static String SUBJECT_MARKER_TAG = "client"; /** Use to mark a contrib */ public final static String CONTRIB_MARKER_TAG = "contrib"; /** Use to mark a login session */ public final static String SESSION_MARKER_TAG = "session"; /** Use for client side XmlBlasterAccess */ public final static String CONNECTION_MARKER_TAG = "connection"; /** Use to mark a queue */ public final static String QUEUE_MARKER_TAG = "queue"; /** Use to mark a service */ public final static String SERVICE_MARKER_TAG = "service"; /** Use to mark a plugin inside the RunlevelManager (xmlBlasterPlugins.xml) */ public final static String RUNLEVEL_PLUGIN_MARKER_TAG = "plugin"; /** Use to mark a protocol plugin like XMLRPC or email */ public final static String PROTOCOL_MARKER_TAG = "protocol"; /** Use to mark a message store map */ public final static String MAP_MARKER_TAG = "map"; /** Use to mark a topic */ public final static String TOPIC_MARKER_TAG = "topic"; /** Use to mark a subscription */ public final static String SUBSCRIPTION_MARKER_TAG = "subscription"; /** Use to mark event methods */ public final static String EVENT_MARKER_TAG = "event"; /** Use to mark a system and configuration properties and command line arguments */ public final static String SYSPROP_MARKER_TAG = "sysprop"; /** Use to mark logging settings */ public final static String LOGGING_MARKER_TAG = "logging"; /** For XPath conforming query */ public final static String SCHEMA_XPATH = "xpath"; /** For JMX conforming ObjectName string */ public final static String SCHEMA_JMX = "jmx"; /** For JMX conforming ObjectName string, "org.xmlBlaster:" is our JMX domain */ public final static String SCHEMA_JMX_DOMAIN = "org.xmlBlaster"; /** For URL conforming string */ public final static String SCHEMA_URL = "url"; private String className; // e.g. "node" private String instanceName; // e.g. "heron" private ContextNode parent; private Map childs; // key=absoluteName, value contains 'new WeakReference(ContextNode)' public static char QUOTE = '\"'; //Placeholder for top level node public final static ContextNode ROOT_NODE = null; // new ContextNode(null, "/xmlBlaster", "", (ContextNode)null); /** * @deprecated Use constructor without global */ public ContextNode(Global glob, String className, String instanceName, ContextNode parent) { this(className, instanceName, parent); } /** * @param className The tag name like 'node' (ContextNode.CLUSTER_MARKER_TAG) or 'client' (ContextNode.SUBJECT_MARKER_TAG) * @param instanceName The instance like 'heron' or 'joe', can be null * @param parent The parent node or null if root ContextNode ('node/heron' etc) */ public ContextNode(String className, String instanceName, ContextNode parent) { if (className == null) { throw new IllegalArgumentException("ContextNode: Missing className argument"); } this.className = className; setInstanceName(instanceName); this.parent = parent; if (this.parent != null) this.parent.addChild(this); } /* public Global getGlobal() { return this.glob; } */ /** * @return The tag name like 'node' (ContextNode.CLUSTER_MARKER_TAG) or 'client' (ContextNode.SUBJECT_MARKER_TAG) */ public String getClassName() { return this.className; } /** * @param className The tag name like 'node' (ContextNode.CLUSTER_MARKER_TAG) or 'client' (ContextNode.SUBJECT_MARKER_TAG) */ public boolean isOfClass(String className) { if (this.className == null) return false; return this.className.equals(className); } public void setInstanceName(String instanceName) { /** TODO: Needs some testing //Escape offending '/' in the name with quotes "joe/the/great" if (instanceName != null && instanceName.indexOf("/") != -1 && instanceName.charAt(0) != QUOTE) { instanceName = QUOTE + instanceName + QUOTE; } //For the time being we suppress '/' in JmxWrapper.validateJmxValue() */ this.instanceName = instanceName; } /** * @return Can be null */ public String getInstanceName() { return this.instanceName; } /** * @return Is never null */ public String getInstanceNameNotNull() { return (this.instanceName==null) ? "" : this.instanceName; } /** * @return The parent node or null */ public ContextNode getParent() { return this.parent; } /** * Walk up the hierarchy and return the matching ContextNode. * @param className The context node to retrieve * @return The parent node or null */ public ContextNode getParent(String className) { if (className == null) { return null; } if (className.equals(this.getClassName())) { return this; } if (this.parent != null ) { return this.parent.getParent(className); } return null; } /** * Walk up the hierarchy until we find the given className and rename the instance name. * * For example rename * "org.xmlBlaster:nodeClass=node,node=clientSUB1,clientClass=connection,connection=jack" * to * "org.xmlBlaster:nodeClass=node,node=heron,clientClass=connection,connection=jack" * * Checks the current node as well. * * @param className The class to change, e.g. "node" * @param instanceName The new name to use, e.g. "heron" */ public void changeParentName(String className, String instanceName) { if (className == null) { return; } ContextNode found = getParent(className); if (found != null) { found.setInstanceName(instanceName); } } /** * Walk up the hierarchy until we find the given className and rename the instance name. * * For example rename * "org.xmlBlaster:nodeClass=node,node=clientSUB1,clientClass=connection,connection=jack" * to * "org.xmlBlaster:nodeClass=node,node=heron,clientClass=connection,connection=jack" * * Checks the current node as well. * * @param newParentNode The new parent name to use, e.g. "heron" */ public void changeParentName(final ContextNode newParentNode) { if (newParentNode == null) { return; } ContextNode found = getParent(newParentNode.getClassName()); if (found != null) { found.setInstanceName(newParentNode.getInstanceName()); } } /** * Add the given child, it exists already nothing happens. * The child is hold as a weak reference, so you don't need to cleanup. * @param child The child to add * @return true if the child was added, the parent of your child is modified! * false if it existed already or if you given child is null */ public boolean addChild(ContextNode child) { return addChild(child, false); } /** * Add the given child, it exists already nothing happens. * The child is hold as a weak reference, so you don't need to cleanup. * @param child The child to add * @param doClone If true the given child is not modified * if false the given child is changed to have us as a new parent * @return true if the child was added, * false if it existed already or if you given child is null */ public boolean addChild(ContextNode child, boolean doClone) { if (child == null) return false; if (this.childs != null && this.childs.get(child.getAbsoluteName()) != null) { return false; // Child is already here } synchronized (this) { if (this.childs == null) { this.childs = new HashMap(); } if (doClone) { ContextNode clone = child.getClone(); clone.parent = this; this.childs.put(clone.getAbsoluteName(), new WeakReference(clone)); } else { if (child.parent != null && this != child.parent) { // If child had another parent already remove it child.parent.removeChild(child); } child.parent = this; this.childs.put(child.getAbsoluteName(), new WeakReference(child)); } } return true; } public ContextNode getClone() { return ContextNode.valueOf(getAbsoluteName()); } /** * Merges the given child, it exists already nothing happens. * <p /> * <pre> * this = "/node/heron/client/joe" * child = "/node/xyz/client/joe/session/1" * results to "/node/heron/client/joe/session/1" * </pre> * <pre> * this = "/node/heron/client/joe/session/1" * child = "/node/xyz/service/Pop3Driver" * results to "/xmlBlaster/node/heron/client/joe/session/1/service/Pop3Driver" * </pre> * @param child The child to add, it is not touched as we take a clone * @return The new leave or null if failed */ public ContextNode mergeChildTree(final ContextNode child) { if (child == null) return null; ContextNode childClone = child.getClone(); ContextNode childParent = childClone; while (true) { ContextNode thisParent = this.getParent(childParent.getClassName()); if (thisParent != null) { //System.out.println("thisParent=" + thisParent.getAbsoluteName() + " - childParent=" + childParent.getAbsoluteName()); if (thisParent.getInstanceNameNotNull().equals(childParent.getInstanceNameNotNull())) { ContextNode childs[] = childParent.getChildren(); for (int i=0; i<childs.length; i++) { thisParent.addChild(childs[i]); // suppresses duplicates } return thisParent.getChild(child.getClassName(), child.getInstanceName()); } ContextNode pp = thisParent.getParent(); if (pp != null) { // Found a node to merge, attach it here pp.addChild(childParent); return thisParent.getChild(child.getClassName(), child.getInstanceName()); } break; // nothing found to merge with } childParent = childParent.getParent(); if (childParent==null) break; } // Append if not merged: this.addChild(childClone); return getChild(child.getClassName(), child.getInstanceName()); } /** * @return All children, never null (but empty array) */ public synchronized ContextNode[] getChildren() { if (this.childs == null || this.childs.size() == 0) { return new ContextNode[0]; } WeakReference[] refs = (WeakReference[])this.childs.values().toArray(new WeakReference[this.childs.size()]); ArrayList list = new ArrayList(refs.length); for (int i=0; i<refs.length; i++) { Object referent = refs[i].get(); if (referent != null) { list.add(referent); } else { this.childs.remove(refs[i]); // Cleanup the obsolete WeakReference // TODO: ReferenceQueue } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -