How to implement security in Spring Cloud API Gateway with Key Cloak for Multi-tenant Application - keycloak

I'm working on a project in which there is a requirement to convert single tenant application to multi tenant application. How to implement Multi-tenant support for Gateway using key cloak with spring security oauth2?
Any references please share

Use ReactiveClientRegistrationRepository to register your clients dynamically at runtime. You can then plug this implementation to a custom Webfilter, which will use your custom repository to compute the client details based on the logged in user's realm(which can be the hostname, email etc.)
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import reactor.core.publisher.Mono;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrations;
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.stereotype.Component;
#Component
public class TenantClientRegistrationRepository implements ReactiveClientRegistrationRepository {
private final Map<String, String> tenants = new HashMap<>();
private final Map<String, Mono<ClientRegistration>> clients = new HashMap<>();
public TenantClientRegistrationRepository() {
this.tenants.put("tenant1", "http://localhost:8080/realms/tenant1");
this.tenants.put("tenant2", "http://localhost:8080/realms/tenant2");
}
#Override
public Mono<ClientRegistration> findByRegistrationId(String registrationId) {
return this.clients.computeIfAbsent(registrationId, this::fromTenant);
}
private Mono<ClientRegistration> fromTenant(String registrationId) {
return Optional.ofNullable(this.tenants.get(registrationId))
.map(uri -> Mono.defer(() -> clientRegistration(uri, registrationId)).cache())
.orElse(Mono.error(new IllegalArgumentException("unknown tenant")));
}
private Mono<ClientRegistration> clientRegistration(String uri, String registrationId) {
return Mono.just(ClientRegistrations.fromIssuerLocation(uri)
.registrationId(registrationId)
.clientId("web-client")//fetch client creds via rest or some other means
.clientSecret("********")
.scope("openid")
.build());
}
#KafkaListener(topics="tenants")
//TODO: Here we will populate tenants(realm) and respective client details based on tenant creation event
public void action(Map<String, Map<String, Object>> action) {
if (action.containsKey("created")) {
Map<String, Object> tenant = action.get("created");
String alias = (String) tenant.get("alias");
String issuerUri = (String) tenant.get("issuerUri");
this.tenants.put(alias, issuerUri);
this.clients.remove(alias);
}
}
}
import static org.springframework.security.config.Customizer.withDefaults;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth2.client.oidc.web.server.logout.OidcClientInitiatedServerLogoutSuccessHandler;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
import org.springframework.security.web.server.WebFilterChainProxy;
import org.springframework.security.web.server.authentication.RedirectServerAuthenticationEntryPoint;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;
import reactor.util.context.Context;
public class TenantFilterChain implements WebFilter, ApplicationContextAware {
private final Map<String, Mono<WebFilter>> tenants = new HashMap<>();
private final ReactiveClientRegistrationRepository clients;
private ApplicationContext context;
public TenantFilterChain(ReactiveClientRegistrationRepository clients) {
this.clients = clients;
}
#Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
Mono<ClientRegistration> tenant = toTenant(exchange);
Mono<WebFilter> filter = tenant.flatMap(this::fromTenant);
return Mono.zip(tenant, filter)
.flatMap(tuple -> tuple.getT2().filter(exchange, chain)
.contextWrite(Context.of(ClientRegistration.class, tuple.getT1()))
.thenReturn(exchange))
.switchIfEmpty(chain.filter(exchange).thenReturn(exchange))
.then(Mono.empty());
}
private Mono<ClientRegistration> toTenant(ServerWebExchange exchange) {
String host = UriComponentsBuilder.fromUri(exchange.getRequest().getURI())
.build().getHost();
return this.clients.findByRegistrationId(host);
}
private Mono<WebFilter> fromTenant(ClientRegistration registration) {
return this.tenants.computeIfAbsent(registration.getRegistrationId(), tenant -> {
ServerHttpSecurity http = new ContextAwareServerHttpSecurity(this.context);
OidcClientInitiatedServerLogoutSuccessHandler handler =
new OidcClientInitiatedServerLogoutSuccessHandler(this.clients);
handler.setPostLogoutRedirectUri("http://localhost:8282");
ServerAuthenticationEntryPoint entryPoint =
new RedirectServerAuthenticationEntryPoint("/oauth2/authorization/" + tenant);
// #formatter:off
http
.authorizeExchange(e -> e
.pathMatchers("/jwks").permitAll()
.anyExchange().authenticated())
.logout(l -> l.logoutSuccessHandler(handler))
.oauth2Login(withDefaults())
.exceptionHandling(e -> e.authenticationEntryPoint(entryPoint));
// #formatter:on
return Mono.just((WebFilter) new WebFilterChainProxy(http.build())).cache();
});
}
#Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
this.context = context;
}
private static class ContextAwareServerHttpSecurity extends ServerHttpSecurity {
ContextAwareServerHttpSecurity(ApplicationContext context) {
super.setApplicationContext(context);
}
}
}
Referenced codebase
Talk by Josh Cummings on multitenancy with spring security OAuth2
Hope this helps !! :)

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
);
}
}
}
}

Showing contact from the contact loader Manager

I am showing the contact list from the contact table but not able to get the phone number using the same on RecyclerView.My code is -
package com.oodles.oodlesapprtc;
import android.annotation.SuppressLint;
import android.app.LoaderManager;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import java.util.ArrayList;
/**
* Created by ankita on 13/4/17.
*/
public class LoginUserActivity extends AppCompatActivity {
public static final int CONTACT_LOADER_ID = 78;
RecyclerView loginUserRecycler;
ArrayList<ContactBeans> contactBeanses;
String sortOrder = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME +
" COLLATE LOCALIZED ASC";
private static final String[] PROJECTION2 = {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY, ContactsContract.Contacts.PHOTO_URI,ContactsContract.Contacts.HAS_PHONE_NUMBER
};
private static final String[] PROJECTION3 = {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY, ContactsContract.Contacts.PHOTO_URI, ContactsContract.Contacts.LOOKUP_KEY
};
private static final String[] PROJECTION = {
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY, ContactsContract.CommonDataKinds.Phone.NUMBER
};
// private static final String[] PROJECTION1 = {
// ContactsContract.Data.CONTACT_ID, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY,
// ContactsContract.CommonDataKinds.Phone.NUMBER
// };
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_user_activity);
initViews();
}
private void initViews() {
getLoaderManager().initLoader(0, null, contactLoaderManager);
initRecycler();
}
private void initRecycler() {
loginUserRecycler = (RecyclerView) findViewById(R.id.loginUserRecycler);
loginUserRecycler.setLayoutManager(new LinearLayoutManager(this));
loginUserRecycler.setItemAnimator(new DefaultItemAnimator());
}
LoaderManager.LoaderCallbacks<Cursor> contactLoaderManager = new LoaderManager.LoaderCallbacks<Cursor>() {
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// String[] projectionFields = new String[]{ContactsContract.Contacts._ID,
// ContactsContract.Contacts.DISPLAY_NAME,ContactsContract.PhoneLookup.NORMALIZED_NUMBER,
// ContactsContract.Contacts.PHOTO_URI};
// Construct the loader
// Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
// ContactsContract.Contacts.CONTENT_URI
// Uri lookupUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
// Uri.encode(phoneNumber));
CursorLoader cursorLoader = new CursorLoader(LoginUserActivity.this,
ContactsContract.Contacts.CONTENT_URI, // URI
PROJECTION2, // projection fields
null, // the selection criteria
null, // the selection args
sortOrder // the sort order
);
return cursorLoader;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
loginUserRecycler.setAdapter(new CursorRecyclerAdapter(LoginUserActivity.this, data));
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
}
};
}
My Adapter is -
package com.oodles.oodlesapprtc;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* Created by ankita on 13/4/17.
*/
public class CursorRecyclerAdapter extends RecyclerView.Adapter<ContactViewHolder> {
private Cursor mCursor;
private final int mNameColIdx,
mIdColIdx;
int phoneNumber;
int hasPhoneNumber;
private Context mContext;
public CursorRecyclerAdapter(Context context, Cursor cursor) {
mCursor = cursor;
this.mContext = context;
mNameColIdx = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY);
mIdColIdx = cursor.getColumnIndex(ContactsContract.Contacts._ID);
hasPhoneNumber = cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER);
}
#Override
public ContactViewHolder onCreateViewHolder(ViewGroup parent, int pos) {
View listItemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.contact_row, parent, false);
return new ContactViewHolder(listItemView);
}
#Override
public void onBindViewHolder(ContactViewHolder contactViewHolder, int pos) {
mCursor.moveToPosition(pos);
String contactName = mCursor.getString(mNameColIdx);
long contactId = mCursor.getLong(mIdColIdx);
Contact c = new Contact();
Log.e("ddhdhdhhdhdhdhd",hasPhoneNumber+"");
c.name = contactName;
c.number = getPhoneNumberFromContactId(contactId);
c.profilePic = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
getPhoneNumberFromContactId(contactId);
contactViewHolder.bind(c);
}
private String getPhoneNumberFromContactId(long contactId) {
String contactNumber = "8874675724";
return contactNumber;
}
#Override
public int getItemCount() {
return mCursor.getCount();
}
}
How can I get the phone number for the same i am getting a cursorindexoutofbound exception and has phone number value as 3 but it can be only 0 or 1 why it is 3 i don't understand this.
Can Anyone please explain this to me also please explain how the contact fetch works
You have a few issues in the code:
You're querying on the Contacts table, but sorting using a CommonDataKinds.Phone table field, that's not good, you can sort using Contacts.DISPLAY_NAME_PRIMARY instead.
cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER) gives you a column index, not the value of the field, that's why you're getting 3 (it's the 4rd field defined in PROJECTION2), change hasPhoneNumber to mHasPhoneNumberIdx to avoid confusion.
add hasPhoneNumber = mCursor.getInt(mHasPhoneNumberIdx); to your onBindViewHolder method, to get the actual value.
Running a long command like a real implementation of getPhoneNumberFromContactId within onBindViewHolder is really bad... you should change your main query so you do two big queries, one for all contacts, one for all phones, and then use some HashMap to get a phone using a contact-id.

Eclipse 4 RCP - application does not have active window

I want to have some helper functions for manipulating UI.
I don't want to pass to them any parameters except what is necessary by my domain model (i don't want to pass EModelService, EPartService etc.)
Question: The problem is i am getting exception application does not have active window.
I found where the problem is.
It happend because i am manipulating parts via EPartService accessed from the application context IWorkbench.getApplication().getContext().get(EPartService.class).
THIS IS IMPORTANT: Currently i am getting that exception when i am trying to modify my UI AFTER i read inputs from dialog. Pleas note that the error does not happened when i am trying to modify the UI just BEFORE i
opened the dialog. Look at the code, i added some comments.
NewFromDirectoryDialog.java
package cz.vutbr.fit.xhriba01.bc.handlers;
import javax.inject.Named;
import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.services.IServiceConstants;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Shell;
import cz.vutbr.fit.xhriba01.bc.BcModel;
import cz.vutbr.fit.xhriba01.bc.resolvers.filesystem.FileSystemResolver;
import cz.vutbr.fit.xhriba01.bc.ui.dialogs.NewFromDirectoryDialog;
import cz.vutbr.fit.xhriba01.bc.ui.UI;
public class NewFromDirectoryHandler {
#Execute
public void execute(MApplication application, EPartService partService, #Named(IServiceConstants.ACTIVE_SHELL) Shell shell) {
FileSystemResolver fsr = new FileSystemResolver("/home/jara/git/cz.vutbr.fit.xhriba01.bc/bc/src",
"/home/jara/git/cz.vutbr.fit.xhriba01.bc/bc/bin");
BcModel.setResolver(fsr);
// THIS CALL IS OK AND EVERYTHING WORKS
UI.changeExplorerView("bc.partdescriptor.filesystemview", fsr);
NewFromDirectoryDialog dialog = new NewFromDirectoryDialog(shell);
dialog.create();
if (dialog.open() == Window.OK) {
String sourceDir = dialog.getSourceDir();
String classDir = dialog.getClassDir();
FileSystemResolver fsr = new FileSystemResolver(classDir, sourceDir);
//THIS CALL LEADS TO EXCEPTION: application does not have active window
UI.changeExplorerView("bc.partdescriptor.filesystemview", fsr);
}
}
}
That EPartService from application context is based on org.eclipse.e4.ui.internal.workbench.ApplicationPartServiceImpl
and not on org.eclipse.e4.ui.internal.workbench.PartServiceImpl
as EPartService instance you get when injected to #PostConstruct annotated method on Part's view.
org.eclipse.e4.ui.internal.workbench.ApplicationPartServiceImpl (not entire source code)
You can see that the error probably happened because at the time ApplicationPartServiceImpl.createPart is called in my UI.changeExplorerView, the Eclipse runtime does not know what window
is currently active.
package org.eclipse.e4.ui.internal.workbench;
import java.util.Collection;
import javax.inject.Inject;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
import org.eclipse.e4.ui.model.application.ui.basic.MInputPart;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.e4.ui.workbench.modeling.IPartListener;
public class ApplicationPartServiceImpl implements EPartService {
private MApplication application;
#Inject
ApplicationPartServiceImpl(MApplication application) {
this.application = application;
}
private EPartService getActiveWindowService() {
IEclipseContext activeWindowContext = application.getContext().getActiveChild();
if (activeWindowContext == null) {
throw new IllegalStateException("Application does not have an active window"); //$NON-NLS-1$
}
EPartService activeWindowPartService = activeWindowContext.get(EPartService.class);
if (activeWindowPartService == null) {
throw new IllegalStateException("Active window context is invalid"); //$NON-NLS-1$
}
if (activeWindowPartService == this) {
throw new IllegalStateException("Application does not have an active window"); //$NON-NLS-1$
}
return activeWindowPartService;
}
#Override
public MPart createPart(String id) {
return getActiveWindowService().createPart(id);
}
}
LifeCycleManager.java (how i initialize the UI helper class)
You can see i am injecting IWorkbench to my UI class.
IWorkbench allows me to access MApplication, so that is all i should
need to modify app UI.
package cz.vutbr.fit.xhriba01.bc;
import javax.inject.Inject;
import org.eclipse.e4.core.contexts.ContextInjectionFactory;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.ui.di.UIEventTopic;
import org.eclipse.e4.ui.workbench.IWorkbench;
import org.eclipse.e4.ui.workbench.UIEvents;
import cz.vutbr.fit.xhriba01.bc.ui.UI;
public class LifeCycleManager {
#Inject
#Optional
private void appCompleted(#UIEventTopic(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE) Object event, IWorkbench workbench) {
ContextInjectionFactory.inject(UI.getDefault(), workbench.getApplication().getContext());
}
}
UI.java
package cz.vutbr.fit.xhriba01.bc.ui;
import javax.inject.Inject;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
import org.eclipse.e4.ui.workbench.IWorkbench;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.e4.ui.workbench.modeling.EPartService.PartState;
import org.eclipse.jface.text.IDocument;
import cz.vutbr.fit.xhriba01.bc.BcModel;
import cz.vutbr.fit.xhriba01.bc.resolvers.ISourceAndClassResolver;
public class UI {
public static final String PART_EXPLORER_ID = "bc.part.inspector";
public static final String PART_EXPLORER_CONTAINER_ID = "bc.partstack.explorer_stack";
public static final String PART_JAVA_SOURCE_VIEWER_ID = "bc.part.javasourceview";
private static UI fInstance = new UI();
#Inject
private IWorkbench fWorkbench;
private UI() {
}
public static void changeExplorerView(String partDescriptorId, ISourceAndClassResolver resolver) {
EModelService modelService = fInstance.fWorkbench.getApplication().getContext().get(EModelService.class);
EPartService partService = fInstance.fWorkbench.getApplication().getContext().get(EPartService.class);
MApplication application = fInstance.fWorkbench.getApplication();
MPart part = partService.createPart(partDescriptorId);
MPart oldPart = partService.findPart(UI.PART_EXPLORER_ID);
MPartStack partStack = (MPartStack) modelService.find(UI.PART_EXPLORER_CONTAINER_ID, application);
partStack.setVisible(true);
if (oldPart != null) {
partService.hidePart(oldPart);
}
part.setElementId(UI.PART_EXPLORER_ID);
partStack.getChildren().add(part);
BcModel.setResolver(resolver);
partService.showPart(part, PartState.VISIBLE);
}
public static UI getDefault() {
return fInstance;
}
public static void setJavaSourceLabel(String label, EPartService partService) {
MPart part = partService.findPart(UI.PART_JAVA_SOURCE_VIEWER_ID);
if (part != null) {
part.setLabel(label);
}
}
public static void setJavaSourceText(String source) {
IDocument document = BcModel.getJavaDocument();
if (document != null) {
document.set(source);
}
}
}
I think the problem is when i open the dialog, the activeChild changes somehow to that new opened dialog and when i close it and try immediately change my UI, it does not work because the activeChild is still not properly setup back. Otherweise i don't know why it works fine just before i opened the dialog and doesn't work just after the dialog is closed.
Does anyone know if it is bug?

Not able to store value getting from Transliteration using GWT

I am new to GWT and I want to make a application in which words are transliterate and store in a varible.which can be used for storing values in database.
But when I am trying to store in variable it gives null value when am printing it.
package com.google.gwt.language.sample.hellolanguage.client;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.language.client.transliteration.LanguageCode;
import com.google.gwt.language.client.transliteration.SupportedDestinationLanguages;
import com.google.gwt.language.client.transliteration.control.TransliterationControl;
import com.google.gwt.language.client.transliteration.control.TransliterationControlOptions;
import com.google.gwt.language.client.transliteration.text.Transliteration;
import com.google.gwt.language.client.transliteration.text.TransliterationCallback;
import com.google.gwt.language.client.transliteration.text.TransliterationResult;
import com.google.gwt.user.client.ui.Composite;
public class Trans extends Composite {
ArrayList<String> wordsArray= new ArrayList<String>();
public String sss;
public void recieve(String ss)
{
this.sss=ss;
System.out.println(sss);
}
public String send(){
return sss;
}
public Trans(ArrayList<String> str) {
initTransliterationControls(str);
//Here I want to print
System.out.println(sss);
}
public void initTransliterationControls(ArrayList<String> wordsArray1) {
//ArrayList<String> wordsArray= new ArrayList<String>();
// wordsArray=wordsArray1;
//System.out.println(wordsArray1.size());
// for(int i=0;i<wordsArray1.size();i++)
//{
//wordsArray.add(wordsArray1.get(i).toString());
//}
wordsArray.add(wordsArray1.get(0).toString());
wordsArray.add("Rerrebok");
wordsArray.add("Woodland j_74_Hi-gh Heels Boots");
//System.out.println(wordsArray);
Transliteration.transliterate(wordsArray, LanguageCode.ENGLISH,
LanguageCode.HINDI, new TransliterationCallback() {
#Override
public void onCallback(TransliterationResult result) {
// System.out.println(result.getTransliterations().toString());
List<List<String>> collection= new ArrayList<List<String>>();
collection=result.getTransliterations();
// Here I am storing it on sss but when I am print outside this function it gives Null
sss=collection.get(0).get(0).toString();
}
});
}
}

Control Netbeans from Commandline: attach Debugger from Shell-script

I'm using a daemon-script which is monitoring a remote server. When the remote server is up, i want that Netbeans automatically connects it's Debugger to the remote Server.
Is it possible to control this behavior from commandline?
To type Something like
netbeans --attach-debugger 192.168.178.34:9009
inside a terminal to do that? Or what other ways do i have to get access to Netbeans-internal stuff? (until now, i was just a "user" of Netbeans so i don't know the internals and how to access them very well)
Or will i have to write a Netbeans Plugin to do that? If yes, can you give me a good starting point to add that functionality?
Ok since there is no option to attach the Debugger from commandline, i wrote a Netbeans Plugin with the help of this blog entry and this thread from the NB-mailinglist. Now i'm able to call my plugin actions from the Commandline.
So build a simple NetBeans Module, which contains 2 important classes.
This is the class which gets the commandline parameters and forwards them to my Action:
import java.awt.event.ActionEvent;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import javax.swing.Action;
import org.netbeans.api.sendopts.CommandException;
import org.netbeans.spi.sendopts.Env;
import org.netbeans.spi.sendopts.OptionProcessor;
import org.netbeans.spi.sendopts.Option;
import org.openide.ErrorManager;
import org.openide.cookies.InstanceCookie;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataObject;
import org.openide.util.lookup.ServiceProvider;
import org.openide.windows.WindowManager;
#ServiceProvider(service = OptionProcessor.class)
public class TriggerActionCommandLine extends OptionProcessor {
//Here we specify "runAction" as the new key in the command,
//but it could be any other string you like, of course:
private static Option action = Option.requiredArgument(Option.NO_SHORT_NAME, "debug");
private static final Logger logger = Logger.getLogger(AttachDebugger.class.getName());
#Override
public Set<org.netbeans.spi.sendopts.Option> getOptions() {
return Collections.singleton(action);
}
#Override
protected void process(Env env, Map<Option, String[]> values) throws CommandException {
final String[] args = (String[]) values.get(action);
if (args.length > 0) {
//Set the value to be the first argument from the command line,
//i.e., this is "GreetAction", for example:
final String ip = args[0];
//Wait until the UI is constructed,
//otherwise you will fail to retrieve your action:
WindowManager.getDefault().invokeWhenUIReady(new Runnable() {
#Override
public void run() {
//Then find & perform the action:
Action a = findAction(AttachDebugger.ACTION_NAME);
// forward IP address to Action
ActionEvent e = new ActionEvent(this, 1, ip);
a.actionPerformed(e);
}
});
}
}
public Action findAction(String actionName) {
FileObject myActionsFolder = FileUtil.getConfigFile("Actions/PSFActions");
FileObject[] myActionsFolderKids = myActionsFolder.getChildren();
for (FileObject fileObject : myActionsFolderKids) {
logger.info(fileObject.getName());
//Probably want to make this more robust,
//but the point is that here we find a particular Action:
if (fileObject.getName().contains(actionName)) {
try {
DataObject dob = DataObject.find(fileObject);
InstanceCookie ic = dob.getLookup().lookup(InstanceCookie.class);
if (ic != null) {
Object instance = ic.instanceCreate();
if (instance instanceof Action) {
Action a = (Action) instance;
return a;
}
}
} catch (Exception e) {
ErrorManager.getDefault().notify(ErrorManager.WARNING, e);
return null;
}
}
}
return null;
}
}
This is my Plugin Action which attaches the Debugger to the given remote address:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.api.debugger.jpda.DebuggerStartException;
import org.netbeans.api.debugger.jpda.JPDADebugger;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.awt.ActionRegistration;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences;
import org.openide.awt.ActionID;
import org.python.util.PythonInterpreter;
#ActionID(category = "PSFActions", id = "de.mackaz.AttachDebugger")
#ActionRegistration(displayName = "#CTL_AttachDebuggerAction")
#ActionReferences({
#ActionReference(path = "Menu/Tools", position = 1800, separatorBefore = 1750, separatorAfter = 1850)
})
public final class AttachDebugger implements ActionListener {
private static final Logger logger = Logger.getLogger(AttachDebugger.class.getName());
public static final String ACTION_NAME="AttachDebugger";
#Override
public void actionPerformed(ActionEvent e) {
String ip;
if (!e.getActionCommand().contains("Attach Debugger")) {
ip = e.getActionCommand();
} else {
ip = lookupIP();
}
try {
logger.log(Level.INFO, "Attaching Debugger to IP {0}", ip);
JPDADebugger.attach(
ip,
9009,
new Object[]{null});
} catch (DebuggerStartException ex) {
int msgType = NotifyDescriptor.ERROR_MESSAGE;
String msg = "Failed to connect debugger to remote IP " + ip;
NotifyDescriptor errorDescriptor = new NotifyDescriptor.Message(msg, msgType);
DialogDisplayer.getDefault().notify(errorDescriptor);
}
}
}
Now i can attach the Netbeans debugger to a specific address by calling netbeans/bin/netbeans --debug 192.168.178.79