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 java.util.Arrays;
025:
026: import javax.management.Descriptor;
027: import javax.management.InvalidAttributeValueException;
028: import javax.management.ObjectName;
029:
030: import org.jboss.logging.Logger;
031: import org.jboss.mx.modelmbean.ModelMBeanConstants;
032: import org.jboss.mx.server.Invocation;
033:
034: /** This interceptor handles the ModelMBean operation caching
035: *
036: * @author <a href="mailto:juha@jboss.org">Adrian Brock</a>.
037: * @author Scott.Stark@jboss.org
038: * @version $Revision: 57200 $
039: */
040: public class ModelMBeanOperationInterceptor extends AbstractInterceptor
041: implements ModelMBeanConstants {
042: // Constants -----------------------------------------------------
043:
044: private static final Logger log = Logger
045: .getLogger(ModelMBeanOperationInterceptor.class);
046:
047: // Attributes ----------------------------------------------------
048:
049: private boolean trace = log.isTraceEnabled();
050:
051: // Constructors --------------------------------------------------
052:
053: public ModelMBeanOperationInterceptor() {
054: super ("ModelMBean Operation Interceptor");
055: }
056:
057: // Public --------------------------------------------------------
058:
059: public Object invoke(Invocation invocation) throws Throwable {
060: // get the operation's descriptor
061: Descriptor d = invocation.getDescriptor();
062: Class clazz = invocation.getReturnTypeClass();
063:
064: String name = null;
065: ObjectName objectName = null;
066: if (trace) {
067: if (d != null)
068: name = (String) d.getFieldValue(NAME);
069: objectName = invocation.getInvoker().getObjectName();
070: }
071:
072: if (trace) {
073: Object args = invocation.getArgs();
074: if (args != null)
075: args = Arrays.asList((Object[]) args);
076: log.trace("Invoking objectName=" + objectName + " oper="
077: + name + " args=" + args + " desc=" + d);
078: }
079:
080: long limit = CACHE_NEVER_LIMIT;
081:
082: if (d != null && clazz != null) {
083: String timeLimit = (String) d
084: .getFieldValue(CURRENCY_TIME_LIMIT);
085: if (timeLimit != null)
086: limit = Long.parseLong(timeLimit);
087:
088: // We are never stale
089: if (limit == CACHE_ALWAYS_LIMIT) {
090: String timeStamp = (String) d
091: .getFieldValue(LAST_UPDATED_TIME_STAMP);
092: if (timeStamp != null) {
093: Object value = d.getFieldValue(CACHED_VALUE);
094: if (trace)
095: log.trace("Always cache objectName="
096: + objectName + " oper=" + name
097: + " value=" + value);
098: checkAssignable("Cached value in descriptor ",
099: clazz, value);
100: return value;
101: }
102: }
103:
104: // is caching enabled
105: if (limit != CACHE_NEVER_LIMIT) {
106: String timeStamp = (String) d
107: .getFieldValue(LAST_UPDATED_TIME_STAMP);
108: long lastUpdate = (timeStamp == null) ? 0 : Long
109: .parseLong(timeStamp);
110:
111: // if the value hasn't gone stale, return from the descriptor
112: long now = System.currentTimeMillis();
113: long expires = lastUpdate * 1000 + limit * 1000;
114: if (now < expires) {
115: Object value = d.getFieldValue(CACHED_VALUE);
116: if (trace)
117: log.trace("Using cache objectName="
118: + objectName + " oper=" + name
119: + " value=" + value + " now=" + now
120: + " expires=" + expires);
121: checkAssignable("Cached value in descriptor ",
122: clazz, value);
123: return value;
124: } else {
125: if (trace)
126: log
127: .trace("Cache expired objectName="
128: + objectName + " oper=" + name
129: + " now=" + now + " expires="
130: + expires);
131: d.removeField(CACHED_VALUE);
132: }
133: } else {
134: // Unfortunatley we have to cope with stupid users
135: if (trace)
136: log.trace("Removing any cached value objectName="
137: + objectName + " oper=" + name
138: + " descriptor=" + d);
139: d.removeField(CACHED_VALUE);
140: }
141: }
142:
143: // we got here means either stale value in descriptior, or no caching
144: Object value = invocation.invoke();
145: if (trace)
146: log.trace("Got result objectName=" + objectName + " oper="
147: + name + " value=" + value);
148:
149: // update the descriptor (unless not caching)
150: if (d != null && limit != CACHE_NEVER_LIMIT) {
151: String timestamp = Long
152: .toString(System.currentTimeMillis() / 1000);
153: if (trace)
154: log.trace("Cache result objectName=" + objectName
155: + " oper=" + name + " value=" + value
156: + " timestamp=" + timestamp);
157: d.setField(CACHED_VALUE, value);
158: d.setField(LAST_UPDATED_TIME_STAMP, timestamp);
159: }
160: return value;
161: }
162:
163: protected void checkAssignable(String context, Class clazz,
164: Object value) throws InvalidAttributeValueException,
165: ClassNotFoundException {
166: if (value != null
167: && clazz.isAssignableFrom(value.getClass()) == false)
168: throw new InvalidAttributeValueException(context
169: + " has class " + value.getClass()
170: + " loaded from "
171: + value.getClass().getClassLoader()
172: + " that is not assignable to attribute class "
173: + clazz + " loaded from " + clazz.getClassLoader());
174: }
175: }
|