Jenkins Plugin. RootAction. index.jelly in seperate window - plugins

i am writing a simple plugin and am forced to create a RootAction which displays a page (the index.jelly) and needs some additional values to confirm and then execute the methode.
My problem is, that the index.jelly file gets always displayed on a blank window.
But i do need it to be included inside of the Jenkinstemplate in the main table, as usual.
Can't seem to figure out why this is happening.
Any ideas?
RestartJksLink.java
package org.jenkinsci.plugins.tomcat_app_restart;
import hudson.Extension;
import hudson.model.ManagementLink;
/**
*
*
* #author [...]
*/
#Extension
public class RestartJksLink extends ManagementLink {
#Override
public String getIconFileName() {
return "/plugin/tomcat-app-restart/images/restart.png";
}
#Override
public String getUrlName() {
return "jksrestart";
}
#Override
public String getDescription() {
return "Restart your Jenkins-Application on Tomcat";
}
public String getDisplayName() {
return "Restart Jenkins-App on Tomcat";
}
}
RestartJksRootAction.java
package org.jenkinsci.plugins.tomcat_app_restart;
import java.io.IOException;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.PasswordAuthentication;
import java.net.URL;
import jenkins.model.Jenkins;
import hudson.Extension;
import hudson.model.RootAction;
import hudson.util.FormValidation;
#Extension
public class RestartJksRootAction implements RootAction {
public String getDisplayName() {
return "Restart Jenkins on Tomcat";
}
public String getIconFileName() {
if (!Jenkins.getInstance().hasPermission(Jenkins.ADMINISTER)) {
return null;
}
if (!Jenkins.getInstance().getLifecycle().canRestart()) {
return null;
}
return "/plugin/tomcat-app-restart/images/restart.png";
}
public String getUrlName() {
return "jksrestart";
}
public FormValidation doJksRestart() {
Authenticator.setDefault (new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication ("admin", "admin".toCharArray());
}
});
URL url;
try {
url = new URL("http://localhost:8888/manager/text/start?path=/jenkins");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
System.out.println("" + connection.getResponseMessage());
return FormValidation.ok("Success");
} catch (IOException e) {
return FormValidation.error("Client error: " + e.getMessage());
}
}
}
index.jelly inside: resources.org.jenkinsci.plugins.tomcat_app_restart.RestartJksRootAction
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt" xmlns:p="/lib/hudson/project">
<f:validateButton
title="${%Restart Jenkins}" progress="${%Restarting...}"
method="JksRestart" with="" />
</j:jelly>
Thank you guys!
I am new to jenkins plugin development, this would help me a lot to understand.
Kind regards.

this demo (rootaction-example-plugin) helped a lot.You can read it.
https://github.com/gustavohenrique/jenkins-plugins/tree/master/rootaction-example-plugin

Add the <l:main-panel> tag and the the <l:layout norefresh="true">tag to the index.jelly file.
And include the side panel:
Pass the the build to Action (through a parameter of the constructor)
The build can be retrieved out of the parameters of the perform method which is inherited from the BuildStepCompatibilityLayer class (by Extending Publisher).
Create a getBuild() method in the Action class
Add the <st:include it="${it.build}" page="sidepanel.jelly" /> tag with the build
Jelly Example (index.jelly):
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt" xmlns:p="/lib/hudson/project">
<l:layout norefresh="true">
<st:include it="${it.build}" page="sidepanel.jelly" />
<l:main-panel>
<f:validateButton title="${%Restart Jenkins}" progress="${%Restarting...}" method="JksRestart" with="" />
</l:main-panel>
</l:layout>
</j:jelly>
Java Action class example:
package tryPublisher.tryPublisher;
import hudson.model.Action;
import hudson.model.AbstractBuild;
public class ExampleAction implements Action {
AbstractBuild<?,?> build;
public ExampleAction(AbstractBuild<?,?> build) {
this.build = build;
}
#Override
public String getIconFileName() {
return "/plugin/action.png";
}
#Override
public String getDisplayName() {
return "ExampleAction";
}
#Override
public String getUrlName() {
return "ExampleActionUrl";
}
public AbstractBuild<?,?> getBuild() {
return this.build;
}
}
Java Publisher class example:
package tryPublisher.tryPublisher;
import java.io.IOException;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Publisher;
public class ExamplePublisher extends Publisher {
#Override
public BuildStepMonitor getRequiredMonitorService() {
return BuildStepMonitor.NONE;
}
#Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,
BuildListener listener) throws InterruptedException, IOException {
build.getActions().add(new ExampleAction(build));
return true;
}
}
The .jelly file has to be in the right resources map of the plugin project. In a map with the same name as the name of the Java class implementing Action. The name of the .jelly is important also.

Related

I want to create a plugin using biometric authentication (Biometric) provided by Google and implement it in Unity

I would like to implement biometric authentication using the biometrics provided by Googole, but I am having trouble getting it to work.
The following is a reference site on biometrics.
https://developer.android.com/jetpack/androidx/releases/biometric
I've never made an Android plugin before, and I'm having a hard time finding information on how to integrate with Unity.
I'm testing it with the following code
java.lang.NoClassDefFoundError: Failed resolution of: Landroidx/activity/ComponentActivity;
java.lang.ClassNotFoundException: androidx.activity.ComponentActivity
I'm getting an error and don't know how to fix it.
Please help me. Please help me.
◇MainActivity.java
package com.example.biometricslibs;
import android.content.Context;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.biometric.BiometricPrompt;
import androidx.fragment.app.FragmentActivity;
import java.util.concurrent.Executor;
public class MainActivity {
public static MainActivity instance() {
return new MainActivity();
}
private Executor executor = new MainThreadExecutor();
private BiometricPrompt biometricPrompt;
private BiometricPrompt.AuthenticationCallback callback = new BiometricPrompt.AuthenticationCallback() {
#Override
public void onAuthenticationError(int errorCode, #NonNull CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
if (errorCode == 13 && biometricPrompt != null)
biometricPrompt.cancelAuthentication();
}
#Override
public void onAuthenticationSucceeded(#NonNull BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
}
#Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
}
};
public void BiometricCheck(Context context) {
Toast.makeText(context, "call", Toast.LENGTH_SHORT).show();
biometricPrompt = new BiometricPrompt((FragmentActivity) context, executor, callback);
BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder()
.setTitle("title")
.setSubtitle("subTitle")
.setDescription("description")
.setNegativeButtonText("cancel")
.build();
biometricPrompt.authenticate(promptInfo);
}
}
◇MainThreadExecutor.java
package com.example.biometricslibs;
import android.os.Handler;
import android.os.Looper;
import java.util.concurrent.Executor;
public class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
#Override
public void execute(Runnable r) {
handler.post(r);
}
}
◇UnityC#
using(var nativeDialog = new AndroidJavaClass("com.example.biometricslibs.MainActivity"))
{
using(var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
using(var currentUnityActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
{
using(var instance = nativeDialog.CallStatic<AndroidJavaObject>("instance"))
{
instance.Call(
"BiometricCheck",
currentUnityActivity
);
}
}
}
}

Javafx: Can't import custom control into Scene Builder

I tried to import my gui control (jar file) into the scene builder but without success. The file was created using eclipse export -> jar. When it was selected in scene builder "import JAR/FXML File", there was nothing inside the Import Dialog.
My control is a TextField with TextFormatter:
import java.text.NumberFormat;
import java.text.ParseException;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.util.StringConverter;
public class CustomTextField extends TextField {
public CustomTextField() {
setText("Custom");
NumberTextFormatter formatter = new NumberTextFormatter(new StringConverter<Number>() {
#Override
public String toString(Number object) {
return object.toString();
}
#Override
public Number fromString(String string) {
try {
return NumberFormat.getInstance().parse(string);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
});
setTextFormatter(formatter);
}
public static class NumberTextFormatter extends TextFormatter<Number> {
public NumberTextFormatter(StringConverter<Number> valueConverter) {
super(valueConverter);
}
}
}
I am sure that the culprit is the usage of TextFormatter. Because the control will works (appear in Import Dialog) if I removed the TextFormatter from the codes.
Whats wrong?
Update: Even if I simplified my constructor to exclude setTextFormatter(), as long as it still have a line of TextFormatter declaration the problem still persist. Such as:
public CustomTextField() {
setText("Custom");
TextFormatter<Integer> formatter = new TextFormatter<Integer>(new IntegerStringConverter());
}
Found the solution. The oracle scene builder 2.0 is too old/ too dumb to work with TextFormatter. Need to upgrade to Gluon scene builder 8.5.0.

Costum Event Handling

I issue I am trying to get rid off is the following:
I intend to setup a costum event handling chain as a workaround for JavaFX's lack of actioncommands.
The issue in particular is, that a menuitem upon clicking it, still fires an ActionEvent instead of the self-written MilvaLabActionEvent.
The code:
Event class
package jpt.gui.items;
import javafx.event.ActionEvent;
public class MilvaLabActionEvent extends ActionEvent {
private static final long serialVersionUID = 6757067652205246280L;
private String actionCommand ="";
public MilvaLabActionEvent(String actionCommand2) {
setActionCommand(actionCommand2);
}
public MilvaLabActionEvent() {}
public String getActionCommand() {
return actionCommand;
}
public void setActionCommand(String actioncommand) {
this.actionCommand = actioncommand;
}
}
My EventHandler:
package jpt.gui.items;
import javafx.event.EventHandler;
import jpt.MilvaLabGlobal;
import jpt.MilvaLabKonst;
import jpt.handle.MilvaLabDateiHandle;
import jpt.handle.MilvaLabEinHandle;
import jpt.handle.MilvaLabHilfeHandle;
import jpt.handle.MilvaLabMilvaHandle;
import jpt.handle.MilvaLabRvAnwendungHandle;
import jpt.handle.MilvaLabrvTextHandle;
import jpt.log4j.MilvaLabLogger;
public class MilvaLabEventHandler implements EventHandler<MilvaLabActionEvent>{
#Override
public void handle(MilvaLabActionEvent event) {
// the command string of the menu item
final String sCmd = event.getActionCommand();
if (sCmd.charAt(0) == 'M')
{//doing something here
}
}
The costum MenuItem-Class I figured out I gotta write.
package jpt.gui.items;
import javafx.event.Event;
import javafx.scene.control.MenuItem;
public class MilvaLabMenuItem extends MenuItem {
private String actionCommand;
public MilvaLabMenuItem(String sText) {
this.setText(sText);
}
#Override
public void fire() {
Event.fireEvent(this, new MilvaLabActionEvent(getActionCommand()));
}
public String getActionCommand() {
return actionCommand;
}
public void setActionCommand(String actionCommand) {
this.actionCommand = actionCommand;
}
}
And the initialization of the costum MenuItem:
final MilvaLabMenuItem jmi = new MilvaLabMenuItem("I am a menuItem");
jmi.addEventHandler(evtype, new MilvaLabEventHandler());
jmi.setOnAction((event) -> {
System.out.print("I have fired an ActionEvent!");
});
Well, as of now, I got "I have fired an ActionEvent" when I click on the MilvaLabMenuItem, nothing else happens. (Looked into that thing already using the debugger).
What I want to happen is that, obviously, the MilvaLabEventHandler is called.
I figured it out again.
I declared two EventTypes, though, only one was necessary.
This helped me finding the solution, though, they use Nodes instead of MenuItems.
How to emit and handle custom events?

Getting user data in NewProjectCreationPage in Eclipse Plugin

I have been successful in making a plugin. However now i need that on project creation page i add some more textboxes to get the user information. Also i need to use this information to add into the auto generated .php files made in project directory.
I want to know how can i override the WizardNewProjectCreationPage to add some more textboxes to the already given layout. I am pretty new to plugin development. Here is the code for my custom wizard.
import java.net.URI;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExecutableExtension;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard;
import rudraxplugin.pages.MyPageOne;
import rudraxplugin.projects.RudraxSupport;
public class CustomProjectNewWizard extends Wizard implements INewWizard, IExecutableExtension {
private WizardNewProjectCreationPage _pageOne;
protected MyPageOne one;
private IConfigurationElement _configurationElement;
public CustomProjectNewWizard() {
// TODO Auto-generated constructor stub
setWindowTitle("RudraX");
}
#Override
public void init(IWorkbench workbench, IStructuredSelection selection) {
// TODO Auto-generated method stub
}
#Override
public void addPages() {
super.addPages();
_pageOne = new WizardNewProjectCreationPage("From Scratch Project Wizard");
_pageOne.setTitle("From Scratch Project");
_pageOne.setDescription("Create something from scratch.");
addPage(one);
addPage(_pageOne);
}
#Override
public boolean performFinish() {
String name = _pageOne.getProjectName();
URI location = null;
if (!_pageOne.useDefaults()) {
location = _pageOne.getLocationURI();
System.err.println("location: " + location.toString()); //$NON-NLS-1$
} // else location == null
RudraxSupport.createProject(name, location);
// Add this
BasicNewProjectResourceWizard.updatePerspective(_configurationElement);
return true;
}
#Override
public void setInitializationData(IConfigurationElement config,
String propertyName, Object data) throws CoreException {
_configurationElement = config;
// TODO Auto-generated method stub
}
}
Ask for any other code required. Any help is appreciated. Thank You.
Instead of using WizardNewProjectCreationPage directly create a new class extending WizardNewProjectCreationPage and override the createControl method to create new controls:
class MyNewProjectCreationPage extends WizardNewProjectCreationPage
{
#Override
public void createControl(Composite parent)
{
super.createControl(parent);
Composite body = (Composite)getControl();
... create new controls here
}
}

Reusable Liferay (6.0.6) service

I am trying to implement resuable Custom Services without using ext and servicebuilder.
I referred this article: http://www.devatwork.nl/2010/04/implementing-a-reusable-liferay-service-without-ext-or-service-builder/ , but I am confused in how should I implement this using eclipse? Following are the steps that I followed to do this:
- Created liferay-plugin project within eclipse.
- Created package containing CustomServices (interface) and CustomServicesUtil.
- Created jar file of package in step 2.
- Placed that jar file in tomcat\lib\ext\
- Then created package (with in same liferay-plugin project), that includes CutomServicesImpl and CustomServicesBaseImpl
- Defined portlet-spring.xml, service.properties, and modified web.xml (as per the article), and finally deployed the project.
On deployment, project is deployed successfully, but when I am trying to use customMethods defined in CustomServicesImpl through CustomServicesUtil.getCustomMethod(), I am getting the following error:
"java.lang.ClassNotFoundException: com.demo.custom.services.CustomServicesUtil"
I configure build path to include customservices.jar file but its not working out, still showing the same error. I don’t know whether this is the correct way to implement resuable services or not. I tried this so that i can make use of custom method in one of my project.
Here is the code for custom services:
CustomServices.java
package com.demo.custom.services;
import com.liferay.portal.model.User;
public interface CustomServices {
String getCustomName(User user);
}
CustomServicesUtil.java
package com.demo.custom.services;
import com.liferay.portal.model.User;
public class CustomServicesUtil {
private static CustomServices services;
public static CustomServices getServices() {
if (services == null) {
throw new RuntimeException("Custom Services not set");
}
return services;
}
public void setServices(CustomServices pServices) {
services = pServices;
}
public static String getCustomName(User user){
return getServices().getCustomName(user);
}
}
CustomServicesBaseImpl.java
package com.demo.custom.services.impl;
import com.demo.custom.services.CustomServices;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.service.base.PrincipalBean;
import com.liferay.portal.util.PortalUtil;
public abstract class CustomServicesBaseImpl extends PrincipalBean implements CustomServices {
protected CustomServices services;
public CustomServices getServices() {
return services;
}
public void setServices(CustomServices pServices) {
this.services = pServices;
}
protected void runSQL(String sql) throws SystemException {
try {
PortalUtil.runSQL(sql);
} catch (Exception e) {
throw new SystemException(e);
}
}
}
CustomServicesImpl.java
package com.demo.custom.services.impl;
import com.liferay.portal.model.User;
public class CustomServicesImpl extends CustomServicesBaseImpl {
#Override
public String getCustomName(User user) {
// TODO Auto-generated method stub
if(user == null){
return null;
}else{
return new StringBuffer().append(user.getFirstName()).append(" ").append(user.getLastName()).toString();
}
}
}
Here is the code of controller class of my another portlet, where i am making use of this service.
HelloCustomName.java
package com.test;
import java.io.IOException;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import com.demo.custom.services.CustomServicesUtil;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.model.User;
import com.liferay.portal.theme.ThemeDisplay;
import com.liferay.util.bridges.mvc.MVCPortlet;
public class HelloCustomName extends MVCPortlet {
#Override
public void doView(RenderRequest renderRequest,
RenderResponse renderResponse) throws IOException, PortletException {
System.out.println("--doview----");
ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(WebKeys.THEME_DISPLAY);
User user = themeDisplay.getUser();
String customName = CustomServicesUtil.getCustomName(user); //getting error here
System.out.println("customName:" + customName);
}
}
Please point me on how to implement resuable services? Any guidance will be really useful.
Thanks.
My mind, you don't need the complexity of services. Simply make utility classes and put this in to tomcat/lib/ext. Be sure that tomcat/lib/ext is correct configured in tomcat/conf/catalina.properties, something like this:
common.loader=${catalina.home}/lib/ext/*.jar