/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2008-2010 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package org.glassfish.admin.runtime.apt;
import com.sun.mirror.apt.*;
import com.sun.mirror.declaration.*;
import com.sun.mirror.type.*;
import java.io.*;
import java.util.*;
import javax.xml.parsers.*;
import javax.management.modelmbean.*;
import javax.management.*;
import org.glassfish.admin.runtime.annotations.ManagedAttribute;
import org.glassfish.admin.runtime.annotations.MBean;
import org.glassfish.admin.runtime.annotations.ManagedOperation;
class RuntimeMgmtAptProcessor implements AnnotationProcessor {
private final AnnotationProcessorEnvironment env;
private final Messager msg;
private final boolean debug;
private String pojoName;
private String pojoClassName;
private String packageName;
private ArrayList<ModelMBeanOperationInfo> mmoiArr;
private ArrayList<ModelMBeanAttributeInfo> mmaiArr;
private HashMap<String, ArrayList> attrMap;
private ModelMBeanInfo mmbinfo;
private void init() {
mmoiArr = new ArrayList<ModelMBeanOperationInfo>();
mmaiArr = new ArrayList<ModelMBeanAttributeInfo>();
attrMap = new HashMap<String, ArrayList>();
mmbinfo = null;
}
public RuntimeMgmtAptProcessor(AnnotationProcessorEnvironment env) {
this.env = env;
msg = env.getMessager();
debug = env.getOptions().containsKey("-Adebug");
}
public void process() {
for (TypeDeclaration decl : env.getSpecifiedTypeDeclarations()) {
if (debug) {
msg.printNotice("type = " + decl.getQualifiedName());
msg.printNotice("package = " + decl.getPackage().getQualifiedName());
}
generateMBeanInfo(decl);
}
}
private void generateMBeanInfo(TypeDeclaration decl) {
init();
if (decl.getAnnotation(MBean.class) == null) return;
pojoName = decl.getSimpleName();
pojoClassName = decl.getQualifiedName();
packageName = decl.getPackage().getQualifiedName();
if (debug)
msg.printNotice("generating mbeaninfo ...");
try {
// generate attributes and operations
/*
for (MethodDeclaration mdecl : decl.getMethods()) {
generateMethods(mdecl);
}
*/
ClassDeclaration cd = (ClassDeclaration) decl;
msg.printNotice("before super classdecl = " + cd);
processSuper((ClassDeclaration) decl);
msg.printNotice("before attrinfo ...");
generateAttrInfo();
// mbean info
Descriptor descriptor = new DescriptorSupport(new String[] {
("name=" + pojoName),
"descriptorType=mbean",
("displayName=" + pojoClassName)
});
ModelMBeanAttributeInfo [] mbaiArr = null;
int k = 0;
if (mmaiArr.size() > 0) {
mbaiArr = new ModelMBeanAttributeInfo[mmaiArr.size()];
for (ModelMBeanAttributeInfo mbai : mmaiArr) {
mbaiArr[k] = mbai;
k++;
}
}
ModelMBeanOperationInfo [] mboiArr = null;
k = 0;
if (mmoiArr.size() > 0) {
mboiArr = new ModelMBeanOperationInfo[mmoiArr.size()];
for (ModelMBeanOperationInfo mboi : mmoiArr) {
mboiArr[k] = mboi;
k++;
}
}
mmbinfo = new ModelMBeanInfoSupport(
pojoClassName,
null,
mbaiArr,
null,
mboiArr,
null
);
mmbinfo.setMBeanDescriptor(descriptor);
msg.printNotice("mbeanInfo = " + mmbinfo);
} catch (Exception ioe) {
throw new RuntimeException(ioe);
}
// serialize data
try {
OutputStream fos = env.getFiler().createBinaryFile(
Filer.Location.CLASS_TREE, packageName, new File(pojoName + ".ser"));
ObjectOutputStream out = new ObjectOutputStream( fos );
out.writeObject(mmbinfo);
out.flush();
out.close();
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
private void processSuper(ClassDeclaration cdecl) {
msg.printNotice("processSuper, cdecl = " + cdecl);
if ((cdecl == null) || ("java.lang.Object".equals(cdecl.getQualifiedName()))) return;
for (MethodDeclaration mdecl : cdecl.getMethods()) {
generateMethods(mdecl);
}
processSuper(cdecl.getSuperclass().getDeclaration());
}
private void generateMethods(MethodDeclaration mdecl) {
if ((mdecl.getAnnotation(ManagedOperation.class) == null) &&
(mdecl.getAnnotation(ManagedAttribute.class) == null))
return;
try {
if (! mdecl.getModifiers().contains(Modifier.PUBLIC)) return;
generateOperation(mdecl);
if (mdecl.getAnnotation(ManagedAttribute.class) != null) {
generateAttribute(mdecl);
}
} catch (Exception ioe) {
throw new RuntimeException(ioe);
}
}
private void generateOperation(MethodDeclaration mdecl) {
try {
String methodName = mdecl.getSimpleName();
Descriptor descriptor = new DescriptorSupport(new String[] {
("name=" + methodName),
"descriptorType=operation",
("class=" + pojoClassName),
"role=operation"
});
String returnType = (mdecl.getReturnType()).toString();
MBeanParameterInfo [] mbpiArr = null;
int paramSize = mdecl.getParameters().size();
if (paramSize > 0) {
mbpiArr = new MBeanParameterInfo[paramSize];
int k = 0;
for (ParameterDeclaration pdecl : mdecl.getParameters()) {
mbpiArr [k] = new MBeanParameterInfo(
pdecl.getSimpleName(),
pdecl.getType().toString(),
null);
k++;
}
}
mmoiArr.add(new ModelMBeanOperationInfo(
methodName,
null,
mbpiArr,
returnType,
MBeanOperationInfo.ACTION,
descriptor));
} catch (Exception ioe) {
throw new RuntimeException(ioe);
}
}
private void generateAttribute(MethodDeclaration mdecl) {
try {
String attrName = null;
String name = mdecl.getSimpleName();
String getterName = null;
String setterName = null;
String isIsName = null;
String returnType = null;
if (name.startsWith("get")) {
attrName = name.substring(3);
getterName = name;
returnType = (mdecl.getReturnType()).toString();
} else if (name.startsWith("is")) {
attrName = name.substring(2);
isIsName = name;
returnType = (mdecl.getReturnType()).toString();
} else if (name.startsWith("set")) {
attrName = name.substring(3);
setterName = name;
// FIXME: need to optimize this later
for (ParameterDeclaration pdecl : mdecl.getParameters()) {
returnType = pdecl.getType().toString();
}
}
if (attrMap == null) {
setAttrMap(new ArrayList(4), attrName, getterName, setterName, isIsName, returnType);
} else {
ArrayList al = attrMap.get(attrName);
if (al == null) {
setAttrMap(new ArrayList(4), attrName, getterName, setterName, isIsName, returnType);
} else {
setAttrMap(al, attrName, getterName, setterName, isIsName, returnType);
}
}
} catch (Exception ioe) {
throw new RuntimeException(ioe);
}
}
private void setAttrMap(ArrayList al, String name,
String getterName, String setterName, String isIsName, String returnType) {
if (al.size() == 0) {
al.add(0, null);
al.add(1, null);
al.add(2, null);
al.add(3, null);
}
// element-0 getter
if (getterName != null) {
al.set(0, getterName);
}
// element-1 setter
if (setterName != null) {
al.set(1, setterName);
}
// element-2 is
if (isIsName != null) {
al.set(2, isIsName);
}
// element-3 type
al.set(3, returnType);
attrMap.put(name, al);
}
private void generateAttrInfo() {
String key = null;
ArrayList al = null;
boolean isReadable = false;
boolean isWritable = false;
boolean isIs = false;
try {
Iterator attrIter = attrMap.keySet().iterator();
while (attrIter.hasNext()) {
key = (String) attrIter.next();
al = (ArrayList) attrMap.get(key);
// get method or is method
String gm = null;
if (al.get(0) != null) {
gm = ("getMethod=" + (String)al.get(0));
isReadable = true;
} else if (al.get(2) != null) {
gm = ("getMethod=" + (String)al.get(2));
isReadable = true;
isIs = true;
}
String sm = null;
if (al.get(1) != null) {
sm = ("setMethod=" + (String) al.get(1));
isWritable = true;
}
// descriptor
Descriptor descriptor = new DescriptorSupport(new String[] {
("name=" + key),
"descriptorType=attribute",
gm,
sm
});
// attributeinfo
mmaiArr.add(new ModelMBeanAttributeInfo(
key,
(String) al.get(3),
null,
isReadable,
isWritable,
isIs,
descriptor));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}