Merge branch 'jetty-9' of ssh://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project into jetty-9

This commit is contained in:
Joakim Erdfelt 2012-07-23 13:53:22 -07:00
commit 697d32beb4
11 changed files with 371 additions and 131 deletions

View File

@ -13,8 +13,10 @@
package org.eclipse.jetty.jmx; package org.eclipse.jetty.jmx;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
@ -48,6 +50,8 @@ import javax.management.modelmbean.ModelMBean;
import org.eclipse.jetty.util.LazyList; import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.Loader; import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.annotation.Managed;
import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
@ -224,69 +228,66 @@ public class ObjectMBean implements DynamicMBean
Object notifications=null; Object notifications=null;
// Find list of classes that can influence the mbean // Find list of classes that can influence the mbean
Class o_class=_managed.getClass(); Class<?> o_class=_managed.getClass();
Object influences = findInfluences(null, _managed.getClass()); Object influences = findInfluences(null, _managed.getClass());
LOG.debug("Influence Count: " + LazyList.size(influences) ); LOG.debug("Influence Count: " + LazyList.size(influences) );
// Set to record defined items // Process Type Annotations
Set defined=new HashSet(); Managed primary = o_class.getAnnotation( Managed.class);
desc = primary.value();
// For each influence // For each influence
for (int i=0;i<LazyList.size(influences);i++) for (int i=0;i<LazyList.size(influences);i++)
{ {
Class oClass = (Class)LazyList.get(influences, i); Class<?> oClass = (Class<?>)LazyList.get(influences, i);
LOG.debug("Influence: " + oClass.getCanonicalName() ); Managed typeAnnotation = oClass.getAnnotation( Managed.class);
// look for a bundle defining methods LOG.debug("Influenced by: " + oClass.getCanonicalName() );
if (Object.class.equals(oClass)) if ( typeAnnotation == null )
oClass=ObjectMBean.class; {
String pName = oClass.getPackage().getName(); LOG.debug("Annotations not found for: " + oClass.getCanonicalName() );
String cName = oClass.getName().substring(pName.length() + 1); continue;
String rName = pName.replace('.', '/') + "/jmx/" + cName+"-mbean"; }
try try
{ {
LOG.debug(rName); // Process Field Annotations
ResourceBundle bundle = Loader.getResourceBundle(o_class, rName,true,Locale.getDefault()); for ( Field field : oClass.getDeclaredFields())
// Extract meta data from bundle
Enumeration e = bundle.getKeys();
while (e.hasMoreElements())
{ {
String key = (String)e.nextElement(); LOG.debug("Checking: " + field.getName());
String value = bundle.getString(key); Managed fieldAnnotation = field.getAnnotation(Managed.class);
// Determin if key is for mbean , attribute or for operation if ( fieldAnnotation != null )
if (key.equals(cName))
{ {
// set the mbean description LOG.debug("Field Annotation found for: " + field.getName() );
if (desc==null) attributes=LazyList.add(attributes, defineAttribute(field.getName(), fieldAnnotation));
desc=value;
} }
else if (key.indexOf('(')>0) }
// Process Method Annotations
for ( Method method : oClass.getDeclaredMethods() )
{
Managed methodAnnotation = method.getAnnotation(Managed.class);
if ( methodAnnotation != null )
{ {
// define an operation if ( methodAnnotation.attribute() )
if (!defined.contains(key) && key.indexOf('[')<0)
{ {
defined.add(key); // TODO sort out how a proper name could get here, its a method name as an attribute at this point.
operations=LazyList.add(operations,defineOperation(key, value, bundle)); LOG.debug("Attribute Annotation found for: " + method.getName() );
attributes=LazyList.add(attributes,defineAttribute(method.getName(),methodAnnotation));
} }
} else
else
{
// define an attribute
if (!defined.contains(key))
{ {
defined.add(key); LOG.debug("Method Annotation found for: " + method.getName() );
MBeanAttributeInfo info=defineAttribute(key, value); operations=LazyList.add(operations, defineOperation(method, methodAnnotation));
if (info!=null)
attributes=LazyList.add(attributes,info);
} }
} }
} }
} }
catch(MissingResourceException e) catch(MissingResourceException e)
{ {
@ -524,6 +525,8 @@ public class ObjectMBean implements DynamicMBean
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* TODO update to new behavior
*
* Define an attribute on the managed object. The meta data is defined by looking for standard * Define an attribute on the managed object. The meta data is defined by looking for standard
* getter and setter methods. Descriptions are obtained with a call to findDescription with the * getter and setter methods. Descriptions are obtained with a call to findDescription with the
* attribute name. * attribute name.
@ -538,30 +541,13 @@ public class ObjectMBean implements DynamicMBean
* </ul> * </ul>
* the access is either "RW" or "RO". * the access is either "RW" or "RO".
*/ */
public MBeanAttributeInfo defineAttribute(String name, String metaData) public MBeanAttributeInfo defineAttribute(String name, Managed fieldAnnotation)
{ {
String description = ""; //String name = field.getName();
boolean writable = true; String description = fieldAnnotation.value();
boolean onMBean = false; boolean writable = fieldAnnotation.readonly();
boolean convert = false; boolean onMBean = fieldAnnotation.proxied();
boolean convert = fieldAnnotation.managed();
if (metaData!= null)
{
String[] tokens = metaData.split(":", 3);
for (int t=0;t<tokens.length-1;t++)
{
tokens[t]=tokens[t].trim();
if ("RO".equals(tokens[t]))
writable=false;
else
{
onMBean=("MMBean".equalsIgnoreCase(tokens[t]) || "MBean".equalsIgnoreCase(tokens[t]));
convert=("MMBean".equalsIgnoreCase(tokens[t]) || "MObject".equalsIgnoreCase(tokens[t]));
}
}
description=tokens[tokens.length-1];
}
String uName = name.substring(0, 1).toUpperCase() + name.substring(1); String uName = name.substring(0, 1).toUpperCase() + name.substring(1);
Class oClass = onMBean ? this.getClass() : _managed.getClass(); Class oClass = onMBean ? this.getClass() : _managed.getClass();
@ -572,12 +558,35 @@ public class ObjectMBean implements DynamicMBean
Class type = null; Class type = null;
Method getter = null; Method getter = null;
Method setter = null; Method setter = null;
String declaredGetter = fieldAnnotation.getter();
String declaredSetter = fieldAnnotation.setter();
Method[] methods = oClass.getMethods(); Method[] methods = oClass.getMethods();
for (int m = 0; m < methods.length; m++) for (int m = 0; m < methods.length; m++)
{ {
if ((methods[m].getModifiers() & Modifier.PUBLIC) == 0) if ((methods[m].getModifiers() & Modifier.PUBLIC) == 0)
continue; continue;
// Check if it is a declared getter
if (methods[m].getName().equals(declaredGetter) && methods[m].getParameterTypes().length == 0)
{
if (getter != null)
{
LOG.warn("Multiple mbean getters for attr " + name+ " in "+oClass);
continue;
}
getter = methods[m];
if (type != null && !type.equals(methods[m].getReturnType()))
{
LOG.warn("Type conflict for mbean attr " + name+ " in "+oClass);
continue;
}
type = methods[m].getReturnType();
LOG.debug("Declared Getter: " + declaredGetter);
}
// Look for a getter // Look for a getter
if (methods[m].getName().equals("get" + uName) && methods[m].getParameterTypes().length == 0) if (methods[m].getName().equals("get" + uName) && methods[m].getParameterTypes().length == 0)
{ {
@ -612,8 +621,8 @@ public class ObjectMBean implements DynamicMBean
type = methods[m].getReturnType(); type = methods[m].getReturnType();
} }
// look for a setter // look for a declared setter
if (writable && methods[m].getName().equals("set" + uName) && methods[m].getParameterTypes().length == 1) if (writable && methods[m].getName().equals(declaredSetter) && methods[m].getParameterTypes().length == 1)
{ {
if (setter != null) if (setter != null)
{ {
@ -626,6 +635,24 @@ public class ObjectMBean implements DynamicMBean
LOG.warn("Type conflict for mbean attr " + name+ " in "+oClass); LOG.warn("Type conflict for mbean attr " + name+ " in "+oClass);
continue; continue;
} }
LOG.debug("Declared Setter: " + declaredSetter);
type = methods[m].getParameterTypes()[0];
}
// look for a setter
if (writable && methods[m].getName().equals("set" + uName) && methods[m].getParameterTypes().length == 1)
{
if (setter != null)
{
LOG.warn("Multiple setters for mbean attr " + name+ " in "+oClass);
continue;
}
setter = methods[m];
if (type != null && !type.equals(methods[m].getParameterTypes()[0]))
{
LOG.warn("Type conflict for mbean attr " + name+ " in "+oClass);
continue;
}
type = methods[m].getParameterTypes()[0]; type = methods[m].getParameterTypes()[0];
} }
} }
@ -674,7 +701,7 @@ public class ObjectMBean implements DynamicMBean
} }
catch (Exception e) catch (Exception e)
{ {
LOG.warn(name+": "+metaData, e); LOG.warn(e);
throw new IllegalArgumentException(e.toString()); throw new IllegalArgumentException(e.toString());
} }
} }
@ -682,6 +709,8 @@ public class ObjectMBean implements DynamicMBean
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* TODO update to new behavior
*
* Define an operation on the managed object. Defines an operation with parameters. Refection is * Define an operation on the managed object. Defines an operation with parameters. Refection is
* used to determine find the method and it's return type. The description of the method is * used to determine find the method and it's return type. The description of the method is
* found with a call to findDescription on "name(signature)". The name and description of each * found with a call to findDescription on "name(signature)". The name and description of each
@ -693,77 +722,59 @@ public class ObjectMBean implements DynamicMBean
* the "Object","MBean", "MMBean" or "MObject" to indicate the method is on the object, the MBean or on the * the "Object","MBean", "MMBean" or "MObject" to indicate the method is on the object, the MBean or on the
* object but converted to an MBean reference, and impact is either "ACTION","INFO","ACTION_INFO" or "UNKNOWN". * object but converted to an MBean reference, and impact is either "ACTION","INFO","ACTION_INFO" or "UNKNOWN".
*/ */
private MBeanOperationInfo defineOperation(String signature, String metaData, ResourceBundle bundle) private MBeanOperationInfo defineOperation(Method method, Managed methodAnnotation)
{ {
String[] tokens=metaData.split(":",3); String description = methodAnnotation.value();
int i=tokens.length-1; boolean onMBean = methodAnnotation.proxied();
String description=tokens[i--]; boolean convert = methodAnnotation.managed();
String impact_name = i<0?"UNKNOWN":tokens[i--].trim(); String impactName = methodAnnotation.impact();
if (i==0)
tokens[0]=tokens[0].trim();
boolean onMBean= i==0 && ("MBean".equalsIgnoreCase(tokens[0])||"MMBean".equalsIgnoreCase(tokens[0]));
boolean convert= i==0 && ("MObject".equalsIgnoreCase(tokens[0])||"MMBean".equalsIgnoreCase(tokens[0]));
if (LOG.isDebugEnabled()) String signature = method.getName();
LOG.debug("defineOperation "+signature+" "+onMBean+":"+impact_name+":"+description);
LOG.debug("defineOperation "+method.getName()+" "+onMBean+":"+impactName+":"+description);
Class oClass = onMBean ? this.getClass() : _managed.getClass();
try try
{ {
// Resolve the impact // Resolve the impact
int impact=MBeanOperationInfo.UNKNOWN; int impact=MBeanOperationInfo.UNKNOWN;
if (impact_name==null || impact_name.equals("UNKNOWN")) if (impactName==null || impactName.equals("UNKNOWN"))
impact=MBeanOperationInfo.UNKNOWN; impact=MBeanOperationInfo.UNKNOWN;
else if (impact_name.equals("ACTION")) else if (impactName.equals("ACTION"))
impact=MBeanOperationInfo.ACTION; impact=MBeanOperationInfo.ACTION;
else if (impact_name.equals("INFO")) else if (impactName.equals("INFO"))
impact=MBeanOperationInfo.INFO; impact=MBeanOperationInfo.INFO;
else if (impact_name.equals("ACTION_INFO")) else if (impactName.equals("ACTION_INFO"))
impact=MBeanOperationInfo.ACTION_INFO; impact=MBeanOperationInfo.ACTION_INFO;
else else
LOG.warn("Unknown impact '"+impact_name+"' for "+signature); LOG.warn("Unknown impact '"+impactName+"' for "+signature);
// split the signature Annotation[][] allParameterAnnotations = method.getParameterAnnotations();
String[] parts=signature.split("[\\(\\)]"); Class<?>[] methodTypes = method.getParameterTypes();
String method_name=parts[0]; MBeanParameterInfo[] pInfo = new MBeanParameterInfo[allParameterAnnotations.length];
String arguments=parts.length==2?parts[1]:null;
String[] args=arguments==null?new String[0]:arguments.split(" *, *");
// Check types and normalize signature. for ( int i = 0 ; i < allParameterAnnotations.length ; ++i )
Class[] types = new Class[args.length];
MBeanParameterInfo[] pInfo = new MBeanParameterInfo[args.length];
signature=method_name;
for (i = 0; i < args.length; i++)
{ {
Class type = TypeUtil.fromName(args[i]); Annotation[] parameterAnnotations = allParameterAnnotations[i];
if (type == null)
type = Thread.currentThread().getContextClassLoader().loadClass(args[i]);
types[i] = type;
args[i] = type.isPrimitive() ? TypeUtil.toName(type) : args[i];
signature+=(i>0?",":"(")+args[i];
}
signature+=(i>0?")":"()");
// Build param infos for ( Annotation anno : parameterAnnotations )
for (i = 0; i < args.length; i++) {
{ if ( anno instanceof Name )
String param_desc = bundle.getString(signature + "[" + i + "]"); {
parts=param_desc.split(" *: *",2); Name nameAnnotation = (Name) anno;
if (LOG.isDebugEnabled())
LOG.debug(parts[0]+": "+parts[1]); pInfo[i] = new MBeanParameterInfo(nameAnnotation.value(),methodTypes[i].getName(),nameAnnotation.description());
pInfo[i] = new MBeanParameterInfo(parts[0].trim(), args[i], parts[1].trim()); }
}
} }
// build the operation info
Method method = oClass.getMethod(method_name, types);
Class returnClass = method.getReturnType(); Class returnClass = method.getReturnType();
_methods.put(signature, method); _methods.put(signature, method);
if (convert) if (convert)
_convert.add(signature); _convert.add(signature);
return new MBeanOperationInfo(method_name, description, pInfo, returnClass.isPrimitive() ? TypeUtil.toName(returnClass) : (returnClass.getName()), impact); return new MBeanOperationInfo(method.getName(), description, pInfo, returnClass.isPrimitive() ? TypeUtil.toName(returnClass) : (returnClass.getName()), impact);
} }
catch (Exception e) catch (Exception e)
{ {

View File

@ -19,7 +19,7 @@ import org.eclipse.jetty.util.annotation.Name;
@Managed("Test the mbean stuff") @Managed("Test the mbean stuff")
public class Derived extends Base implements Signature public class Derived extends Base implements Signature
{ {
@Managed("The full name of something") @Managed(value="The full name of something", getter="getFullName", setter="setFullName")
String fname="Full Name"; String fname="Full Name";
public String getFullName() public String getFullName()

View File

@ -51,12 +51,17 @@ public class ObjectMBeanTest
Assert.assertEquals("name does not match", "com.acme.Derived", info.getClassName()); Assert.assertEquals("name does not match", "com.acme.Derived", info.getClassName());
Assert.assertEquals("description does not match", "Test the mbean stuff", info.getDescription()); Assert.assertEquals("description does not match", "Test the mbean stuff", info.getDescription());
for ( MBeanAttributeInfo i : info.getAttributes())
{
LOG.debug(i.toString());
}
/* /*
* 6 attributes from lifecycle and 1 from Derived * 6 attributes from lifecycle and 1 from Derived
*/ */
Assert.assertEquals("attribute count does not match", 7, info.getAttributes().length); Assert.assertEquals("attribute count does not match", 7, info.getAttributes().length);
Assert.assertEquals("attribute values does not match", "Full Name", mbean.getAttribute("fullName") ); Assert.assertEquals("attribute values does not match", "Full Name", mbean.getAttribute("fname") );
Assert.assertEquals("operation count does not match", 4, info.getOperations().length); Assert.assertEquals("operation count does not match", 4, info.getOperations().length);
@ -82,8 +87,8 @@ public class ObjectMBeanTest
MBeanParameterInfo[] pinfos = opinfo.getSignature(); MBeanParameterInfo[] pinfos = opinfo.getSignature();
Assert.assertEquals("parameter description doesn't match", "A description of the argument.", pinfos[0].getDescription()); Assert.assertEquals("parameter description doesn't match", "A description of the argument", pinfos[0].getDescription());
Assert.assertEquals("parameter name doesn't match", "argname", pinfos[0].getName()); Assert.assertEquals("parameter name doesn't match", "doodle", pinfos[0].getName());
} }
} }

View File

@ -69,7 +69,6 @@ import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.annotation.Managed; import org.eclipse.jetty.util.annotation.Managed;
import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.util.component.AggregateLifeCycle; import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.component.Dumpable; import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
@ -1204,8 +1203,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/* /*
* @see javax.servlet.ServletContext#removeAttribute(java.lang.String) * @see javax.servlet.ServletContext#removeAttribute(java.lang.String)
*/ */
@Managed("Remove context attribute") public void removeAttribute(String name)
public void removeAttribute( @Name(value = "name", description="attribute name") String name)
{ {
checkManagedAttribute(name,null); checkManagedAttribute(name,null);
_attributes.removeAttribute(name); _attributes.removeAttribute(name);
@ -1218,8 +1216,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
* *
* @see javax.servlet.ServletContext#setAttribute(java.lang.String, java.lang.Object) * @see javax.servlet.ServletContext#setAttribute(java.lang.String, java.lang.Object)
*/ */
@Managed("Set context attribute") public void setAttribute( String name, Object value)
public void setAttribute(@Name(value = "name", description="attribute name") String name, @Name(value = "value", description="attribute value") Object value)
{ {
checkManagedAttribute(name,value); checkManagedAttribute(name,value);
_attributes.setAttribute(name,value); _attributes.setAttribute(name,value);

View File

@ -19,6 +19,8 @@ import java.util.Map;
import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.Attributes; import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.annotation.Managed;
import org.eclipse.jetty.util.annotation.Name;
public class ContextHandlerMBean extends AbstractHandlerMBean public class ContextHandlerMBean extends AbstractHandlerMBean
{ {
@ -27,6 +29,7 @@ public class ContextHandlerMBean extends AbstractHandlerMBean
super(managedObject); super(managedObject);
} }
@Managed(value="Map of context attributes", readonly=true, attribute=true)
public Map getContextAttributes() public Map getContextAttributes()
{ {
Map map = new HashMap(); Map map = new HashMap();
@ -41,19 +44,22 @@ public class ContextHandlerMBean extends AbstractHandlerMBean
return map; return map;
} }
public void setContextAttribute(String name, Object value) @Managed(value="Set context attribute", impact="ACTION")
public void setContextAttribute(@Name(value = "name", description="attribute name") String name, @Name(value = "value", description="attribute value") Object value)
{ {
Attributes attrs = ((ContextHandler)_managed).getAttributes(); Attributes attrs = ((ContextHandler)_managed).getAttributes();
attrs.setAttribute(name,value); attrs.setAttribute(name,value);
} }
public void setContextAttribute(String name, String value) @Managed(value="Set context attribute", impact="ACTION")
public void setContextAttribute(@Name(value = "name", description="attribute name") String name, @Name(value = "value", description="attribute value") String value)
{ {
Attributes attrs = ((ContextHandler)_managed).getAttributes(); Attributes attrs = ((ContextHandler)_managed).getAttributes();
attrs.setAttribute(name,value); attrs.setAttribute(name,value);
} }
public void removeContextAttribute(String name) @Managed(value="Remove context attribute", impact="ACTION")
public void removeContextAttribute(@Name(value = "name", description="attribute name") String name)
{ {
Attributes attrs = ((ContextHandler)_managed).getAttributes(); Attributes attrs = ((ContextHandler)_managed).getAttributes();
attrs.removeAttribute(name); attrs.removeAttribute(name);

View File

@ -23,7 +23,77 @@ import java.lang.annotation.Target;
@Target( { ElementType.TYPE, ElementType.METHOD, ElementType.FIELD } ) @Target( { ElementType.TYPE, ElementType.METHOD, ElementType.FIELD } )
public @interface Managed public @interface Managed
{ {
/**
* Description of the Managed Object
*
* @return
*/
String value() default "Not Specified"; String value() default "Not Specified";
/**
* Is the managed field read-only?
*
* NOTE: applies to FIELD
*
* @return true if readonly
*/
boolean readonly() default false; boolean readonly() default false;
/**
* Is the managed field itself a Managed Object?
*
* NOTE: applies to FIELD
*
* @return true if the target is a Managed Object
*/
boolean managed() default false; boolean managed() default false;
/**
* Does the managed field or method exist on a proxy object?
*
* NOTE: applies to FIELD and METHOD
*
* @return true if a proxy object is involved
*/
boolean proxied() default false;
/**
* The impact of an operation.
*
* NOTE: Valid values are UNKNOWN, ACTION, INFO, ACTION_INFO
*
* NOTE: applies to METHOD
*
* @return String representing the impact of the operation
*/
String impact() default "UNKNOWN";
/**
* If is a field references a getter that doesn't conform to standards for discovery
* it can be set here.
*
* NOTE: applies to FIELD
*
* @return the full name of the getter in question
*/
String getter() default "";
/**
* If is a field references a setter that doesn't conform to standards for discovery
* it can be set here.
*
* NOTE: applies to FIELD
*
* @return the full name of the setter in question
*/
String setter() default "";
/**
* Treat method as an attribute and not an operation
*
* NOTE: applies to METHOD
*
* @return true of the method should be treating as an attribute
*/
boolean attribute() default false;
} }

View File

@ -0,0 +1,71 @@
package org.eclipse.jetty.util.annotation;
//========================================================================
//Copyright 2011-2012 Mort Bay Consulting Pty. Ltd.
//------------------------------------------------------------------------
//All rights reserved. This program and the accompanying materials
//are made available under the terms of the Eclipse Public License v1.0
//and Apache License v2.0 which accompanies this distribution.
//The Eclipse Public License is available at
//http://www.eclipse.org/legal/epl-v10.html
//The Apache License v2.0 is available at
//http://www.opensource.org/licenses/apache2.0.php
//You may elect to redistribute this code under either of these licenses.
//========================================================================
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target( { ElementType.METHOD, ElementType.FIELD } )
public @interface ManagedAttribute
{
/**
* Description of the Managed Object
*
* @return
*/
String value() default "Not Specified";
/**
* Is the managed field read-only?
*
* @return true if readonly
*/
boolean readonly() default false;
/**
* Is the managed field itself a Managed Object?
*
* @return true if the target is a Managed Object
*/
boolean managed() default false;
/**
* Does the managed field exist on a proxy object?
*
*
* @return true if a proxy object is involved
*/
boolean proxied() default false;
/**
* If is a field references a getter that doesn't conform to standards for discovery
* it can be set here.
*
* @return the full name of the getter in question
*/
String getter() default "";
/**
* If is a field references a setter that doesn't conform to standards for discovery
* it can be set here.
*
* @return the full name of the setter in question
*/
String setter() default "";
}

View File

@ -0,0 +1,21 @@
package org.eclipse.jetty.util.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target( { ElementType.TYPE, ElementType.METHOD, ElementType.FIELD } )
public @interface ManagedObject
{
/**
* Description of the Managed Object
*
* @return
*/
String value() default "Not Specified";
}

View File

@ -0,0 +1,45 @@
package org.eclipse.jetty.util.annotation;
//========================================================================
//Copyright 2011-2012 Mort Bay Consulting Pty. Ltd.
//------------------------------------------------------------------------
//All rights reserved. This program and the accompanying materials
//are made available under the terms of the Eclipse Public License v1.0
//and Apache License v2.0 which accompanies this distribution.
//The Eclipse Public License is available at
//http://www.eclipse.org/legal/epl-v10.html
//The Apache License v2.0 is available at
//http://www.opensource.org/licenses/apache2.0.php
//You may elect to redistribute this code under either of these licenses.
//========================================================================
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target( { ElementType.METHOD } )
public @interface ManagedOperation
{
/**
* Description of the Managed Object
*
* @return
*/
String value() default "Not Specified";
/**
* The impact of an operation.
*
* NOTE: Valid values are UNKNOWN, ACTION, INFO, ACTION_INFO
*
* NOTE: applies to METHOD
*
* @return String representing the impact of the operation
*/
String impact() default "UNKNOWN";
}

View File

@ -15,6 +15,7 @@ package org.eclipse.jetty.util.component;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import org.eclipse.jetty.util.annotation.Managed;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
@ -23,14 +24,22 @@ import org.eclipse.jetty.util.log.Logger;
* *
* *
*/ */
@Managed("Abstract Implementation of LifeCycle")
public abstract class AbstractLifeCycle implements LifeCycle public abstract class AbstractLifeCycle implements LifeCycle
{ {
private static final Logger LOG = Log.getLogger(AbstractLifeCycle.class); private static final Logger LOG = Log.getLogger(AbstractLifeCycle.class);
@Managed(value="instance is stopped", readonly=true, getter="isStopped")
public static final String STOPPED="STOPPED"; public static final String STOPPED="STOPPED";
@Managed(value="instance is failed", readonly=true, getter="isFailed")
public static final String FAILED="FAILED"; public static final String FAILED="FAILED";
@Managed(value="instance is starting", readonly=true, getter="isStarting")
public static final String STARTING="STARTING"; public static final String STARTING="STARTING";
@Managed(value="instance is started", readonly=true, getter="isStarted")
public static final String STARTED="STARTED"; public static final String STARTED="STARTED";
@Managed(value="instance is stopping", readonly=true, getter="isStopping")
public static final String STOPPING="STOPPING"; public static final String STOPPING="STOPPING";
@Managed(value="instance is running", readonly=true, getter="isRunning")
public static final String RUNNING="RUNNING"; public static final String RUNNING="RUNNING";
private final CopyOnWriteArrayList<LifeCycle.Listener> _listeners=new CopyOnWriteArrayList<LifeCycle.Listener>(); private final CopyOnWriteArrayList<LifeCycle.Listener> _listeners=new CopyOnWriteArrayList<LifeCycle.Listener>();

View File

@ -15,6 +15,8 @@ package org.eclipse.jetty.util.component;
import java.util.EventListener; import java.util.EventListener;
import org.eclipse.jetty.util.annotation.Managed;
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* The lifecycle interface for generic components. * The lifecycle interface for generic components.
@ -24,6 +26,7 @@ import java.util.EventListener;
* *
* *
*/ */
@Managed("Lifecycle Interface for startable components")
public interface LifeCycle public interface LifeCycle
{ {
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -34,6 +37,7 @@ public interface LifeCycle
* @see #stop() * @see #stop()
* @see #isFailed() * @see #isFailed()
*/ */
@Managed("Starts the instance")
public void start() public void start()
throws Exception; throws Exception;
@ -47,6 +51,7 @@ public interface LifeCycle
* @see #start() * @see #start()
* @see #isFailed() * @see #isFailed()
*/ */
@Managed("Stops the instance")
public void stop() public void stop()
throws Exception; throws Exception;