i finished my Eclipse RCP Application and wanted to configure the update manager. My Product is feature based and updates are working like they should, but i want to limit the user. i.e. force a special update site or display only grouped etc.
I tried using Policy but it does not work:
public class EPolicy extends Policy {
public EPolicy() {
setRepositoriesVisible(false);
setGroupByCategory(false);
setShowLatestVersionsOnly(false);
setRestartPolicy(RESTART_POLICY_FORCE);
}
}
registering in the Activator:
public void start(BundleContext context) throws Exception {
super.start(context);
Policy policy = new EPolicy();
context.registerService(Policy.class.getName(), policy, null);
}
am i missing something?
Try to set your policy with higher ranking,
public void start(BundleContext context) throws Exception {
super.start(context);
Policy policy = new EPolicy();
Dictionary props = new Hashtable();
props.put(org.osgi.framework.Constants.SERVICE_RANKING, new Integer(99));
context.registerService(Policy.class.getName(), policy, props);
}
Related
I want to keep some information in Keycloak as custom user attributes.
Some of them should be managed by the user itself. Other attributes should be managed only by a Keycloak administrator. Attributes managed by the administrator should be read-only visible in the "Edit account" web page for the user.
I went through the guide to add custom user attributes in this page and customized the "Edit account" web page.
My question is:
Is it ensured that the user cannot change the attribute that is meant as read-only for the user? E.g. by submitting a form where he/she sends correct data that will be automatically mapped on the server side to the user attribute.
For what you've said, it seems that you have three choices.
One would be to keep the keycloak "Edit Account" page and use an update profile listener to check what attributes are stored or which ones are updated by who, something like this:
public class UpdateProfile implements RequiredActionProvider, RequiredActionFactory, DisplayTypeRequiredActionFactory {
#Override
public InitiatedActionSupport initiatedActionSupport() {
return InitiatedActionSupport.SUPPORTED;
}
#Override
public void evaluateTriggers(RequiredActionContext context) {
}
#Override
public void requiredActionChallenge(RequiredActionContext context) {
Response challenge = context.form()
.createResponse(UserModel.RequiredAction.UPDATE_PROFILE);
context.challenge(challenge);
}
// Check the custom attribute 1 not being modified by the user
#Override
public void processAction(RequiredActionContext context) {
EventBuilder event = context.getEvent();
event.event(EventType.UPDATE_PROFILE);
MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
UserModel user = context.getUser();
KeycloakSession session = context.getSession();
RealmModel realm = context.getRealm();
String newYourCustomAttribute1 = formData.getFirst("yourCustomAttribute1");
String oldYourCustomAttribute1 = user.getFirstAttribute("yourCustomAttribute1")
if (!newYourCustomAttribute1.equals(oldYourCustomAttribute1)) {
Response challenge = context.form()
.setError("User cannot change the attribute")
.setFormData(formData)
.createResponse(UserModel.RequiredAction.UPDATE_PROFILE);
context.challenge(challenge);
return;
}
context.success();
}
#Override
public void close() {
}
#Override
public RequiredActionProvider create(KeycloakSession session) {
return this;
}
#Override
public RequiredActionProvider createDisplay(KeycloakSession session, String displayType) {
if (displayType == null) return this;
if (!OAuth2Constants.DISPLAY_CONSOLE.equalsIgnoreCase(displayType)) return null;
return ConsoleUpdateProfile.SINGLETON;
}
#Override
public void init(Config.Scope config) {
}
#Override
public void postInit(KeycloakSessionFactory factory) {
}
#Override
public String getDisplayText() {
return "Update Profile";
}
#Override
public String getId() {
return UserModel.RequiredAction.UPDATE_PROFILE.name();
}
}
What I don't know is if this listener will be called when you update the profile from your client application too. If it gets called, you'll need to check which is the logged in client, if it's the public client do not let update the attributes, if it's your service client, let it.
The second one would be to only let your service client update the user profiles and make a custom view in your application which sends a form POST to your client, instead of to keycloak directly. This way you can validate it in the service before sending it to keycloak.
The third one is to implement a FormAction interface, which would allow you to validate the incoming form at server side:
The core interface you have to implement is the FormAction interface. A FormAction is responsible for rendering and processing a portion of the page. Rendering is done in the buildPage() method, validation is done in the validate() method, post validation operations are done in success().
#Override
public void validate(ValidationContext context) {
MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
UserModel user = context.getUser();
KeycloakSession session = context.getSession();
RealmModel realm = context.getRealm();
String newYourCustomAttribute1 = formData.getFirst("yourCustomAttribute1");
String oldYourCustomAttribute1 = user.getFirstAttribute("yourCustomAttribute1")
if (!newYourCustomAttribute1.equals(oldYourCustomAttribute1)) {
Response challenge = context.form()
.setError("User cannot change the attribute")
.setFormData(formData)
.createResponse(UserModel.RequiredAction.UPDATE_PROFILE);
context.challenge(challenge);
return;
}
context.success();
}
perform an update to version 12.0.4.
There were some issues < 12.0.4 with dropping all attributes if user updates his profile.
Additionally with 12.0.4 you can create user- and admin-read only attributes.
Check documentation: https://www.keycloak.org/docs/latest/server_admin/#_read_only_user_attributes
Cheers
I am trying to programmatically refresh a folder inside the project for my Eclipse plugin. I have also included a simple semaphore rule in the Job. Here is the code:
public class MutexRule implements ISchedulingRule {
public boolean isConflicting(ISchedulingRule rule) {
return rule == this;
}
public boolean contains(ISchedulingRule rule) {
return rule == this;
}
}
...
Job refreshJob = new Job("Refreshing...") {
public void run() {
IResource myFolder = ...
if(myFolder != null)
myFolder.refreshLocal(DEPTH_INFINITE, null);
}
};
refreshJob.setRule(
When I schedule two jobs, and run the refresh, I get the following exception:
Attempted to beginRule: P/test, does not match outer scope rule: ...
What am I missing?
What is a possible solution / workaround?
The error you are getting is because the IResource you are refreshing also has a scheduling rule (IResource implements ISchedulingRule). When there are nested scheduling rules the outer rule must 'contain' the inner rule - your MutexRule doesn't do this.
Because the resource already has a scheduling rule there is no need to set a rule on your job.
refreshLocal does not have to in a Job but if it is run from the UI thread a progress monitor should be provided using IProgressService or similar.
Update: refreshLocal can generate many resource changed events, to minimize these use a WorkspaceModifyOperation or a WorkspaceJob:
Job job = new WorkspaceJob("Refreshing") {
public IStatus runInWorkspace(IProgressMonitor monitor) {
monitor.beginTask("", IProgressMonitor.UNKNOWN);
try {
resource.refreshLocal(monitor);
}
finally {
monitor.done();
}
return Status.OK_STATUS;
}
});
or
WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
#Override
protected void execute(IProgressMonitor monitor) throws CoreException {
resource.refreshLocal(monitor);
}
};
If you are in a wizard page you can run the WorkspaceModifyOperation with:
getContainer().run(true, true, op);
elsewhere you can use:
IProgressService service = PlatformUI.getWorkbench().getProgressService();
service.run(true, true, op);
Even better is to use the Eclipse IFile and IFolder APIs to create files and folders, in this case refreshLocal is not required.
I'm developing an Eclipse 4 RCP application and I need it to do some tasks before it gets visible, then restart.
I'm running an application that checks a P2 repository and automatically updates/installs/uninstalls certain plugins. I want this step to be transparent to the user, so I am running this in the "postContextCreate" method, using the LifeCycleURI property.
Once this is done, I need the application to restart (in order to correctly load the plugins), but I can't inject the workbench here since it's not yet created. I would appreciate any suggestions or ideas.
Thanks in advance!
Probably the earliest you can get the workbench is by subscribing to the application startup complete event UIEvents.UILifeCycle.APP_STARTUP_COMPLETE with the event broker. However this does not fire until just after the UI is displayed.
Update:
The event handler would be something like:
private static final class AppStartupCompleteEventHandler implements EventHandler
{
private final IEclipseContext _context;
AppStartupCompleteEventHandler(final IEclipseContext context)
{
_context = context;
}
#Override
public void handleEvent(final Event event)
{
IWorkbench workbench = _context.get(IWorkbench.class);
workbench.restart();
}
}
Subscribe to this event in the #PostContextCreate method.
#PostContextCreate
public void postContextCreate(IEclipseContext context, IEventBroker eventBroker)
{
eventBroker.subscribe(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE, new AppStartupCompleteEventHandler(context));
}
I often minimize Eclipse to read or work on something else for a few minutes while I wait for it to do something (e.g., run a large JUnit test suite, synchronize a huge number of files with a repo, run a long Ant build, etc.). I have to check back every 30 seconds or so to see if it's finished yet. I would like Eclipse to alert me, preferably by blinking its taskbar icon, after it finishes a time consuming operation. Are there any settings or plugins that can make this happen?
I believe is you have Mylyn installed, this should be enabled by default for Windows 7. See here and here. Regarding the post-build actions, I do not know of any existing Eclipse plugins that do this. However, I have not exhaustively searched the marketplace. However, this could be accomplished with existing Eclipse APIs but it would require someone to author a new Eclipse plugin.
The Eclipse Platform jobs framework has an API called IJobManager. A developer could write a new Eclipse plugin that could use this API to listen for job changes and do the following:
Create an eclipse plugin, register a listener to IJobManager on startup.
Once any interesting job is completed, it could fire off some external task/script using normal java process execution API in the JDK
This all could be accomplished in one Java file, probably less than 500 lines long.
You could use this template to setup a basic Eclipse plugin project including build system and have it built and ready to install into your existing Eclipse.
Update I just found a maven archetype for building eclipse plugins with tycho here. It would be my recommendation for someone new to building an eclipse feature/updatesite.
You can create a new plugin project and create this kind of functionality for yourself. The
IJobchangeListener from the Eclipse Jobs API is probably very interesting for you.
The IJobChangeListener is an interface where you can receive notifications for the different type of job states.
I have created a class called JobListener which adds the IJobchangeListener to the JobManager. With the action SampleAction you can register or unregister the listener. that means, if the listener is registered and your application is minimized you will be notified with a MessageDialog (no blinking taskbar).
I found a link where someone made his swing application blink. This functionality should be included in the method public void done(final IJobChangeEvent event). I haven't done this in my test class.
You can also get additional information about the Job with
event.getJob();
Here you are able to check the Job name:
String jobName = event.getJob().getName();
The name of the Job is human readable, for example "Collecting garbage", "Update for Decoration Completion", "Building workspace", etc.
The JobListener class.
/**
* A job listener which may be added to a job manager
*/
public class JobListener {
private MyJobListener listener = null;
private IWorkbenchWindow window = null;
private boolean active = false;
public JobListener(IWorkbenchWindow window) {
this.window = window;
}
/**
* register the job listener
*/
public void register() {
listener = new MyJobListener(window);
IJobManager jobMan = Job.getJobManager();
jobMan.addJobChangeListener(listener);
active = true;
}
/**
* unregister the job listener
*/
public void unregister() {
IJobManager jobMan = Job.getJobManager();
jobMan.removeJobChangeListener(listener);
active = false;
}
public boolean isActive() {
return active;
}
class MyJobListener implements IJobChangeListener {
private IWorkbenchWindow window;
public MyJobListener(IWorkbenchWindow window) {
this.window = window;
}
#Override
public void sleeping(IJobChangeEvent event) {
}
#Override
public void scheduled(IJobChangeEvent event) {
}
#Override
public void running(IJobChangeEvent event) {
}
#Override
public void done(final IJobChangeEvent event) {
window.getShell().getDisplay().asyncExec(new Runnable() {
#Override
public void run() {
if(window.getShell().getMinimized()) {
MessageDialog.openInformation(
window.getShell(),
"Test",
"Job " + event.getJob().getName() + " done.");
}
}
});
}
#Override
public void awake(IJobChangeEvent event) {
}
#Override
public void aboutToRun(IJobChangeEvent event) {
System.out.println("About to run: " + event.getJob().getName());
}
}
}
I called this class from a class called SampleAction.java
public class SampleAction implements IWorkbenchWindowActionDelegate {
private IWorkbenchWindow window;
private JobListener listener;
/**
* The constructor.
*/
public SampleAction() {
}
public void run(IAction action) {
if(listener.isActive()) {
listener.unregister();
MessageDialog.openInformation(
window.getShell(),
"Lrt",
"Unregistered");
}
else {
listener.register();
MessageDialog.openInformation(
window.getShell(),
"Lrt",
"Registered");
}
}
public void selectionChanged(IAction action, ISelection selection) {
}
public void dispose() {
}
public void init(IWorkbenchWindow window) {
this.window = window;
this.listener = new JobListener(window);
}
You can get started with eclipse plugin development by creating a new plugin project:
File > New > Project > Plugin Project
I used the Hello World plugin project template to test the code above.
I have an app that consists of several activities, and I use the Application Context (entended from the Application Class, and I made it persistent) to share data and objects between all the activities. I use the Application Class instead of a background service for several good reasons, which I won't go into here.
I also recently added an custom contact sync adapter to my app. It's under the same package, in the same APK. So, I set it up to access the Application Context just like everything else in my app to give it access to all the shared data and objects. However, even though it works (mostly), it creates a new instance of the Application Context. So there are basically 2 separate instances of my application running, and the data isn't shared between them.
I think that the problem is that my Applicattion never starts the sync service, the OS does. All my other activities are either started by the application, or the main activity accesses the Application Context when it launches, and then the App Context controls everything else. Is there a way to have the sync service access the existing Application Context, instead of creating the new instance of it?
Here's the basic structure of my app:
The application
package com.mycomany.myapp;
public class MyApp extends Application{
...
}
Activity1
package com.mycomany.myapp;
public class MyActivity1 extends Activity{
MyApp a;
#Override
public void onCreate(Bundle savedInstanceState){
a = (MyApp) getApplicationContext();
...
}
}
SyncAdapterService
package com.mycomany.myapp;
public class SyncAdapterService extends Service {
private static SyncAdapterImpl sSyncAdapter = null;
private static final Object sSyncAdapterLock = new Object();
private static ContentResolver mContentResolver = null;
private static MyApp a;
public SyncAdapterService() {
super();
}
private static class SyncAdapterImpl extends AbstractThreadedSyncAdapter {
private Context mContext;
public SyncAdapterImpl(Context context) {
super(context, true);
mContext = context;
}
#Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
try {
SyncAdapterService.performSync(mContext, account, extras, authority, provider, syncResult);
} catch (OperationCanceledException e) {}
}
}
#Override
public void onCreate() {
super.onCreate();
synchronized (sSyncAdapterLock) {
if(a == null){
a = (MyApp) getApplicationContext();
}
if (sSyncAdapter == null) {
sSyncAdapter = new SyncAdapterImpl(getApplicationContext());
}
}
}
#Override
public IBinder onBind(Intent intent) {
return sSyncAdapter.getSyncAdapterBinder();
}
private static void performSync(Context context, Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult)
throws OperationCanceledException {
...
}
}
Have you copy&pasted this training for the SyncAdapter http://developer.android.com/training/sync-adapters/creating-sync-adapter.html?
At the end there is this XML Snippet:
<service
android:name="com.example.android.datasync.SyncService"
android:exported="true"
android:process=":sync">
<intent-filter>com.example.android.datasync.provider
<action android:name="android.content.SyncAdapter"/>
</intent-filter>
<meta-data android:name="android.content.SyncAdapter"
android:resource="#xml/syncadapter" />
</service>
With the attribute android:process=":sync" meaning you create a separate sync process. Remove it and you're good to go.
You might want to look into binding the service to your Application context. That way, if your application context does not exist, the service won't exist, as it runs in the same process (that of the Application) . See bindSerivce()
If your service is a remote one try using callbacks
Are you still having this problem?
If the service is declared in your manifest file without specifying a different android:process, isn't it supposed to run in the default process defined by your task?
Can't you in that case just use getApplicationContext to get what you need?
I have my sync adapter implemented in this way and it is working