modules/helpers/pluginAnnotations/src/main/java/org/rhq/helpers/pluginAnnotations/agent/Parameter.java
| 5
modules/helpers/pluginAnnotations/src/main/java/org/rhq/helpers/pluginAnnotations/agent/RhqType.java
| 77 +++
modules/helpers/pluginGen/pom.xml
| 7
modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/AnnotationProcessor.java
| 44 +
modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/DirectoryClassLoader.java
| 142 ++++++
modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Generator.java
| 229 ++++++----
modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/PluginGen.java
| 31 +
modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Prop.java
| 59 +-
modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
| 110 ++++
modules/helpers/pluginGen/src/main/resources/component.ftl
| 9
modules/helpers/pluginGen/src/main/resources/descriptor.ftl
| 5
modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl
| 17
modules/helpers/pluginGen/src/main/resources/pom.ftl
| 15
modules/helpers/pluginGen/src/test/java/org/rhq/helpers/pluginGen/test/FooBean.java
| 55 ++
14 files changed, 671 insertions(+), 134 deletions(-)
New commits:
commit ae96f1c0ad6e797e889923dc47a1f3c55c8eb394
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed Jul 17 11:06:21 2013 +0200
Allow to specify a directory with classes to scan for plugin annotations and to
auto-create metrics+operations from them.
diff --git
a/modules/helpers/pluginAnnotations/src/main/java/org/rhq/helpers/pluginAnnotations/agent/Parameter.java
b/modules/helpers/pluginAnnotations/src/main/java/org/rhq/helpers/pluginAnnotations/agent/Parameter.java
index 4b82a13..29dcc1e 100644
---
a/modules/helpers/pluginAnnotations/src/main/java/org/rhq/helpers/pluginAnnotations/agent/Parameter.java
+++
b/modules/helpers/pluginAnnotations/src/main/java/org/rhq/helpers/pluginAnnotations/agent/Parameter.java
@@ -29,13 +29,14 @@ import java.lang.annotation.Target;
/**
* Parameter.
- *
+ *
* @author Galder ZamarreƱo
* @since 4.0
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Parameter {
- String name() default "";
+ String name() ;
String description() default "";
+ RhqType type() default RhqType.VOID;
}
diff --git
a/modules/helpers/pluginAnnotations/src/main/java/org/rhq/helpers/pluginAnnotations/agent/RhqType.java
b/modules/helpers/pluginAnnotations/src/main/java/org/rhq/helpers/pluginAnnotations/agent/RhqType.java
new file mode 100644
index 0000000..1487a51
--- /dev/null
+++
b/modules/helpers/pluginAnnotations/src/main/java/org/rhq/helpers/pluginAnnotations/agent/RhqType.java
@@ -0,0 +1,77 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.helpers.pluginAnnotations.agent;
+
+import java.io.File;
+
+
+/**
+ * Base data types from RHQ for properties
+ * @author Heiko W. Rupp
+ */
+public enum RhqType {
+ INTEGER(new Class<?>[]{Integer.class,int.class},Boolean.class),
+ LONG(new Class<?>[]{Long.class,long.class},Long.class),
+ DOUBLE(new Class<?>[]{Double.class,double.class},Double.class),
+ STRING(new Class<?>[]{String.class},String.class),
+ LONG_STRING(new Class<?>[]{},String.class),
+ PASSWORD(new Class<?>[]{},String.class),
+ BOOLEAN(new Class<?>[]{Boolean.class, boolean.class},Boolean.class),
+ FLOAT(new Class<?>[]{Float.class, float.class},Float.class),
+ FILE(new Class<?>[]{File.class},File.class),
+ DIRECTORY(new Class<?>[]{},File.class),
+ VOID(new Class<?>[]{Void.class,void.class},Void.class)
+ ;
+ private Class<?>[] fromClasses;
+ private Class<?> toClass;
+
+ private RhqType(Class<?>[] fromClasses,Class<?> toClass) {
+
+ this.fromClasses = fromClasses;
+ this.toClass = toClass;
+ }
+
+ public Class<?>[] getFromClasses() {
+ return fromClasses;
+ }
+
+ public Class<?> getToClass() {
+ return toClass;
+ }
+
+ public static RhqType findType(Class<?> clazz) {
+ for (RhqType type : RhqType.values()) {
+ for (Class from : type.getFromClasses()) {
+ if (clazz.equals(from)) {
+ return type;
+ }
+ }
+ }
+ return null;
+ }
+
+ public String getRhqName() {
+ String name = name().toLowerCase();
+ if (name.equals("long_string")) {
+ name = "longString";
+ }
+ return name;
+ }
+}
diff --git a/modules/helpers/pluginGen/pom.xml b/modules/helpers/pluginGen/pom.xml
index 5aa512c..e7744e4 100644
--- a/modules/helpers/pluginGen/pom.xml
+++ b/modules/helpers/pluginGen/pom.xml
@@ -19,6 +19,11 @@
<name>RHQ plugin generator</name>
<description>Helper to generate plugin skeletons</description>
+ <properties>
+ <!-- we are using JDK 1.7 here, as JavaFX needs this and the generator is
standalone anyway -->
+
<animal.sniffer.java.signature.artifactId>java17</animal.sniffer.java.signature.artifactId>
+ </properties>
+
<build>
<plugins>
@@ -104,7 +109,7 @@
<dependency>
<groupId>org.rhq.helpers</groupId>
<artifactId>rhq-pluginAnnotations</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.9.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
diff --git
a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/AnnotationProcessor.java
b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/AnnotationProcessor.java
new file mode 100644
index 0000000..3c90b7b
--- /dev/null
+++
b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/AnnotationProcessor.java
@@ -0,0 +1,44 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.helpers.pluginGen;
+
+import java.util.List;
+
+/**
+ * Processor that scans a directory for annotated classes and generates metrics etc. from
them.
+ * @author Heiko W. Rupp
+ */
+public class AnnotationProcessor {
+
+ private List<Class> classList;
+ private final DirectoryClassLoader classLoader;
+
+ public AnnotationProcessor(String baseDirectory) {
+ classLoader = new DirectoryClassLoader();
+ classLoader.setBaseDir(baseDirectory);
+ }
+
+ public void populate(Props props) {
+ classList = classLoader.findClasses();
+
+ props.populateMetrics(classList);
+ props.populateOperations(classList);
+ }
+}
diff --git
a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/DirectoryClassLoader.java
b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/DirectoryClassLoader.java
new file mode 100644
index 0000000..b4a729f
--- /dev/null
+++
b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/DirectoryClassLoader.java
@@ -0,0 +1,142 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.helpers.pluginGen;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+
+/**
+ * Classloader to load from a given directory
+ * @author Heiko W. Rupp
+ */
+public class DirectoryClassLoader extends ClassLoader {
+ private Hashtable classes = new Hashtable(); //used to cache already defined classes
+ private String baseDir;
+
+ @Override
+ protected Class<?> findClass(String pathName) throws ClassNotFoundException {
+
+
+ if (baseDir==null) {
+ throw new IllegalStateException("Must set baseDir first");
+ }
+
+ byte classByte[];
+ Class result = null;
+
+ String className = pathName.substring(baseDir.length()+1); // remove base dir
+ className = className.substring(0,className.length()-6); // remove .class
+ className = className.replaceAll(File.separator,"."); // change / ->
.
+
+ result = (Class) classes.get(className); //checks in cached classes
+ if (result != null) {
+ return result;
+ }
+ try {
+ File classFile = new File(pathName);
+ FileInputStream fis = new FileInputStream(classFile);
+
+ ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+ int nextValue = fis.read();
+ while (-1 != nextValue) {
+ byteStream.write(nextValue);
+ nextValue = fis.read();
+ }
+
+ classByte = byteStream.toByteArray();
+ result = defineClass(className, classByte, 0, classByte.length, null);
+ classes.put(className, result);
+ return result;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public void setBaseDir(String baseDir) {
+ this.baseDir = baseDir;
+ }
+
+ public List<Class> findClasses() {
+ if (baseDir==null) {
+ throw new IllegalStateException("Must set baseDir first");
+ }
+
+ File baseFile = new File(baseDir);
+ if(!baseFile.isDirectory()) {
+ throw new IllegalStateException("BaseDir is no directory");
+ }
+ if (!baseFile.canRead()) {
+ throw new IllegalStateException("BaseDir is not readable");
+ }
+
+ List<File> files = walk(baseFile);
+
+ List<Class> classes = new ArrayList<>();
+ for (File file : files) {
+ String fileName = file.getAbsolutePath();
+
+ Class clazz = null;
+ try {
+ clazz = findClass(fileName);
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace(); // TODO: Customise this generated block
+ }
+ classes.add(clazz);
+
+ }
+
+ return classes;
+ }
+
+ private List<File> walk(File path) {
+
+ List<File> files = new ArrayList<>();
+
+ File[] list = path.listFiles();
+
+ if (list == null) {
+ return files;
+ }
+
+ for ( File f : list ) {
+ if ( f.isDirectory() ) {
+ List<File> newFiles = walk( f );
+ System.out.println( "Dir:" + f.getAbsoluteFile() );
+ files.addAll(newFiles);
+ }
+ else {
+ System.out.println( "File:" + f.getAbsoluteFile() );
+ if (f.getName().endsWith(".class") &&
!f.getName().contains("$")) {
+ files.add(f);
+ }
+
+ }
+ }
+ return files;
+ }
+}
diff --git
a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Generator.java
b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Generator.java
index e7da952..21d0d4d 100644
--- a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Generator.java
+++ b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Generator.java
@@ -149,9 +149,12 @@ public class Generator extends Application{
Label label = new Label("Messages:");
msgBox.getChildren().add(label);
errorMessage = new Text();
- errorMessage.setFont(Font.font("Arial", FontWeight.SEMI_BOLD, 12));
+ errorMessage.setFont(Font.font("Arial", FontWeight.SEMI_BOLD, 15));
errorMessage.setId("errorMessage");
msgBox.getChildren().add(errorMessage);
+ msgBox.setPadding(new Insets(5));
+ msgBox.setSpacing(3);
+ msgBox.setAlignment(Pos.BASELINE_LEFT);
return msgBox;
}
@@ -172,94 +175,14 @@ public class Generator extends Application{
// Now add the field itself
final Class propType = prop.getType();
if (propType.equals(String.class)) {
- final Pattern pattern = Pattern.compile(prop.getValidationRegex());
-
- final TextField input = new TextField();
- // Add field leave event to fill in the props with the result
- input.focusedProperty().addListener(new ChangeListener<Boolean>()
{
- @Override
- public void changed(ObservableValue<? extends Boolean>
observableValue, Boolean oldState,
- Boolean newState) {
- if (newState) { // User entered input field
- descriptionField.setText(prop.getDescription());
- }
- else { // User left input field
- descriptionField.setText("");
- setPropsValue(prop.getVariableName(),input.getText(),
propType); // TODO right place?
- }
- }
- });
- // Add validation of the input
- input.textProperty().addListener(new ChangeListener<String>() {
- @Override
- public void changed(ObservableValue<? extends String>
observableValue, String s, String newText) {
- Matcher m = pattern.matcher(newText);
- if (!m.matches()) {
- setErrorMessage("Input does not match " +
prop.getValidationRegex());
- } else {
- clearErrorMessage();
- }
-
- }
- });
- root.add(input, 1, row);
+ addStringField(root, descriptionField, row, prop);
} else if (propType.equals(Boolean.class) || propType.equals(boolean.class))
{
- final ChoiceBox choiceBox = new ChoiceBox();
- choiceBox.getItems().addAll("Yes", "No");
- choiceBox.getSelectionModel().selectLast(); // NO is default
- choiceBox.getSelectionModel().selectedItemProperty().addListener(new
ChangeListener<String>() {
- @Override
- public void changed(ObservableValue<? extends String>
observableValue, String s, String newValue) {
- setPropsValue(prop.getVariableName(),
newValue.equals("Yes"), propType);
- }
- });
- Tooltip tooltip = new Tooltip(prop.getDescription()); // TODO make this a
hover listener
- choiceBox.setTooltip(tooltip);
-
- root.add(choiceBox, 1, row);
+ addBooleanField(root, row, prop);
} else if (propType.equals(ResourceCategory.class)) {
- final ChoiceBox choiceBox = new ChoiceBox();
- for (ResourceCategory cat : ResourceCategory.values()) {
- choiceBox.getItems().add(cat.getLowerName());
- }
- choiceBox.getSelectionModel().selectLast(); // service is default
- choiceBox.getSelectionModel().selectedItemProperty().addListener(new
ChangeListener<String>() {
- @Override
- public void changed(ObservableValue<? extends String>
observableValue, String s, String newValue) {
- ResourceCategory newCategory =
ResourceCategory.valueOf(newValue.toUpperCase());
- setPropsValue(prop.getVariableName(),newCategory,propType);
- }
- });
- Tooltip tooltip = new Tooltip(prop.getDescription()); // TODO make this a
hover listener
- choiceBox.setTooltip(tooltip);
- root.add(choiceBox,1,row);
+ addResourceTypeChooser(root, row, prop);
} else if (propType.equals(File.class)) {
- // Can not add this directly, so add a button to trigger it
- final Text text = new Text();
- text.setText("Pick a directory");
- root.add(text,1,row);
- Tooltip tooltip = new Tooltip("Pick the (parent) directory where the
plugin will be put in.");
- Button pickButton = new Button("Pick");
- pickButton.setTooltip(tooltip);
- pickButton.setOnAction(new EventHandler<ActionEvent>() {
- @Override
- public void handle(ActionEvent actionEvent) {
- DirectoryChooser chooser = new DirectoryChooser();
- chooser.setTitle("Pick a directory where the plugin will be
put in.");
- File dir = chooser.showDialog(primaryStage);
- if (dir != null) {
- String dirName = dir.getAbsolutePath();
- props.setFileSystemRoot(dirName);
- clearErrorMessage();
- text.setText(dirName);
- } else {
- setErrorMessage("No directory selected");
- text.setText("Pick a directory");
- }
- }
- });
-
- root.add(pickButton,2,row);
+ addDirectoryChooserField(root, row, prop, descriptionField);
+
}
row++;
@@ -269,6 +192,115 @@ public class Generator extends Application{
return row;
}
+ private void addDirectoryChooserField(GridPane root, int row, final Prop prop, final
Text descriptionField) {
+ // Can not add this directly, so add a button to trigger it
+ final TextField input = new TextField();
+ root.add(input,1,row);
+ Tooltip tooltip = new Tooltip(prop.getDescription());
+ Button pickButton = new Button("Pick");
+ input.setTooltip(tooltip);
+ pickButton.setTooltip(tooltip);
+ pickButton.setOnAction(new EventHandler<ActionEvent>() {
+ @Override
+ public void handle(ActionEvent actionEvent) {
+ DirectoryChooser chooser = new DirectoryChooser();
+ chooser.setTitle(prop.getDescription());
+ File dir = chooser.showDialog(primaryStage);
+ if (dir != null) {
+ String dirName = dir.getAbsolutePath();
+ setPropsValue(prop.getVariableName(), dirName, String.class);
+ clearErrorMessage();
+ input.setText(dirName);
+ } else {
+ setErrorMessage("No directory selected");
+ input.setText("Pick a directory");
+ }
+ }
+ });
+ input.focusedProperty().addListener(new
ShowFieldDescriptionHandler(prop,descriptionField,input));
+ // Add validation of the input
+ input.textProperty().addListener(new ChangeListener<String>() {
+ @Override
+ public void changed(ObservableValue<? extends String> observableValue,
String s, String newText) {
+ File file = new File(newText);
+ if (!file.isDirectory()) {
+ setErrorMessage(newText + " is no directory");
+ } else if (prop.isDirectoryWriteable() && !file.canWrite()) {
+ setErrorMessage(newText + " is not writable");
+ } else if (!prop.isDirectoryWriteable() && !file.canRead()) {
+ setErrorMessage(newText + " is not readable");
+ } else {
+ clearErrorMessage();
+ }
+
+ }
+ });
+
+
+
+ root.add(pickButton,2,row);
+ }
+
+ private void addResourceTypeChooser(GridPane root, int row, final Prop prop) {
+ final ChoiceBox choiceBox = new ChoiceBox();
+ for (ResourceCategory cat : ResourceCategory.values()) {
+ choiceBox.getItems().add(cat.getLowerName());
+ }
+ choiceBox.getSelectionModel().selectLast(); // service is default
+ choiceBox.getSelectionModel().selectedItemProperty().addListener(new
ChangeListener<String>() {
+ @Override
+ public void changed(ObservableValue<? extends String> observableValue,
String s, String newValue) {
+ ResourceCategory newCategory =
ResourceCategory.valueOf(newValue.toUpperCase());
+ setPropsValue(prop.getVariableName(),newCategory,prop.getType());
+ }
+ });
+ Tooltip tooltip = new Tooltip(prop.getDescription()); // TODO make this a hover
listener
+ choiceBox.setTooltip(tooltip);
+ root.add(choiceBox,1,row);
+ }
+
+ private void addBooleanField(GridPane root, int row, final Prop prop) {
+ final ChoiceBox choiceBox = new ChoiceBox();
+ choiceBox.getItems().addAll("Yes", "No");
+ choiceBox.getSelectionModel().selectLast(); // NO is default
+ choiceBox.getSelectionModel().selectedItemProperty().addListener(new
ChangeListener<String>() {
+ @Override
+ public void changed(ObservableValue<? extends String> observableValue,
String s, String newValue) {
+ setPropsValue(prop.getVariableName(), newValue.equals("Yes"),
prop.getType());
+ }
+ });
+ Tooltip tooltip = new Tooltip(prop.getDescription()); // TODO make this a hover
listener
+ choiceBox.setTooltip(tooltip);
+
+ root.add(choiceBox, 1, row);
+ }
+
+ private void addStringField(GridPane root, final Text descriptionField, int row,
final Prop prop) {
+ final Pattern pattern = Pattern.compile(prop.getValidationRegex());
+
+ final TextField input = new TextField();
+ if (prop.getDefaultValue()!=null && !prop.getDefaultValue().isEmpty()) {
+ input.setText(prop.getDefaultValue());
+ setPropsValue(prop.getVariableName(),prop.getDefaultValue(),prop.getType());
+ }
+ // Add field leave event to fill in the props with the result
+ input.focusedProperty().addListener(new
ShowFieldDescriptionHandler(prop,descriptionField,input));
+ // Add validation of the input
+ input.textProperty().addListener(new ChangeListener<String>() {
+ @Override
+ public void changed(ObservableValue<? extends String> observableValue,
String s, String newText) {
+ Matcher m = pattern.matcher(newText);
+ if (!m.matches()) {
+ setErrorMessage("Input does not match " +
prop.getValidationRegex());
+ } else {
+ clearErrorMessage();
+ }
+
+ }
+ });
+ root.add(input, 1, row);
+ }
+
private void setInfoMessage(String message) {
errorMessage.setText(message);
errorMessage.setFill(Color.DARKGREEN);
@@ -297,4 +329,29 @@ public class Generator extends Application{
}
}
+
+ private class ShowFieldDescriptionHandler implements ChangeListener<Boolean> {
+
+ private Prop prop;
+ private Text descriptionField;
+ private TextField input;
+
+ private ShowFieldDescriptionHandler(Prop prop,Text descriptionField, TextField
input) {
+ this.prop = prop;
+ this.descriptionField = descriptionField;
+ this.input = input;
+ }
+
+ @Override
+ public void changed(ObservableValue<? extends Boolean> observableValue,
Boolean oldState,
+ Boolean newState) {
+ if (newState) { // User entered input field
+ descriptionField.setText(prop.getDescription());
+ }
+ else { // User left input field
+ descriptionField.setText("");
+ setPropsValue(prop.getVariableName(),input.getText(), String.class); //
TODO right place?
+ }
+ }
+ }
}
diff --git
a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/PluginGen.java
b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/PluginGen.java
index 64b5509..8722446 100644
--- a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/PluginGen.java
+++ b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/PluginGen.java
@@ -51,6 +51,19 @@ public class PluginGen {
private final Log log = LogFactory.getLog(PluginGen.class);
public static void main(String[] arg) throws Exception {
+
+ if (arg.length>0) {
+ if (arg[0].equals("-ui")) {
+ Generator.main(arg);
+
+ }
+ else {
+ System.out.println("use option -ui to start the UI version");
+ }
+ System.exit(0);
+ }
+
+
PluginGen pg = new PluginGen();
pg.run();
@@ -121,10 +134,24 @@ public class PluginGen {
String pkg = props.getPackagePrefix() + "." + props.getName();
props.setPkg(pkg);
+ String name = props.getName(); // Type name
+
+ if (props.getComponentClass().contains("{name}")) {
+
props.setComponentClass(props.getComponentClass().replace("{name}",name));
+ }
+
+ if (props.getDiscoveryClass().contains("{name}")) {
+
props.setDiscoveryClass(props.getDiscoveryClass().replace("{name}",name));
+ }
+
for (Props cProp : props.getChildren()) {
cProp.setPkg(pkg);
}
+ if (props.getScanForAnnotations()!=null) {
+ AnnotationProcessor ap = new
AnnotationProcessor(props.getScanForAnnotations());
+ ap.populate(props);
+ }
}
/**
@@ -247,7 +274,7 @@ public class PluginGen {
}
boolean success;
- File activeDirectory = new File(props.getFileSystemRoot(), props.getName());
+ File activeDirectory = new File(props.getFileSystemRoot(),
props.getPluginName());
if (!activeDirectory.exists()) {
success = activeDirectory.mkdir();
@@ -260,7 +287,7 @@ public class PluginGen {
// write pom.xml
createFile(props, "pom", "pom.xml",
activeDirectory.getAbsolutePath());
- // Create java directory hierarchie
+ // Create java directory hierarchy
String path = activeDirectory.getAbsolutePath() + File.separator +
"src" + File.separator + "main"
+ File.separator;
diff --git a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Prop.java
b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Prop.java
index 4ed019a..40e729c 100644
--- a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Prop.java
+++ b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Prop.java
@@ -30,48 +30,62 @@ public enum Prop {
PLUGIN_NAME("pluginName", String.class,"Name of the plugin",
"\\w+" , true ),
PLUGIN_DESCRIPTION("pluginDescription", String.class,"Description of
the plugin",".*" , true ),
PACKAGE("packagePrefix", String.class,"Default
Package","[a-zA-Z\\.]+",true ),
- FILE_ROOT("fileSystemRoot", File.class,"Root directory to put the
plugin",".*",true ),
+ FILE_ROOT("fileSystemRoot", File.class,"Root directory to put the
plugin into",".*",true , true,null),
RHQ_VERSION("rhqVersion",String.class,"RHQ version to
use","[0-9][0-9\\.]+",true),
CATEGORY("category", ResourceCategory.class, "Category of the resource
type (platform = host level)",null),
TYPE_NAME("name", String.class, "Name of the resource type",
"\\w+"),
DESCRIPTION("description", String.class, "Description of the
type", ".*"),
- DISCOVERY_CLASS("discoveryClass", String.class, "Discovery
class", "[A-Z][a-zA-Z0-9]*"),
- COMPONENT_CLASS("componentClass", String.class, "Discovery
class", "[A-Z][a-zA-Z0-9]*"),
+ DISCOVERY_CLASS("discoveryClass", String.class, "Name of the Discovery
class. '{name}' will be replaced with the type name",
"[A-Z][a-zA-Z0-9]*",false,false,"{name}Discovery"),
+ COMPONENT_CLASS("componentClass", String.class, "Name of the Discovery
class. '{name}' will be replaced with the type name",
"[A-Z][a-zA-Z0-9]*",false,false,"{name}Component"),
IS_SINGLETON("singleton",boolean.class,"Is this type a singleton,
which means that" +
- " there can only be one resource of that type for the given
parent?",null),
- HAS_METRICS("hasMetrics",boolean.class,"Does this type support taking
metrics?",null),
- HAS_OPERATIONS("hasOperations",boolean.class,"Does this type support
operations?",null),
- HAS_EVENTS("events",boolean.class,"Does this type support
events?",null),
- HAS_SUPPORT_FACET("supportFacet",boolean.class,"Does this type support
the support facet?",null),
+ " there can only be one resource of that type for the given parent?"),
+ HAS_METRICS("hasMetrics",boolean.class,"Does this type support taking
metrics?"),
+ HAS_OPERATIONS("hasOperations",boolean.class,"Does this type support
operations?"),
+ HAS_EVENTS("events",boolean.class,"Does this type support
events?"),
+ HAS_SUPPORT_FACET("supportFacet",boolean.class,"Does this type support
the support facet?"),
RESOURCE_CONFIGURATION("resourceConfiguration",boolean.class,"Does
this type support " +
- "configuring the resource?",".*"),
- CAN_CREATE_CHILDREN("createChildren",boolean.class,"Can the type
create child resources?",null),
- CAN_DELETE_CHILDREN("deleteChildren",boolean.class,"Can the type
delete child resources?",null),
-
- // TODO add the remaining properties from Prop.class
-
+ "configuring the resource?"),
+ CAN_CREATE_CHILDREN("createChildren",boolean.class,"Can the type
create child resources?"),
+ CAN_DELETE_CHILDREN("deleteChildren",boolean.class,"Can the type
delete child resources?"),
+ USE_EXTENAL_JARS("usesExternalJarsInPlugin",boolean.class,"Will the
plugin use external jars in the plugin jar?"),
+ ALLOW_MANUAL_ADD("manualAddOfResourceType",boolean.class,"Should
manually adding resource be supported?"),
+ USE_LIFECYLE_API("usePluginLifecycleListenerApi",boolean.class,"Should
the plugin lifecycle api be supported?"),
+ DEPENDS_ON_JMX_PLUGIN("dependsOnJmxPlugin",boolean.class,"Does the
plugin use JMX and extend the JMX Plugin?"),
+ DEPENDS_ON_AS7_PLUGIN("dependsOnAs7Plugin",boolean.class,"Does the
plugin use DMR and extend the AS7 Plugin?"),
+ USE_SUPPORT_FACET("supportFacet",boolean.class,"Will the support facet
be used?"),
+
+ SCAN_FOR_ANNOTATIONS("scanForAnnotations",File.class,"Directory to
scan for plugin annotations to include in type",null, false,false, null)
;
private String variableName;
private Class type;
private String description;
private boolean pluginLevel;
+ private boolean directoryWriteable;
+ private String defaultValue;
private String validationRegex;
- private Prop(String variableName, Class type, String description, String
validationRegex, boolean pluginLevel) {
+ private Prop(String variableName, Class type, String description, String
validationRegex, boolean pluginLevel, boolean directoryWriteable, String defaultValue) {
this.variableName = variableName;
this.type = type;
this.description = description;
this.validationRegex = validationRegex;
this.pluginLevel = pluginLevel;
+ this.directoryWriteable = directoryWriteable;
+ this.defaultValue = defaultValue;
+ }
+
+ private Prop(String variableName, Class type, String description, String
validationRegex, boolean pluginLevel) {
+ this(variableName,type,description,validationRegex,pluginLevel,false,null);
}
private Prop(String variableName, Class type, String description, String
validationRegex) {
- this.variableName = variableName;
- this.type = type;
- this.description = description;
- this.validationRegex = validationRegex;
+ this(variableName,type,description,validationRegex,false,false,null);
+ }
+
+ private Prop(String variableName, Class type, String description) {
+ this(variableName,type,description,null,false,false,null);
}
public String getVariableName() {
@@ -111,4 +125,11 @@ public enum Prop {
return builder.toString();
}
+ public boolean isDirectoryWriteable() {
+ return directoryWriteable;
+ }
+
+ public String getDefaultValue() {
+ return defaultValue;
+ }
}
diff --git a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
index 237f5ad..95be574 100644
--- a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
+++ b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
@@ -18,6 +18,9 @@
*/
package org.rhq.helpers.pluginGen;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
@@ -26,6 +29,9 @@ import java.util.Set;
import org.rhq.helpers.pluginAnnotations.agent.DataType;
import org.rhq.helpers.pluginAnnotations.agent.DisplayType;
import org.rhq.helpers.pluginAnnotations.agent.Metric;
+import org.rhq.helpers.pluginAnnotations.agent.Operation;
+import org.rhq.helpers.pluginAnnotations.agent.Parameter;
+import org.rhq.helpers.pluginAnnotations.agent.RhqType;
import org.rhq.helpers.pluginAnnotations.agent.Units;
/**
@@ -33,6 +39,7 @@ import org.rhq.helpers.pluginAnnotations.agent.Units;
*
* @author Heiko W. Rupp
*/
+@SuppressWarnings("unused")
public class Props {
/** What category is this ? */
@@ -69,7 +76,7 @@ public class Props {
private boolean createChildren;
/** Can the service delete children ? */
private boolean deleteChildren;
- /** Use externals chars in the plugin jar ? */
+ /** Use externals jars in the plugin jar ? */
private boolean usesExternalJarsInPlugin;
/** Does it support manual add of children ? */
private boolean manualAddOfResourceType;
@@ -77,8 +84,12 @@ public class Props {
private boolean usePluginLifecycleListenerApi;
/** Depends on JMX plugin ? */
private boolean dependsOnJmxPlugin;
+ /** Depends on AS7 plugin ? */
+ private boolean dependsOnAs7Plugin;
+ /** Directory with java files to scan for plugin annotations */
+ private String scanForAnnotations;
/** What version of RHQ should this plugin's pom use ? */
- private String rhqVersion = "3.0.0";
+ private String rhqVersion = "4.8.0";
/** Embedded children */
private Set<Props> children = new HashSet<Props>();
@@ -336,22 +347,97 @@ public class Props {
this.runsInsides = runsInsides;
}
+ public boolean isDependsOnAs7Plugin() {
+ return dependsOnAs7Plugin;
+ }
+
+ public void setDependsOnAs7Plugin(boolean dependsOnAs7Plugin) {
+ this.dependsOnAs7Plugin = dependsOnAs7Plugin;
+ }
+
+ public String getScanForAnnotations() {
+ return scanForAnnotations;
+ }
+
+ public void setScanForAnnotations(String scanForAnnotations) {
+ this.scanForAnnotations = scanForAnnotations;
+ }
+
public void populateMetrics(List<Class> classes) {
- for (Class<?> clazz : classes) {
- Metric metricAnnot = clazz.getAnnotation(Metric.class);
- if (metricAnnot != null) {
- MetricProps metric = new MetricProps(metricAnnot.property());
+ for (Class<?> clazz : classes) {
+ for (Field field : clazz.getDeclaredFields()) {
+ Metric metricAnnot = field.getAnnotation(Metric.class);
+ addMetric(metricAnnot, field.getName());
+ }
+
+ for (Method method : clazz.getDeclaredMethods()) {
+ Metric metricAnnot = method.getAnnotation(Metric.class);
+ addMetric(metricAnnot, method.getName());
+ }
+ }
+ }
+
+ public void populateOperations(List<Class> classes) {
+ for (Class<?> clazz : classes) {
+ for (Method method : clazz.getDeclaredMethods()) {
+ Operation operationAnnot = method.getAnnotation(Operation.class);
+ if (operationAnnot != null) {
+ String property = operationAnnot.name();
+ if (property.isEmpty()) {
+ property = method.getName();
+ }
+ OperationProps op = new OperationProps(property);
+ op.setDisplayName(operationAnnot.displayName());
+ op.setDescription(operationAnnot.description());
+ RhqType type = RhqType.findType(method.getReturnType());
+ if (type != RhqType.VOID) {
+ SimpleProperty simpleProperty = new
SimpleProperty(type.getRhqName());
+ op.setResult(simpleProperty);
+ }
+
+ Class[] types = method.getParameterTypes();
+ int i=0;
+ for (Annotation[] annotations : method.getParameterAnnotations() ) {
+ for (Annotation annotation : annotations) {
+ if (annotation instanceof Parameter) {
+ Parameter parameter = (Parameter) annotation;
+ SimpleProperty simpleProperty = new
SimpleProperty(parameter.name());
+ simpleProperty.setDescription(parameter.description());
+ Class typeClass = types[i];
+ RhqType rhqType = RhqType.findType(typeClass);
+ if (parameter.type()!=RhqType.VOID){
+ rhqType = parameter.type();
+ }
+ simpleProperty.setType(rhqType.getRhqName());
+ op.getParams().add(simpleProperty);
+ }
+ }
+ i++;
+ }
+ operations.add(op);
+ }
+
+ }
+ }
+ }
+
+ private void addMetric(Metric metricAnnot, String name) {
+ if (metricAnnot != null) {
+ String property = metricAnnot.property();
+ if (property.isEmpty()) {
+ property = name;
+ }
+ MetricProps metric = new MetricProps(property);
metric.setDisplayName(metricAnnot.displayName());
metric.setDisplayType(metricAnnot.displayType());
metric.setDataType(metricAnnot.dataType());
metric.setDescription(metricAnnot.description());
+ metric.setUnits(metricAnnot.units());
metrics.add(metric);
- }
-
- }
- }
+ }
+ }
- @Override
+ @Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("Props");
@@ -387,7 +473,7 @@ public class Props {
return sb.toString();
}
- public static class TypeKey {
+ public static class TypeKey {
private String name;
private String pluginName;
diff --git a/modules/helpers/pluginGen/src/main/resources/component.ftl
b/modules/helpers/pluginGen/src/main/resources/component.ftl
index 1b3dda1..b445008 100644
--- a/modules/helpers/pluginGen/src/main/resources/component.ftl
+++ b/modules/helpers/pluginGen/src/main/resources/component.ftl
@@ -187,7 +187,6 @@ public class ${props.componentClass} implements
ResourceComponent<#if props.pare
<#if props.operations??>
-
public void startOperationFacet(OperationContext context) {
}
@@ -203,6 +202,13 @@ public class ${props.componentClass} implements
ResourceComponent<#if props.pare
public OperationResult invokeOperation(String name, Configuration params) throws
Exception {
OperationResult res = new OperationResult();
+<#if props.operations?has_content>
+ <#list props.operations as operation>
+ if (name.equals("${operation.name}") {
+ // TODO implement me
+ }
+ </#list>
+<#else>
if ("dummyOperation".equals(name)) {
// TODO implement me
@@ -210,6 +216,7 @@ public class ${props.componentClass} implements
ResourceComponent<#if props.pare
return res;
}
</#if>
+</#if>
<#if props.resourceConfiguration>
diff --git a/modules/helpers/pluginGen/src/main/resources/descriptor.ftl
b/modules/helpers/pluginGen/src/main/resources/descriptor.ftl
index 85195e8..1fe2a6b 100644
--- a/modules/helpers/pluginGen/src/main/resources/descriptor.ftl
+++ b/modules/helpers/pluginGen/src/main/resources/descriptor.ftl
@@ -1,7 +1,7 @@
<#--
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -38,6 +38,9 @@
<#if props.dependsOnJmxPlugin>
<depends plugin="JMX" useClasses="true"/>
</#if>
+<#if props.dependsOnAs7Plugin>
+ <depends plugin="JBossAS7" useClasses="true"/>
+</#if>
<${props.category.lowerName} <#include "descriptorMain.ftl"/>
diff --git a/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl
b/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl
index b650f7a..5579806 100644
--- a/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl
+++ b/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl
@@ -1,7 +1,7 @@
<#--
/*
* RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -39,6 +39,11 @@ name="${props.name}"
</#list>
</runs-inside>
</#if>
+ <#if props.dependsOnAs7Plugin>
+ <runs-inside> <!-- TODO adjust type -->
+ <parent-resource-type name="JBossAS7 Standalone Server"
plugin="JBossAS7"/>
+ </runs-inside>
+ </#if>
<#if props.simpleProps?has_content>
<plugin-configuration>
@@ -57,14 +62,14 @@ name="${props.name}"
</plugin-configuration>
</#if>
- <#if props.hasOperations>
+ <#if props.hasOperations || props.operations?has_content>
<#if props.operations?has_content>
<#list props.operations as operation>
- <operation name="${operation.name}"
displayName="${operation.displayName}"
description="${operation.description}">
+ <operation name="${operation.name}" <#if
operation.displayName?has_content>displayName="${operation.displayName}"</#if>
description="${operation.description}">
<#if operation.params?has_content>
<parameters>
<#list operation.params as param>
- <c:simple-property name="${param.name}" <#if
param.description??>description="${param.description}"</#if>/>
+ <c:simple-property name="${param.name}" <#if
param.description??>description="${param.description}"</#if>
type="${param.type}"/>
</#list>
</parameters>
</#if>
@@ -82,10 +87,10 @@ name="${props.name}"
</#if>
</#if>
- <#if props.hasMetrics>
+ <#if props.hasMetrics || props.metrics?has_content>
<#if props.metrics?has_content>
<#list props.metrics as metric>
- <metric property="${metric.property}"
displayName="${metric.displayName}"
displayType="${metric.displayType}" units="${metric.units}"
dataType="${metric.dataType}"
+ <metric property="${metric.property}" <#if
metric.displayName?has_content>displayName="${metric.displayName}"</#if>
displayType="${metric.displayType}" units="${metric.units}"
dataType="${metric.dataType}"
description="${metric.description}" />
</#list>
<#else>
diff --git a/modules/helpers/pluginGen/src/main/resources/pom.ftl
b/modules/helpers/pluginGen/src/main/resources/pom.ftl
index 01daca1..7c799b8 100644
--- a/modules/helpers/pluginGen/src/main/resources/pom.ftl
+++ b/modules/helpers/pluginGen/src/main/resources/pom.ftl
@@ -2,7 +2,7 @@
<#--
/*
* RHQ Management Platform
- * Copyright (C) 2005-20012 Red Hat, Inc.
+ * Copyright (C) 2005-20013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -35,10 +35,10 @@
</parent>
<groupId>org.rhq</groupId>
- <artifactId>${props.name}-plugin</artifactId>
+ <artifactId>${props.pluginName}-plugin</artifactId>
<packaging>jar</packaging>
- <name>RHQ ${props.name} Plugin</name>
+ <name>RHQ ${props.pluginName} Plugin</name>
<#if props.description??>
<description>${props.description}</description>
</#if>
@@ -86,7 +86,6 @@
</executions>
</plugin>
</#if>
-
</plugins>
</build>
@@ -232,6 +231,14 @@
<scope>provided</scope>
</dependency>
</#if>
+<#if props.dependsOnAs7Plugin>
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-jboss-as-7-plugin</artifactId>
+ <version>${r"${project.version}"}</version>
+ <scope>provided</scope>
+ </dependency>
+</#if>
<!-- TODO add your dependencies here -->
diff --git
a/modules/helpers/pluginGen/src/test/java/org/rhq/helpers/pluginGen/test/FooBean.java
b/modules/helpers/pluginGen/src/test/java/org/rhq/helpers/pluginGen/test/FooBean.java
new file mode 100644
index 0000000..fbc571b
--- /dev/null
+++ b/modules/helpers/pluginGen/src/test/java/org/rhq/helpers/pluginGen/test/FooBean.java
@@ -0,0 +1,55 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.helpers.pluginGen.test;
+
+import org.rhq.helpers.pluginAnnotations.agent.DataType;
+import org.rhq.helpers.pluginAnnotations.agent.DisplayType;
+import org.rhq.helpers.pluginAnnotations.agent.MeasurementType;
+import org.rhq.helpers.pluginAnnotations.agent.Metric;
+import org.rhq.helpers.pluginAnnotations.agent.Operation;
+import org.rhq.helpers.pluginAnnotations.agent.Parameter;
+import org.rhq.helpers.pluginAnnotations.agent.RhqType;
+
+/**
+ * Just a sample
+ * @author Heiko W. Rupp
+ */
+
+public class FooBean {
+
+ @Metric(description = "How often was this bean invoked", displayType =
DisplayType.SUMMARY, measurementType = MeasurementType.DYNAMIC)
+ int invocationCount;
+
+ @Metric(description = "Just a foo", dataType = DataType.TRAIT)
+ String lastCommand;
+
+ @Operation(description = "Increase the invocation count")
+ public int increaseCounter() {
+ invocationCount++;
+ return invocationCount;
+ }
+
+ @Operation(description = "Decrease the counter")
+ public void decreaseCounter(@Parameter(description = "How much to
decrease?", name = "by") int by) {
+ invocationCount -= by;
+ }
+
+
+}