0001: /*
0002: * JavaModelHelper.java
0003: *
0004: * Created on November 14, 2006, 11:49 AM
0005: *
0006: * To change this template, choose Tools | Template Manager
0007: * and open the template in the editor.
0008: */
0009:
0010: package org.netbeans.modules.jmx;
0011:
0012: import com.sun.javadoc.Doc;
0013: import com.sun.source.tree.AnnotationTree;
0014: import com.sun.source.tree.BlockTree;
0015: import com.sun.source.tree.ClassTree;
0016: import com.sun.source.tree.CompilationUnitTree;
0017: import com.sun.source.tree.ExpressionStatementTree;
0018: import com.sun.source.tree.ExpressionTree;
0019: import com.sun.source.tree.IdentifierTree;
0020: import com.sun.source.tree.LiteralTree;
0021: import com.sun.source.tree.MemberSelectTree;
0022: import com.sun.source.tree.MethodInvocationTree;
0023: import com.sun.source.tree.MethodTree;
0024: import com.sun.source.tree.ModifiersTree;
0025: import com.sun.source.tree.NewClassTree;
0026: import com.sun.source.tree.StatementTree;
0027: import com.sun.source.tree.Tree;
0028: import com.sun.source.tree.TypeParameterTree;
0029: import com.sun.source.tree.VariableTree;
0030: import com.sun.source.tree.VariableTree;
0031: import com.sun.source.tree.ImportTree;
0032: import com.sun.source.util.SourcePositions;
0033: import com.sun.source.util.TreePathScanner; //import com.sun.tools.javac.code.Symbol.TypeSymbol;
0034: import java.io.IOException;
0035: import java.util.ArrayList;
0036: import java.util.Collections;
0037: import java.util.HashMap;
0038: import java.util.HashSet;
0039: import java.util.Iterator;
0040: import java.util.List;
0041: import java.util.Map;
0042: import java.util.Set;
0043: import javax.lang.model.element.Element;
0044: import javax.lang.model.element.ElementKind;
0045: import javax.lang.model.element.ExecutableElement;
0046: import javax.lang.model.element.Modifier;
0047: import javax.lang.model.element.PackageElement;
0048: import javax.lang.model.element.TypeElement;
0049: import javax.lang.model.element.TypeParameterElement;
0050: import javax.lang.model.element.VariableElement;
0051: import javax.lang.model.type.TypeKind;
0052: import javax.lang.model.type.TypeMirror;
0053: import javax.lang.model.element.AnnotationMirror;
0054: import javax.lang.model.element.AnnotationValue;
0055: import javax.lang.model.util.ElementFilter;
0056: import javax.lang.model.util.Elements;
0057: import org.netbeans.api.java.project.JavaProjectConstants;
0058: import org.netbeans.api.java.source.CancellableTask;
0059: import org.netbeans.api.java.source.ClasspathInfo;
0060: import org.netbeans.api.java.source.CompilationController;
0061: import org.netbeans.api.java.source.CompilationInfo;
0062: import org.netbeans.api.java.source.JavaSource;
0063: import org.netbeans.api.java.source.JavaSource.Phase;
0064: import org.netbeans.api.java.source.SourceUtils;
0065: import org.netbeans.api.java.source.TreeMaker;
0066: import org.netbeans.api.java.source.WorkingCopy;
0067: import org.netbeans.api.java.source.SourceUtils;
0068: import org.netbeans.api.project.Project;
0069: import org.netbeans.api.project.ProjectUtils;
0070: import org.netbeans.api.project.SourceGroup;
0071: import org.netbeans.api.project.Sources;
0072: import org.openide.filesystems.FileObject;
0073: import java.text.MessageFormat;
0074: import javax.lang.model.type.ArrayType;
0075: import javax.lang.model.type.DeclaredType;
0076: import javax.management.NotCompliantMBeanException;
0077: import org.netbeans.api.java.source.Comment;
0078: import org.netbeans.api.java.source.Comment.Style;
0079:
0080: /**
0081: *
0082: * @author jfdenise
0083: */
0084: public class JavaModelHelper {
0085:
0086: private static final String METHOD_SIGNATURE_DEF = "String[] methodSignature;\n\n"; // NOI18N
0087:
0088: private static final String METHOD_SIGNATURE = "methodSignature = new String[] {\n"; // NOI18N
0089:
0090: // {0} = operation name
0091: // {1} = operation code
0092: // {2} = operation name code to check
0093: private static final String OPERATION_CHECK_PATTERN = "if ({2}.equals(\"{0}\") && Arrays.equals(signature, methodSignature)) '{'\n"
0094: + // NOI18N
0095: " {1}\n" + // NOI18N
0096: "'}'\n\n"; // NOI18N
0097:
0098: public static String INIT_METHOD_NAME = "init";// NOI18N
0099: public static String GET_MBEANSERVER_METHOD_NAME = "getMBeanServer";// NOI18N
0100:
0101: private static class ValueHolder {
0102: Object value;
0103:
0104: void setValue(Object value) {
0105: this .value = value;
0106: }
0107:
0108: Object getValue() {
0109: return value;
0110: }
0111: }
0112:
0113: private abstract static class MemberVisitor extends
0114: TreePathScanner<Void, Void> {
0115: protected CompilationInfo info;
0116: protected ValueHolder holder;
0117:
0118: public MemberVisitor(CompilationInfo info, ValueHolder holder) {
0119: this .info = info;
0120: this .holder = holder;
0121: }
0122: }
0123:
0124: private static class IsDynamicMBeanVisitor extends MemberVisitor {
0125: public IsDynamicMBeanVisitor(CompilationInfo info,
0126: ValueHolder holder) {
0127: super (info, holder);
0128: }
0129:
0130: @Override
0131: public Void visitClass(ClassTree t, Void v) {
0132: Element el = info.getTrees().getElement(getCurrentPath());
0133: if (el == null) {
0134: throw new RuntimeException("Invalid Class");// NOI18N
0135: }
0136: TypeElement te = (TypeElement) el;
0137: if (te.getKind().equals(ElementKind.INTERFACE)) {
0138: holder.setValue(null);
0139: return null;
0140: }
0141: // Is it a DynamicMBean
0142: TypeElement dmb = info.getElements().getTypeElement(
0143: "javax.management.DynamicMBean");// NOI18N
0144:
0145: if (dmb == null) {
0146: holder.setValue(null);
0147: return null;
0148: }
0149:
0150: boolean isDynamic = info.getTypes().isSubtype(te.asType(),
0151: dmb.asType());
0152: holder.setValue(isDynamic);
0153: return null;
0154: }
0155: }
0156:
0157: private static class SearchInterfaceVisitor extends MemberVisitor {
0158: private String itf;
0159:
0160: public SearchInterfaceVisitor(CompilationInfo info,
0161: ValueHolder holder, String itf) {
0162: super (info, holder);
0163: this .itf = itf;
0164: }
0165:
0166: @Override
0167: public Void visitClass(ClassTree t, Void v) {
0168: Element el = info.getTrees().getElement(getCurrentPath());
0169: if (el == null) {
0170: throw new RuntimeException("Invalid Class");// NOI18N
0171: }
0172: TypeElement te = (TypeElement) el;
0173:
0174: if (te.getKind().equals(ElementKind.INTERFACE)) {
0175: holder.setValue(null);
0176: return null;
0177: }
0178:
0179: List<? extends TypeMirror> interfaces = te.getInterfaces();
0180: TypeElement type = info.getElements().getTypeElement(itf);
0181: if (type != null
0182: && info.getTypes().isSubtype(te.asType(),
0183: type.asType()))
0184: holder.setValue(type);
0185:
0186: return null;
0187: }
0188: }
0189:
0190: private static class ConstructorsMemberVisitor extends
0191: MemberVisitor {
0192: public ConstructorsMemberVisitor(CompilationInfo info,
0193: ValueHolder holder) {
0194: super (info, holder);
0195: }
0196:
0197: @Override
0198: public Void visitClass(ClassTree t, Void v) {
0199: Element el = info.getTrees().getElement(getCurrentPath());
0200: if (el == null) {
0201: throw new RuntimeException("Invalid Class");// NOI18N
0202: }
0203: TypeElement te = (TypeElement) el;
0204: String className = te.getSimpleName().toString();
0205: List<ExecutableElement> constructors = ElementFilter
0206: .constructorsIn(te.getEnclosedElements());
0207: Map<String, ExecutableElement> mapConstructors = new HashMap<String, ExecutableElement>();
0208: int i = 0;
0209: for (ExecutableElement constructor : constructors) {
0210: List<? extends VariableElement> params = constructor
0211: .getParameters();
0212: String construct = className + "("; // NOI18N
0213: for (Iterator<? extends VariableElement> it = params
0214: .iterator(); it.hasNext();) {
0215: // javax.lang.model ELement
0216: VariableElement param = it.next();
0217: // To type
0218: TypeMirror type = param.asType();
0219: String tName = null;
0220: //if(typeElement == null)
0221: // tName = getPrimitive(type.getKind());
0222: //else
0223: tName = type.toString();
0224: // We should access the quli
0225: construct += tName;
0226: if (it.hasNext())
0227: construct += ", "; // NOI18N
0228: }
0229: construct += ")"; // NOI18N
0230: mapConstructors.put(construct, constructor);
0231: i++;
0232: }
0233: holder.setValue(mapConstructors);
0234: return null;
0235: }
0236: }
0237:
0238: private static class SimpleClassNameMemberVisitor extends
0239: MemberVisitor {
0240: public SimpleClassNameMemberVisitor(CompilationInfo info,
0241: ValueHolder holder) {
0242: super (info, holder);
0243: }
0244:
0245: @Override
0246: public Void visitClass(ClassTree t, Void v) {
0247: Element el = info.getTrees().getElement(getCurrentPath());
0248: if (el == null) {
0249: throw new RuntimeException("Invalid Class");// NOI18N
0250: }
0251: TypeElement te = (TypeElement) el;
0252: holder.setValue(te.getSimpleName().toString());
0253: return null;
0254: }
0255: }
0256:
0257: private static class IsInterfaceVisitor extends MemberVisitor {
0258: public IsInterfaceVisitor(CompilationInfo info,
0259: ValueHolder holder) {
0260: super (info, holder);
0261: }
0262:
0263: @Override
0264: public Void visitClass(ClassTree t, Void v) {
0265: Element el = info.getTrees().getElement(getCurrentPath());
0266: if (el == null) {
0267: throw new RuntimeException("Invalid Class");// NOI18N
0268: }
0269: holder.setValue(el.getKind().equals(ElementKind.INTERFACE));
0270: return null;
0271: }
0272: }
0273:
0274: private static class HasClassModifierVisitor extends MemberVisitor {
0275: Modifier m;
0276:
0277: public HasClassModifierVisitor(CompilationInfo info,
0278: ValueHolder holder, Modifier m) {
0279: super (info, holder);
0280: this .m = m;
0281: }
0282:
0283: @Override
0284: public Void visitClass(ClassTree t, Void v) {
0285: Element el = info.getTrees().getElement(getCurrentPath());
0286: if (el == null) {
0287: throw new RuntimeException("Invalid Class");// NOI18N
0288: }
0289: holder.setValue(el.getModifiers().contains(m));
0290: return null;
0291: }
0292: }
0293:
0294: private static class StandardMBeanItfVisitor extends MemberVisitor {
0295: private JavaSource mbeanClass;
0296:
0297: public StandardMBeanItfVisitor(CompilationInfo info,
0298: ValueHolder holder, JavaSource mbeanClass) {
0299: super (info, holder);
0300: this .mbeanClass = mbeanClass;
0301: }
0302:
0303: @Override
0304: public Void visitClass(ClassTree t, Void v) {
0305: Element el = info.getTrees().getElement(getCurrentPath());
0306: if (el == null) {
0307: throw new RuntimeException("Invalid Class");// NOI18N
0308: }
0309:
0310: TypeElement te = (TypeElement) el;
0311:
0312: String itfName = te.getQualifiedName().toString()
0313: + WizardConstants.MBEAN_ITF_SUFFIX;
0314:
0315: TypeElement itfType = info.getElements().getTypeElement(
0316: itfName);
0317: FileObject sourceFile = SourceUtils.getFile(itfType, info
0318: .getClasspathInfo());
0319: JavaSource js = null;
0320: if (sourceFile != null) {
0321: //Has sources
0322: js = mbeanClass.forFileObject(sourceFile);
0323: }
0324:
0325: holder.setValue(js);
0326: return null;
0327: }
0328: }
0329:
0330: private static class FullClassNameMemberVisitor extends
0331: MemberVisitor {
0332: private boolean leafFound;
0333:
0334: public FullClassNameMemberVisitor(CompilationInfo info,
0335: ValueHolder holder) {
0336: super (info, holder);
0337: }
0338:
0339: @Override
0340: public Void visitClass(ClassTree t, Void v) {
0341: if (leafFound)
0342: return null;
0343: leafFound = true;
0344: Element el = info.getTrees().getElement(getCurrentPath());
0345: if (el == null) {
0346: throw new RuntimeException("Invalid Class");// NOI18N
0347: }
0348: TypeElement te = (TypeElement) el;
0349: holder.setValue(te.getQualifiedName().toString());
0350: return null;
0351: }
0352: }
0353:
0354: private static class PackageMemberVisitor extends MemberVisitor {
0355: public PackageMemberVisitor(CompilationInfo info,
0356: ValueHolder holder) {
0357: super (info, holder);
0358: }
0359:
0360: @Override
0361: public Void visitClass(ClassTree t, Void v) {
0362: Element el = info.getTrees().getElement(getCurrentPath());
0363: if (el == null) {
0364: throw new RuntimeException("Invalid Class");// NOI18N
0365: }
0366: TypeElement te = (TypeElement) el;
0367: // Should be the package because the current class is not an
0368: // inner class.
0369: String name = ((PackageElement) SourceUtils
0370: .getOutermostEnclosingTypeElement(te)
0371: .getEnclosingElement()).getQualifiedName()
0372: .toString();
0373: holder.setValue(name);
0374: return null;
0375: }
0376: }
0377:
0378: private static class HasOnlyDefaultConstructorMemberVisitor extends
0379: MemberVisitor {
0380: public HasOnlyDefaultConstructorMemberVisitor(
0381: CompilationInfo info, ValueHolder holder) {
0382: super (info, holder);
0383: }
0384:
0385: @Override
0386: public Void visitClass(ClassTree t, Void v) {
0387: Element el = info.getTrees().getElement(getCurrentPath());
0388: if (el == null) {
0389: throw new RuntimeException("Invalid Class");// NOI18N
0390: }
0391: TypeElement te = (TypeElement) el;
0392: boolean super ClassCheck = false;
0393: if (te.getSuperclass() != null) {
0394: super ClassCheck = checkDefaultConstruct(te
0395: .getSuperclass());
0396: }
0397: List<ExecutableElement> constructors = ElementFilter
0398: .constructorsIn(te.getEnclosedElements());
0399: holder.setValue((constructors.size() == 0)
0400: && super ClassCheck);
0401: return null;
0402: }
0403:
0404: private boolean checkDefaultConstruct(TypeMirror clazz) {
0405: boolean super ClassCheck = true;
0406: TypeElement te = (TypeElement) info.getTypes().asElement(
0407: clazz);
0408: if (te.getSuperclass() != null) {
0409: super ClassCheck = checkDefaultConstruct(te
0410: .getSuperclass());
0411: }
0412: List<ExecutableElement> constructors = ElementFilter
0413: .constructorsIn(te.getEnclosedElements());
0414:
0415: boolean defaultExists = false;
0416: for (ExecutableElement constructor : constructors) {
0417: boolean isPrivate = false;
0418: for (Modifier m : constructor.getModifiers()) {
0419: if (m.compareTo(Modifier.PRIVATE) == 0)
0420: isPrivate = true;
0421: }
0422: if ((constructor.getParameters().size() == 0)
0423: && !isPrivate) {
0424: defaultExists = true;
0425: break;
0426: }
0427: }
0428: return super ClassCheck
0429: && (defaultExists || (constructors.size() == 0));
0430: }
0431: }
0432:
0433: private static class InterfacesMemberVisitor extends MemberVisitor {
0434: public InterfacesMemberVisitor(CompilationInfo info,
0435: ValueHolder holder) {
0436: super (info, holder);
0437: }
0438:
0439: @Override
0440: public Void visitClass(ClassTree t, Void v) {
0441: Element el = info.getTrees().getElement(getCurrentPath());
0442: if (el == null) {
0443: throw new RuntimeException("Invalid Class");// NOI18N
0444: }
0445: Set results = new HashSet();
0446: TypeElement te = (TypeElement) el;
0447: getInterfaceNames(te, results);
0448:
0449: holder
0450: .setValue(results
0451: .toArray(new String[results.size()]));
0452: return null;
0453: }
0454:
0455: private void getInterfaceNames(TypeElement te, Set results) {
0456: if (te.getSuperclass() != null) {
0457: TypeElement super Class = (TypeElement) info.getTypes()
0458: .asElement(te.getSuperclass());
0459: List<? extends TypeMirror> super Interfaces = super Class
0460: .getInterfaces();
0461: for (TypeMirror super Interface : super Interfaces) {
0462: TypeElement interfaceElement = (TypeElement) info
0463: .getTypes().asElement(super Interface);
0464: String intfName = interfaceElement
0465: .getQualifiedName().toString();
0466: //if (!containsString(results, intfName))
0467: results.add(intfName);
0468: getInterfaceNames(interfaceElement, results);
0469: }
0470: }
0471: List<? extends TypeMirror> interfaces = te.getInterfaces();
0472: for (TypeMirror interf : interfaces) {
0473: TypeElement interfaceElement = (TypeElement) info
0474: .getTypes().asElement(interf);
0475: String intfName = interfaceElement.getQualifiedName()
0476: .toString();
0477: //if (!containsString(results, intfName))
0478: results.add(intfName);
0479: }
0480: }
0481: }
0482:
0483: private static class MBeanModelVisitor extends MemberVisitor {
0484:
0485: private static final String attributeDescription = "Attribute exposed for management"; // NOI18N
0486: private static final String operationDescription = "Operation exposed for management"; // NOI18N
0487: private static final String constructorDescription = "Public constructor of the MBean"; // NOI18N
0488: private static final String mbeanInfoDescription = "Information on the management interface of the MBean"; // NOI18N
0489: private boolean real;
0490: private TypeElement itfType;
0491: private CompilationInfo info;
0492: private boolean introspectedLeaf;
0493:
0494: public MBeanModelVisitor(CompilationInfo info,
0495: ValueHolder holder, boolean real, TypeElement itfType) {
0496: super (info, holder);
0497: this .real = real;
0498: this .itfType = itfType;
0499: this .info = info;
0500:
0501: }
0502:
0503: @Override
0504: public Void visitClass(ClassTree t, Void v) {
0505: if (introspectedLeaf)
0506: return null;
0507: introspectedLeaf = true;
0508: Element el = info.getTrees().getElement(getCurrentPath());
0509: if (el == null) {
0510: throw new RuntimeException("Invalid Class");// NOI18N
0511: }
0512: Set results = new HashSet();
0513: TypeElement te = (TypeElement) el;
0514:
0515: // XXX REVISIT, WHAT ABOUT MXBEAN
0516: /* String suffix = isMXBean ?
0517: WizardConstants.MXBEAN_SUFFIX : WizardConstants.MBEAN_ITF_SUFFIX;
0518: String itfName = te.getQualifiedName().toString() + suffix;
0519:
0520: TypeElement itfType = null;
0521: */
0522: // Real means that we are intorpsecting a real Standard MBean
0523: // !Real means that we are trying to map any Java Class to MBean
0524: if (!real)
0525: // itfType = info.getElements().getTypeElement(itfName);
0526: //else
0527: itfType = te;
0528:
0529: List<MBeanAttribute> attributes = new ArrayList<MBeanAttribute>();
0530: List<MBeanOperation> operations = new ArrayList<MBeanOperation>();
0531: try {
0532: //First, current interface
0533: deepIntrospection(te, itfType, attributes, operations);
0534: } catch (Exception ex) {
0535: // XXX REVISIT With LOGGING
0536: ex.printStackTrace();
0537: }
0538: // XXX REVISIT
0539: // DO WE REALLY NEED TO CHECK FOR DUPLICATION?
0540: // WAITING FOR TOMAS REPLY ON THAT
0541: //System.out.println("CREATE result 1");
0542: holder.setValue(constructResult(attributes, operations,
0543: info));
0544: //System.out.println("CREATE result 2");
0545: return null;
0546: }
0547:
0548: private boolean isObjectMethod(ExecutableElement method) {
0549: Element el = method.getEnclosingElement();
0550: TypeMirror obj = info.getElements().getTypeElement(
0551: "java.lang.Object").asType(); // NOI18N
0552: if (info.getTypes().isSameType(obj, el.asType()))
0553: return true;
0554: return false;
0555: }
0556:
0557: private void deepIntrospection(TypeElement clazz,
0558: TypeElement itftype, List<MBeanAttribute> attributes,
0559: List<MBeanOperation> operations)
0560: throws NotCompliantMBeanException {
0561: if (itftype == null)
0562: return;
0563:
0564: //Top level loop to iterate on all interfaces
0565: List<? extends TypeMirror> itfs = itftype.getInterfaces();
0566: for (TypeMirror itf : itfs) {
0567: TypeElement itfElement = (TypeElement) info.getTypes()
0568: .asElement(itf);
0569: deepIntrospection(clazz, itfElement, attributes,
0570: operations);
0571: }
0572: List<ExecutableElement> methods = ElementFilter
0573: .methodsIn(itftype.getEnclosedElements());
0574: // Now analyze each method.
0575: for (ExecutableElement method : methods) {
0576: if (isObjectMethod(method))
0577: continue;
0578: if (!method.getModifiers().contains(Modifier.PUBLIC))
0579: continue;
0580: String name = method.getSimpleName().toString();
0581: //System.out.println("METHOD NAME : " + name);
0582: List<? extends VariableElement> args = method
0583: .getParameters();
0584: TypeMirror ret = method.getReturnType();
0585: boolean isVoid = ret.getKind().equals(TypeKind.VOID);
0586: int argCount = args.size();
0587: final MBeanAttribute attr;
0588:
0589: if (name.startsWith("get") && !name.equals("get") // NOI18N
0590: && argCount == 0 && !isVoid) {
0591: // if the method is "T getX()" it is a getter
0592: attr = new MBeanAttribute(name.substring(3),
0593: attributeDescription, method, null, clazz
0594: .getTypeParameters(), info);
0595: } else if (name.startsWith("set")
0596: && !name.equals("set") // NOI18N
0597: && argCount == 1 && isVoid) {
0598: // if the method is "void setX(T x)" it is a setter
0599: attr = new MBeanAttribute(name.substring(3),
0600: attributeDescription, null, method, clazz
0601: .getTypeParameters(), info);
0602: } else if (name.startsWith("is")
0603: && !name.equals("is") // NOI18N
0604: && argCount == 0
0605: && ret.getKind().equals(TypeKind.BOOLEAN)) {
0606: // if the method is "boolean isX()" it is a getter
0607: attr = new MBeanAttribute(name.substring(2),
0608: attributeDescription, method, null, clazz
0609: .getTypeParameters(), info);
0610: } else {
0611: // in all other cases it is an operation
0612: attr = null;
0613: }
0614:
0615: if (attr != null) {
0616: //System.out.println("We have a anattribute to add "
0617: // + attr.getName());
0618: if (testConsistency(attributes, attr)) {
0619: // System.out.println("Adding " +
0620: // attr.getName());
0621: attributes.add(attr);
0622: }
0623: } else {
0624: final MBeanOperation oper = new MBeanOperation(
0625: method, operationDescription, clazz
0626: .getTypeParameters(), info);
0627: operations.add(oper);
0628: }
0629: }
0630:
0631: }
0632:
0633: /**
0634: * Checks if the types and the signatures of
0635: * getters/setters/operations are conform to the MBean design patterns.
0636: *
0637: * Error cases:
0638: * - It exposes a method void Y getXX() AND a method void setXX(Z)
0639: * (parameter type mismatch)
0640: * - It exposes a method void setXX(Y) AND a method void setXX(Z)
0641: * (parameter type mismatch)
0642: * - It exposes a boolean isXX() method AND a YY getXX() or a void setXX(Y).
0643: * Returns false if the attribute is already in attributes List
0644: */
0645: private static boolean testConsistency(
0646: List/*<MBeanAttribute>*/attributes, MBeanAttribute attr)
0647: throws NotCompliantMBeanException {
0648: for (Iterator it = attributes.iterator(); it.hasNext();) {
0649: MBeanAttribute mb = (MBeanAttribute) it.next();
0650: if (mb.getName().equals(attr.getName())) {
0651: if ((attr.isReadable() && mb.isReadable())) {
0652: final String msg = "Conflicting getters for attribute "
0653: + mb.getName(); // NOI18N
0654: throw new NotCompliantMBeanException(msg);
0655: }
0656: if (!mb.getTypeName().equals(attr.getTypeName())) {
0657: if (mb.isWritable() && attr.isWritable()) {
0658: final String msg = "Type mismatch between parameters of set"
0659: + // NOI18N
0660: mb.getName() + " methods"; // NOI18N
0661: throw new NotCompliantMBeanException(msg);
0662: } else {
0663: final String msg = "Type mismatch between parameters of get or is"
0664: + // NOI18N
0665: mb.getName()
0666: + ", set"
0667: + mb.getName() + " methods"; // NOI18N
0668: throw new NotCompliantMBeanException(msg);
0669: }
0670: }
0671: if (attr.isReadable() && mb.isReadable()) {
0672: return false;
0673: }
0674: if (attr.isWritable() && mb.isWritable()) {
0675: return false;
0676: }
0677: }
0678: }
0679: return true;
0680: }
0681:
0682: /*
0683: * We are merging getters and setters in a single Attribute.
0684: *
0685: */
0686: private MBeanDO constructResult(
0687: List<MBeanAttribute> attributes,
0688: List<MBeanOperation> operations, CompilationInfo info) {
0689: final int len = attributes.size();
0690: final MBeanAttribute[] attrlist = new MBeanAttribute[len];
0691: attributes.toArray(attrlist);
0692: final ArrayList mergedAttributes = new ArrayList();
0693: //System.out.println("LEN : " + len);
0694: for (int i = 0; i < len; i++) {
0695: final MBeanAttribute bi = attrlist[i];
0696:
0697: // bi can be null if it has already been eliminated
0698: // by the loop below at an earlier iteration
0699: // (cf. attrlist[j]=null;) In this case, just skip it.
0700: //
0701: if (bi == null)
0702: continue;
0703:
0704: // Placeholder for the final attribute info we're going to
0705: // keep.
0706: //
0707: MBeanAttribute att = bi;
0708:
0709: // The loop below will try to find whether bi is also present
0710: // elsewhere further down the list.
0711: // If it is not, att will be left unchanged.
0712: // Otherwise, the found attribute info will be merged with
0713: // att and `removed' from the array by setting them to `null'
0714: //
0715: for (int j = i + 1; j < len; j++) {
0716: MBeanAttribute mi = attrlist[j];
0717:
0718: // mi can be null if it has already been eliminated
0719: // by this loop at an earlier iteration.
0720: // (cf. attrlist[j]=null;) In this case, just skip it.
0721: //
0722: if (mi == null)
0723: continue;
0724: if ((mi.getName().compareTo(bi.getName()) == 0)) {
0725: if (mi.getTypeName().equals(bi.getTypeName())) {
0726: // mi and bi have the same name, which means that
0727: // that the attribute has been inserted twice in
0728: // the list, which means that it is a read-write
0729: // attribute.
0730: // So we're going to replace att with a new
0731: // attribute info with read-write mode.
0732: // We also set attrlist[j] to null in order to avoid
0733: // duplicates (attrlist[j] and attrlist[i] are now
0734: // merged into att).
0735: //
0736: attrlist[j] = null;
0737: att = new MBeanAttribute(bi.getName(), bi
0738: .getDescription(),
0739: bi.getGetter() != null ? bi
0740: .getGetter() : mi
0741: .getGetter(), bi
0742: .getSetter() != null ? bi
0743: .getSetter() : mi
0744: .getSetter(), bi
0745: .getClassParameterTypes(),
0746: info);
0747: // I think we could break, but it is probably
0748: // safer not to...
0749: //
0750: // break;
0751: }
0752: }
0753: }
0754:
0755: // Now all attributes info which had the same name than bi
0756: // have been merged together in att.
0757: // Simply add att to the merged list.
0758: //
0759: mergedAttributes.add(att);
0760: }
0761: /*final int opNb = operations.size();
0762: final MBeanOperation[] oplist = new MBeanOperation[opNb];
0763: operations.toArray(oplist);
0764: final ArrayList mergedOperations = new ArrayList();
0765:
0766: for (int i = 0; i < opNb; i++) {
0767: final MBeanOperation bi = oplist[i];
0768:
0769: // bi can be null if it has already been eliminated
0770: // by the loop below at an earlier iteration
0771: // (cf. attrlist[j]=null;) In this case, just skip it.
0772: //
0773: if (bi == null) {
0774: continue;
0775: }
0776:
0777: // Placeholder for the final attribute info we're going to
0778: // keep.
0779: //
0780: MBeanOperation op = bi;
0781:
0782: // The loop below will try to find whether bi is also present
0783: // elsewhere further down the list.
0784: // If it is not, op will be left unchanged.
0785: // Otherwise, the found attribute info will be merged with
0786: // att and `removed' from the array by setting them to `null'
0787: //
0788: for (int j = i + 1; j < opNb; j++) {
0789: MBeanOperation mi = oplist[j];
0790:
0791: // mi can be null if it has already been eliminated
0792: // by this loop at an earlier iteration.
0793: // (cf. attrlist[j]=null;) In this case, just skip it.
0794: //
0795: if (mi == null) {
0796: continue;
0797: }
0798: if (bi.getName().equals(mi.getName())) {
0799: if (isEqual(bi, mi)) {
0800: // bi override mi so mi will not be be added to merged operations.
0801:
0802: oplist[j] = null;
0803:
0804: op = new MBeanOperation(bi.getMethod(), bi.getDescription(), bi.getClassParameterTypes(), info);
0805: }
0806: }
0807: }
0808:
0809: // Now all operations info which had the same name and the same signature
0810: // or herited signature than have been merged together in op.
0811: // Simply add op to the merged list.
0812: //
0813: mergedOperations.add(op);
0814: }
0815: */
0816: return new MBeanDO(mergedAttributes, operations);
0817: }
0818:
0819: private boolean isEqual(MBeanOperation bi, MBeanOperation mi) {
0820: if (bi.getParametersSize() != mi.getParametersSize()) {
0821: return false;
0822: }
0823:
0824: for (int i = 0; i < bi.getParametersSize(); i++) {
0825: TypeMirror biParam = bi.getParameter(i).getTypeMirror();
0826: TypeMirror miParam = mi.getParameter(i).getTypeMirror();
0827: if (bi.compareTo(mi) != 0)
0828: return false;
0829: }
0830:
0831: return true;
0832: }
0833:
0834: }
0835:
0836: private static class MBeanModelFromClassVisitor extends
0837: MemberVisitor {
0838:
0839: private static final String attributeDescription = "Attribute exposed for management"; // NOI18N
0840: private static final String operationDescription = "Operation exposed for management"; // NOI18N
0841: private static final String constructorDescription = "Public constructor of the MBean"; // NOI18N
0842: private static final String mbeanInfoDescription = "Information on the management interface of the MBean"; // NOI18N
0843: private boolean real;
0844: private TypeElement itfType;
0845: private CompilationInfo info;
0846: private boolean introspectedLeaf;
0847:
0848: public MBeanModelFromClassVisitor(CompilationInfo info,
0849: ValueHolder holder, boolean real, TypeElement itfType) {
0850: super (info, holder);
0851: this .real = real;
0852: this .itfType = itfType;
0853: this .info = info;
0854: }
0855:
0856: @Override
0857: public Void visitClass(ClassTree t, Void v) {
0858: if (introspectedLeaf)
0859: return null;
0860: introspectedLeaf = true;
0861: Element el = info.getTrees().getElement(getCurrentPath());
0862: if (el == null) {
0863: throw new RuntimeException("Invalid Class");// NOI18N
0864: }
0865: Set results = new HashSet();
0866: TypeElement te = (TypeElement) el;
0867:
0868: itfType = te;
0869:
0870: List<MBeanAttribute> attributes = new ArrayList<MBeanAttribute>();
0871: List<MBeanOperation> operations = new ArrayList<MBeanOperation>();
0872: try {
0873: //Introspect class
0874: //System.out.println("ROOT INTROSPECT " + itfType.getQualifiedName());
0875: deepIntrospection(te, itfType, attributes, operations);
0876: } catch (Exception ex) {
0877: // XXX REVISIT With LOGGING
0878: ex.printStackTrace();
0879: }
0880: // XXX REVISIT
0881: // DO WE REALLY NEED TO CHECK FOR DUPLICATION?
0882: // WAITING FOR TOMAS REPLY ON THAT
0883: //System.out.println("CREATE result 1");
0884: holder.setValue(constructResult(attributes, operations,
0885: info));
0886: //System.out.println("CREATE result 2");
0887: return null;
0888: }
0889:
0890: private boolean isObjectMethod(ExecutableElement method) {
0891: Element el = method.getEnclosingElement();
0892: TypeMirror obj = info.getElements().getTypeElement(
0893: "java.lang.Object").asType();// NOI18N
0894: if (info.getTypes().isSameType(obj, el.asType()))
0895: return true;
0896: return false;
0897: }
0898:
0899: private void deepIntrospection(TypeElement clazz,
0900: TypeElement itftype, List<MBeanAttribute> attributes,
0901: List<MBeanOperation> operations)
0902: throws NotCompliantMBeanException {
0903: if (itftype == null)
0904: return;
0905:
0906: //Top level loop to iterate on all Mother classes
0907: TypeMirror mother = itftype.getSuperclass();
0908: TypeElement itfElement = (TypeElement) info.getTypes()
0909: .asElement(mother);
0910: deepIntrospection(clazz, itfElement, attributes, operations);
0911:
0912: List<ExecutableElement> methods = ElementFilter
0913: .methodsIn(itftype.getEnclosedElements());
0914: // Now analyze each method.
0915: //System.out.println("ITERATING METHODS of " + itftype.getQualifiedName().toString());
0916: for (ExecutableElement method : methods) {
0917: //System.out.println("ITERATING METHOD " + method.getSimpleName());
0918: if (isObjectMethod(method))
0919: continue;
0920: if (!method.getModifiers().contains(Modifier.PUBLIC))
0921: continue;
0922: String name = method.getSimpleName().toString();
0923: //System.out.println("METHOD NAME : " + name);
0924: List<? extends VariableElement> args = method
0925: .getParameters();
0926: TypeMirror ret = method.getReturnType();
0927: boolean isVoid = ret.getKind().equals(TypeKind.VOID);
0928: int argCount = args.size();
0929: final MBeanAttribute attr;
0930:
0931: if (name.startsWith("get") && !name.equals("get") // NOI18N
0932: && argCount == 0 && !isVoid) {
0933: // if the method is "T getX()" it is a getter
0934: attr = new MBeanAttribute(name.substring(3),
0935: attributeDescription, method, null, clazz
0936: .getTypeParameters(), info);
0937: } else if (name.startsWith("set")
0938: && !name.equals("set") // NOI18N
0939: && argCount == 1 && isVoid) {
0940: // if the method is "void setX(T x)" it is a setter
0941: attr = new MBeanAttribute(name.substring(3),
0942: attributeDescription, null, method, clazz
0943: .getTypeParameters(), info);
0944: } else if (name.startsWith("is")
0945: && !name.equals("is") // NOI18N
0946: && argCount == 0
0947: && ret.getKind().equals(TypeKind.BOOLEAN)) {
0948: // if the method is "boolean isX()" it is a getter
0949: attr = new MBeanAttribute(name.substring(2),
0950: attributeDescription, method, null, clazz
0951: .getTypeParameters(), info);
0952: } else {
0953: // in all other cases it is an operation
0954: attr = null;
0955: }
0956:
0957: if (attr != null) {
0958: /* System.out.println("We have a anattribute to add "
0959: + attr.getName());
0960: if (testConsistency(attributes, attr)) {
0961: System.out.println("Adding " +
0962: attr.getName());
0963: attributes.add(attr);
0964: }*/
0965: attributes.add(attr);
0966: } else {
0967: final MBeanOperation oper = new MBeanOperation(
0968: method, operationDescription, clazz
0969: .getTypeParameters(), info);
0970: operations.add(oper);
0971: }
0972: }
0973: }
0974:
0975: /**
0976: * Checks if the types and the signatures of
0977: * getters/setters/operations are conform to the MBean design patterns.
0978: *
0979: * Error cases:
0980: * - It exposes a method void Y getXX() AND a method void setXX(Z)
0981: * (parameter type mismatch)
0982: * - It exposes a method void setXX(Y) AND a method void setXX(Z)
0983: * (parameter type mismatch)
0984: * - It exposes a boolean isXX() method AND a YY getXX() or a void setXX(Y).
0985: * Returns false if the attribute is already in attributes List
0986: */
0987: private static boolean testConsistency(
0988: List<MBeanAttribute> attributes, MBeanAttribute attr)
0989: throws NotCompliantMBeanException {
0990: for (Iterator it = attributes.iterator(); it.hasNext();) {
0991: MBeanAttribute mb = (MBeanAttribute) it.next();
0992: if (mb.getName().equals(attr.getName())) {
0993: //if ((attr.isReadable() && mb.isReadable())) {
0994: // final String msg =
0995: // "Conflicting getters for attribute " + mb.getName(); // NOI18N
0996: // throw new NotCompliantMBeanException(msg);
0997: return false;
0998: }
0999: if (mb.getTypeName().equals(attr.getTypeName())) {
1000: if (mb.isWritable() && attr.isWritable()) {
1001: // final String msg =
1002: // "Type mismatch between parameters of set" + // NOI18N
1003: // mb.getName() + " methods"; // NOI18N
1004: //throw new NotCompliantMBeanException(msg);
1005: return false;
1006: } else {
1007: //final String msg =
1008: // "Type mismatch between parameters of get or is" + // NOI18N
1009: // mb.getName() + ", set" + mb.getName() + " methods"; // NOI18N
1010: //throw new NotCompliantMBeanException(msg);
1011: return false;
1012: }
1013: }
1014: if (attr.isReadable() && mb.isReadable()) {
1015: return false;
1016: }
1017: if (attr.isWritable() && mb.isWritable()) {
1018: return false;
1019: }
1020: }
1021:
1022: return true;
1023: }
1024:
1025: /*
1026: * We are merging getters and setters in a single Attribute.
1027: *
1028: */
1029: private MBeanDO constructResult(
1030: List<MBeanAttribute> attributes,
1031: List<MBeanOperation> operations, CompilationInfo info) {
1032: final int len = attributes.size();
1033: final MBeanAttribute[] attrlist = new MBeanAttribute[len];
1034: attributes.toArray(attrlist);
1035: final ArrayList<MBeanAttribute> mergedAttributes = new ArrayList<MBeanAttribute>();
1036: //System.out.println("LEN : " + len);
1037: for (int i = 0; i < len; i++) {
1038: final MBeanAttribute bi = attrlist[i];
1039:
1040: // bi can be null if it has already been eliminated
1041: // by the loop below at an earlier iteration
1042: // (cf. attrlist[j]=null;) In this case, just skip it.
1043: //
1044: if (bi == null) {
1045: continue;
1046: }
1047:
1048: // Placeholder for the final attribute info we're going to
1049: // keep.
1050: //
1051: MBeanAttribute att = bi;
1052:
1053: // The loop below will try to find whether bi is also present
1054: // elsewhere further down the list.
1055: // If it is not, att will be left unchanged.
1056: // Otherwise, the found attribute info will be merged with
1057: // att and `removed' from the array by setting them to `null'
1058: //
1059: for (int j = i + 1; j < len; j++) {
1060: MBeanAttribute mi = attrlist[j];
1061:
1062: // mi can be null if it has already been eliminated
1063: // by this loop at an earlier iteration.
1064: // (cf. attrlist[j]=null;) In this case, just skip it.
1065: //
1066: if (mi == null) {
1067: continue;
1068: }
1069: if ((mi.getName().compareTo(bi.getName()) == 0)) {
1070: if ((mi.getTypeName().compareTo(
1071: bi.getTypeName()) == 0)) {
1072:
1073: // mi and bi have the same name, which means that
1074: // that the attribute has been inserted twice in
1075: // the list, which means that it is a read-write
1076: // attribute.
1077: // So we're going to replace att with a new
1078: // attribute info with read-write mode.
1079: // We also set attrlist[j] to null in order to avoid
1080: // duplicates (attrlist[j] and attrlist[i] are now
1081: // merged into att).
1082: //
1083: attrlist[j] = null;
1084: att = new MBeanAttribute(bi.getName(), bi
1085: .getDescription(),
1086: bi.getGetter() != null ? bi
1087: .getGetter() : mi
1088: .getGetter(), bi
1089: .getSetter() != null ? bi
1090: .getSetter() : mi
1091: .getSetter(), bi
1092: .getClassParameterTypes(),
1093: info);
1094: // I think we could break, but it is probably
1095: // safer not to...
1096: //
1097: // break;
1098: } else
1099: // mi and bi have the same name, which means that
1100: // that the attribute has been inserted twice in
1101: // the list, which means that it is two different
1102: // attributes with different type.
1103: att = new MBeanAttribute(bi.getName(), bi
1104: .getDescription(), bi.getGetter(),
1105: bi.getSetter(), bi
1106: .getClassParameterTypes(),
1107: info);
1108: }
1109: }
1110:
1111: // Now all attributes info which had the same name than bi
1112: // have been merged together in att.
1113: // Simply add att to the merged list.
1114: //
1115: //System.out.println("ADDING MERGED ATTRIBUTE " + att);
1116: mergedAttributes.add(att);
1117: }
1118:
1119: // Remove Overriden attributes
1120: int len2 = mergedAttributes.size();
1121: final MBeanAttribute[] attrlist2 = new MBeanAttribute[len2];
1122: mergedAttributes.toArray(attrlist2);
1123: final ArrayList<MBeanAttribute> finalMergedAttributes = new ArrayList<MBeanAttribute>();
1124: for (int i = 0; i < len2; i++) {
1125: final MBeanAttribute bi = attrlist2[i];
1126: // bi can be null if it has already been eliminated
1127: // by the loop below at an earlier iteration
1128: // (cf. attrlist[j]=null;) In this case, just skip it.
1129: //
1130: if (bi == null) {
1131: continue;
1132: }
1133:
1134: // Placeholder for the final attribute info we're going to
1135: // keep.
1136: //
1137: MBeanAttribute att = bi;
1138:
1139: // The loop below will try to find whether bi is also present
1140: // elsewhere further down the list.
1141: // If it is not, att will be left unchanged.
1142: // Otherwise, the found attribute info will be merged with
1143: // att and `removed' from the array by setting them to `null'
1144: //
1145: for (int j = i + 1; j < len2; j++) {
1146: MBeanAttribute mi = attrlist2[j];
1147:
1148: // mi can be null if it has already been eliminated
1149: // by this loop at an earlier iteration.
1150: // (cf. attrlist[j]=null;) In this case, just skip it.
1151: //
1152: if (mi == null) {
1153: continue;
1154: }
1155: if ((bi.getName().compareTo(mi.getName()) == 0)) {
1156: if (overridedType(bi.getTypeMirror(), mi
1157: .getTypeMirror(), info)) {
1158: att = mi;
1159: attrlist2[j] = null;
1160: } else if (overridedType(mi.getTypeMirror(), bi
1161: .getTypeMirror(), info)) {
1162: att = bi;
1163: attrlist2[j] = null;
1164: }
1165: }
1166: }
1167: //System.out.println("Finally adding : " + att.getName() + " " +
1168: // att.getAccess());
1169: finalMergedAttributes.add(att);
1170: }
1171:
1172: final int opNb = operations.size();
1173: final MBeanOperation[] oplist = new MBeanOperation[opNb];
1174: operations.toArray(oplist);
1175: final ArrayList mergedOperations = new ArrayList();
1176:
1177: for (int i = 0; i < opNb; i++) {
1178: final MBeanOperation bi = oplist[i];
1179:
1180: // bi can be null if it has already been eliminated
1181: // by the loop below at an earlier iteration
1182: // (cf. attrlist[j]=null;) In this case, just skip it.
1183: //
1184: if (bi == null) {
1185: continue;
1186: }
1187:
1188: // Placeholder for the final attribute info we're going to
1189: // keep.
1190: //
1191: MBeanOperation op = bi;
1192:
1193: // The loop below will try to find whether bi is also present
1194: // elsewhere further down the list.
1195: // If it is not, op will be left unchanged.
1196: // Otherwise, the found attribute info will be merged with
1197: // att and `removed' from the array by setting them to `null'
1198: //
1199: for (int j = i + 1; j < opNb; j++) {
1200: MBeanOperation mi = oplist[j];
1201:
1202: // mi can be null if it has already been eliminated
1203: // by this loop at an earlier iteration.
1204: // (cf. attrlist[j]=null;) In this case, just skip it.
1205: //
1206: if (mi == null) {
1207: continue;
1208: }
1209: if (bi.getName().equals(mi.getName())) {
1210:
1211: if (override(bi, mi, info)) {
1212: // bi override mi so mi will not be be added to merged operations.
1213:
1214: oplist[j] = null;
1215:
1216: op = new MBeanOperation(mi.getMethod(), mi
1217: .getDescription(), mi
1218: .getClassParameterTypes(), info);
1219: } else if (override(mi, bi, info)) {
1220: // bi override mi so mi will not be be added to merged operations.
1221:
1222: oplist[j] = null;
1223:
1224: op = new MBeanOperation(bi.getMethod(), bi
1225: .getDescription(), bi
1226: .getClassParameterTypes(), info);
1227: } else {
1228: // mi and bi have the same name, which means that
1229: // that the attribute has been inserted twice in
1230: // the list, which means that it is two different
1231: // attributes with different type.
1232: op = new MBeanOperation(bi.getMethod(), bi
1233: .getDescription(), bi
1234: .getClassParameterTypes(), info);
1235: }
1236: }
1237: }
1238:
1239: // Now all operations info which had the same name and the same signature
1240: // or herited signature than have been merged together in op.
1241: // Simply add op to the merged list.
1242: //
1243: mergedOperations.add(op);
1244: }
1245: return new MBeanDO(finalMergedAttributes, mergedOperations);
1246: }
1247:
1248: private boolean override(MBeanOperation bi, MBeanOperation mi,
1249: CompilationInfo info) {
1250: if (bi.getParametersSize() != mi.getParametersSize()) {
1251: return false;
1252: }
1253:
1254: for (int i = 0; i < bi.getParametersSize(); i++) {
1255: TypeMirror biParam = bi.getParameter(i).getTypeMirror();
1256: TypeMirror miParam = mi.getParameter(i).getTypeMirror();
1257: if (!overridedType(biParam, miParam, info)) {
1258: return false;
1259: }
1260: }
1261:
1262: return true;
1263: }
1264:
1265: private boolean overridedType(TypeMirror bi, TypeMirror mi,
1266: CompilationInfo info) {
1267: //System.out.println("TYPE KIND : " + bi.getKind());
1268: TypeKind biKind = bi.getKind();
1269: TypeKind miKind = mi.getKind();
1270: if (biKind.equals(miKind)) {
1271: if (biKind.equals(TypeKind.BOOLEAN)
1272: || biKind.equals(TypeKind.BYTE)
1273: || biKind.equals(TypeKind.CHAR)
1274: || biKind.equals(TypeKind.DOUBLE)
1275: || biKind.equals(TypeKind.FLOAT)
1276: || biKind.equals(TypeKind.INT)
1277: || biKind.equals(TypeKind.LONG)
1278: || biKind.equals(TypeKind.SHORT))
1279: return true;
1280: if (biKind.equals(TypeKind.DECLARED)) {
1281: //System.out.println("BI " + bi + " MI " + mi);
1282: if (info.getTypeUtilities().isCastable(bi, mi)) {
1283: //System.out.println("Overriding !!!!!");
1284: return true;
1285: }
1286: }
1287: if (biKind.equals(TypeKind.ARRAY)) {
1288: int dim1 = getArrayDimension(bi);
1289: int dim2 = getArrayDimension(mi);
1290: //System.out.println("ARRAY DIM " + dim1 + " ARRAY DIM " + dim2);
1291: if (dim1 != dim2)
1292: return false;
1293: bi = getComponentType(bi);
1294: mi = getComponentType(mi);
1295: TypeElement ex1 = (TypeElement) info.getTypes()
1296: .asElement(bi);
1297: TypeElement ex2 = (TypeElement) info.getTypes()
1298: .asElement(mi);
1299: boolean over = ex1.getQualifiedName().toString()
1300: .equals(ex2.getQualifiedName().toString());
1301: if (over)
1302: //System.out.println("Overriding !!!!!");
1303: return over;
1304: }
1305: }
1306: return false;
1307:
1308: }
1309: }
1310:
1311: private static class AgentGeneratorSampleCodeTransformer extends
1312: TreePathScanner<Void, Object> {
1313: private static final String NO_SAMPLE_BODY = "{//TODO Add your MBean registration code here}";// NOI18N
1314: private static final String PROP_AGENT_INIT_METHOD_NAME = "init";// NOI18N
1315: private final WorkingCopy w;
1316: private final boolean removeSampleCode;
1317:
1318: public AgentGeneratorSampleCodeTransformer(WorkingCopy w,
1319: boolean removeSampleCode) {
1320: this .w = w;
1321: this .removeSampleCode = removeSampleCode;
1322: }
1323:
1324: //Called for every method in the java source file
1325: @Override
1326: public Void visitMethod(MethodTree tree, Object p) {
1327: ClassTree owner = (ClassTree) getCurrentPath()
1328: .getParentPath().getLeaf();
1329:
1330: //is this method a main method
1331: //Get the Element for this method tree - Trees.getElement(TreePath)
1332: ExecutableElement currentMethod = (ExecutableElement) w
1333: .getTrees().getElement(getCurrentPath());
1334: if (PROP_AGENT_INIT_METHOD_NAME.contentEquals(currentMethod
1335: .getSimpleName().toString())) { // NOI18N
1336:
1337: if (!removeSampleCode) {
1338: // XXX REVISIT WAITING FOR METHOD REWRITING TO WORK!!!
1339: }
1340: }
1341: // super.visitMethod(tree, p);
1342: return null;
1343: }
1344: }
1345:
1346: private static class UpdateClassJavaDocTransformer extends
1347: TreePathScanner<Void, Void> {
1348:
1349: private String text;
1350: private WorkingCopy w;
1351:
1352: public UpdateClassJavaDocTransformer(WorkingCopy w, String text) {
1353: this .w = w;
1354: this .text = text;
1355: }
1356:
1357: @Override
1358: public Void visitClass(ClassTree clazz, Void v) {
1359: Element el = w.getTrees().getElement(getCurrentPath());
1360: updateDescription(w, el, w.getTreeMaker(), text, clazz);
1361: return null;
1362: }
1363: }
1364:
1365: private static class AddAttributesTransformer extends
1366: TreePathScanner<Void, Void> {
1367:
1368: private MBeanAttribute[] attributes;
1369: private WorkingCopy w;
1370: private boolean isClass;
1371:
1372: public AddAttributesTransformer(WorkingCopy w,
1373: MBeanAttribute[] attributes) {
1374: this .w = w;
1375: this .attributes = attributes;
1376: }
1377:
1378: @Override
1379: public Void visitClass(ClassTree clazz, Void v) {
1380: TreeMaker make = w.getTreeMaker();
1381: Element el = w.getTrees().getElement(getCurrentPath());
1382: if (el == null) {
1383: throw new RuntimeException("Invalid Class");// NOI18N
1384: }
1385: // Needed not to update the method body
1386: isClass = !el.getKind().equals(ElementKind.INTERFACE);
1387: ClassTree updated = clazz;
1388: for (int i = 0; i < attributes.length; i++) {
1389: boolean hasGetter = (attributes[i].getGetMethodExits() || attributes[i]
1390: .getIsMethodExits())
1391: && !attributes[i].isWrapped();
1392: boolean hasSetter = (attributes[i].getSetMethodExits() && !attributes[i]
1393: .isWrapped());
1394:
1395: if (attributes[i].isReadable()) {
1396: if (!isClass || !hasGetter) {
1397: MethodTree method = addGetAttrMethod(attributes[i]);
1398: updated = make.addClassMember(updated, method);
1399: }
1400: }
1401:
1402: if (attributes[i].isWritable()) {
1403: if (!isClass || !hasSetter) {
1404: MethodTree method = addSetAttrMethod(attributes[i]);
1405: updated = make.addClassMember(updated, method);
1406: //w.rewrite(clazz, copy);
1407: }
1408: }
1409: }
1410:
1411: if (isClass) {
1412: for (int i = attributes.length - 1; i >= 0; i--) {
1413: if (!attributes[i].getIsMethodExits()
1414: && !attributes[i].getGetMethodExits()
1415: && !attributes[i].getSetMethodExits()
1416: && !attributes[i].isWrapped()) {
1417: VariableTree var = addAttrField(attributes[i]);
1418: updated = make.insertClassMember(updated, 0,
1419: var);
1420: //w.rewrite(clazz, clazzCopy);
1421: }
1422: }
1423: }
1424: w.rewrite(clazz, updated);
1425: return null;
1426: }
1427:
1428: private MethodTree addGetAttrMethod(MBeanAttribute attribute) {
1429: TreeMaker make = w.getTreeMaker();
1430: String methodBody = "{return " + // NOI18N
1431: WizardHelpers.forceFirstLetterLowerCase(attribute
1432: .getName()) + ";}"; // NOI18N
1433:
1434: String prefix = "get";// NOI18N
1435:
1436: if (attribute.isWrapped()) {
1437: if (attribute.getIsMethodExits())
1438: prefix = "is";// NOI18N
1439:
1440: methodBody = "{return theRef." + prefix
1441: + attribute.getName() + "();}"; // NOI18N
1442: } else if (attribute.getSetMethodExits())
1443: methodBody = "{return " + // NOI18N
1444: WizardHelpers.getDefaultValue(attribute
1445: .getTypeName()) + ";}"; // NOI18N
1446:
1447: //Exceptions
1448: StringBuffer doc = new StringBuffer();
1449: List<String> exceps = attribute.getGetterExceptions();
1450: List<ExpressionTree> exceptions = new ArrayList<ExpressionTree>();
1451: for (String excep : exceps) {
1452: exceptions.add(make.Identifier(excep));
1453: doc.append("@throws " + excep + " " + // NOI18N
1454: excep + "\n"); // NOI18N
1455: }
1456: // String t = attribute.
1457: // if(attribute.isArray()) {
1458: // }
1459: ExpressionTree retType = getType(w,
1460: attribute.getTypeName(), attribute.getTypeMirror());
1461: TypeElement retTypeElement = w.getElements()
1462: .getTypeElement(attribute.getTypeName());
1463:
1464: MethodTree newMethod = null;
1465: String operationName = prefix + attribute.getName();
1466: if (isClass) {
1467: newMethod = make.Method(make.Modifiers(Collections
1468: .singleton(Modifier.PUBLIC)), // modifiers and annotations
1469: operationName, // name
1470: retType, // ret type
1471: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
1472: Collections.<VariableTree> emptyList(), // parameters
1473: exceptions, // throws
1474: methodBody,//body
1475: null // default value - not applicable here, used by annotations
1476: );
1477: } else {
1478: newMethod = make.Method(make.Modifiers(Collections
1479: .singleton(Modifier.PUBLIC)), // modifiers and annotations
1480: operationName, // name
1481: retType, // ret type
1482: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
1483: Collections.<VariableTree> emptyList(), // parameters
1484: exceptions, // throws
1485: (BlockTree) null, //body
1486: null // default value - not applicable here, used by annotations
1487: );
1488: }
1489: JavaModelHelper.addComment(make, newMethod, Style.JAVADOC,
1490: "Get " + attribute.getDescription() + "\n"
1491: + doc.toString()); // NOI18N
1492: return newMethod;
1493: }
1494:
1495: private MethodTree addSetAttrMethod(MBeanAttribute attribute) {
1496: TreeMaker make = w.getTreeMaker();
1497: String methodBody = "{" + // NOI18N
1498: WizardHelpers.forceFirstLetterLowerCase(attribute
1499: .getName()) + " = value;}"; // NOI18N
1500:
1501: if (attribute.isWrapped()) {
1502: methodBody = "{theRef.set" + // NOI18N
1503: WizardHelpers.capitalizeFirstLetter(attribute
1504: .getName()) + "(value);}"; // NOI18N
1505: } else if (attribute.getGetMethodExits()
1506: || attribute.getIsMethodExits())
1507: methodBody = "{//TODO add your own implementation.}"; // NOI18N
1508:
1509: //Exceptions
1510: StringBuffer doc = new StringBuffer();
1511: List<String> exceps = attribute.getSetterExceptions();
1512: List<ExpressionTree> exceptions = new ArrayList<ExpressionTree>();
1513: for (String excep : exceps) {
1514: exceptions.add(make.Identifier(excep));
1515: doc.append("@throws " + excep + " " + // NOI18N
1516: excep + "\n"); // NOI18N
1517: }
1518:
1519: //Create a parameter
1520: ModifiersTree parMods = make.Modifiers(Collections
1521: .<Modifier> emptySet(), Collections
1522: .<AnnotationTree> emptyList());
1523: ExpressionTree t = getType(w, attribute.getTypeName(),
1524: attribute.getTypeMirror());
1525: VariableTree par1 = make
1526: .Variable(parMods, "value", t, null);// NOI18N
1527: List<VariableTree> parList = new ArrayList<VariableTree>(1);
1528: parList.add(par1);
1529:
1530: // now, start the method creation
1531: MethodTree newMethod = null;
1532: String opName = "set" + attribute.getName();// NOI18N
1533: if (isClass) {
1534: newMethod = make.Method(make.Modifiers(Collections
1535: .singleton(Modifier.PUBLIC)), // modifiers and annotations
1536: opName, // name
1537: make.PrimitiveType(TypeKind.VOID), // return type
1538: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
1539: parList, // parameters
1540: exceptions, // throws
1541: methodBody, //body
1542: null // default value - not applicable here, used by annotations
1543: );
1544: } else {
1545: newMethod = make.Method(make.Modifiers(Collections
1546: .singleton(Modifier.PUBLIC)), // modifiers and annotations
1547: opName, // name
1548: make.PrimitiveType(TypeKind.VOID), // return type
1549: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
1550: parList, // parameters
1551: exceptions, // throws
1552: (BlockTree) null, //body
1553: null // default value - not applicable here, used by annotations
1554: );
1555: }
1556: JavaModelHelper.addComment(make, newMethod,
1557: Comment.Style.JAVADOC, "Set "
1558: + attribute.getDescription() + "\n"
1559: + doc.toString()); // NOI18N
1560: return newMethod;
1561: }
1562:
1563: private VariableTree addAttrField(MBeanAttribute attribute) {
1564: ExpressionTree t = getType(w, attribute.getTypeName(),
1565: attribute.getTypeMirror());
1566: TreeMaker make = w.getTreeMaker();
1567: Set<Modifier> modifiers = new HashSet<Modifier>();
1568: modifiers.add(Modifier.PRIVATE);
1569: VariableTree var = make.Variable(make.Modifiers(modifiers),
1570: WizardHelpers.forceFirstLetterLowerCase(attribute
1571: .getName()), t, null);
1572: JavaModelHelper.addComment(make, var,
1573: Comment.Style.JAVADOC, "Attribute : "
1574: + attribute.getName()); // NOI18N
1575: return var;
1576: }
1577: }
1578:
1579: private static class AddOperationsTransformer extends
1580: TreePathScanner<Void, Void> {
1581:
1582: private MBeanOperation[] operations;
1583: private WorkingCopy w;
1584: private boolean isClass;
1585:
1586: public AddOperationsTransformer(WorkingCopy w,
1587: MBeanOperation[] operations) {
1588: this .w = w;
1589: this .operations = operations;
1590: }
1591:
1592: @Override
1593: public Void visitClass(ClassTree clazz, Void v) {
1594: TreeMaker make = w.getTreeMaker();
1595: Element el = w.getTrees().getElement(getCurrentPath());
1596: if (el == null) {
1597: throw new RuntimeException("Invalid Class");// NOI18N
1598: }
1599: // Needed not to update the method body
1600: isClass = !el.getKind().equals(ElementKind.INTERFACE);
1601: ClassTree updated = clazz;
1602: for (int i = 0; i < operations.length; i++) {
1603: if (isClass && operations[i].isMethodExists())
1604: continue;
1605: MethodTree method = addOperation(operations[i]);
1606: updated = make.addClassMember(updated, method);
1607: }
1608: w.rewrite(clazz, updated);
1609: return null;
1610: }
1611:
1612: private MethodTree addOperation(MBeanOperation operation) {
1613: TreeMaker make = w.getTreeMaker();
1614:
1615: StringBuffer body = new StringBuffer();
1616: if (operation.isWrapped()) {
1617: body.append("{");// NOI18N
1618: if (!operation.getReturnTypeName().equals(
1619: WizardConstants.VOID_NAME))
1620: body.append("return "); // NOI18N
1621: body.append("theRef." + operation.getName() + "("); // NOI18N
1622: for (int i = 0; i < operation.getParametersSize(); i++) {
1623: MBeanOperationParameter param = operation
1624: .getParameter(i);
1625: body.append(param.getParamName());
1626: if (i < operation.getParametersSize() - 1)
1627: body.append(","); // NOI18N
1628: }
1629: body.append(");}"); // NOI18N
1630: } else {
1631: body.append("{//TODO add your own implementation\n"); // NOI18N
1632: if (!operation.getReturnTypeName().equals(
1633: WizardConstants.VOID_NAME)) {
1634: body.append("return " + // NOI18N
1635: WizardHelpers.getDefaultValue(operation
1636: .getReturnTypeName()) + ";"); // NOI18N
1637: }
1638: body.append("}");// NOI18N
1639: }
1640:
1641: StringBuffer doc = new StringBuffer();
1642: doc.append(operation.getDescription() + "\n"); // NOI18N
1643:
1644: ModifiersTree parMods = make.Modifiers(Collections
1645: .<Modifier> emptySet(), Collections
1646: .<AnnotationTree> emptyList());
1647: List<VariableTree> params = new ArrayList<VariableTree>(
1648: operation.getParametersSize());
1649: for (int i = 0; i < operation.getParametersSize(); i++) {
1650: MBeanOperationParameter param = operation
1651: .getParameter(i);
1652: ExpressionTree t = getType(w, param.getParamType(),
1653: param.getTypeMirror());
1654: VariableTree par = make.Variable(parMods, param
1655: .getParamName(), t, null);
1656: params.add(par);
1657: doc.append("@param " + param.getParamName() + " " + // NOI18N
1658: param.getParamDescription() + "\n"); // NOI18N
1659: }
1660:
1661: List<ExpressionTree> exceptions = new ArrayList<ExpressionTree>();
1662: for (int i = 0; i < operation.getExceptionsSize(); i++) {
1663: MBeanOperationException exception = operation
1664: .getException(i);
1665: ExpressionTree t = getType(w, exception
1666: .getExceptionClass(), null);
1667: exceptions.add(t);
1668: doc.append("@throws " + exception.getExceptionClass()
1669: + " " + // NOI18N
1670: exception.getExceptionDescription() + "\n"); // NOI18N
1671: }
1672:
1673: if (!operation.getReturnTypeName().equals(
1674: WizardConstants.VOID_NAME)) {
1675: doc.append("@return " + operation.getReturnTypeName()
1676: + "\n"); // NOI18N
1677: }
1678: ExpressionTree t = getType(w,
1679: operation.getReturnTypeName(), operation
1680: .getTypeMirror());
1681: String opName = operation.getName();
1682: MethodTree newMethod = null;
1683: if (isClass) {
1684: newMethod = make.Method(make.Modifiers(Collections
1685: .singleton(Modifier.PUBLIC)), // modifiers and annotations
1686: opName, // name
1687: t, // return type
1688: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
1689: params, // parameters
1690: exceptions, // throws
1691: body.toString(), //body
1692: null // default value - not applicable here, used by annotations
1693: );
1694: } else {
1695: newMethod = make.Method(make.Modifiers(Collections
1696: .singleton(Modifier.PUBLIC)), // modifiers and annotations
1697: opName, // name
1698: t, // return type
1699: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
1700: params, // parameters
1701: exceptions, // throws
1702: (BlockTree) null, //body
1703: null // default value - not applicable here, used by annotations
1704: );
1705: }
1706: JavaModelHelper.addComment(make, newMethod,
1707: Comment.Style.JAVADOC, doc.toString());
1708: return newMethod;
1709: }
1710: }
1711:
1712: private static class AttributeImplementationVisitor extends
1713: MemberVisitor {
1714:
1715: private MBeanAttribute attribute;
1716: private boolean leafDone;
1717:
1718: public AttributeImplementationVisitor(CompilationInfo info,
1719: ValueHolder holder, MBeanAttribute attribute) {
1720: super (info, holder);
1721: this .attribute = attribute;
1722: }
1723:
1724: @Override
1725: public Void visitClass(ClassTree t, Void v) {
1726: if (leafDone)
1727: return null;
1728: leafDone = true;
1729: Element el = info.getTrees().getElement(getCurrentPath());
1730: if (el == null) {
1731: throw new RuntimeException("Invalid Class");// NOI18N
1732: }
1733: TypeElement te = (TypeElement) el;
1734: //System.out.println("SERACHING 1");
1735:
1736: MBeanAttribute found = searchAttributeImplementation(te,
1737: info);
1738: //System.out.println("SERACHING 2");
1739: holder.setValue(found);
1740: return null;
1741: }
1742:
1743: private MBeanAttribute searchAttributeImplementation(
1744: TypeElement clazz, CompilationInfo info) {
1745: if (clazz == null)
1746: return null;
1747: TypeMirror sup = clazz.getSuperclass();
1748: MBeanAttribute found = null;
1749: if (sup != null) {
1750: TypeElement supElement = (TypeElement) info.getTypes()
1751: .asElement(sup);
1752: searchAttributeImplementation(supElement, info);
1753: }
1754: //System.out.println("SERACHING FOR " + clazz.getSimpleName());
1755: List<ExecutableElement> methods = ElementFilter
1756: .methodsIn(clazz.getEnclosedElements());
1757: for (ExecutableElement method : methods) {
1758: //System.out.println("METHOD " + method.getSimpleName());
1759: if (method.getSimpleName().toString().equals(
1760: "get" + attribute.getName())) {// NOI18N
1761: attribute.setGetMethodExits(method.getParameters()
1762: .isEmpty());// &&
1763: // method.getModifiers().contains(Modifier.PUBLIC));
1764: // Update with potential Exceptions
1765: if (attribute.getGetMethodExits()) {
1766: updateAttributeWithExceptions(method,
1767: attribute, info);
1768: }
1769: }
1770: if (method.getSimpleName().toString().equals(
1771: "is" + attribute.getName())) {// NOI18N
1772: attribute.setIsMethodExits(method.getParameters()
1773: .isEmpty());// &&
1774: //method.getModifiers().contains(Modifier.PUBLIC));
1775: // Update with potential Exceptions
1776: if (attribute.getIsMethodExits()) {
1777: updateAttributeWithExceptions(method,
1778: attribute, info);
1779: }
1780: }
1781: if (method.getSimpleName().toString().equals(
1782: "set" + attribute.getName())) {// NOI18N
1783: boolean sameType = false;
1784:
1785: if (method.getParameters().size() == 1) {
1786: List<? extends VariableElement> params = method
1787: .getParameters();
1788: VariableElement p = params.get(0);
1789:
1790: //System.out.println("set" + attribute.getName());
1791: //System.out.println("What is the impl type " + p.asType());
1792: //System.out.println("What is the itf type " + attribute.getTypeMirror());
1793: // XXX equals on MirrorType seems not to work in some cases...
1794: //TypeMirror tm = attribute.getTypeMirror();
1795: //if(tm != null)
1796: // sameType = p.asType().equals(tm);
1797: //else {
1798: String tn = getTypeName(p.asType(), null, null,
1799: info);
1800: sameType = tn.contains(attribute.getTypeName());
1801: //}
1802: }
1803: attribute.setSetMethodExits(sameType);// &&
1804: // method.getModifiers().contains(Modifier.PUBLIC));
1805: // Update with potential Exceptions
1806: if (attribute.getSetMethodExits()) {
1807: updateAttributeWithExceptions(method,
1808: attribute, info);
1809: }
1810: }
1811: }
1812:
1813: if (attribute.getIsMethodExits()
1814: || attribute.getGetMethodExits()
1815: || attribute.getSetMethodExits())
1816: return attribute;
1817: else
1818: return null;
1819: }
1820:
1821: private static void updateAttributeWithExceptions(
1822: ExecutableElement method, MBeanAttribute attribute,
1823: CompilationInfo info) {
1824: List<? extends TypeMirror> exceptions = method
1825: .getThrownTypes();
1826: List<String> attrExceptions = attribute
1827: .getGetterExceptions();
1828: for (TypeMirror exception : exceptions) {
1829: TypeElement elem = (TypeElement) info.getTypes()
1830: .asElement(exception);
1831: attrExceptions.add(elem.getQualifiedName().toString());
1832: }
1833: }
1834: }
1835:
1836: private static class OperationImplementationVisitor extends
1837: MemberVisitor {
1838:
1839: private MBeanOperation operation;
1840: private boolean leafVisited;
1841:
1842: public OperationImplementationVisitor(CompilationInfo info,
1843: ValueHolder holder, MBeanOperation operation) {
1844: super (info, holder);
1845: this .operation = operation;
1846: }
1847:
1848: @Override
1849: public Void visitClass(ClassTree t, Void v) {
1850: if (leafVisited)
1851: return null;
1852: leafVisited = true;
1853: Element el = info.getTrees().getElement(getCurrentPath());
1854: if (el == null) {
1855: throw new RuntimeException("Invalid Class");// NOI18N
1856: }
1857: TypeElement te = (TypeElement) el;
1858: // System.out.println("Search Operatione 1");
1859: MBeanOperation found = searchOperationImplementation(te,
1860: info);
1861: // System.out.println("Search Operatione 2");
1862:
1863: holder.setValue(found);
1864: return null;
1865: }
1866:
1867: private MBeanOperation searchOperationImplementation(
1868: TypeElement clazz, CompilationInfo info) {
1869: if (clazz == null)
1870: return null;
1871: TypeMirror sup = clazz.getSuperclass();
1872: MBeanOperation found = null;
1873: if (sup != null) {
1874: TypeElement supElement = (TypeElement) info.getTypes()
1875: .asElement(sup);
1876: found = searchOperationImplementation(supElement, info);
1877: }
1878: if (found != null)
1879: return found;
1880: List<ExecutableElement> methods = ElementFilter
1881: .methodsIn(clazz.getEnclosedElements());
1882: //System.out.println("CLAZZ " + clazz.getSimpleName());
1883: for (ExecutableElement method : methods) {
1884: // System.out.println("OPERATION " + method.getSimpleName());
1885: if (method.getSimpleName().toString().equals(
1886: operation.getName())) {
1887: // System.out.println("SAME OPERATION " + method.getSimpleName());
1888: List<? extends VariableElement> params = method
1889: .getParameters();
1890: if (params.size() == operation.getParametersList()
1891: .size()) {
1892: // System.out.println("SAME SIZE " + params.size());
1893: List<MBeanOperationParameter> ps = operation
1894: .getParametersList();
1895: int i = 0;
1896: boolean sameParams = true;
1897: for (VariableElement param : params) {
1898: TypeMirror type = param.asType();
1899: MBeanOperationParameter p = ps.get(i);
1900: //TypeElement te = info.getElements().getTypeElement(WizardHelpers.getFullTypeName(p.getParamType()));
1901: //System.out.println("IS SAME" + te.asType() + " " + type );
1902: //System.out.println("IS SAME" + te.asType().equals(type) );
1903: //String tn = getTypeName(te.asType(), null, null, info);
1904: //System.out.println("IS SAME" + p.getParamType() + " " + type );
1905: boolean sameType = type.toString()
1906: .contains(p.getParamType());
1907: sameParams = sameParams && sameType;
1908: i++;
1909: }
1910: if (sameParams) {// && method.getModifiers().contains(Modifier.PUBLIC)) {
1911: operation.setMethodExists(true);
1912: //updateOperationWithExceptions(method, operation, info);
1913: return operation;
1914: }
1915: }
1916: }
1917: }
1918: return null;
1919: }
1920:
1921: }
1922:
1923: private static class IsGeneratedAgentAgentVisitor extends
1924: MemberVisitor {
1925: public IsGeneratedAgentAgentVisitor(CompilationInfo info,
1926: ValueHolder holder) {
1927: super (info, holder);
1928: }
1929:
1930: @Override
1931: public Void visitClass(ClassTree t, Void v) {
1932: Element el = info.getTrees().getElement(getCurrentPath());
1933: if (el == null) {
1934: throw new RuntimeException("Invalid Class");// NOI18N
1935: }
1936: TypeElement te = (TypeElement) el;
1937: // How do I test the TypeElement to be an Interface????
1938: if (te.getClass().isInterface()) {
1939: holder.setValue(Boolean.FALSE);
1940: } else {
1941: boolean hasInit = false;
1942: boolean hasGetMBS = false;
1943: List<ExecutableElement> methods = ElementFilter
1944: .methodsIn(te.getEnclosedElements());
1945: for (ExecutableElement method : methods) {
1946: if (method.getSimpleName().toString().equals(
1947: INIT_METHOD_NAME))
1948: hasInit = true;
1949: if (method.getSimpleName().toString().equals(
1950: GET_MBEANSERVER_METHOD_NAME)) {
1951: hasGetMBS = method.getParameters().isEmpty();
1952: }
1953: }
1954: holder.setValue((hasInit && hasGetMBS));
1955: }
1956: return null;
1957: }
1958: }
1959:
1960: private static class MBeanNotificationTransformer extends
1961: TreePathScanner<Void, Void> {
1962: // MBeanNotificationInfo instantiation pattern
1963: // {0} = notification type
1964: // {1} = notification class
1965: // {2} = notification description
1966: private static final String MBEAN_NOTIF_INFO_PATTERN = " new MBeanNotificationInfo(new String[] '{'\n"
1967: + // NOI18N
1968: " {0}'}',\n" + // NOI18N
1969: " {1}.class.getName(),\n" + // NOI18N
1970: " \"{2}\")"; // NOI18N
1971:
1972: private static final String BODY_COMMENT = "{//TODO add your code here}"; // NOI18N
1973:
1974: private final WorkingCopy w;
1975: private final MBeanNotification[] notifs;
1976: private final boolean genBroadcastDeleg;
1977: private final boolean genSeqNumber;
1978:
1979: public MBeanNotificationTransformer(WorkingCopy w,
1980: MBeanNotification[] notifs, boolean genBroadcastDeleg,
1981: boolean genSeqNumber) {
1982: this .w = w;
1983: this .notifs = notifs;
1984: this .genSeqNumber = genSeqNumber;
1985: this .genBroadcastDeleg = genBroadcastDeleg;
1986: }
1987:
1988: @Override
1989: public Void visitClass(ClassTree clazz, Void v) {
1990: //Obtain the owner of this method, getCurrentPath() returns a path from root (CompilationUnitTree) to current node (tree)
1991: // XXX REVISIT WITH API CHANGES
1992: TreeMaker make = w.getTreeMaker();
1993: TypeElement emitter = w.getElements().getTypeElement(
1994: "javax.management.NotificationEmitter");// NOI18N
1995: ClassTree copy = make.addClassImplementsClause(clazz, make
1996: .QualIdent(emitter));
1997:
1998: MethodTree m = addAddNotifListMethod(genBroadcastDeleg);
1999: copy = make.addClassMember(copy, m);
2000:
2001: // Remove existing getNotificationInfo
2002: List<? extends Tree> members = copy.getMembers();
2003: for (Tree t : members) {
2004: if (t instanceof MethodTree) {
2005: MethodTree mt = (MethodTree) t;
2006: String methodName = mt.getName().toString();
2007: if ("getNotificationInfo".equals(methodName)) {//NOI18N
2008: TreeMaker treeMaker = w.getTreeMaker();
2009: //Create a new class tree without main method
2010: copy = treeMaker.removeClassMember(copy, mt);
2011: }
2012: }
2013: }
2014: m = addGetNotifInfoMethod(notifs);
2015: copy = make.addClassMember(copy, m);
2016:
2017: m = addRemoveNotifListMethod1Param(genBroadcastDeleg);
2018: copy = make.addClassMember(copy, m);
2019:
2020: m = addRemoveNotifListMethod(genBroadcastDeleg);
2021: copy = make.addClassMember(copy, m);
2022:
2023: if (genSeqNumber) {
2024: m = addGetSeqNumberMethod();
2025: copy = make.addClassMember(copy, m);
2026: }
2027:
2028: if (genSeqNumber) {
2029: VariableTree var = addSeqNumField();
2030: copy = make.insertClassMember(copy, 0, var);
2031: }
2032: if (genBroadcastDeleg) {
2033: VariableTree var = addBroadcasterField();
2034: copy = make.insertClassMember(copy, 0, var);
2035: }
2036:
2037: copy = addNotifTypes(notifs, copy);
2038: w.rewrite(clazz, copy);
2039: super .visitClass(clazz, v);
2040: return null;
2041: }
2042:
2043: private MethodTree addAddNotifListMethod(
2044: boolean genBroadcastDeleg) {
2045: TreeMaker make = w.getTreeMaker();
2046: ModifiersTree parMods = make.Modifiers(Collections
2047: .<Modifier> emptySet(), Collections
2048: .<AnnotationTree> emptyList());
2049: // make a variable trees - representing parameters
2050: TypeElement listenerType = w.getElements().getTypeElement(
2051: "javax.management.NotificationListener");// NOI18N
2052: TypeElement filterType = w.getElements().getTypeElement(
2053: "javax.management.NotificationFilter");// NOI18N
2054: TypeElement handbackType = w.getElements().getTypeElement(
2055: "java.lang.Object");// NOI18N
2056: VariableTree par1 = make.Variable(parMods, "listener", make
2057: .QualIdent(listenerType), null);// NOI18N
2058: VariableTree par2 = make.Variable(parMods, "filter", make
2059: .QualIdent(filterType), null);// NOI18N
2060: VariableTree par3 = make.Variable(parMods, "handback", make
2061: .QualIdent(handbackType), null);// NOI18N
2062: List<VariableTree> parList = new ArrayList<VariableTree>(3);
2063: parList.add(par1);
2064: parList.add(par2);
2065: parList.add(par3);
2066:
2067: // now, start the method creation
2068: MethodTree newMethod = make
2069: .Method(
2070: make.Modifiers(Collections
2071: .singleton(Modifier.PUBLIC)),// NOI18N // modifiers and annotations
2072: "addNotificationListener",// NOI18N // name
2073: make.PrimitiveType(TypeKind.VOID), // return type
2074: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
2075: parList, // parameters
2076: Collections
2077: .singletonList(make
2078: .Identifier("IllegalArgumentException")), // NOI18N// throws
2079: (genBroadcastDeleg ? "{broadcaster.addNotificationListener(listener, filter, handback);}"
2080: : BODY_COMMENT), // NOI18N //body
2081: null // default value - not applicable here, used by annotations
2082: );
2083: return newMethod;
2084: }
2085:
2086: private MethodTree addGetNotifInfoMethod(
2087: MBeanNotification[] notifs) {
2088: TreeMaker make = w.getTreeMaker();
2089: // remove getNotificationInfo() if it already exists
2090: List params = new ArrayList();
2091:
2092: // XXX Revisit, Don't understand this the current method shouldn't have any getNotificationInfo method
2093: //Method getNotifInfo = tgtClass.getMethod("getNotificationInfo", params,false); // NOI18N
2094: //if (getNotifInfo != null)
2095: // getNotifInfo.refDelete();
2096:
2097: StringBuffer methodBody = new StringBuffer();
2098: methodBody
2099: .append("{return new MBeanNotificationInfo[] {\n"); // NOI18N
2100: MessageFormat notifInfo = new MessageFormat(
2101: MBEAN_NOTIF_INFO_PATTERN);
2102: TypeElement te = w.getElements().getTypeElement(
2103: "javax.management.MBeanNotificationInfo");// NOI18N
2104:
2105: Tree retValue = make.ArrayType(make.QualIdent(te));
2106: int notifTypeIndex = 0;
2107: for (int i = 0; i < notifs.length; i++) {
2108: StringBuffer notifType = new StringBuffer();
2109: for (int j = 0; j < notifs[i]
2110: .getNotificationTypeCount(); j++) {
2111: if (!notifs[i]
2112: .getNotificationClass()
2113: .equals(
2114: WizardConstants.ATTRIBUTECHANGE_NOTIFICATION)) {
2115: notifType
2116: .append("NOTIF_TYPE_" + notifTypeIndex); // NOI18N
2117: notifTypeIndex++;
2118: } else {
2119: notifType
2120: .append(WizardConstants.ATTRIBUTECHANGE_TYPE);
2121: }
2122: if (j < notifs[i].getNotificationTypeCount() - 1) {
2123: notifType.append(",\n "); // NOI18N
2124: }
2125: }
2126: Object[] notifArguments = { notifType.toString(),
2127: notifs[i].getNotificationClass(),
2128: notifs[i].getNotificationDescription() };
2129: methodBody.append(notifInfo.format(notifArguments));
2130: if ((notifs.length > 1) && (i < (notifs.length - 1))) {
2131: methodBody.append(","); // NOI18N
2132: }
2133: methodBody.append("\n"); // NOI18N
2134: }
2135: methodBody.append("};}"); // NOI18N
2136:
2137: MethodTree newMethod = make.Method(make
2138: .Modifiers(Collections.singleton(Modifier.PUBLIC)), // modifiers and annotations
2139: "getNotificationInfo", // NOI18N// name
2140: retValue, // return type
2141: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
2142: Collections.<VariableTree> emptyList(), // parameters
2143: Collections.<ExpressionTree> emptyList(), // throws
2144: methodBody.toString(), //body
2145: null // default value - not applicable here, used by annotations
2146: );
2147: return newMethod;
2148: }
2149:
2150: private MethodTree addRemoveNotifListMethod1Param(
2151: boolean genBroadcastDeleg) {
2152: TreeMaker make = w.getTreeMaker();
2153:
2154: ModifiersTree parMods = make.Modifiers(Collections
2155: .<Modifier> emptySet(), Collections
2156: .<AnnotationTree> emptyList());
2157: // make a variable trees - representing parameters
2158: TypeElement listenerType = w.getElements().getTypeElement(
2159: "javax.management.NotificationListener");// NOI18N
2160: VariableTree par1 = make.Variable(parMods, "listener", make
2161: .QualIdent(listenerType), null);// NOI18N
2162: List<VariableTree> parList = new ArrayList<VariableTree>(1);
2163: parList.add(par1);
2164:
2165: // now, start the method creation
2166: MethodTree newMethod = make
2167: .Method(
2168: make.Modifiers(Collections
2169: .singleton(Modifier.PUBLIC)), // modifiers and annotations
2170: "removeNotificationListener", // NOI18N // name
2171: make.PrimitiveType(TypeKind.VOID), // return type
2172: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
2173: parList, // parameters
2174: Collections
2175: .singletonList(make
2176: .Identifier("ListenerNotFoundException")), // NOI18N // throws
2177: (genBroadcastDeleg ? "{broadcaster.removeNotificationListener(listener);}"
2178: : BODY_COMMENT), // NOI18N //body
2179: null // default value - not applicable here, used by annotations
2180: );
2181: return newMethod;
2182: }
2183:
2184: private MethodTree addRemoveNotifListMethod(
2185: boolean genBroadcastDeleg) {
2186: TreeMaker make = w.getTreeMaker();
2187: ModifiersTree parMods = make.Modifiers(Collections
2188: .<Modifier> emptySet(), Collections
2189: .<AnnotationTree> emptyList());
2190: // make a variable trees - representing parameters
2191: TypeElement listenerType = w.getElements().getTypeElement(
2192: "javax.management.NotificationListener");// NOI18N
2193: TypeElement filterType = w.getElements().getTypeElement(
2194: "javax.management.NotificationFilter");// NOI18N
2195: TypeElement handbackType = w.getElements().getTypeElement(
2196: "java.lang.Object");// NOI18N
2197: VariableTree par1 = make.Variable(parMods, "listener", make
2198: .QualIdent(listenerType), null);// NOI18N
2199: VariableTree par2 = make.Variable(parMods, "filter", make
2200: .QualIdent(filterType), null);// NOI18N
2201: VariableTree par3 = make.Variable(parMods, "handback", make
2202: .QualIdent(handbackType), null);// NOI18N
2203: List<VariableTree> parList = new ArrayList<VariableTree>(3);
2204: parList.add(par1);
2205: parList.add(par2);
2206: parList.add(par3);
2207:
2208: // now, start the method creation
2209: MethodTree newMethod = make
2210: .Method(
2211: make.Modifiers(Collections
2212: .singleton(Modifier.PUBLIC)), // modifiers and annotations
2213: "removeNotificationListener", // NOI18N // name
2214: make.PrimitiveType(TypeKind.VOID), // return type
2215: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
2216: parList, // parameters
2217: Collections
2218: .singletonList(make
2219: .Identifier("ListenerNotFoundException")), // NOI18N // throws
2220: (genBroadcastDeleg ? "{broadcaster.removeNotificationListener(listener, filter, handback);}"
2221: : BODY_COMMENT), // NOI18N //body
2222: null // default value - not applicable here, used by annotations
2223: );
2224: return newMethod;
2225: }
2226:
2227: private MethodTree addGetSeqNumberMethod() {
2228: TreeMaker make = w.getTreeMaker();
2229: String methodBody = "{return seqNumber++;}"; // NOI18N
2230: Set<Modifier> modifiers = new HashSet<Modifier>(2);
2231: modifiers.add(Modifier.PUBLIC);
2232: modifiers.add(Modifier.SYNCHRONIZED);
2233: MethodTree newMethod = make.Method(make
2234: .Modifiers(modifiers), // modifiers and annotations
2235: "getNextSeqNumber", // NOI18N // name
2236: make.PrimitiveType(TypeKind.LONG), // return type
2237: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
2238: Collections.<VariableTree> emptyList(), // parameters
2239: Collections.<ExpressionTree> emptyList(), // throws
2240: methodBody, //body
2241: null // default value - not applicable here, used by annotations
2242: );
2243: return newMethod;
2244: }
2245:
2246: private VariableTree addSeqNumField() {
2247: TreeMaker make = w.getTreeMaker();
2248: Set<Modifier> modifiers = new HashSet<Modifier>();
2249: modifiers.add(Modifier.PRIVATE);
2250: VariableTree var = make.Variable(make.Modifiers(modifiers),
2251: "seqNumber", make.PrimitiveType(TypeKind.LONG),
2252: null);// NOI18N
2253: return var;
2254: }
2255:
2256: private VariableTree addBroadcasterField() {
2257: TreeMaker make = w.getTreeMaker();
2258: TypeElement supportType = w.getElements().getTypeElement(
2259: "javax.management.NotificationBroadcasterSupport");// NOI18N
2260: // Write a new XX
2261: ExpressionTree ex = make.QualIdent(supportType);
2262: NewClassTree initializer = make.NewClass(null, Collections
2263: .<ExpressionTree> emptyList(), ex, Collections
2264: .<ExpressionTree> emptyList(), null);
2265: Set<Modifier> modifiers = new HashSet<Modifier>();
2266: modifiers.add(Modifier.PRIVATE);
2267: VariableTree var = make.Variable(make.Modifiers(modifiers),
2268: "broadcaster", ex, initializer);// NOI18N
2269: return var;
2270: }
2271:
2272: private ClassTree addNotifTypes(MBeanNotification[] notifs,
2273: ClassTree copy) {
2274: TreeMaker make = w.getTreeMaker();
2275: String comments = "Notification types definitions. To use when creating JMX Notifications."; // NOI18N
2276: int notifTypeIndex = 0;
2277: Set<Modifier> modifiers = new HashSet<Modifier>();
2278: modifiers.add(Modifier.PRIVATE);
2279: modifiers.add(Modifier.STATIC);
2280: modifiers.add(Modifier.FINAL);
2281: TypeElement stringElem = w.getElements().getTypeElement(
2282: "java.lang.String");// NOI18N
2283: ExpressionTree stringType = make.QualIdent(stringElem);
2284: for (int i = 0; i < notifs.length; i++) {
2285: if (!notifs[i].getNotificationClass().equals(
2286: WizardConstants.ATTRIBUTECHANGE_NOTIFICATION)) {
2287: for (int j = 0; j < notifs[i]
2288: .getNotificationTypeCount(); j++) {
2289: VariableTree var = make.Variable(make
2290: .Modifiers(modifiers), "NOTIF_TYPE_"
2291: + notifTypeIndex,// NOI18N
2292: stringType, make.Literal(notifs[i]
2293: .getNotificationType(j)
2294: .getNotificationType()));
2295: if (notifTypeIndex == 0) {
2296: JavaModelHelper.addComment(make, var,
2297: Comment.Style.JAVADOC, comments);
2298: }
2299: copy = make.addClassMember(copy, var);
2300: notifTypeIndex++;
2301: }
2302: }
2303: }
2304: return copy;
2305: }
2306: }
2307:
2308: private static class MBeanRegistrationTransformer extends
2309: TreePathScanner<Void, Void> {
2310:
2311: private static final String PRE_REGISTER_JAVADOC = "Allows the MBean to perform any operations it needs before being\n"
2312: + // NOI18N
2313: "registered in the MBean server. If the name of the MBean is not\n"
2314: + // NOI18N
2315: "specified, the MBean can provide a name for its registration. If\n"
2316: + // NOI18N
2317: "any exception is raised, the MBean will not be registered in the\n"
2318: + // NOI18N
2319: "MBean server.\n"
2320: + // NOI18N
2321: "@param server The MBean server in which the MBean will be registered.\n"
2322: + // NOI18N
2323: "@param name The object name of the MBean. This name is null if the\n"
2324: + // NOI18N
2325: "name parameter to one of the createMBean or registerMBean methods in\n"
2326: + // NOI18N
2327: "the MBeanServer interface is null. In that case, this method must\n"
2328: + // NOI18N
2329: "return a non-null ObjectName for the new MBean.\n"
2330: + // NOI18N
2331: "@return The name under which the MBean is to be registered. This value\n"
2332: + // NOI18N
2333: "must not be null. If the name parameter is not null, it will usually\n"
2334: + // NOI18N
2335: "but not necessarily be the returned value.\n"
2336: + // NOI18N
2337: "@throws Exception This exception will be caught by the MBean server and\n"
2338: + // NOI18N
2339: "re-thrown as an MBeanRegistrationException."; // NOI18N
2340:
2341: private static final String POST_REGISTER_JAVADOC = "Allows the MBean to perform any operations needed after having\n"
2342: + // NOI18N
2343: "been registered in the MBean server or after the registration has\n"
2344: + // NOI18N
2345: "failed.\n"
2346: + // NOI18N
2347: "@param registrationDone Indicates wether or not the MBean has been\n"
2348: + // NOI18N
2349: "successfully registered in the MBean server. The value false means\n"
2350: + // NOI18N
2351: "that the registration has failed.\n"; // NOI18N
2352:
2353: private static final String PRE_DEREGISTER_JAVADOC = "Allows the MBean to perform any operations it needs before being\n"
2354: + // NOI18N
2355: "unregistered by the MBean server.\n"
2356: + // NOI18N
2357: "@throws Exception This exception will be caught by the MBean server and\n"
2358: + // NOI18N
2359: "re-thrown as an MBeanRegistrationException."; // NOI18N
2360:
2361: private static final String POST_DEREGISTER_JAVADOC = "Allows the MBean to perform any operations needed after having been\n"
2362: + // NOI18N
2363: "unregistered in the MBean server.\n"; // NOI18N
2364:
2365: private final WorkingCopy w;
2366: private final boolean keepRefSelected;
2367:
2368: public MBeanRegistrationTransformer(WorkingCopy w,
2369: boolean keepRefSelected) {
2370: this .w = w;
2371: this .keepRefSelected = keepRefSelected;
2372: }
2373:
2374: @Override
2375: public Void visitClass(ClassTree clazz, Void v) {
2376: TreeMaker make = w.getTreeMaker();
2377: TypeElement emitter = w.getElements().getTypeElement(
2378: "javax.management.MBeanRegistration");// NOI18N
2379: ClassTree copy = make.addClassImplementsClause(clazz, make
2380: .QualIdent(emitter));
2381:
2382: MethodTree m = addPreRegisterMethod();
2383: copy = make.addClassMember(copy, m);
2384:
2385: m = addPostRegisterMethod();
2386: copy = make.addClassMember(copy, m);
2387:
2388: m = addPreDeregisterMethod();
2389: copy = make.addClassMember(copy, m);
2390:
2391: m = addPostDeregisterMethod();
2392: copy = make.addClassMember(copy, m);
2393:
2394: if (keepRefSelected) {
2395: VariableTree var = addMBeanServerField();
2396: copy = make.insertClassMember(copy, 0, var);
2397: var = addObjectNameField();
2398: copy = make.insertClassMember(copy, 0, var);
2399: }
2400: w.rewrite(clazz, copy);
2401: super .visitClass(clazz, v);
2402: return null;
2403: }
2404:
2405: private MethodTree addPreRegisterMethod() {
2406: TreeMaker make = w.getTreeMaker();
2407:
2408: String methodBody = "return name;"; // NOI18N
2409: if (keepRefSelected)
2410: methodBody = "objectName = name;" + // NOI18N
2411: "mbeanServer = server;" + // NOI18N
2412: methodBody;
2413:
2414: methodBody = "{" + methodBody + "}";// NOI18N
2415:
2416: ModifiersTree parMods = make.Modifiers(Collections
2417: .<Modifier> emptySet(), Collections
2418: .<AnnotationTree> emptyList());
2419: // make a variable trees - representing parameters
2420: TypeElement serverType = w.getElements().getTypeElement(
2421: "javax.management.MBeanServer");// NOI18N
2422: TypeElement nameType = w.getElements().getTypeElement(
2423: "javax.management.ObjectName");// NOI18N
2424: Tree nameTree = make.QualIdent(nameType);
2425: VariableTree par1 = make.Variable(parMods, "server", make
2426: .QualIdent(serverType), null);// NOI18N
2427: VariableTree par2 = make.Variable(parMods, "name", make
2428: .QualIdent(nameType), null);// NOI18N
2429:
2430: List<VariableTree> parList = new ArrayList<VariableTree>(2);
2431: parList.add(par1);
2432: parList.add(par2);
2433:
2434: // now, start the method creation
2435: MethodTree newMethod = make.Method(make
2436: .Modifiers(Collections.singleton(Modifier.PUBLIC)), // modifiers and annotations
2437: "preRegister", // NOI18N
2438: nameTree, // return type
2439: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
2440: parList, // parameters
2441: Collections.singletonList(make
2442: .Identifier("Exception")), // NOI18N
2443: methodBody,//body
2444: null // default value - not applicable here, used by annotations
2445: );
2446: JavaModelHelper.addComment(make, newMethod,
2447: Comment.Style.JAVADOC, PRE_REGISTER_JAVADOC);
2448:
2449: return newMethod;
2450: }
2451:
2452: private MethodTree addPostRegisterMethod() {
2453: TreeMaker make = w.getTreeMaker();
2454: String methodBody = "{//TODO postRegister implementation;}"; // NOI18N
2455: ModifiersTree parMods = make.Modifiers(Collections
2456: .<Modifier> emptySet(), Collections
2457: .<AnnotationTree> emptyList());
2458: // make a variable trees - representing parameters
2459: VariableTree par1 = make.Variable(parMods,
2460: "registrationDone", make.Identifier("Boolean"),
2461: null); // NOI18N
2462:
2463: List<VariableTree> parList = new ArrayList<VariableTree>(1);
2464: parList.add(par1);
2465:
2466: // now, start the method creation
2467: MethodTree newMethod = make.Method(make
2468: .Modifiers(Collections.singleton(Modifier.PUBLIC)), // modifiers and annotations
2469: "postRegister", // NOI18N // name
2470: make.PrimitiveType(TypeKind.VOID), // return type
2471: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
2472: parList, // parameters
2473: Collections.<ExpressionTree> emptyList(), // throws
2474: methodBody,//body
2475: null // default value - not applicable here, used by annotations
2476: );
2477:
2478: JavaModelHelper.addComment(make, newMethod,
2479: Comment.Style.JAVADOC, POST_REGISTER_JAVADOC);
2480: return newMethod;
2481: }
2482:
2483: private MethodTree addPreDeregisterMethod() {
2484: TreeMaker make = w.getTreeMaker();
2485:
2486: String methodBody = "{//TODO preDeregister implementation}"; // NOI18N
2487:
2488: MethodTree newMethod = make.Method(make
2489: .Modifiers(Collections.singleton(Modifier.PUBLIC)), // modifiers and annotations
2490: "preDeregister", // NOI18N // name
2491: make.PrimitiveType(TypeKind.VOID), // return type
2492: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
2493: Collections.<VariableTree> emptyList(), // parameters
2494: Collections.singletonList(make
2495: .Identifier("Exception")), // NOI18N // throws
2496: methodBody, //body
2497: null // default value - not applicable here, used by annotations
2498: );
2499:
2500: JavaModelHelper.addComment(make, newMethod,
2501: Comment.Style.JAVADOC, PRE_DEREGISTER_JAVADOC);
2502: return newMethod;
2503: }
2504:
2505: private MethodTree addPostDeregisterMethod() {
2506: TreeMaker make = w.getTreeMaker();
2507:
2508: String methodBody = "{//TODO postDeregister implementation}"; // NOI18N
2509:
2510: MethodTree newMethod = make.Method(make
2511: .Modifiers(Collections.singleton(Modifier.PUBLIC)), // modifiers and annotations
2512: "postDeregister", // NOI18N // name
2513: make.PrimitiveType(TypeKind.VOID), // return type
2514: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
2515: Collections.<VariableTree> emptyList(), // parameters
2516: Collections.<ExpressionTree> emptyList(), // throws
2517: methodBody, //body
2518: null // default value - not applicable here, used by annotations
2519: );
2520:
2521: JavaModelHelper.addComment(make, newMethod,
2522: Comment.Style.JAVADOC, POST_DEREGISTER_JAVADOC);
2523: return newMethod;
2524: }
2525:
2526: private VariableTree addMBeanServerField() {
2527: TreeMaker make = w.getTreeMaker();
2528: Set<Modifier> modifiers = new HashSet<Modifier>();
2529: modifiers.add(Modifier.PRIVATE);
2530: TypeElement serverType = w.getElements().getTypeElement(
2531: "javax.management.MBeanServer");// NOI18N
2532: VariableTree var = make.Variable(make.Modifiers(modifiers),
2533: "mbeanServer", make.QualIdent(serverType), null);// NOI18N
2534: return var;
2535: }
2536:
2537: private VariableTree addObjectNameField() {
2538: TreeMaker make = w.getTreeMaker();
2539: Set<Modifier> modifiers = new HashSet<Modifier>();
2540: modifiers.add(Modifier.PRIVATE);
2541: TypeElement nameType = w.getElements().getTypeElement(
2542: "javax.management.ObjectName");// NOI18N
2543: VariableTree var = make.Variable(make.Modifiers(modifiers),
2544: "objectName", make.QualIdent(nameType), null);// NOI18N
2545: return var;
2546: }
2547: }
2548:
2549: private static class UpdateDynamicMBeanTemplateTransformer extends
2550: TreePathScanner<Void, Void> {
2551:
2552: // {0} = attribute name to check
2553: // {1} = attribute name
2554: // {2} = code to execute for attribute
2555: // {3} = return statement
2556: private static final String CHECK_ATTR_NAME_PATTERN = "if ({0}.equals(\"{1}\")) '{'\n\n"
2557: + // NOI18N
2558: " {2}\n\n{3}" + // NOI18N
2559: "'}'"; // NOI18N
2560:
2561: // {0} = attribute name
2562: // {1} = return or set
2563: private static final String COMMENT_ATTR_VALUE_PATTERN = "//TODO {1} value of {0} attribute"; // NOI18N
2564:
2565: // {0} = attribute name
2566: private static final String THROW_ATTR_VALUE_PATTERN = "throw new MBeanException(\n"
2567: + // NOI18N
2568: " new IllegalArgumentException(\"{0} is read-only.\"));"; // NOI18N
2569:
2570: private static final String COMMENT_INVOKE = "\n" + // NOI18N
2571: " //TODO add your code here\n\n" + // NOI18N
2572: " return "; // NOI18N
2573:
2574: // {0} = attribute name
2575: // {1} = attribute type
2576: // {2} = attribute description
2577: // {3} = isReadable
2578: // {4} = isWritable
2579: // {5} = isIs
2580: private static final String MBEAN_ATT_INFO_PATTERN = new String(
2581: " new MBeanAttributeInfo(\"{0}\",\n" + // NOI18N
2582: " {1},\n" + // NOI18N
2583: " \"{2}\",\n" + // NOI18N
2584: " {3},\n" + // NOI18N
2585: " {4},\n" + // NOI18N
2586: " {5})");// NOI18N
2587:
2588: // {0} = operation name
2589: // {1} = operation desc
2590: // {2} = operation type full name
2591: // {3} = operation index
2592: private static final String MBEAN_OPERATION_INFO_PATTERN = new String(
2593: " new MBeanOperationInfo(\"{0}\",\n" + // NOI18N
2594: " \"{1}\",\n" + // NOI18N
2595: " op{3}Params,\n" + // NOI18N
2596: " {2},\n" + // NOI18N
2597: " MBeanOperationInfo.ACTION)");// NOI18N
2598:
2599: // {0} = operation index
2600: private static final String MBEAN_PARAMS_INFO_PATTERN = new String(
2601: " MBeanParameterInfo[] op{0}Params = new MBeanParameterInfo[] '{'\n");// NOI18N
2602:
2603: // {0} = param name
2604: // {1} = param type full name
2605: // {2} = param desc
2606: private static final String MBEAN_PARAM_INFO_PATTERN = new String(
2607: " new MBeanParameterInfo(\"{0}\",{1},\"{2}\")");// NOI18N
2608:
2609: private final WorkingCopy w;
2610: private final MBeanDO mbean;
2611:
2612: public UpdateDynamicMBeanTemplateTransformer(WorkingCopy w,
2613: MBeanDO mbean) {
2614: this .w = w;
2615: this .mbean = mbean;
2616: }
2617:
2618: @Override
2619: public Void visitClass(ClassTree clazz, Void v) {
2620: TreeMaker maker = w.getTreeMaker();
2621: Element el = w.getTrees().getElement(getCurrentPath());
2622: updateDescription(w, el, maker, mbean.getDescription(),
2623: clazz);
2624:
2625: List attrList = mbean.getAttributes();
2626: MBeanAttribute[] attributes = (MBeanAttribute[]) attrList
2627: .toArray(new MBeanAttribute[attrList.size()]);
2628:
2629: ClassTree copy = addGetAttribute(maker, mbean, attributes,
2630: clazz);
2631: copy = addSetAttribute(maker, mbean, attributes, copy);
2632: copy = addInvoke(maker, mbean, copy);
2633: copy = addBuildMBeanInfo(maker, mbean, attributes, copy);
2634:
2635: w.rewrite(clazz, copy);
2636: super .visitClass(clazz, v);
2637: return null;
2638: }
2639:
2640: private ClassTree addGetAttribute(TreeMaker maker,
2641: MBeanDO mbean, MBeanAttribute[] attributes,
2642: ClassTree clazz) {
2643: TypeElement teret = w.getElements().getTypeElement(
2644: "java.lang.Object");// NOI18N
2645: Tree retVal = maker.QualIdent(teret);
2646:
2647: ModifiersTree parMods = maker.Modifiers(Collections
2648: .<Modifier> emptySet(), Collections
2649: .<AnnotationTree> emptyList());
2650: // make a variable trees - representing parameters
2651: TypeElement attributeType = w.getElements().getTypeElement(
2652: "java.lang.String");// NOI18N
2653: VariableTree par1 = maker.Variable(parMods,
2654: "attributeName", maker.QualIdent(attributeType),
2655: null);// NOI18N
2656: List<VariableTree> parList = new ArrayList<VariableTree>(1);
2657: parList.add(par1);
2658: List<ExpressionTree> exceptions = new ArrayList<ExpressionTree>(
2659: 3);
2660: exceptions.add(maker
2661: .Identifier("AttributeNotFoundException"));// NOI18N
2662: exceptions.add(maker.Identifier("MBeanException"));// NOI18N
2663: exceptions.add(maker.Identifier("ReflectionException"));// NOI18N
2664:
2665: // getAttribute Content
2666:
2667: StringBuffer content = new StringBuffer();
2668:
2669: content.append("{");// NOI18N
2670: MessageFormat formCheckAttr = new MessageFormat(
2671: CHECK_ATTR_NAME_PATTERN);
2672: MessageFormat formAttrComment = new MessageFormat(
2673: COMMENT_ATTR_VALUE_PATTERN);
2674: Object[] args;
2675: for (int i = 0; i < attributes.length; i++) {
2676: args = new Object[] {
2677: "attributeName",
2678: attributes[i].getName(), // NOI18N
2679: formAttrComment.format(new Object[] {
2680: attributes[i].getName(), "return" }), // NOI18N
2681: "return " + WizardHelpers.getDefaultValue( // NOI18N
2682: attributes[i].getTypeName()) + ";\n" // NOI18N
2683: };
2684: content.append(formCheckAttr.format(args) + "\n\n"); // NOI18N
2685: }
2686: content
2687: .append("throw new AttributeNotFoundException(\"Unknown Attribute \" + attributeName);"); // NOI18N
2688: content.append("}");// NOI18N
2689: // MethodTree mt = w.getTrees().getTree(method);
2690: // BlockTree copyBody = maker.createMethodBody(mt, content.toString());
2691: // w.rewrite(mt.getBody(), copyBody);
2692:
2693: MethodTree newMethod = maker.Method(maker
2694: .Modifiers(Collections.singleton(Modifier.PUBLIC)), // modifiers and annotations
2695: "getAttribute", // NOI18N // name
2696: retVal, // return type
2697: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
2698: parList, // parameters
2699: exceptions, // throws
2700: content.toString(), //body
2701: null // default value - not applicable here, used by annotations
2702: );
2703: JavaModelHelper.addComment(maker, newMethod,
2704: Comment.Style.JAVADOC,
2705: "Gets the value of the specified attribute of the DynamicMBean.\n"
2706: + // NOI18N
2707: " @param attributeName The attribute name");// NOI18N
2708: ClassTree copy = maker.insertClassMember(clazz, 1,
2709: newMethod);
2710: return copy;
2711: }
2712:
2713: private ClassTree addSetAttribute(TreeMaker maker,
2714: MBeanDO mbean, MBeanAttribute[] attributes,
2715: ClassTree clazz) {
2716: ModifiersTree parMods = maker.Modifiers(Collections
2717: .<Modifier> emptySet(), Collections
2718: .<AnnotationTree> emptyList());
2719: TypeElement attributeType = w.getElements().getTypeElement(
2720: "javax.management.Attribute");// NOI18N
2721: VariableTree par1 = maker.Variable(parMods, "attribute",
2722: maker.QualIdent(attributeType), null);// NOI18N
2723: List<VariableTree> parList = new ArrayList<VariableTree>(1);
2724: parList.add(par1);
2725: List<ExpressionTree> exceptions = new ArrayList<ExpressionTree>(
2726: 4);
2727: exceptions.add(maker
2728: .Identifier("AttributeNotFoundException"));// NOI18N
2729: exceptions.add(maker.Identifier("MBeanException"));// NOI18N
2730: exceptions.add(maker.Identifier("ReflectionException"));// NOI18N
2731: exceptions.add(maker
2732: .Identifier("InvalidAttributeValueException"));// NOI18N
2733:
2734: // setAttribute content
2735: StringBuffer content = new StringBuffer();
2736: content.append("{");// NOI18N
2737: MessageFormat formCheckAttr = new MessageFormat(
2738: CHECK_ATTR_NAME_PATTERN);
2739: MessageFormat formAttrComment = new MessageFormat(
2740: COMMENT_ATTR_VALUE_PATTERN);
2741: MessageFormat formAttrThrow = new MessageFormat(
2742: THROW_ATTR_VALUE_PATTERN);
2743:
2744: for (int i = 0; i < attributes.length; i++) {
2745: String checkedAttrBody;
2746: if (attributes[i].isWritable())
2747: checkedAttrBody = formAttrComment
2748: .format(new Object[] {
2749: attributes[i].getName(), "set" }); // NOI18N
2750: else
2751: checkedAttrBody = formAttrThrow
2752: .format(new Object[] { attributes[i]
2753: .getName() });
2754: Object[] args = new Object[] { "attribute.getName()",
2755: attributes[i].getName(), // NOI18N
2756: checkedAttrBody, "" // NOI18N
2757: };
2758: content.append(formCheckAttr.format(args));
2759: content.append(" else ");// NOI18N
2760: if (i == attributes.length - 1)
2761: content.append("\n ");// NOI18N
2762: }
2763: content
2764: .append("throw new AttributeNotFoundException(\"Unknown Attribute \" + attribute.getName());"); // NOI18N
2765: content.append("}");// NOI18N
2766:
2767: MethodTree newMethod = maker.Method(maker
2768: .Modifiers(Collections.singleton(Modifier.PUBLIC)), // modifiers and annotations
2769: "setAttribute", // NOI18N // name
2770: maker.PrimitiveType(TypeKind.VOID), // return type
2771: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
2772: parList, // parameters
2773: exceptions, // throws
2774: content.toString(), //body
2775: null // default value - not applicable here, used by annotations
2776: );
2777: JavaModelHelper.addComment(maker, newMethod,
2778: Comment.Style.JAVADOC,
2779: "Sets the value of the specified attribute of the DynamicMBean.\n"
2780: + // NOI18N
2781: "@param attribute The attribute to set");// NOI18N
2782: ClassTree copy = maker.insertClassMember(clazz, 2,
2783: newMethod);
2784:
2785: return copy;
2786: }
2787:
2788: private ClassTree addInvoke(TreeMaker maker, MBeanDO mbean,
2789: ClassTree clazz) {
2790: TypeElement operName = w.getElements().getTypeElement(
2791: "java.lang.String");// NOI18N
2792: TypeElement paramsType = w.getElements().getTypeElement(
2793: "java.lang.Object");// NOI18N
2794: Tree params = maker.ArrayType(maker.QualIdent(paramsType));
2795: TypeElement signType = w.getElements().getTypeElement(
2796: "java.lang.String");// NOI18N
2797: Tree sign = maker.ArrayType(maker.QualIdent(signType));
2798:
2799: ModifiersTree parMods = maker.Modifiers(Collections
2800: .<Modifier> emptySet(), Collections
2801: .<AnnotationTree> emptyList());
2802:
2803: VariableTree par1 = maker.Variable(parMods,
2804: "operationName", maker.QualIdent(operName), null);// NOI18N
2805: VariableTree par2 = maker.Variable(parMods, "params",
2806: params, null);// NOI18N
2807: VariableTree par3 = maker.Variable(parMods, "signature",
2808: sign, null);// NOI18N
2809: List<VariableTree> parList = new ArrayList<VariableTree>(1);
2810: parList.add(par1);
2811: parList.add(par2);
2812: parList.add(par3);
2813:
2814: List<ExpressionTree> exceptions = new ArrayList<ExpressionTree>(
2815: 2);
2816: exceptions.add(maker.Identifier("MBeanException"));// NOI18N
2817: exceptions.add(maker.Identifier("ReflectionException"));// NOI18N
2818:
2819: // Invoke content
2820: List opList = mbean.getOperations();
2821: MBeanOperation[] operations = (MBeanOperation[]) opList
2822: .toArray(new MBeanOperation[opList.size()]);
2823: StringBuffer content = new StringBuffer();
2824: content.append("{");// NOI18N
2825: if (operations.length > 0) {
2826: content.append(METHOD_SIGNATURE_DEF);
2827: }
2828:
2829: MessageFormat formOperation = new MessageFormat(
2830: OPERATION_CHECK_PATTERN);
2831: for (int i = 0; i < operations.length; i++) {
2832: content.append(METHOD_SIGNATURE);
2833: for (int j = 0; j < operations[i].getParametersSize(); j++) {
2834: MBeanOperationParameter param = operations[i]
2835: .getParameter(j);
2836: content.append(WizardHelpers.getFullTypeNameCode( // NOI18N
2837: param.getParamType()));
2838: if (j < operations[i].getParametersSize() - 1) {
2839: content.append(","); // NOI18N
2840: }
2841: content.append("\n"); // NOI18N
2842: }
2843: content.append("};\n"); // NOI18N
2844: String code = COMMENT_INVOKE
2845: + WizardHelpers.getDefaultValue(operations[i]
2846: .getReturnTypeName()) + ";"; // NOI18N
2847: Object[] arg = { operations[i].getName(), code,
2848: "operationName" }; // NOI18N
2849: content.append(formOperation.format(arg));
2850: content.append("\n"); // NOI18N
2851: }
2852: content
2853: .append("throw new IllegalArgumentException(\"Unknown Operation \" +\n"
2854: + // NOI18N
2855: "operationName);");// NOI18N
2856: content.append("}");// NOI18N
2857:
2858: MethodTree newMethod = maker.Method(maker
2859: .Modifiers(Collections.singleton(Modifier.PUBLIC)), // modifiers and annotations
2860: "invoke", // NOI18N // name
2861: maker.QualIdent(w.getElements().getTypeElement(
2862: "java.lang.Object")), // NOI18N // return type
2863: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
2864: parList, // parameters
2865: exceptions, // throws
2866: content.toString(), //body
2867: null // default value - not applicable here, used by annotations
2868: );
2869: JavaModelHelper
2870: .addComment(maker, newMethod,
2871: Comment.Style.JAVADOC,
2872: "Allows an operation to be invoked on the DynamicMBean.");// NOI18N
2873: ClassTree copy = maker.insertClassMember(clazz, 3,
2874: newMethod);
2875:
2876: return copy;
2877: }
2878:
2879: private ClassTree addBuildMBeanInfo(TreeMaker maker,
2880: MBeanDO mbean, MBeanAttribute[] attributes,
2881: ClassTree clazz) {
2882:
2883: StringBuffer attrInfo = new StringBuffer();
2884: attrInfo.append("{\n"); // NOI18N
2885: MessageFormat attrInfoForm = new MessageFormat(
2886: MBEAN_ATT_INFO_PATTERN);
2887: for (int i = 0; i < attributes.length; i++) {
2888: Object[] args = new Object[] {
2889: attributes[i].getName(),
2890: WizardHelpers.getFullTypeNameCode(attributes[i]
2891: .getTypeName()),
2892: attributes[i].getDescription(),
2893: attributes[i].isReadable(),
2894: attributes[i].isWritable(), "false" // NOI18N
2895: };
2896: attrInfo.append(attrInfoForm.format(args));
2897: if (i != attributes.length - 1)
2898: attrInfo.append(","); // NOI18N
2899: attrInfo.append("\n"); // NOI18N
2900: }
2901: attrInfo.append("}"); // NOI18N
2902:
2903: // add MBeanOperationInfo
2904: List opList = mbean.getOperations();
2905: MBeanOperation[] operations = (MBeanOperation[]) opList
2906: .toArray(new MBeanOperation[opList.size()]);
2907: StringBuffer opInfo = new StringBuffer();
2908: StringBuffer paramsInfo = new StringBuffer();
2909: MessageFormat opInfoForm = new MessageFormat(
2910: MBEAN_OPERATION_INFO_PATTERN);
2911: MessageFormat opParamsForm = new MessageFormat(
2912: MBEAN_PARAMS_INFO_PATTERN);
2913: MessageFormat opParamForm = new MessageFormat(
2914: MBEAN_PARAM_INFO_PATTERN);
2915: opInfo.append("{\n"); // NOI18N
2916: for (int i = 0; i < operations.length; i++) {
2917: //add MBeanParameterInfo
2918: Object[] args = new Object[] { i };
2919: paramsInfo.append(opParamsForm.format(args));
2920: int nbParam = operations[i].getParametersSize();
2921: for (int j = 0; j < nbParam; j++) {
2922: MBeanOperationParameter param = operations[i]
2923: .getParameter(j);
2924: Object[] pargs = new Object[] {
2925: param.getParamName(),
2926: WizardHelpers.getFullTypeNameCode(param
2927: .getParamType()),
2928: param.getParamDescription() };
2929: paramsInfo.append(opParamForm.format(pargs));
2930: if (j != nbParam - 1)
2931: paramsInfo.append(","); // NOI18N
2932: paramsInfo.append("\n"); // NOI18N
2933: }
2934: paramsInfo.append("};\n"); // NOI18N
2935:
2936: //add MBeanOperationInfo
2937: args = new Object[] {
2938: operations[i].getName(),
2939: operations[i].getDescription(),
2940: WizardHelpers.getFullTypeNameCode(operations[i]
2941: .getReturnTypeName()), i };
2942: opInfo.append(opInfoForm.format(args));
2943: if (i != operations.length - 1)
2944: opInfo.append(","); // NOI18N
2945: opInfo.append("\n"); // NOI18N
2946: }
2947: opInfo.append("}"); // NOI18N
2948: StringBuffer content = new StringBuffer();
2949: content.append("{");// NOI18N
2950: content
2951: .append("MBeanAttributeInfo[] dAttributes = new MBeanAttributeInfo[]");// NOI18N
2952: content.append(attrInfo.toString());
2953: content.append(";");// NOI18N
2954: content
2955: .append("MBeanConstructorInfo[] dConstructors = createConstructors();");// NOI18N
2956: content.append(paramsInfo.toString());
2957: content
2958: .append("MBeanOperationInfo[] dOperations = new MBeanOperationInfo[]");// NOI18N
2959: content.append(opInfo.toString());
2960: content.append(";");// NOI18N
2961: content.append("dMBeanInfo = new MBeanInfo(\""
2962: + mbean.getName() + "\",\n" + // NOI18N
2963: "\"");// NOI18N
2964: content.append(mbean.getDescription());
2965: content.append("\",\n" + // NOI18N
2966: "dAttributes,\n" + // NOI18N
2967: "dConstructors,\n" + // NOI18N
2968: "dOperations,\n" + // NOI18N
2969: "getNotificationInfo());" + // NOI18N
2970: "}");// NOI18N
2971: MethodTree newMethod = maker.Method(
2972: maker.Modifiers(Collections
2973: .singleton(Modifier.PRIVATE)), // modifiers and annotations
2974: "buildDynamicMBeanInfo", // NOI18N // name
2975: maker.PrimitiveType(TypeKind.VOID), // return type
2976: Collections.EMPTY_LIST, Collections.EMPTY_LIST,
2977: Collections.EMPTY_LIST, content.toString(),//body
2978: null // default value - not applicable here, used by annotations
2979: );
2980: JavaModelHelper.addComment(maker, newMethod,
2981: Comment.Style.JAVADOC,
2982: "Build the private dMBeanInfo field,\n"
2983: + // NOI18N
2984: "which represents the management interface exposed by the MBean,\n"
2985: + // NOI18N
2986: "that is, the set of attributes, constructors, operations and\n"
2987: + // NOI18N
2988: "notifications which are available for management.\n"
2989: + // NOI18N
2990: "A reference to the dMBeanInfo object is returned by the getMBeanInfo()\n"
2991: + // NOI18N
2992: "method of the DynamicMBean interface. Note that, once constructed,\n"
2993: + // NOI18N
2994: "an MBeanInfo object is immutable.");// NOI18N
2995: ClassTree copy = maker.insertClassMember(clazz, 5,
2996: newMethod);
2997:
2998: return copy;
2999: }
3000: }
3001:
3002: private static class UpdateExtendedStandardMBeanTemplateTransformer
3003: extends TreePathScanner<Void, Void> {
3004:
3005: private static final String OPERATION_SIGNATURE = "MBeanParameterInfo[] params = info.getSignature();\n"
3006: + // NOI18N
3007: "String[] signature = new String[params.length];\n" + // NOI18N
3008: "for (int i = 0; i < params.length; i++)\n" + // NOI18N
3009: " signature[i] = params[i].getType();\n"; // NOI18N
3010:
3011: private static String METADATA_MBEANINFO_UPDATE_COMMENT = " Override customization hook:\n"
3012: + // NOI18N
3013: " You can supply a customized description for MBeanInfo.getDescription()";// NOI18N
3014:
3015: private static String METADATA_MBEANPARAMATER_NAME_UPDATE_COMMENT = " Override customization hook:\n"
3016: + // NOI18N
3017: " You can supply a customized description for MBeanParameterInfo.getName()";// NOI18N
3018:
3019: private static String METADATA_MBEANPARAMATER_DESCRIPTION_UPDATE_COMMENT = " Override customization hook:\n"
3020: + // NOI18N
3021: " You can supply a customized description for MBeanParameterInfo.getDescription()";// NOI18N
3022:
3023: private static String METADATA_MBEANATTRIBUTE_DESCRIPTION_UPDATE_COMMENT = " Override customization hook:\n"
3024: + // NOI18N
3025: " You can supply a customized description for MBeanAttributeInfo.getDescription()";// NOI18N
3026: private static String METADATA_MBEANOPERATION_DESCRIPTION_UPDATE_COMMENT = " Override customization hook:\n"
3027: + // NOI18N
3028: " You can supply a customized description for MBeanOperationInfo.getDescription()";// NOI18N
3029:
3030: private final WorkingCopy w;
3031: private final MBeanDO mbean;
3032:
3033: public UpdateExtendedStandardMBeanTemplateTransformer(
3034: WorkingCopy w, MBeanDO mbean) {
3035: this .w = w;
3036: this .mbean = mbean;
3037: }
3038:
3039: @Override
3040: public Void visitClass(ClassTree clazz, Void v) {
3041: TreeMaker make = w.getTreeMaker();
3042: Element el = w.getTrees().getElement(getCurrentPath());
3043: updateDescription(w, el, make, mbean.getDescription()
3044: + "\nDynamic MBean based on StandardMBean\n", clazz); // NOI18N
3045: addMethods(mbean, clazz);
3046: super .visitClass(clazz, v);
3047: return null;
3048: }
3049:
3050: private void addMethods(MBeanDO mbean, ClassTree clazz) {
3051: TreeMaker maker = w.getTreeMaker();
3052: ClassTree copy = clazz;
3053: if (mbean.isWrapppedClass()) {
3054: ExpressionTree t = getType(w, mbean
3055: .getWrappedClassName(), null);
3056:
3057: // Add a field
3058: Set<Modifier> modifiers = new HashSet<Modifier>();
3059: modifiers.add(Modifier.PRIVATE);
3060: VariableTree theRef = maker.Variable(maker
3061: .Modifiers(modifiers), "theRef", t, null);// NOI18N
3062: copy = maker.insertClassMember(copy, 0, theRef);
3063:
3064: // Add a constructor
3065:
3066: VariableTree p = maker.Variable(maker
3067: .Modifiers(Collections.<Modifier> emptySet()),
3068: "theRef", t, null); // NOI18N
3069: List<VariableTree> params = new ArrayList<VariableTree>(
3070: 1);
3071: params.add(p);
3072:
3073: Set<Modifier> modifiers2 = new HashSet<Modifier>(1);
3074: modifiers2.add(Modifier.PUBLIC);
3075: List<ExpressionTree> exceptions = new ArrayList<ExpressionTree>(
3076: 1);
3077: exceptions.add(maker
3078: .Identifier("NotCompliantMBeanException"));// NOI18N
3079: StringBuffer body = new StringBuffer();
3080: body
3081: .append("{//WARNING Uncomment the following call to super() to make this class compile (see BUG ID 122377)\n");
3082: body.append("// super(" + mbean.getName()
3083: + WizardConstants.MBEAN_ITF_SUFFIX + ".class");// NOI18N
3084: if (mbean.isWrapppedClassMXBean())
3085: body.append(", true");// NOI18N
3086: body.append(");\n");// NOI18N
3087: body.append("this.theRef = theRef;}"); // NOI18N
3088: MethodTree newConstructor = maker.Constructor(maker
3089: .Modifiers(modifiers2), Collections.EMPTY_LIST,
3090: params, exceptions, body.toString());
3091: copy = maker.insertClassMember(copy, 1, newConstructor);
3092: }
3093: TypeElement annotationType = w.getElements()
3094: .getTypeElement("java.lang.Override"); // NOI18N
3095: Tree annotationTree = maker.QualIdent(annotationType);
3096: AnnotationTree overrideAnnotation = maker.Annotation(
3097: annotationTree, Collections
3098: .<ExpressionTree> emptyList());
3099: List<AnnotationTree> annotations = new ArrayList<AnnotationTree>();
3100: annotations.add(overrideAnnotation);
3101: ModifiersTree parMods = maker.Modifiers(Collections
3102: .<Modifier> emptySet());
3103: ModifiersTree mt = maker.Modifiers(Collections
3104: .singleton(Modifier.PROTECTED), annotations);
3105: IdentifierTree strTree = maker.Identifier("String"); // NOI18N
3106:
3107: // Add protected String getDescription(MBeanInfo info)
3108: TypeElement infoType = w.getElements().getTypeElement(
3109: "javax.management.MBeanInfo"); // NOI18N
3110: ExpressionTree mbeanInfo = maker.QualIdent(infoType);
3111: VariableTree descMBeanInfo = maker.Variable(parMods,
3112: "info", mbeanInfo, null); // NOI18N
3113: List<VariableTree> paramsMBeanInfo = new ArrayList<VariableTree>(
3114: 1);
3115: paramsMBeanInfo.add(descMBeanInfo);
3116: MethodTree methodDescrMBeanInfo = maker.Method(mt, // modifiers and annotations
3117: "getDescription", // NOI18N
3118: strTree, // return type
3119: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
3120: paramsMBeanInfo, // parameters
3121: Collections.<ExpressionTree> emptyList(), // throws
3122: "{return \"" + mbean.getDescription() + "\";}", // NOI18N
3123: null // default value - not applicable here, used by annotations
3124: );
3125: JavaModelHelper.addComment(maker, methodDescrMBeanInfo,
3126: Comment.Style.JAVADOC,
3127: METADATA_MBEANINFO_UPDATE_COMMENT);
3128:
3129: copy = maker.addClassMember(copy, methodDescrMBeanInfo);
3130:
3131: // Add protected String getDescription(MBeanAttributeInfo info)
3132: TypeElement attrInfoType = w.getElements().getTypeElement(
3133: "javax.management.MBeanAttributeInfo"); // NOI18N
3134: ExpressionTree attrInfo = maker.QualIdent(attrInfoType);
3135: VariableTree descAttrInfo = maker.Variable(parMods, "info",
3136: attrInfo, null); // NOI18N
3137: List<VariableTree> paramsAttrInfo = new ArrayList<VariableTree>(
3138: 1);
3139: paramsAttrInfo.add(descAttrInfo);
3140:
3141: MethodTree methodDescrAttributeInfo = maker.Method(mt, // modifiers and annotations
3142: "getDescription", // NOI18N
3143: strTree, // return type
3144: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
3145: paramsAttrInfo, // parameters
3146: Collections.<ExpressionTree> emptyList(), // throws
3147: "{String description = null;\n"
3148: + getAttDescCode(mbean)
3149: + "\nreturn description;}", // NOI18N
3150: null // default value - not applicable here, used by annotations
3151: );
3152: JavaModelHelper.addComment(maker, methodDescrAttributeInfo,
3153: Comment.Style.JAVADOC,
3154: METADATA_MBEANATTRIBUTE_DESCRIPTION_UPDATE_COMMENT);
3155: copy = maker.addClassMember(copy, methodDescrAttributeInfo);
3156:
3157: // Add protected String getDescription(MBeanOperationInfo op, MBeanParameterInfo param,int sequence)
3158: TypeElement operInfoType = w.getElements().getTypeElement(
3159: "javax.management.MBeanOperationInfo"); // NOI18N
3160: TypeElement paramInfoType = w.getElements().getTypeElement(
3161: "javax.management.MBeanParameterInfo"); // NOI18N
3162: ExpressionTree operInfo = maker.QualIdent(operInfoType);
3163: ExpressionTree paramInfo = maker.QualIdent(paramInfoType);
3164: ExpressionTree seq = maker.Identifier("int");// NOI18N
3165: VariableTree param1 = maker.Variable(parMods, "op",
3166: operInfo, null); // NOI18N
3167: VariableTree param2 = maker.Variable(parMods, "param",
3168: paramInfo, null); // NOI18N
3169: VariableTree param3 = maker.Variable(parMods, "sequence",
3170: seq, null); // NOI18N
3171: List<VariableTree> paramsOperParamInfo = new ArrayList<VariableTree>(
3172: 3);
3173: paramsOperParamInfo.add(param1);
3174: paramsOperParamInfo.add(param2);
3175: paramsOperParamInfo.add(param3);
3176:
3177: MethodTree methodDescrOperationParamInfo = maker.Method(mt, // modifiers and annotations
3178: "getDescription", // NOI18N
3179: strTree, // return type
3180: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
3181: paramsOperParamInfo, // parameters
3182: Collections.<ExpressionTree> emptyList(), // throws
3183: "{" + getParamDescCode(mbean, true)
3184: + "\nreturn null;}", // NOI18N
3185: null // default value - not applicable here, used by annotations
3186: );
3187: JavaModelHelper.addComment(maker,
3188: methodDescrOperationParamInfo,
3189: Comment.Style.JAVADOC,
3190: METADATA_MBEANPARAMATER_DESCRIPTION_UPDATE_COMMENT);
3191: copy = maker.addClassMember(copy,
3192: methodDescrOperationParamInfo);
3193:
3194: // Add protected String getParameterName(MBeanOperationInfo op, MBeanParameterInfo param, int sequence)
3195: // Idem signature than previous one.
3196: MethodTree methodParamName = maker.Method(mt, // modifiers and annotations
3197: "getParameterName", // NOI18N
3198: strTree, // return type
3199: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
3200: paramsOperParamInfo, // parameters
3201: Collections.<ExpressionTree> emptyList(), // throws
3202: "{" + getParamDescCode(mbean, false)
3203: + "\nreturn null;}", // NOI18N
3204: null // default value - not applicable here, used by annotations
3205: );
3206: JavaModelHelper.addComment(maker, methodParamName,
3207: Comment.Style.JAVADOC,
3208: METADATA_MBEANPARAMATER_NAME_UPDATE_COMMENT);
3209: copy = maker.addClassMember(copy, methodParamName);
3210:
3211: // Add getDescription(MBeanOperationInfo)
3212: List<VariableTree> paramsOperInfo = new ArrayList<VariableTree>(
3213: 1);
3214: VariableTree param = maker.Variable(parMods, "info",
3215: operInfo, null); // NOI18N
3216: paramsOperInfo.add(param);
3217:
3218: MethodTree methodDescrOperationInfo = maker.Method(mt, // modifiers and annotations
3219: "getDescription", // NOI18N
3220: strTree, // return type
3221: Collections.<TypeParameterTree> emptyList(), // type parameters for parameters
3222: paramsOperInfo, // parameters
3223: Collections.<ExpressionTree> emptyList(), // throws
3224: "{String description = null;\n"
3225: + getOpDescCode(mbean)
3226: + "\nreturn description;}", // NOI18N
3227: null // default value - not applicable here, used by annotations
3228: );
3229: JavaModelHelper.addComment(maker, methodDescrOperationInfo,
3230: Comment.Style.JAVADOC,
3231: METADATA_MBEANOPERATION_DESCRIPTION_UPDATE_COMMENT);
3232: copy = maker.addClassMember(copy, methodDescrOperationInfo);
3233:
3234: w.rewrite(clazz, copy);
3235: }
3236:
3237: private String getOpDescCode(MBeanDO mbean) {
3238: List opList = mbean.getOperations();
3239: MBeanOperation[] operations = (MBeanOperation[]) opList
3240: .toArray(new MBeanOperation[opList.size()]);
3241: StringBuffer content = new StringBuffer();
3242: if (operations.length > 0) {
3243: content.append(OPERATION_SIGNATURE);
3244: content.append(METHOD_SIGNATURE_DEF);
3245: }
3246: MessageFormat formOperation = new MessageFormat(
3247: OPERATION_CHECK_PATTERN);
3248: for (int i = 0; i < operations.length; i++) {
3249: content.append(METHOD_SIGNATURE);
3250: for (int j = 0; j < operations[i].getParametersSize(); j++) {
3251: MBeanOperationParameter param = operations[i]
3252: .getParameter(j);
3253: content.append(WizardHelpers
3254: .getFullTypeNameCode(removeGeneric(param
3255: .getParamType())));
3256: if (j < operations[i].getParametersSize() - 1) {
3257: content.append(","); // NOI18N
3258: }
3259: content.append("\n"); // NOI18N
3260: }
3261: content.append("};\n"); // NOI18N
3262: String descCode = " description = \"" + // NOI18N
3263: operations[i].getDescription() + "\";"; // NOI18N
3264: Object[] arg = { operations[i].getName(), descCode,
3265: "info.getName()" }; // NOI18N
3266: content.append(formOperation.format(arg));
3267: }
3268:
3269: return content.toString();
3270: }
3271:
3272: private String getParamDescCode(MBeanDO mbean,
3273: boolean isGetDescription) {
3274: List opList = mbean.getOperations();
3275: MBeanOperation[] operations = (MBeanOperation[]) opList
3276: .toArray(new MBeanOperation[opList.size()]);
3277: StringBuffer content = new StringBuffer();
3278: for (int i = 0; i < operations.length; i++) {
3279: if (i != 0) {
3280: content.append("} else "); // NOI18N
3281: }
3282: content.append("if (op.getName().equals(\""); // NOI18N
3283: content.append(operations[i].getName());
3284: content.append("\")) {\n"); // NOI18N
3285: content.append(" switch (sequence) {\n"); // NOI18N
3286: for (int j = 0; j < operations[i].getParametersSize(); j++) {
3287: content.append(" case " + j + ": return \""); // NOI18N
3288: String stringToReturn = null;
3289: MBeanOperationParameter param = operations[i]
3290: .getParameter(j);
3291: if (isGetDescription) {
3292: stringToReturn = param.getParamDescription();
3293: } else {
3294: stringToReturn = param.getParamName();
3295: }
3296: content.append(stringToReturn);
3297: content.append("\";\n"); // NOI18N
3298: }
3299: content.append(" default : return null;\n"); // NOI18N
3300: content.append(" }\n"); // NOI18N
3301: }
3302: if (operations.length != 0) {
3303: content.append("}\n"); // NOI18N
3304: }
3305: return content.toString();
3306: }
3307:
3308: private String getAttDescCode(MBeanDO mbean) {
3309: List attrList = mbean.getAttributes();
3310: MBeanAttribute[] attributes = (MBeanAttribute[]) attrList
3311: .toArray(new MBeanAttribute[attrList.size()]);
3312: StringBuffer content = new StringBuffer();
3313: for (int i = 0; i < attributes.length; i++) {
3314: if (i != 0)
3315: content.append("} else "); // NOI18N
3316: content.append("if (info.getName().equals(\""); // NOI18N
3317: content.append(attributes[i].getName());
3318: content.append("\")) {\n"); // NOI18N
3319: content.append(" description = \""); // NOI18N
3320: content
3321: .append(attributes[i].getDescription()
3322: + "\";\n"); // NOI18N
3323: if (i == attributes.length - 1) {
3324: content.append("}\n"); // NOI18N
3325: }
3326: }
3327: return content.toString();
3328: }
3329:
3330: }
3331:
3332: private static class AddMBeanRegistrationCodeTransformer extends
3333: TreePathScanner<Void, Object> {
3334: private final String objectName;
3335: private final WorkingCopy w;
3336: private final ExecutableElement constructor;
3337: private final static String REGISTRATION_COMMENTS = "TODO update MBean constructor parameters with valid values."; // NOI18N
3338:
3339: public AddMBeanRegistrationCodeTransformer(WorkingCopy w,
3340: String objectName, ExecutableElement constructor) {
3341: this .w = w;
3342: this .constructor = constructor;
3343: this .objectName = objectName;
3344: }
3345:
3346: //Called for every method in the java source file
3347: @Override
3348: public Void visitMethod(MethodTree tree, Object p) {
3349: //Obtain the owner of this method, getCurrentPath() returns a path from root (CompilationUnitTree) to current node (tree)
3350: //Tree owner = getCurrentPath().getParentPath();
3351: if ("init".contentEquals(tree.getName())) { // NOI18N
3352: List<? extends StatementTree> statements = tree
3353: .getBody().getStatements();
3354: List<StatementTree> newStatements = new ArrayList<StatementTree>(
3355: statements);
3356:
3357: // Write the code generation
3358: TreeMaker treeMaker = w.getTreeMaker();
3359:
3360: // Access to the getMbeanServer
3361: //Element el = w.getTrees().getElement(getCurrentPath().getParentPath());
3362: //TypeElement te = (TypeElement) el;
3363:
3364: // Access to the ObjectName constructor
3365: TypeElement objectNameClass = w.getElements()
3366: .getTypeElement("javax.management.ObjectName");// NOI18N
3367: // ObjectName creation
3368: LiteralTree objNameValTree = treeMaker
3369: .Literal(objectName);
3370: ArrayList<ExpressionTree> initializer = new ArrayList<ExpressionTree>(
3371: 1);
3372: initializer.add(objNameValTree);
3373: ExpressionTree ex = treeMaker
3374: .QualIdent(objectNameClass);
3375: NewClassTree objectNameConstructor = treeMaker
3376: .NewClass(null, Collections
3377: .<ExpressionTree> emptyList(), ex,
3378: initializer, null);
3379:
3380: // MBean creation
3381: ArrayList<ExpressionTree> initializerMBeanClass = new ArrayList<ExpressionTree>(
3382: 1);
3383: // Workaround. We go to string to come back to type
3384: // Better handling of imports
3385: String mbeanClassStr = ((TypeElement) constructor
3386: .getEnclosingElement()).getQualifiedName()
3387: .toString();
3388: TypeElement mbeanClass = w.getElements()
3389: .getTypeElement(mbeanClassStr);
3390: ExpressionTree mbeanClassEx = treeMaker
3391: .QualIdent(mbeanClass);
3392: List<? extends VariableElement> params = constructor
3393: .getParameters();
3394: for (VariableElement param : params) {
3395: // Just put null for all
3396: // XXX REVISIT IS IT LIKE THAT?
3397: initializerMBeanClass.add(treeMaker.Literal(null));
3398: }
3399: NewClassTree mbeanConstructor = treeMaker.NewClass(
3400: null, Collections.<ExpressionTree> emptyList(),
3401: mbeanClassEx, initializerMBeanClass, null);
3402:
3403: // getMBeanServer()
3404: IdentifierTree getMBSTree = w.getTreeMaker()
3405: .Identifier("getMBeanServer");// NOI18N
3406: MethodInvocationTree getMBSInvocation = treeMaker
3407: .MethodInvocation(Collections
3408: .<ExpressionTree> emptyList(),
3409: getMBSTree, Collections
3410: .<ExpressionTree> emptyList());
3411:
3412: // getMBeanServer().registerMBean
3413: MemberSelectTree registerMBeanSelIdent = w
3414: .getTreeMaker().MemberSelect(getMBSInvocation,
3415: "registerMBean");// NOI18N
3416:
3417: // Now register MBean MethodInvocation
3418: List<ExpressionTree> registerParams = new ArrayList<ExpressionTree>(
3419: 2);
3420: registerParams.add(mbeanConstructor);
3421: registerParams.add(objectNameConstructor);
3422: //IdentifierTree registTree = w.getTreeMaker().Identifier("registerMBean");
3423: MethodInvocationTree registerInvocation = treeMaker
3424: .MethodInvocation(Collections
3425: .<ExpressionTree> emptyList(),
3426: // registTree,
3427: registerMBeanSelIdent, registerParams);
3428:
3429: // Add at the end of the statements
3430: ExpressionStatementTree t = treeMaker
3431: .ExpressionStatement(registerInvocation);
3432: newStatements.add((StatementTree) t);
3433:
3434: if (constructor != null
3435: && constructor.getParameters().size() != 0) {
3436: JavaModelHelper.addComment(treeMaker, t,
3437: Comment.Style.LINE, REGISTRATION_COMMENTS);
3438: }
3439:
3440: BlockTree newBody = treeMaker.Block(newStatements,
3441: false);
3442: w.rewrite(tree.getBody(), newBody);
3443: }
3444: super .visitMethod(tree, p);
3445: return null;
3446: }
3447:
3448: /**
3449: * Returns an array of this method param types.
3450: * @param completeSignature <CODE>String</CODE> a method signature
3451: * @return <CODE>String[]</CODE> an array of param types.
3452: */
3453: private static String[] getSignature(String completeSignature) {
3454: int signBegin = completeSignature.lastIndexOf("(");// NOI18N
3455: int signEnd = completeSignature.lastIndexOf(")");// NOI18N
3456: String[] params = completeSignature.substring(
3457: signBegin + 1, signEnd).split(",");// NOI18N
3458: if ((params.length == 1) && (params[0].equals("")))// NOI18N
3459: params = new String[] {};
3460: for (int i = 0; i < params.length; i++)
3461: params[i] = params[i].trim();
3462: return params;
3463: }
3464: }
3465:
3466: private static class AddStandardMBeanRegistrationCodeTransformer
3467: extends TreePathScanner<Void, Object> {
3468: private final String objectName;
3469: private final String itf;
3470: private final WorkingCopy w;
3471: private final ExecutableElement constructor;
3472: private final static String REGISTRATION_COMMENTS = "TODO update MBean constructor parameters with valid values."; // NOI18N
3473:
3474: public AddStandardMBeanRegistrationCodeTransformer(
3475: WorkingCopy w, String objectName, String itf,
3476: ExecutableElement constructor) {
3477: this .w = w;
3478: this .constructor = constructor;
3479: this .objectName = objectName;
3480: this .itf = itf;
3481: }
3482:
3483: //Called for every method in the java source file
3484: @Override
3485: public Void visitMethod(MethodTree tree, Object p) {
3486: //Obtain the owner of this method, getCurrentPath() returns a path from root (CompilationUnitTree) to current node (tree)
3487: //Tree owner = getCurrentPath().getParentPath();
3488: if ("init".contentEquals(tree.getName())) { // NOI18N
3489: List<? extends StatementTree> statements = tree
3490: .getBody().getStatements();
3491: List<StatementTree> newStatements = new ArrayList<StatementTree>(
3492: statements);
3493:
3494: // Write the code generation
3495: TreeMaker treeMaker = w.getTreeMaker();
3496:
3497: // Access to the getMbeanServer
3498: //Element el = w.getTrees().getElement(getCurrentPath().getParentPath());
3499: //TypeElement te = (TypeElement) el;
3500:
3501: // Access to the ObjectName constructor
3502: TypeElement objectNameClass = w.getElements()
3503: .getTypeElement("javax.management.ObjectName");// NOI18N
3504: // ObjectName creation
3505: LiteralTree objNameValTree = treeMaker
3506: .Literal(objectName);
3507: ArrayList<ExpressionTree> initializer = new ArrayList<ExpressionTree>(
3508: 1);
3509: initializer.add(objNameValTree);
3510: ExpressionTree ex = treeMaker
3511: .QualIdent(objectNameClass);
3512: NewClassTree objectNameConstructor = treeMaker
3513: .NewClass(null, Collections
3514: .<ExpressionTree> emptyList(), ex,
3515: initializer, null);
3516:
3517: // Standard MBean creation
3518: ArrayList<ExpressionTree> initializerStdMBeanClass = new ArrayList<ExpressionTree>(
3519: 1);
3520: TypeElement stdMbeanClass = w.getElements()
3521: .getTypeElement(
3522: "javax.management.StandardMBean");// NOI18N
3523: ExpressionTree stdMbeanClassEx = treeMaker
3524: .QualIdent(stdMbeanClass);
3525:
3526: // Means that we need to generate the Wrapped Object creation
3527: String wrappedClassStr = null;
3528: if (constructor != null) {
3529: ArrayList<ExpressionTree> initializerWrappedClass = new ArrayList<ExpressionTree>(
3530: 1);
3531: wrappedClassStr = ((TypeElement) constructor
3532: .getEnclosingElement()).getQualifiedName()
3533: .toString();
3534: TypeElement wrappedClass = w.getElements()
3535: .getTypeElement(wrappedClassStr);
3536: ExpressionTree mbeanClassEx = treeMaker
3537: .QualIdent(wrappedClass);
3538: List<? extends VariableElement> params = constructor
3539: .getParameters();
3540: for (VariableElement param : params) {
3541: // Just put null for all
3542: // XXX REVISIT IS IT LIKE THAT?
3543: initializerWrappedClass.add(treeMaker
3544: .Literal(null));
3545: }
3546: NewClassTree wrappedConstructor = treeMaker
3547: .NewClass(null, Collections
3548: .<ExpressionTree> emptyList(),
3549: mbeanClassEx,
3550: initializerWrappedClass, null);
3551:
3552: // Add wrapped creation as the first parameter of StandardMBean constructor
3553: initializerStdMBeanClass.add(wrappedConstructor);
3554: } else
3555: initializerStdMBeanClass.add(treeMaker
3556: .Literal(null));
3557:
3558: // Handle Management Interface
3559: if (itf != null) {
3560: TypeElement mgtItf = w.getElements()
3561: .getTypeElement(itf);
3562: ExpressionTree mgtItfEx = treeMaker
3563: .QualIdent(mgtItf);
3564: MemberSelectTree mst = treeMaker.MemberSelect(
3565: mgtItfEx, "class");// NOI18N
3566: initializerStdMBeanClass.add(mst);
3567: } else
3568: initializerStdMBeanClass.add(treeMaker
3569: .Literal(null));
3570:
3571: NewClassTree stdMbeanConstructor = treeMaker
3572: .NewClass(null, Collections
3573: .<ExpressionTree> emptyList(),
3574: stdMbeanClassEx,
3575: initializerStdMBeanClass, null);
3576:
3577: // getMBeanServer()
3578: IdentifierTree getMBSTree = w.getTreeMaker()
3579: .Identifier("getMBeanServer");// NOI18N
3580: MethodInvocationTree getMBSInvocation = treeMaker
3581: .MethodInvocation(Collections
3582: .<ExpressionTree> emptyList(),
3583: getMBSTree, Collections
3584: .<ExpressionTree> emptyList());
3585:
3586: // getMBeanServer().registerMBean
3587: MemberSelectTree registerMBeanSelIdent = w
3588: .getTreeMaker().MemberSelect(getMBSInvocation,
3589: "registerMBean");// NOI18N
3590:
3591: // Now register MBean MethodInvocation
3592: List<ExpressionTree> registerParams = new ArrayList<ExpressionTree>(
3593: 2);
3594:
3595: registerParams.add(stdMbeanConstructor);
3596: registerParams.add(objectNameConstructor);
3597: //IdentifierTree registTree = w.getTreeMaker().Identifier("registerMBean");
3598: MethodInvocationTree registerInvocation = treeMaker
3599: .MethodInvocation(Collections
3600: .<ExpressionTree> emptyList(),
3601: // registTree,
3602: registerMBeanSelIdent, registerParams);
3603:
3604: // Add at the end of the statements
3605: ExpressionStatementTree t = treeMaker
3606: .ExpressionStatement(registerInvocation);
3607: newStatements.add((StatementTree) t);
3608: if (constructor == null) {
3609: JavaModelHelper.addComment(treeMaker, t,
3610: Comment.Style.LINE,
3611: "TODO replace first StandardMBean constructor parameter by your own "
3612: + wrappedClassStr + " object."); // NOI18N
3613: }
3614:
3615: if (constructor != null
3616: && constructor.getParameters().size() != 0) {
3617: JavaModelHelper.addComment(treeMaker, t,
3618: Comment.Style.LINE, REGISTRATION_COMMENTS);
3619: }
3620:
3621: BlockTree newBody = treeMaker.Block(newStatements,
3622: false);
3623: w.rewrite(tree.getBody(), newBody);
3624: }
3625: super .visitMethod(tree, p);
3626: return null;
3627: }
3628:
3629: /**
3630: * Returns an array of this method param types.
3631: * @param completeSignature <CODE>String</CODE> a method signature
3632: * @return <CODE>String[]</CODE> an array of param types.
3633: */
3634: private static String[] getSignature(String completeSignature) {
3635: int signBegin = completeSignature.lastIndexOf("(");// NOI18N
3636: int signEnd = completeSignature.lastIndexOf(")");// NOI18N
3637: String[] params = completeSignature.substring(
3638: signBegin + 1, signEnd).split(",");// NOI18N
3639: if ((params.length == 1) && (params[0].equals("")))// NOI18N
3640: params = new String[] {};
3641: for (int i = 0; i < params.length; i++)
3642: params[i] = params[i].trim();
3643: return params;
3644: }
3645: }
3646:
3647: /** Creates a new instance of JavaModelHelper */
3648: private JavaModelHelper() {
3649: }
3650:
3651: public static JavaSource getSource(FileObject fo) {
3652: JavaSource js = JavaSource.forFileObject(fo);
3653: return js;
3654: }
3655:
3656: public static String[] getInterfaceNames(JavaSource clazz)
3657: throws IOException {
3658: final ValueHolder value = new ValueHolder();
3659: // Check if the Agent has getMBeanServer method and a method named init
3660: clazz.runUserActionTask(
3661: new CancellableTask<CompilationController>() {
3662: public void cancel() {
3663: }
3664:
3665: public void run(CompilationController parameter)
3666: throws IOException {
3667: parameter.toPhase(Phase.ELEMENTS_RESOLVED);
3668: new InterfacesMemberVisitor(parameter, value)
3669: .scan(parameter.getCompilationUnit(),
3670: null);
3671: }
3672: }, true);
3673: return (String[]) value.getValue();
3674: }
3675:
3676: public static void addImports(final List<String> imports,
3677: JavaSource clazz) throws IOException {
3678: if (imports == null || imports.size() == 0)
3679: return;
3680: clazz.runModificationTask(new CancellableTask<WorkingCopy>() {
3681: public void cancel() {
3682: }
3683:
3684: public void run(WorkingCopy w) throws IOException {
3685: w.toPhase(Phase.ELEMENTS_RESOLVED);
3686: // XXX REVISIT
3687: TreeMaker make = w.getTreeMaker();
3688: CompilationUnitTree cut = w.getCompilationUnit();
3689: List<? extends ImportTree> currentImports = cut
3690: .getImports();
3691:
3692: for (ImportTree current : currentImports) {
3693: String toAdd = current.getQualifiedIdentifier()
3694: .toString();
3695: if (imports.contains(toAdd))
3696: imports.remove(toAdd);
3697: }
3698: CompilationUnitTree copy = cut;
3699: for (String imp : imports) {
3700: copy = make.addCompUnitImport(copy, make.Import(
3701: make.Identifier(imp), false));
3702: }
3703: w.rewrite(cut, copy);
3704: }
3705: }).commit();
3706: }
3707:
3708: /**
3709: * Returns an array containing all public constructors of the specified class.
3710: *
3711: * @param clazz <code>JavaClass</code> examine
3712: * @return <code>Method[]</code> class methods or <code>null</code> if
3713: * there is no method
3714: */
3715: public static Map<String, ExecutableElement> getConstructors(
3716: JavaSource clazz) throws IOException {
3717: final ValueHolder value = new ValueHolder();
3718: // Check if the Agent has getMBeanServer method and a method named init
3719: clazz.runUserActionTask(
3720: new CancellableTask<CompilationController>() {
3721: public void cancel() {
3722: }
3723:
3724: public void run(CompilationController parameter)
3725: throws IOException {
3726: parameter.toPhase(Phase.ELEMENTS_RESOLVED);
3727: new ConstructorsMemberVisitor(parameter, value)
3728: .scan(parameter.getCompilationUnit(),
3729: null);
3730: }
3731: }, true);
3732: return (Map<String, ExecutableElement>) value.getValue();
3733: }
3734:
3735: public static final boolean isGeneratedAgent(final JavaSource src)
3736: throws IOException {
3737: final ValueHolder value = new ValueHolder();
3738: // Check if the Agent has getMBeanServer method and a method named init
3739: src.runUserActionTask(
3740: new CancellableTask<CompilationController>() {
3741: public void cancel() {
3742: }
3743:
3744: public void run(CompilationController parameter)
3745: throws IOException {
3746: parameter.toPhase(Phase.ELEMENTS_RESOLVED);
3747: new IsGeneratedAgentAgentVisitor(parameter,
3748: value).scan(parameter
3749: .getCompilationUnit(), null);
3750: }
3751: }, true);
3752: return (Boolean) value.getValue();
3753: }
3754:
3755: public static JavaSource findClassInProject(Project project,
3756: final String fullClassName) throws IOException {
3757: Sources sources = ProjectUtils.getSources(project);
3758: SourceGroup[] grps = sources
3759: .getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
3760: final FileObject[] fo = new FileObject[1];
3761:
3762: for (int i = 0; i < grps.length; i++) {
3763: FileObject root = grps[i].getRootFolder();
3764: final ClasspathInfo cpi = ClasspathInfo.create(root);
3765: JavaSource javaSrc = JavaSource.create(cpi);
3766: javaSrc.runUserActionTask(
3767: new CancellableTask<CompilationController>() {
3768: public void run(CompilationController c)
3769: throws IOException {
3770: Elements e = c.getElements();
3771: TypeElement te = e
3772: .getTypeElement(fullClassName);
3773: if (te != null) {
3774: //The element is under this root
3775: fo[0] = SourceUtils.getFile(te, cpi);
3776: }
3777: }
3778:
3779: public void cancel() {
3780: }
3781: }, true);
3782: if (fo[0] != null) {
3783: return getSource(fo[0]);
3784: }
3785: }
3786:
3787: return null;
3788: }
3789:
3790: public static boolean isDynamicMBean(final JavaSource baseClass)
3791: throws IOException {
3792: final ValueHolder value = new ValueHolder();
3793: // Check if the Agent has getMBeanServer method and a method named init
3794: baseClass.runUserActionTask(
3795: new CancellableTask<CompilationController>() {
3796: public void cancel() {
3797: }
3798:
3799: public void run(CompilationController parameter)
3800: throws IOException {
3801: parameter.toPhase(Phase.ELEMENTS_RESOLVED);
3802: new IsDynamicMBeanVisitor(parameter, value)
3803: .scan(parameter.getCompilationUnit(),
3804: null);
3805: }
3806: }, true);
3807: Object val = value.getValue();
3808: if (val == null)
3809: return false;
3810: return (Boolean) value.getValue();
3811: }
3812:
3813: public static boolean testMBeanCompliance(JavaSource baseClass)
3814: throws IOException {
3815: Object itf = getManagementInterface(baseClass);
3816: if (itf != null)
3817: return true;
3818: return isDynamicMBean(baseClass);
3819: }
3820:
3821: public static boolean checkKnownType(JavaSource baseClass,
3822: final String type) {
3823: try {
3824: final ValueHolder value = new ValueHolder();
3825: // Check if the Agent has getMBeanServer method and a method named init
3826: baseClass.runUserActionTask(
3827: new CancellableTask<CompilationController>() {
3828: public void cancel() {
3829: }
3830:
3831: public void run(CompilationController ctrl)
3832: throws IOException {
3833: ctrl.toPhase(Phase.ELEMENTS_RESOLVED);
3834: value.setValue(isKnownType(ctrl, type));
3835: }
3836: }, true);
3837: Object val = value.getValue();
3838: if (val == null)
3839: return false;
3840: return (Boolean) val;
3841: } catch (IOException ex) {
3842: // System.out.println("Eoor occured" + ex);
3843: }
3844: return false;
3845: }
3846:
3847: public static String getFullClassName(JavaSource baseClass)
3848: throws IOException {
3849: final ValueHolder value = new ValueHolder();
3850: // Check if the Agent has getMBeanServer method and a method named init
3851: baseClass.runUserActionTask(
3852: new CancellableTask<CompilationController>() {
3853: public void cancel() {
3854: }
3855:
3856: public void run(CompilationController parameter)
3857: throws IOException {
3858: parameter.toPhase(Phase.ELEMENTS_RESOLVED);
3859: new FullClassNameMemberVisitor(parameter, value)
3860: .scan(parameter.getCompilationUnit(),
3861: null);
3862: }
3863: }, true);
3864: return (String) value.getValue();
3865: }
3866:
3867: public static boolean implements MBeanRegistrationItf(
3868: JavaSource baseClass) throws IOException {
3869: final ValueHolder value = new ValueHolder();
3870: // Check if the Agent has getMBeanServer method and a method named init
3871: baseClass.runUserActionTask(
3872: new CancellableTask<CompilationController>() {
3873: public void cancel() {
3874: }
3875:
3876: public void run(CompilationController parameter)
3877: throws IOException {
3878: parameter.toPhase(Phase.ELEMENTS_RESOLVED);
3879: new SearchInterfaceVisitor(parameter, value,
3880: "javax.management.MBeanRegistration")
3881: .scan(parameter.getCompilationUnit(),
3882: null);// NOI18N
3883: }
3884: }, true);
3885:
3886: return value.getValue() != null;
3887: }
3888:
3889: public static MBeanAttribute[] getAttributes(JavaSource baseClass)
3890: throws IOException {
3891: MBeanDO mbeando = getMBeanModel(baseClass);
3892: if (mbeando == null)
3893: return null;
3894: List<MBeanAttribute> attributes = mbeando.getAttributes();
3895: return attributes
3896: .toArray(new MBeanAttribute[attributes.size()]);
3897: }
3898:
3899: public static MBeanOperation[] getOperations(JavaSource baseClass)
3900: throws IOException {
3901: MBeanDO mbeando = getMBeanModel(baseClass);
3902: if (mbeando == null)
3903: return null;
3904: List<MBeanOperation> operations = mbeando.getOperations();
3905: return operations
3906: .toArray(new MBeanOperation[operations.size()]);
3907: }
3908:
3909: public static MBeanDO getMBeanModel(JavaSource baseClass)
3910: throws IOException {
3911: return getMBeanModel(baseClass, true);
3912: }
3913:
3914: public static MBeanDO getMBeanLikeModel(JavaSource baseClass)
3915: throws IOException {
3916: return getMBeanModel(baseClass, false);
3917: }
3918:
3919: public static String getManagementInterfaceSimpleName(
3920: JavaSource baseClass) throws IOException {
3921: TypeElement itf = getManagementInterface(baseClass);
3922: return itf.getSimpleName().toString();
3923: }
3924:
3925: private static TypeElement getManagementInterface(
3926: JavaSource baseClass) throws IOException {
3927: TypeElement itf = isStandardMBean(baseClass);
3928: if (itf != null)
3929: return itf;
3930: itf = isMXBean(baseClass);
3931: return itf;
3932: }
3933:
3934: private static MBeanDO getMBeanModel(final JavaSource baseClass,
3935: final boolean real) throws IOException {
3936: final ValueHolder value = new ValueHolder();
3937: // Check if the Agent has getMBeanServer method and a method named init
3938: baseClass.runUserActionTask(
3939: new CancellableTask<CompilationController>() {
3940: public void cancel() {
3941: }
3942:
3943: public void run(CompilationController parameter)
3944: throws IOException {
3945: parameter.toPhase(Phase.ELEMENTS_RESOLVED);
3946: TypeElement mgtItf = null;
3947: if (real) {
3948: mgtItf = getManagementInterface(baseClass);
3949: if (mgtItf == null) {
3950: throw new IOException(
3951: "Invalid MBean class "
3952: + baseClass);// NOI18N
3953: }// NOI18N
3954:
3955: new MBeanModelVisitor(parameter, value,
3956: real, mgtItf).scan(parameter
3957: .getCompilationUnit(), null);
3958: } else
3959: new MBeanModelFromClassVisitor(parameter,
3960: value, real, mgtItf).scan(parameter
3961: .getCompilationUnit(), null);
3962: }
3963: }, true);
3964: return (MBeanDO) value.getValue();
3965: }
3966:
3967: public static final TypeElement isStandardMBean(
3968: final JavaSource baseClass) throws IOException {
3969: final ValueHolder value = new ValueHolder();
3970: final String fullClassName = getFullClassName(baseClass);
3971: baseClass.runUserActionTask(
3972: new CancellableTask<CompilationController>() {
3973: public void cancel() {
3974: }
3975:
3976: public void run(CompilationController parameter)
3977: throws IOException {
3978: parameter.toPhase(Phase.ELEMENTS_RESOLVED);
3979: new SearchInterfaceVisitor(
3980: parameter,
3981: value,
3982: fullClassName
3983: + WizardConstants.MBEAN_ITF_SUFFIX)
3984: .scan(parameter.getCompilationUnit(),
3985: null);
3986: }
3987: }, true);
3988: TypeElement itf = (TypeElement) value.getValue();
3989: if (itf != null && itf.getModifiers().contains(Modifier.PUBLIC))
3990: return itf;
3991: return null;
3992: }
3993:
3994: public static final TypeElement isMXBean(final JavaSource baseClass)
3995: throws IOException {
3996: final ValueHolder value = new ValueHolder();
3997: final String fullClassName = getFullClassName(baseClass);
3998:
3999: baseClass.runUserActionTask(
4000: new CancellableTask<CompilationController>() {
4001: public void cancel() {
4002: }
4003:
4004: public void run(CompilationController parameter)
4005: throws IOException {
4006: parameter.toPhase(Phase.ELEMENTS_RESOLVED);
4007: new SearchInterfaceVisitor(
4008: parameter,
4009: value,
4010: fullClassName
4011: + WizardConstants.MXBEAN_ITF_SUFFIX)
4012: .scan(parameter.getCompilationUnit(),
4013: null);
4014: TypeElement itf = (TypeElement) value
4015: .getValue();
4016:
4017: if (itf == null)
4018: return;
4019:
4020: if (!itf.getModifiers().contains(
4021: Modifier.PUBLIC))
4022: value.setValue(null);
4023:
4024: boolean isMXBean = true;
4025: List<? extends AnnotationMirror> annotations = itf
4026: .getAnnotationMirrors();
4027: for (AnnotationMirror annotation : annotations) {
4028: if ("javax.management.MXBean"
4029: .equals(((TypeElement) // NOI18N
4030: annotation.getAnnotationType()
4031: .asElement())
4032: .getQualifiedName()
4033: .toString())) {
4034: Map<? extends ExecutableElement, ? extends AnnotationValue> values = parameter
4035: .getElements()
4036: .getElementValuesWithDefaults(
4037: annotation);
4038: for (ExecutableElement name : values
4039: .keySet()) {
4040: if ("value"
4041: .equals(name
4042: .getSimpleName()
4043: .toString())) {// NOI18N
4044: AnnotationValue value = values
4045: .get(name);
4046: if (Boolean.FALSE.equals(value
4047: .getValue())) {
4048: isMXBean = false;
4049: }
4050: break;
4051: }
4052: }
4053: break;
4054: }
4055: }
4056: if (!isMXBean)
4057: value.setValue(null);
4058: }
4059: }, true);
4060: return (TypeElement) value.getValue();
4061: }
4062:
4063: /*public static boolean implementsDynamicMBeanItf(JavaSource baseClass) throws IOException {
4064: final ValueHolder value = new ValueHolder();
4065: // Check if the Agent has getMBeanServer method and a method named init
4066: baseClass.runUserActionTask(new CancellableTask<CompilationController>() {
4067: public void cancel() {}
4068: public void run(CompilationController parameter) throws IOException {
4069: parameter.toPhase(Phase.ELEMENTS_RESOLVED);
4070: new SearchInterfaceVisitor(parameter, value, "javax.management.DynamicMBean").scan(parameter.getCompilationUnit(), null);// NOI18N
4071: }
4072: }, true);
4073: return value.getValue() != null;
4074: }
4075: */
4076: public static boolean implements NotificationBroadcaster(
4077: JavaSource baseClass) throws IOException {
4078: final ValueHolder value = new ValueHolder();
4079: // Check if the Agent has getMBeanServer method and a method named init
4080: baseClass.runUserActionTask(
4081: new CancellableTask<CompilationController>() {
4082: public void cancel() {
4083: }
4084:
4085: public void run(CompilationController parameter)
4086: throws IOException {
4087: parameter.toPhase(Phase.ELEMENTS_RESOLVED);
4088: new SearchInterfaceVisitor(parameter, value,
4089: "javax.management.NotificationBroadcaster")
4090: .scan(parameter.getCompilationUnit(),
4091: null);// NOI18N
4092: }
4093: }, true);
4094: return value.getValue() != null;
4095: }
4096:
4097: public static boolean hasOnlyDefaultConstruct(JavaSource clazz)
4098: throws IOException {
4099: final ValueHolder value = new ValueHolder();
4100: // Check if the Agent has getMBeanServer method and a method named init
4101: clazz.runUserActionTask(
4102: new CancellableTask<CompilationController>() {
4103: public void cancel() {
4104: }
4105:
4106: public void run(CompilationController parameter)
4107: throws IOException {
4108: parameter.toPhase(Phase.ELEMENTS_RESOLVED);
4109: new HasOnlyDefaultConstructorMemberVisitor(
4110: parameter, value).scan(parameter
4111: .getCompilationUnit(), null);
4112: }
4113: }, true);
4114: return (Boolean) value.getValue();
4115: }
4116:
4117: public static String getSimpleName(JavaSource clazz)
4118: throws IOException {
4119: final ValueHolder value = new ValueHolder();
4120: // Check if the Agent has getMBeanServer method and a method named init
4121: clazz.runUserActionTask(
4122: new CancellableTask<CompilationController>() {
4123: public void cancel() {
4124: }
4125:
4126: public void run(CompilationController parameter)
4127: throws IOException {
4128: parameter.toPhase(Phase.ELEMENTS_RESOLVED);
4129: new SimpleClassNameMemberVisitor(parameter,
4130: value).scan(parameter
4131: .getCompilationUnit(), null);
4132: }
4133: }, true);
4134: return (String) value.getValue();
4135: }
4136:
4137: public static String getPackage(JavaSource clazz)
4138: throws IOException {
4139: final ValueHolder value = new ValueHolder();
4140: // Check if the Agent has getMBeanServer method and a method named init
4141: clazz.runUserActionTask(
4142: new CancellableTask<CompilationController>() {
4143: public void cancel() {
4144: }
4145:
4146: public void run(CompilationController parameter)
4147: throws IOException {
4148: parameter.toPhase(Phase.ELEMENTS_RESOLVED);
4149: new PackageMemberVisitor(parameter, value)
4150: .scan(parameter.getCompilationUnit(),
4151: null);
4152: }
4153: }, true);
4154: return (String) value.getValue();
4155: }
4156:
4157: public static String getBodyText(MethodTree method,
4158: WorkingCopy workingCopy) {
4159: BlockTree body = method.getBody();
4160: CompilationUnitTree cut = workingCopy.getCompilationUnit();
4161: // get SourcePositions instance for your working copy and
4162: // fetch out start and end position.
4163: SourcePositions sp = workingCopy.getTrees()
4164: .getSourcePositions();
4165: int start = (int) sp.getStartPosition(cut, body);
4166: int end = (int) sp.getEndPosition(cut, body);
4167: // get body text from source text
4168: String bodyText = workingCopy.getText().substring(start, end);
4169: return bodyText;
4170: }
4171:
4172: public static void updateMBeanWithNotificationEmitter(
4173: JavaSource js, final MBeanNotification[] notifs,
4174: final boolean genBroadcastDeleg, final boolean genSeqNumber)
4175: throws IOException {
4176: js.runModificationTask(new CancellableTask<WorkingCopy>() {
4177: public void cancel() {
4178: }
4179:
4180: public void run(WorkingCopy w) throws IOException {
4181: w.toPhase(Phase.ELEMENTS_RESOLVED);
4182: // XXX REVISIT
4183: new MBeanNotificationTransformer(w, notifs,
4184: genBroadcastDeleg, genSeqNumber).scan(w
4185: .getCompilationUnit(), null);
4186: }
4187: }).commit(); //Commit the changes into document;
4188: }
4189:
4190: public static void updateMBeanWithRegistration(JavaSource js,
4191: final boolean keepRefSelected) throws IOException {
4192: js.runModificationTask(new CancellableTask<WorkingCopy>() {
4193: public void cancel() {
4194: }
4195:
4196: public void run(WorkingCopy w) throws IOException {
4197: w.toPhase(Phase.ELEMENTS_RESOLVED);
4198: // XXX REVISIT
4199: new MBeanRegistrationTransformer(w, keepRefSelected)
4200: .scan(w.getCompilationUnit(), null);
4201: }
4202: }).commit(); //Commit the changes into document;
4203: }
4204:
4205: public static MBeanAttribute searchAttributeImplementation(
4206: final JavaSource baseClass, final MBeanAttribute attribute)
4207: throws IOException {
4208: final ValueHolder value = new ValueHolder();
4209:
4210: baseClass.runUserActionTask(
4211: new CancellableTask<CompilationController>() {
4212: public void cancel() {
4213: }
4214:
4215: public void run(CompilationController parameter)
4216: throws IOException {
4217: parameter.toPhase(Phase.ELEMENTS_RESOLVED);
4218: new AttributeImplementationVisitor(parameter,
4219: value, attribute).scan(parameter
4220: .getCompilationUnit(), null);
4221: }
4222: }, true);
4223: return (MBeanAttribute) value.getValue();
4224: }
4225:
4226: public static MBeanOperation searchOperationImplementation(
4227: final JavaSource baseClass, final MBeanOperation operation)
4228: throws IOException {
4229: final ValueHolder value = new ValueHolder();
4230:
4231: baseClass.runUserActionTask(
4232: new CancellableTask<CompilationController>() {
4233: public void cancel() {
4234: }
4235:
4236: public void run(CompilationController parameter)
4237: throws IOException {
4238: parameter.toPhase(Phase.ELEMENTS_RESOLVED);
4239: new OperationImplementationVisitor(parameter,
4240: value, operation).scan(parameter
4241: .getCompilationUnit(), null);
4242: }
4243: }, true);
4244: return (MBeanOperation) value.getValue();
4245: }
4246:
4247: private static void addAttributes(JavaSource baseClass,
4248: final MBeanAttribute[] attributes) throws IOException {
4249: baseClass.runModificationTask(
4250: new CancellableTask<WorkingCopy>() {
4251: public void cancel() {
4252: }
4253:
4254: public void run(WorkingCopy w) throws IOException {
4255: w.toPhase(Phase.ELEMENTS_RESOLVED);
4256: new AddAttributesTransformer(w, attributes)
4257: .scan(w.getCompilationUnit(), null);
4258: }
4259: }).commit(); //Commit the changes into document;
4260: }
4261:
4262: private static void addOperations(JavaSource baseClass,
4263: final MBeanOperation[] operations) throws IOException {
4264: baseClass.runModificationTask(
4265: new CancellableTask<WorkingCopy>() {
4266: public void cancel() {
4267: }
4268:
4269: public void run(WorkingCopy w) throws IOException {
4270: w.toPhase(Phase.ELEMENTS_RESOLVED);
4271: new AddOperationsTransformer(w, operations)
4272: .scan(w.getCompilationUnit(), null);
4273: }
4274: }).commit(); //Commit the changes into document;
4275: }
4276:
4277: private static JavaSource getStandardMBeanItf(
4278: final JavaSource baseClass) throws IOException {
4279: final ValueHolder value = new ValueHolder();
4280:
4281: baseClass.runUserActionTask(
4282: new CancellableTask<CompilationController>() {
4283: public void cancel() {
4284: }
4285:
4286: public void run(CompilationController parameter)
4287: throws IOException {
4288: parameter.toPhase(Phase.ELEMENTS_RESOLVED);
4289: new StandardMBeanItfVisitor(parameter, value,
4290: baseClass).scan(parameter
4291: .getCompilationUnit(), null);
4292: }
4293: }, true);
4294: return (JavaSource) value.getValue();
4295: }
4296:
4297: public static void generateMBeanRegistration(JavaSource baseClass,
4298: final String objectName, final ExecutableElement constructor)
4299: throws IOException {
4300: baseClass.runModificationTask(
4301: new CancellableTask<WorkingCopy>() {
4302: public void cancel() {
4303: }
4304:
4305: public void run(WorkingCopy w) throws IOException {
4306: w.toPhase(Phase.ELEMENTS_RESOLVED);
4307: new AddMBeanRegistrationCodeTransformer(w,
4308: objectName, constructor).scan(w
4309: .getCompilationUnit(), null);
4310: }
4311: }).commit(); //Commit the changes into document;
4312: }
4313:
4314: public static void generateStdMBeanRegistration(
4315: JavaSource baseClass, final String objectName,
4316: final String itfName, final ExecutableElement constructor)
4317: throws IOException {
4318: baseClass.runModificationTask(
4319: new CancellableTask<WorkingCopy>() {
4320: public void cancel() {
4321: }
4322:
4323: public void run(WorkingCopy w) throws IOException {
4324: w.toPhase(Phase.ELEMENTS_RESOLVED);
4325: new AddStandardMBeanRegistrationCodeTransformer(
4326: w, objectName, itfName, constructor)
4327: .scan(w.getCompilationUnit(), null);
4328: }
4329: }).commit(); //Commit the changes into document;
4330: }
4331:
4332: public static void addCommentSurroundedByWhiteLine(
4333: TreeMaker treeMaker, Tree t, Comment.Style style,
4334: String content) {
4335: Comment commentEmptyLine = Comment.create(
4336: Comment.Style.WHITESPACE, -1, -1, -1, "\n\n");// NOI18N
4337: treeMaker.insertComment(t, commentEmptyLine, -1, true);
4338: addComment(treeMaker, t, style, content);
4339: Comment commentEmptyLine2 = Comment.create(
4340: Comment.Style.WHITESPACE, -1, -1, -1, "\n\n");// NOI18N
4341: treeMaker.insertComment(t, commentEmptyLine2, -1, true);
4342: }
4343:
4344: public static void addCommentPrefixedByWhiteLine(
4345: TreeMaker treeMaker, Tree t, Comment.Style style,
4346: String content) {
4347: Comment commentEmptyLine = Comment.create(
4348: Comment.Style.WHITESPACE, -1, -1, -1, "\n\n");// NOI18N
4349: treeMaker.insertComment(t, commentEmptyLine, -1, true);
4350: addComment(treeMaker, t, style, content);
4351: }
4352:
4353: public static void addCommentFollowedByWhiteLine(
4354: TreeMaker treeMaker, Tree t, Comment.Style style,
4355: String content) {
4356: addComment(treeMaker, t, style, content);
4357: Comment commentEmptyLine = Comment.create(
4358: Comment.Style.WHITESPACE, -1, -1, -1, "\n\n");// NOI18N
4359: treeMaker.insertComment(t, commentEmptyLine, -1, true);
4360: }
4361:
4362: public static void addComment(TreeMaker treeMaker, Tree t,
4363: Comment.Style style, String content) {
4364: Comment comment = Comment.create(style, -1, -1, -1, content);
4365: treeMaker.insertComment(t, comment, -1, true);
4366: }
4367:
4368: public static void addAttributesToMBean(final JavaSource baseClass,
4369: final MBeanAttribute[] attributes) throws IOException {
4370: baseClass.runUserActionTask(
4371: new CancellableTask<CompilationController>() {
4372: public void cancel() {
4373: }
4374:
4375: public void run(CompilationController parameter)
4376: throws IOException {
4377: parameter.toPhase(Phase.ELEMENTS_RESOLVED);
4378: TypeElement itfType = getManagementInterface(baseClass);
4379:
4380: FileObject sourceFile = SourceUtils.getFile(
4381: itfType, parameter.getClasspathInfo());
4382: JavaSource itfSource = null;
4383: if (sourceFile != null)
4384: itfSource = baseClass
4385: .forFileObject(sourceFile);
4386:
4387: addAttributes(baseClass, attributes);
4388: addAttributes(itfSource, attributes);
4389: }
4390: }, true);
4391:
4392: }
4393:
4394: public static boolean canUpdateAttributesOrOperations(
4395: JavaSource baseClass) throws IOException {
4396: return getManagementInterface(baseClass) != null;
4397: }
4398:
4399: public static void addOperationsToMBean(final JavaSource baseClass,
4400: final MBeanOperation[] operations) throws IOException {
4401: baseClass.runUserActionTask(
4402: new CancellableTask<CompilationController>() {
4403: public void cancel() {
4404: }
4405:
4406: public void run(CompilationController parameter)
4407: throws IOException {
4408: parameter.toPhase(Phase.ELEMENTS_RESOLVED);
4409: TypeElement itfType = isStandardMBean(baseClass);
4410: if (itfType == null)
4411: itfType = isMXBean(baseClass);
4412: if (itfType == null)
4413: throw new IOException(
4414: "Invalid MBean class " + baseClass);// NOI18N
4415:
4416: FileObject sourceFile = SourceUtils.getFile(
4417: itfType, parameter.getClasspathInfo());
4418: JavaSource itfSource = null;
4419: if (sourceFile != null)
4420: itfSource = baseClass
4421: .forFileObject(sourceFile);
4422:
4423: addOperations(baseClass, operations);
4424: addOperations(itfSource, operations);
4425: }
4426: }, true);
4427: }
4428:
4429: public static void updateStandardMBeanTemplate(
4430: JavaSource baseClass, JavaSource itf, final MBeanDO mbean)
4431: throws IOException {
4432: MBeanAttribute[] attributes = new MBeanAttribute[mbean
4433: .getAttributes().size()];
4434: attributes = mbean.getAttributes().toArray(attributes);
4435: MBeanOperation[] operations = new MBeanOperation[mbean
4436: .getOperations().size()];
4437: operations = mbean.getOperations().toArray(operations);
4438:
4439: //Update description
4440: updateClassJavaDoc(baseClass, mbean.getDescription());
4441: updateClassJavaDoc(itf, mbean.getDescription());
4442: addAttributes(baseClass, attributes);
4443: addAttributes(itf, attributes);
4444: addOperations(baseClass, operations);
4445: addOperations(itf, operations);
4446: }
4447:
4448: public static void updateExtendedStandardMBeanTemplate(
4449: JavaSource baseClass, JavaSource itf, final MBeanDO mbean)
4450: throws IOException {
4451: MBeanAttribute[] attributes = new MBeanAttribute[mbean
4452: .getAttributes().size()];
4453: attributes = mbean.getAttributes().toArray(attributes);
4454: MBeanOperation[] operations = new MBeanOperation[mbean
4455: .getOperations().size()];
4456: operations = mbean.getOperations().toArray(operations);
4457: if (mbean.isWrapppedClass()) {
4458: // Remove constructor
4459: removeMethod(baseClass, "<init>");// NOI18N
4460: }
4461:
4462: // Update Template (Metadata + description methods)
4463: baseClass.runModificationTask(
4464: new CancellableTask<WorkingCopy>() {
4465: public void cancel() {
4466: }
4467:
4468: public void run(WorkingCopy w) throws IOException {
4469: w.toPhase(Phase.ELEMENTS_RESOLVED);
4470: new UpdateExtendedStandardMBeanTemplateTransformer(
4471: w, mbean).scan(w.getCompilationUnit(),
4472: null);
4473: }
4474: }).commit();
4475:
4476: //Update Interface description
4477: updateClassJavaDoc(itf, mbean.getDescription());
4478:
4479: // Update Attributes and Operations
4480: addAttributes(baseClass, attributes);
4481: addAttributes(itf, attributes);
4482: addOperations(baseClass, operations);
4483: addOperations(itf, operations);
4484: }
4485:
4486: private static void updateClassJavaDoc(JavaSource clazz,
4487: final String text) throws IOException {
4488: clazz.runModificationTask(new CancellableTask<WorkingCopy>() {
4489: public void cancel() {
4490: }
4491:
4492: public void run(WorkingCopy w) throws IOException {
4493: w.toPhase(Phase.ELEMENTS_RESOLVED);
4494: new UpdateClassJavaDocTransformer(w, text).scan(w
4495: .getCompilationUnit(), null);
4496: }
4497: }).commit(); //Commit the changes into document;
4498: }
4499:
4500: public static void updateDynamicMBeanTemplate(JavaSource template,
4501: final MBeanDO mbean) throws IOException {
4502: template.runModificationTask(
4503: new CancellableTask<WorkingCopy>() {
4504: public void cancel() {
4505: }
4506:
4507: public void run(WorkingCopy w) throws IOException {
4508: w.toPhase(Phase.ELEMENTS_RESOLVED);
4509: new UpdateDynamicMBeanTemplateTransformer(w,
4510: mbean).scan(w.getCompilationUnit(),
4511: null);
4512: }
4513: }).commit(); //Commit the changes into document;
4514: }
4515:
4516: // XXX REVISIT to be private
4517: public static void rewriteMethod(String text,
4518: WorkingCopy workingCopy, MethodTree method) {
4519: TreeMaker make = workingCopy.getTreeMaker();
4520: MethodTree modified = make.Method(
4521: method.getModifiers(), // copy original values
4522: method.getName(), method.getReturnType(), method
4523: .getTypeParameters(), method.getParameters(),
4524: method.getThrows(), text, // replace body with the new text
4525: null // not applicable here
4526: );
4527: // rewrite the original modifiers with the new one:
4528: workingCopy.rewrite(method, modified);
4529: }
4530:
4531: public static boolean isInterface(JavaSource js) throws IOException {
4532: final ValueHolder value = new ValueHolder();
4533: // Check if the Agent has getMBeanServer method and a method named init
4534: js.runUserActionTask(
4535: new CancellableTask<CompilationController>() {
4536: public void cancel() {
4537: }
4538:
4539: public void run(CompilationController parameter)
4540: throws IOException {
4541: parameter.toPhase(Phase.ELEMENTS_RESOLVED);
4542: new IsInterfaceVisitor(parameter, value).scan(
4543: parameter.getCompilationUnit(), null);
4544: }
4545: }, true);
4546: return (Boolean) value.getValue();
4547: }
4548:
4549: public static boolean isMain(ExecutableElement method) {
4550: //has "main" name
4551: if (!"main".contentEquals(method.getSimpleName())) {// NOI18N
4552: return false;
4553: }
4554: //is public static?
4555: Set<Modifier> modifiers = method.getModifiers();
4556: if (!modifiers.contains(Modifier.STATIC)
4557: || !modifiers.contains(Modifier.PUBLIC)) {
4558: return false;
4559: }
4560: //has String[] arg?
4561: List<? extends VariableElement> params = method.getParameters();
4562: //Has single arg
4563: if (params.size() != 1) {
4564: return false;
4565: }
4566: //Is arg an array?
4567: TypeMirror type = params.get(0).asType();
4568: if (type.getKind() != TypeKind.ARRAY) {
4569: return false;
4570: }
4571: //Is it an array of declared type?
4572: type = ((ArrayType) type).getComponentType();
4573: if (type.getKind() != TypeKind.DECLARED) {
4574: return false;
4575: }
4576: //Is it an array of String?
4577: if (!"java.lang.String"
4578: .contentEquals(((TypeElement) ((DeclaredType) type)
4579: .asElement()).getQualifiedName())) {// NOI18N
4580: return false;
4581: }
4582: return true;
4583: }
4584:
4585: public static boolean isAbstract(JavaSource js) throws IOException {
4586: final ValueHolder value = new ValueHolder();
4587: // Check if the Agent has getMBeanServer method and a method named init
4588: js.runUserActionTask(
4589: new CancellableTask<CompilationController>() {
4590: public void cancel() {
4591: }
4592:
4593: public void run(CompilationController parameter)
4594: throws IOException {
4595: parameter.toPhase(Phase.ELEMENTS_RESOLVED);
4596: new HasClassModifierVisitor(parameter, value,
4597: Modifier.ABSTRACT).scan(parameter
4598: .getCompilationUnit(), null);
4599: }
4600: }, true);
4601: return (Boolean) value.getValue();
4602: }
4603:
4604: public static void removeMethod(JavaSource js, final String name)
4605: throws IOException {
4606: js.runModificationTask(new CancellableTask<WorkingCopy>() {
4607: public void run(WorkingCopy w) throws Exception {
4608: w.toPhase(JavaSource.Phase.RESOLVED);
4609: CompilationUnitTree cut = w.getCompilationUnit();
4610: TreeMaker make = w.getTreeMaker();
4611: for (Tree typeDecl : cut.getTypeDecls()) {
4612: // ensure that it is correct type declaration, i.e. class
4613: if (Tree.Kind.CLASS == typeDecl.getKind()) {
4614: ClassTree clazz = (ClassTree) typeDecl;
4615: List<? extends Tree> members = clazz
4616: .getMembers();
4617: for (Tree t : members) {
4618: if (t instanceof MethodTree) {
4619: MethodTree mt = (MethodTree) t;
4620: String methodName = mt.getName()
4621: .toString();
4622: if (name.equals(methodName)) {
4623: TreeMaker treeMaker = w
4624: .getTreeMaker();
4625: //Create a new class tree without main method
4626: ClassTree newTree = treeMaker
4627: .removeClassMember(clazz,
4628: mt);
4629: //do the change
4630: w.rewrite(clazz, newTree);
4631: }
4632: }
4633: }
4634: }
4635: }
4636: }
4637:
4638: public void cancel() {
4639: //Not important for userActionTasks
4640: }
4641: }).commit(); //Commit the changes into document
4642: }
4643:
4644: public static void generateAgent(JavaSource js,
4645: final boolean removeMainMethod,
4646: final boolean removeSampleCode) throws IOException {
4647: //Perform an action which changes the content of the java file
4648: js.runModificationTask(new CancellableTask<WorkingCopy>() {
4649: public void run(WorkingCopy w) throws Exception {
4650: w.toPhase(JavaSource.Phase.RESOLVED);
4651: //Visitor for scanning javac's trees
4652: AgentGeneratorSampleCodeTransformer gen = new AgentGeneratorSampleCodeTransformer(
4653: w, removeSampleCode);
4654: //execute the visitor on the root (CompilationUnitTree) with no parameter (null)
4655: gen.scan(w.getCompilationUnit(), null);
4656: }
4657:
4658: public void cancel() {
4659: //Not important for userActionTasks
4660: }
4661: }).commit(); //Commit the changes into document
4662:
4663: if (removeMainMethod)
4664: removeMethod(js, "main");// NOI18N
4665: }
4666:
4667: public static TypeMirror getComponentType(TypeMirror array) {
4668: if (!(array instanceof ArrayType))
4669: return array;
4670: else
4671: return getComponentType(((ArrayType) array)
4672: .getComponentType());
4673: }
4674:
4675: public static int getArrayDimension(TypeMirror array) {
4676: if (!(array instanceof ArrayType))
4677: return 0;
4678: else
4679: return getArrayDimension(((ArrayType) array)
4680: .getComponentType()) + 1;
4681: }
4682:
4683: public static String getTypeName(TypeMirror type,
4684: List<? extends TypeParameterElement> methodParameterTypes,
4685: List<? extends TypeParameterElement> classParameterTypes,
4686: CompilationInfo info) {
4687:
4688: String tName = type.toString();
4689:
4690: TypeMirror comp = JavaModelHelper.getComponentType(type);
4691: if (comp == null)
4692: throw new RuntimeException("Unknown Type : " + // NOI18N
4693: tName);
4694: if (comp.getKind().equals(TypeKind.TYPEVAR))
4695: tName = "java.lang.Object";// NOI18N
4696:
4697: return tName;
4698: }
4699:
4700: public static String getPrimitive(TypeKind type) {
4701: if (type.equals(TypeKind.VOID))
4702: return WizardConstants.VOID_NAME;
4703:
4704: if (type.equals(TypeKind.BOOLEAN))
4705: return WizardConstants.BOOLEAN_NAME;
4706:
4707: if (type.equals(TypeKind.BYTE))
4708: return WizardConstants.BYTE_NAME;
4709:
4710: if (type.equals(TypeKind.CHAR))
4711: return WizardConstants.CHAR_NAME;
4712:
4713: if (type.equals(TypeKind.INT))
4714: return WizardConstants.INT_NAME;
4715:
4716: if (type.equals(TypeKind.LONG))
4717: return WizardConstants.LONG_NAME;
4718:
4719: if (type.equals(TypeKind.FLOAT))
4720: return WizardConstants.FLOAT_NAME;
4721:
4722: if (type.equals(TypeKind.DOUBLE))
4723: return WizardConstants.DOUBLE_NAME;
4724:
4725: return null;
4726: }
4727:
4728: private static String getMethodBodyText(CompilationInfo info,
4729: ExecutableElement m) {
4730: MethodTree method = info.getTrees().getTree(m);
4731: BlockTree body = method.getBody();
4732:
4733: // get SourcePositions instance for your working copy and
4734: // fetch out start and end position.
4735: SourcePositions sp = info.getTrees().getSourcePositions();
4736: int start = (int) sp.getStartPosition(
4737: info.getCompilationUnit(), body);
4738: int end = (int) sp.getEndPosition(info.getCompilationUnit(),
4739: body);
4740: // get body text from source text
4741: String bodyText = info.getText().substring(start, end);
4742: return bodyText;
4743: }
4744:
4745: static String removeGeneric(String type) {
4746: int gen = type.indexOf("<");// NOI18N
4747: if (gen != -1)
4748: type = type.substring(0, gen);
4749: return type;
4750: }
4751:
4752: private static boolean isKnownTypeNoVoid(
4753: CompilationController ctrl, String type) {
4754: if (getTypeElement(ctrl, type) != null)
4755: return true;
4756: if (WizardHelpers.isPrimitiveType(type)
4757: || WizardHelpers.isStandardWrapperType(type))
4758: return true;
4759: if (getArrayType(ctrl, type) != null)
4760: return true;
4761: return false;
4762:
4763: }
4764:
4765: private static boolean isKnownType(CompilationController ctrl,
4766: String type) {
4767: if (type == null)
4768: return false;
4769: if (isKnownTypeNoVoid(ctrl, type))
4770: return true;
4771:
4772: return "void".equals(type);// NOI18N
4773: }
4774:
4775: private static TypeElement getTypeElement(
4776: CompilationController ctrl, String type) {
4777: TypeElement retTypeElement = null;
4778: if (type == null)
4779: return null;
4780: type = removeGeneric(type);
4781: retTypeElement = ctrl.getElements().getTypeElement(type);
4782: // System.out.println("retTypeElement " + retTypeElement);
4783: return retTypeElement;
4784: }
4785:
4786: private static ExpressionTree getType(WorkingCopy w, String type,
4787: TypeMirror mirror) {
4788: // System.out.println("TYPE " + type + " MIRROR " + mirror);
4789: if (type == null && mirror == null)
4790: return null;
4791: TypeElement retTypeElement = null;
4792:
4793: /*if (mirror != null) {
4794: Object obj = w.getTypes().asElement(mirror);
4795: if (obj instanceof TypeElement) {
4796: retTypeElement = (TypeElement) obj;
4797: } else {
4798: String primitive = getPrimitive(mirror.getKind());
4799: if(primitive == null)
4800: return w.getTreeMaker().Identifier("Object"); // NOI18N
4801: else
4802: return w.getTreeMaker().Identifier(primitive);
4803: }
4804: if (retTypeElement != null) {
4805: return w.getTreeMaker().QualIdent(retTypeElement);
4806: }
4807: }
4808: */
4809:
4810: if (type != null) {
4811: if (retTypeElement == null)
4812: retTypeElement = getTypeElement(w, type);
4813: if (retTypeElement == null)
4814: retTypeElement = w.getElements().getTypeElement(type);
4815: if (retTypeElement != null)
4816: return w.getTreeMaker().QualIdent(retTypeElement);
4817: ExpressionTree arrayType = getArrayTree(w, type);
4818: if (arrayType != null)
4819: return arrayType;
4820: if (WizardHelpers.isPrimitiveType(type)
4821: || WizardHelpers.isStandardWrapperType(type)
4822: || "void".equals(type))// NOI18N
4823: return w.getTreeMaker().Identifier(type);
4824:
4825: // XXX REVISIT, THIS SHOULD NEVER HAPPEN IF THEN INPUT WERE CHECKED
4826: return w.getTreeMaker().Identifier(type);
4827: }
4828:
4829: throw new IllegalArgumentException("Unknown type " + type);// NOI18N
4830: }
4831:
4832: private static Object getArrayType(CompilationController ctrl,
4833: String type) {
4834: //System.out.println("getArrayType " + type);
4835: TypeMirror ret = null;
4836: int length = type.length();
4837: int current = type.indexOf("[]");// NOI18N
4838: if (current == -1)
4839: return null;
4840: String componentType = type.substring(0, current);
4841: //System.out.println("COmnent type " + componentType);
4842: if (WizardHelpers.isPrimitiveType(componentType)
4843: || WizardHelpers.isStandardWrapperType(componentType))
4844: return componentType;
4845: ret = ctrl.getElements().getTypeElement(componentType).asType();
4846: if (ret == null)
4847: return null;
4848: String arrays = type.substring(current, type.length());
4849: int dim = arrays.length() / 2;
4850: for (int i = 0; i < dim; i++) {
4851: ret = ctrl.getTypes().getArrayType(ret);
4852: }
4853: return ret;
4854: }
4855:
4856: public static ExpressionTree getArrayTree(WorkingCopy w, String type) {
4857: String componentType = null;
4858: Object o = getArrayType(w, type);
4859: if (o instanceof String)
4860: return w.getTreeMaker().Identifier(type);
4861: if (o instanceof TypeMirror)
4862: return (ExpressionTree) w.getTreeMaker().Type(
4863: (TypeMirror) o);
4864: return null;
4865: }
4866:
4867: private static void updateDescription(WorkingCopy ctrl,
4868: Element clazzElement, TreeMaker make, String text,
4869: ClassTree clazz) {
4870: Doc doc = ctrl.getElementUtilities().javaDocFor(clazzElement);
4871: //doc.setRawCommentText("TEST IT TEST OY");
4872: String txt = doc.commentText();
4873: int i = txt.indexOf("{0}");// NOI18N
4874: //System.out.println( "JAVADOC TEXT : [" + txt + "]");
4875: MessageFormat formDoc = new MessageFormat(txt);
4876: Object[] args = new Object[] { text };
4877: //addComment(make, clazz, Comment.Style.JAVADOC, formDoc.format(args));
4878: //ctrl.rewriteInComment(i,3,text);
4879: //ctrl.getTreeMaker().removeComment(clazz, 1, true);
4880: //ctrl.rewrite(clazz,clazz);
4881: }
4882:
4883: }
|