View Javadoc

1   package cz.cuni.amis.pogamut.base.utils.jmx;
2   
3   import javax.management.ObjectName;
4   
5   import cz.cuni.amis.pogamut.base.agent.IAgentId;
6   import cz.cuni.amis.pogamut.base.agent.impl.AbstractAgent;
7   import cz.cuni.amis.pogamut.base.utils.Pogamut;
8   import cz.cuni.amis.pogamut.base.utils.PogamutProperty;
9   import cz.cuni.amis.pogamut.base.utils.exception.PogamutJMXNameException;
10  import cz.cuni.amis.utils.NullCheck;
11  import cz.cuni.amis.utils.token.IToken;
12  
13  /**
14   * PogamutJMX serves as a placeholder for creating {@link ObjectName}s for various Pogamut components (classes).
15   * <p><p>
16   * It will be important to you only in the case when you will need to interface Pogamut agents via JMX, it will allow
17   * you to construct correct {@link ObjectName}s that identifies them inside the MBean server.
18   * <p><p>
19   * Still the biggest trick is to obtain {@link IAgentId} (or at least its {@link IAgentId#getToken()}) in order to obtain
20   * correct {@link PogamutJMX#getAgentObjectName(IToken)}.
21   * <p><p>
22   * Note that concrete object names of various agent's components might be obtained by calling static method on concrete class,
23   * i.e., JMXLogCategories#getJMXLogCategoryName.
24   * 
25   * @author Jimmy
26   */
27  public class PogamutJMX {
28  
29  	/**
30  	 * Used by AbstractAgent (i.e., AgentJMXComponents) class
31  	 */
32  	public static final String AGENT_SUBTYPE = "agent";
33  	
34  	/**
35  	 * Used by Act class
36  	 */
37  	public static final String ACT_NAME = "act";
38  	
39  	/**
40  	 * Used by LogCategory class
41  	 */
42  	public static final String LOGCATEGORIES_NAME = "logcat";
43  	
44  	/**
45  	 * LogCategory class
46  	 */ 
47  	public static final String LOGCATEGORY_SUBTYPE = "logcategory";
48  	
49  	/**
50  	 * Flag class
51  	 */
52  	public static final String FLAGS_SUBTYPE = "flags";
53  
54  	/**
55  	 * introspection FolderToJMXEnabledAdapter class
56  	 */
57  	public static final String INTROSPECTION_NAME = "introspection";
58  
59  	/**
60  	 * Used by AgentLogger class. 
61  	 */
62  	public static String AGENT_LOGGER_SUBTYPE = "agentlogger";
63  	
64  	/*====================================================================================*/
65  	
66  	/**
67  	 * Returns an ObjectName for the Pogamut's agents given by his 'agentId'.
68  	 * <p><p>
69  	 * Used by AgentJMXComponents.
70  	 * 
71  	 * @param agentId id of the agent that 
72  	 */
73  	public static ObjectName getAgentObjectName(IToken agentId) {
74  		return getAgentObjectName(agentId.getToken());
75  	}
76  
77  	/**
78  	 * Returns an ObjectName for the Pogamut's agents given by his 'agentId'.
79  	 * <p><p>
80  	 * Used by AgentJMXComponents.
81  	 * 
82  	 * @param agentId id of the agent that
83  	 */
84  	public static ObjectName getAgentObjectName(String agentId) {
85  		return PogamutJMX.getObjectName(getPogamutJMXDomain(), PogamutJMX.AGENT_SUBTYPE + "-" + Pogamut.getPlatform().getProperty(PogamutProperty.POGAMUT_JMX_SUBDOMAIN.getKey()), agentId);
86  	}
87  	
88  	/*====================================================================================*/
89  	
90  	/**
91  	 * Returns an JMX Domain id used by Pogamut's agents.
92  	 * 
93  	 * @return jmx domain used by Pogamut's agents.
94  	 */
95  	public static String getPogamutJMXDomain() {
96  		return Pogamut.getPlatform().getProperty(PogamutProperty.POGAMUT_JMX_DOMAIN.getKey());
97  	}
98  	
99  	/**
100 	 * Creates hierarchical ObjectNames given a parent and name of the MBean.
101 	 * Extra elements can be inserted into the path through typeExtra param.
102 	 * 
103 	 * @param parent
104 	 *            parent's ObjectName
105 	 * @param childName
106 	 *            name of this object, if null no name element will be appended
107 	 * @param childTypeExtra
108 	 *            extra element inserted to the end of hierarchical path, may be null
109 	 * @return ObjectName of form: domain=[parent's domain],type=[parent's
110 	 *         type].[parent's name].[child extra type],name=[childName]
111 	 * @throws PogamutJMXNameException
112 	 */
113 	public static ObjectName getObjectName(ObjectName parent, String childName, String childTypeExtra) throws PogamutJMXNameException {
114 		NullCheck.check(parent, "parent");
115 		
116 		String parentDomain = parent.getDomain();
117 		String parentType = parent.getKeyProperty("type");
118 		String parentName = parent.getKeyProperty("name");
119 		
120 		if (childTypeExtra != null) {
121 			String[] childTypeParts = childTypeExtra.split(".");
122 			if (childTypeParts.length != 0) {
123 				for (int i = 0; i < childTypeParts.length; ++i) {
124 					childTypeParts[i] = getSafeObjectNamePart(childTypeParts[i]);
125 				}
126 				childTypeExtra = childTypeParts[0];
127 				for (int i = 1; i < childTypeParts.length; ++i) {
128 					childTypeExtra += "." + childTypeParts[i];
129 				}
130 			} else {
131 				childTypeExtra = getSafeObjectNamePart(childTypeExtra);
132 			}
133 		}
134 		
135 		String childType = (childTypeExtra == null ?
136 									parentType + "." + parentName
137 								:	parentType + "." + parentName + "." + childTypeExtra
138 						   );
139 		
140 		return getObjectName(parentDomain, childType, childName);		
141 	}
142 	
143 	/**
144 	 * Creates hierarchical ObjectNames given a parent and name of the MBean.
145 	 * Extra elements can be inserted into the path through typeExtra param.
146 	 * 
147 	 * @param parent 
148 	 *            parent's ObjectName
149 	 * @param childName
150 	 *            name of this object, if null no name element will be appended
151 	 * @return ObjectName of form: domain=[parent's domain],type=[parent's
152 	 *         type].[parent's name],name=[name]
153 	 * @throws PogamutJMXNameException
154 	 */
155 	public static ObjectName getObjectName(ObjectName parent, String childName) throws PogamutJMXNameException {
156 		NullCheck.check(parent, "parent");
157 		NullCheck.check(childName, "childName");
158 		
159 		String parentDomain = parent.getKeyProperty("domain");
160 		String parentType = parent.getKeyProperty("type");
161 		String parentName = parent.getKeyProperty("name");
162 		
163 		String childType = parentType + "." + parentName;
164 		
165 		return getObjectName(parentDomain, childType, childName);		
166 	}
167 	
168 	/**
169 	 * Replaces JMX URL chars with '_'.
170 	 * @param str
171 	 * @return
172 	 */
173 	public static String getSafeObjectNamePart(String str) {
174 		return 
175 			str.replace('[', '_').replace(']', '_').replace('(', '_').replace(')', '_')
176 			   .replace('.', '_').replace(',', '_').replace('/', '_').replace('*', '_')
177 			   .replace('?', '_').replace(':', '_');
178 	}
179 	
180 	/**
181 	 * Returns well formed JMX indentificator based on the domain / type / name.
182 	 * <p><p>
183 	 * Can be used to create ObjectName instance from javax.management package to identify
184 	 * the object inside MBeanServer.
185 	 * 
186 	 * @param jmxDomain must be well formed
187 	 * @param type must be well formed
188 	 * @param name may be null, may contain invalid chars (will be replaced with '_')
189 	 * @return instance containing well-formed ObjectName
190 	 * @throws PogamutJMXNameException
191 	 */
192 	public static ObjectName getObjectName(String jmxDomain, String type, String name) throws PogamutJMXNameException {
193 		
194 		if (name != null) {
195 			name = getSafeObjectNamePart(name);
196 		}
197 		
198 		String jmxName = (name == null ?
199 								jmxDomain+":type="+type
200 							:	jmxDomain+":type="+type+",name="+name
201 						 );
202 		try {
203 			return ObjectName.getInstance(jmxName);
204 		} catch (Exception e) {
205 			throw new PogamutJMXNameException(jmxName, e);
206 		}
207 	}
208 
209 }