001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.mx.interceptor;
023:
024: import javax.management.Attribute;
025: import javax.management.Descriptor;
026: import javax.management.InvalidAttributeValueException;
027: import javax.management.ObjectName;
028:
029: import org.jboss.logging.Logger;
030: import org.jboss.mx.modelmbean.ModelMBeanConstants;
031: import org.jboss.mx.modelmbean.ModelMBeanInvoker;
032: import org.jboss.mx.server.Invocation;
033: import org.jboss.util.UnreachableStatementException;
034:
035: /** This interceptor handles the ModelMBean attribute caching and setter
036: * and getter dispatches.
037: *
038: * @author <a href="mailto:juha@jboss.org">Juha Lindfors</a>.
039: * @author Scott.Stark@jboss.org
040: * @author <a href="mailto:dimitris@jboss.org">Dimitris Andreadis</a>.
041: * @version $Revision: 57200 $
042: */
043: public class ModelMBeanAttributeInterceptor extends AbstractInterceptor
044: implements ModelMBeanConstants {
045: // Constants -----------------------------------------------------
046:
047: private static final Logger log = Logger
048: .getLogger(ModelMBeanAttributeInterceptor.class);
049:
050: // Attributes ----------------------------------------------------
051:
052: private boolean trace = log.isTraceEnabled();
053:
054: // Constructors --------------------------------------------------
055:
056: public ModelMBeanAttributeInterceptor() {
057: super ("ModelMBean Attribute Interceptor");
058: }
059:
060: // Public --------------------------------------------------------
061:
062: public Object invoke(Invocation invocation) throws Throwable {
063: // get the attribute's descriptor
064: Descriptor d = invocation.getDescriptor();
065: Class clazz = invocation.getAttributeTypeClass();
066:
067: String name = null;
068: ObjectName objectName = null;
069: if (trace) {
070: name = (String) d.getFieldValue(NAME);
071: objectName = invocation.getInvoker().getObjectName();
072: }
073:
074: // check the invocation access point: setAttribute()
075: if (invocation.getType().equals(Invocation.OP_SETATTRIBUTE)) {
076: // setAttribute always contains one arg
077: Object value = invocation.getArgs()[0];
078: if (trace)
079: log.trace("Setting objectName=" + objectName + " attr="
080: + name + " value=" + value);
081:
082: checkAssignable("Set attribute ", clazz, value);
083:
084: // remember the old value of this attribute for AVC notification
085: Object oldValue = d.getFieldValue(ATTRIBUTE_VALUE);
086: if (trace)
087: log.trace("Setting objectName=" + objectName + " attr="
088: + name + " oldValue=" + value);
089:
090: // check if the attribute maps to a setter
091: String setMethod = (String) d.getFieldValue(SET_METHOD);
092: if (trace)
093: log.trace("Setting objectName=" + objectName + " attr="
094: + name + " setMethod=" + setMethod);
095:
096: if (setMethod != null) {
097: // if setter was found, invoke the corresponding setter operation
098: invocation.invoke();
099: }
100:
101: // Don't cache the value or last update when not caching
102: String timeLimit = (String) d
103: .getFieldValue(CURRENCY_TIME_LIMIT);
104: long limit = (timeLimit == null) ? CACHE_NEVER_LIMIT : Long
105: .parseLong(timeLimit);
106: String timestamp = Long
107: .toString(System.currentTimeMillis() / 1000);
108:
109: if (limit != CACHE_NEVER_LIMIT) {
110: if (trace)
111: log.trace("Setting objectName=" + objectName
112: + " attr=" + name + " value=" + value
113: + " timestamp=" + timestamp);
114: d.setField(CACHED_VALUE, value);
115: d.setField(LAST_UPDATED_TIME_STAMP, timestamp);
116: }
117:
118: // Always store the attribute value set, for persistence and AVC purposes mainly
119: // independent of whether caching is enabled or not.
120: // Note that if the resource updates its internal attribute value
121: // we will not know, unless set is performed through the ModelMBean
122: // interface, or the following descriptor gets updated somehow.
123: d.setField(ATTRIBUTE_VALUE, value);
124: d.setField(LAST_UPDATED_TIME_STAMP2, timestamp);
125:
126: // send AVC notification
127: ModelMBeanInvoker invoker = (ModelMBeanInvoker) invocation
128: .getInvoker();
129: invoker.sendAttributeChangeNotification(new Attribute(
130: invocation.getName(), oldValue), new Attribute(
131: invocation.getName(), value));
132: return null;
133: } else if (invocation.getType().equals(
134: Invocation.OP_GETATTRIBUTE)) {
135: if (trace)
136: log.trace("Getting objectName=" + objectName + " attr="
137: + name);
138:
139: String timeLimit = (String) d
140: .getFieldValue(CURRENCY_TIME_LIMIT);
141: long limit = (timeLimit == null) ? CACHE_NEVER_LIMIT : Long
142: .parseLong(timeLimit);
143:
144: // We are never stale
145: if (limit == CACHE_ALWAYS_LIMIT) {
146: String timeStamp = (String) d
147: .getFieldValue(LAST_UPDATED_TIME_STAMP);
148: if (timeStamp != null) {
149: Object value = d.getFieldValue(CACHED_VALUE);
150: if (trace)
151: log.trace("Always cache objectName="
152: + objectName + " attr=" + name
153: + " value=" + value);
154: checkAssignable("Cached value in descriptor ",
155: clazz, value);
156: return value;
157: }
158: }
159:
160: // is caching enabled
161: if (limit != CACHE_NEVER_LIMIT) {
162: String timeStamp = (String) d
163: .getFieldValue(LAST_UPDATED_TIME_STAMP);
164: long lastUpdate = (timeStamp == null) ? 0 : Long
165: .parseLong(timeStamp);
166:
167: // if the value hasn't gone stale, return from the descriptor
168: long now = System.currentTimeMillis();
169: long expires = lastUpdate * 1000 + limit * 1000;
170: if (now < expires) {
171: Object value = d.getFieldValue(CACHED_VALUE);
172: if (trace)
173: log.trace("Using cache objectName="
174: + objectName + " attr=" + name
175: + " value=" + value + " now=" + now
176: + " expires=" + expires);
177: checkAssignable("Cached value in descriptor ",
178: clazz, value);
179: return value;
180: } else {
181: if (trace)
182: log
183: .trace("Cache expired objectName="
184: + objectName + " attr=" + name
185: + " now=" + now + " expires="
186: + expires);
187: d.removeField(CACHED_VALUE);
188: }
189: } else {
190: // Unfortunatley we have to cope with stupid users
191: if (trace)
192: log.trace("Removing any cached value objectName="
193: + objectName + " attr=" + name
194: + " descriptor=" + d);
195: d.removeField(CACHED_VALUE);
196: }
197:
198: // get the attribute's descriptor
199: String getMethod = (String) d.getFieldValue(GET_METHOD);
200: if (trace)
201: log.trace("Get attribute objectName=" + objectName
202: + " attr=" + name + " getMethod=" + getMethod);
203:
204: if (getMethod != null) {
205: // we got here means either stale value in descriptior, or no caching
206: Object value = invocation.invoke();
207: if (trace)
208: log.trace("Got attribute objectName=" + objectName
209: + " attr=" + name + " value=" + value);
210:
211: // update the descriptor (unless not caching)
212: if (limit != CACHE_NEVER_LIMIT) {
213: String timestamp = Long.toString(System
214: .currentTimeMillis() / 1000);
215: if (trace)
216: log.trace("Cache attribute objectName="
217: + objectName + " attr=" + name
218: + " value=" + value + " timestamp="
219: + timestamp);
220: d.setField(CACHED_VALUE, value);
221: d.setField(LAST_UPDATED_TIME_STAMP, timestamp);
222: }
223: return value;
224: } else {
225: // There is no instance accessor so check for a default value
226: Object value = d.getFieldValue(DEFAULT);
227: if (trace)
228: log.trace("Get attribute use default objectName="
229: + objectName + " attr=" + name
230: + " default=" + value);
231: checkAssignable("Default value ", clazz, value);
232: return value;
233: }
234: } else
235: throw new UnreachableStatementException(invocation
236: .getType());
237: }
238:
239: protected void checkAssignable(String context, Class clazz,
240: Object value) throws InvalidAttributeValueException,
241: ClassNotFoundException {
242: if (value != null
243: && clazz.isAssignableFrom(value.getClass()) == false)
244: throw new InvalidAttributeValueException(context
245: + " has class " + value.getClass()
246: + " loaded from "
247: + value.getClass().getClassLoader()
248: + " that is not assignable to attribute class "
249: + clazz + " loaded from " + clazz.getClassLoader());
250: }
251: }
|