1 /*
2 * Copyright 1999-2004 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package javax.management;
27
28
29 import com.sun.jmx.mbeanserver.Introspector;
30 import java.io.IOException;
31 import java.io.ObjectInputStream;
32
33 /**
34 * <p>Represents attributes used as arguments to relational constraints.
35 * Instances of this class are usually obtained using {@link Query#attr(String)
36 * Query.attr}.</p>
37 *
38 * <p>An <CODE>AttributeValueExp</CODE> may be used anywhere a
39 * <CODE>ValueExp</CODE> is required.
40 *
41 * @since 1.5
42 */
43 public class AttributeValueExp implements ValueExp {
44
45
46 /* Serial version */
47 private static final long serialVersionUID = -7768025046539163385L;
48
49 /**
50 * @serial The name of the attribute
51 */
52 private String attr;
53
54 private transient int dotIndex;
55
56 /**
57 * An <code>AttributeValueExp</code> with a null attribute.
58 * @deprecated An instance created with this constructor cannot be
59 * used in a query.
60 */
61 @Deprecated
62 public AttributeValueExp() {
63 }
64
65 /**
66 * Creates a new <CODE>AttributeValueExp</CODE> representing the
67 * specified object attribute, named attr.
68 *
69 * @param attr the name of the attribute whose value is the value
70 * of this {@link ValueExp}.
71 */
72 public AttributeValueExp(String attr) {
73 this.attr = attr;
74 setDotIndex();
75 }
76
77 private void setDotIndex() {
78 if (attr != null)
79 dotIndex = attr.indexOf('.');
80 }
81
82 private void readObject(ObjectInputStream in)
83 throws ClassNotFoundException, IOException {
84 in.defaultReadObject();
85 setDotIndex();
86 }
87
88 /**
89 * Returns a string representation of the name of the attribute.
90 *
91 * @return the attribute name.
92 */
93 public String getAttributeName() {
94 return attr;
95 }
96
97 /**
98 * <p>Applies the <CODE>AttributeValueExp</CODE> on an MBean.
99 * This method calls {@link #getAttribute getAttribute(name)} and wraps
100 * the result as a {@code ValueExp}. The value returned by
101 * {@code getAttribute} must be a {@code Number}, {@code String},
102 * or {@code Boolean}; otherwise this method throws a
103 * {@code BadAttributeValueExpException}, which will cause
104 * the containing query to be false for this {@code name}.</p>
105 *
106 * @param name The name of the MBean on which the <CODE>AttributeValueExp</CODE> will be applied.
107 *
108 * @return The <CODE>ValueExp</CODE>.
109 *
110 * @exception BadAttributeValueExpException
111 * @exception InvalidApplicationException
112 * @exception BadStringOperationException
113 * @exception BadBinaryOpValueExpException
114 *
115 */
116 @Override
117 public ValueExp apply(ObjectName name) throws BadStringOperationException, BadBinaryOpValueExpException,
118 BadAttributeValueExpException, InvalidApplicationException {
119 Object result = getAttribute(name);
120
121 if (result instanceof Number) {
122 return new NumericValueExp((Number)result);
123 } else if (result instanceof String) {
124 return new StringValueExp((String)result);
125 } else if (result instanceof Boolean) {
126 return new BooleanValueExp((Boolean)result);
127 } else {
128 throw new BadAttributeValueExpException(result);
129 }
130 }
131
132 /**
133 * Returns the string representing its value.
134 */
135 @Override
136 public String toString() {
137 return QueryParser.quoteId(attr);
138 }
139
140
141 /**
142 * Sets the MBean server on which the query is to be performed.
143 *
144 * @param s The MBean server on which the query is to be performed.
145 *
146 * @deprecated This method has no effect. The MBean Server used to
147 * obtain an attribute value is {@link QueryEval#getMBeanServer()}.
148 */
149 /* There is no need for this method, because if a query is being
150 evaluted an AttributeValueExp can only appear inside a QueryExp,
151 and that QueryExp will itself have done setMBeanServer. */
152 @Deprecated
153 @Override
154 public void setMBeanServer(MBeanServer s) {
155 }
156
157
158 /**
159 * <p>Return the value of the given attribute in the named MBean.
160 * If the attempt to access the attribute generates an exception,
161 * return null.</p>
162 *
163 * <p>Let <em>n</em> be the {@linkplain #getAttributeName attribute
164 * name}. Then this method proceeds as follows. First it calls
165 * {@link MBeanServer#getAttribute getAttribute(name, <em>n</em>)}. If that
166 * generates an {@link AttributeNotFoundException}, and if <em>n</em>
167 * contains at least one dot ({@code .}), then the method calls {@code
168 * getAttribute(name, }<em>n</em>{@code .substring(0, }<em>n</em>{@code
169 * .indexOf('.')))}; in other words it calls {@code getAttribute}
170 * with the substring of <em>n</em> before the first dot. Then it
171 * extracts a component from the retrieved value, as described in the <a
172 * href="monitor/package-summary.html#complex">documentation for the {@code
173 * monitor} package</a>.</p>
174 *
175 * <p>The MBean Server used is the one returned by {@link
176 * QueryEval#getMBeanServer()}.</p>
177 *
178 * @param name the name of the MBean whose attribute is to be returned.
179 *
180 * @return the value of the attribute, or null if it could not be
181 * obtained.
182 */
183 protected Object getAttribute(ObjectName name) {
184 try {
185 // Get the value from the MBeanServer
186
187 MBeanServer server = QueryEval.getMBeanServer();
188
189 try {
190 return server.getAttribute(name, attr);
191 } catch (AttributeNotFoundException e) {
192 if (dotIndex < 0)
193 throw e;
194 }
195
196 String toGet = attr.substring(0, dotIndex);
197
198 Object value = server.getAttribute(name, toGet);
199
200 return extractElement(value, attr.substring(dotIndex + 1));
201 } catch (Exception re) {
202 return null;
203 }
204 }
205
206 private Object extractElement(Object value, String elementWithDots)
207 throws AttributeNotFoundException {
208 while (true) {
209 int dot = elementWithDots.indexOf('.');
210 String element = (dot < 0) ?
211 elementWithDots : elementWithDots.substring(0, dot);
212 value = Introspector.elementFromComplex(value, element);
213 if (dot < 0)
214 return value;
215 elementWithDots = elementWithDots.substring(dot + 1);
216 }
217 }
218
219 }