I am writing a plug-in to extend Eclipse for a custom programming language. I have all the launch configuration working and any program in the custom language launches correctly but I cannot seem to activate the Terminate button in the Debug view.
From what I have researched, I know that implementing the Debugger framework provides for the Terminate action but say, I do not want to implement the framework at this stage and would just like to have the option of terminating the program instead of having to cancel via the Task Manager. Is that possible to do? Or is the Debugger Framework the only way to do this?
Here is the code from the LaunchConfigurationDelegate class,
public void launch(ILaunchConfiguration configuration, String mode,
ILaunch launch, IProgressMonitor monitor) throws CoreException {
// getting the resource from the workspace
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRoot root = workspace.getRoot();
List<String> filenames = configuration.getAttribute(RELATIVE_PATH,
Collections.EMPTY_LIST);
List<String> rawPaths = configuration.getAttribute(RAW_PATH,
Collections.EMPTY_LIST);
List<String> projPaths = configuration.getAttribute(PROJECT_PATH,
Collections.EMPTY_LIST);
//CustomRunner is the interface to manage the custom language execution
CustomRunner runner = null;
try {
CustomOutputHandler outHand = new CustomOutputHandler();
runner = new CustomRunner(new File(projPaths.get(0)));
runner.setOutputHandler(outHand);
for (int i = 0; i < filenames.size(); i++) {
IPath temp = new Path(filenames.get(i));
IResource CustomFile = root.findMember(temp);
if (CustomFile == null) {
String msg = "The file "
+ "<"
+ temp.toString()
+ ">"
+ " could not be found in the workspace.\nIt may have been deleted or renamed.";
throw new FileNotFoundException(msg);
}
CustomFile.deleteMarkers(IMarker.PROBLEM, false,
IResource.DEPTH_INFINITE);
CustomErrorHandler errHand = new CustomErrorHandler(CustomFile);
runner.setErrorHandler(errHand);
//Runs the custom language file
runner.run(rawPaths.get(i));
}
After that there is just a bunch of catch blocks.
I need to be able to now terminate this launch via the Debug view and in the case of Run mode via the Run menu's terminate command.
I do not have any DebugTarget right now at this stage. And my question is: Is there another way to terminate this launch without extending the Debug Framework?
I did try launch.Terminate() in this launch method but that did not work.
Unless you extend the Platform-debug support you cannot hook into the Terminate button in the Debug view - at least there isn't an API for that. You can hack into the internals of the debug framework to add support without extending, but extending might be lot easier than that and will work in the future versions of Eclipse
Related
I am working on a GUI application that uses JavaFX(not fxml) and exported as a JAR. For slow machine, impatient user click more than once on JAR, and multiple instances of application started.
I'm looking for a solution to let only one instance can be run at a time on a system and if the user clicks again while the application is running nothing happens. I think it's called singleton but don't know how to implement it.
You could try JUnique. It's an open source library doing exactly what you ask for. Import junique-1.0.4.jar to your project as a library. It's just 10kb file.
It's manual neatly describes how to implement it on a project. For a JavaFX application, implementation would look something like this:
Make sure to import these classes to your main
import it.sauronsoftware.junique.AlreadyLockedException;
import it.sauronsoftware.junique.JUnique;
public static void main(String[] args) {
String appId = "myapplicationid";
boolean alreadyRunning;
try {
JUnique.acquireLock(appId);
alreadyRunning = false;
} catch (AlreadyLockedException e) {
alreadyRunning = true;
}
if (!alreadyRunning) {
launch(args); // <-- This the your default JavaFX start sequence
}else{ //This else is optional. Just to free up memory if you're calling the program from a terminal.
System.exit(1);
}
}
One easy solution that I've used is, when you start the application, it creates a file (I named it .lock but you can call it whatever you want), unless the file already exists, in which case the application terminates its execution instead of creating the file.
You will need to bind your application with a resource. It can be a file, port etc.
You can change the code on startup to check if the file is locked. The below code will give you some idea
FileOutputStream foStream = new FileOutputStream("/tmp/testfile.txt");
FileChannel channel = fileOutputStream.getChannel();
FileLock lock = channel.lock();
If you'd properly package your JavaFX code as a real application instead of just throwing it into a jar, you might get that functionality for free and without all these hacks. If I package my JavaFX code on my Mac with the jpackage tool, the result will be a full featured macOS application. That means that when I double-click its icon somewhere several times, only one instance of the application will be started. This is the default behaviour on Macs and properly packaged JavaFX applications just stick to that rule too. I can't say however what the behaviour on Windows or Linux is because I currently don't have such a box running. Maybe someone who knows can add this as a comment.
I am developing a eclipse plugin. I need to open my prespective when we open the eclipse at first time. Any ways to achieve this? i guess some listener must be available but could not trace out.
We can open a prespective after eclipse start using PlatformUI.getWorkbench().showPrespective(<prespective id>)
Similarly is there a way to open the prespective on eclipse startup, so that our desired prespective gets opened when starting the eclipse.
You can use the org.eclipse.ui.startup extension point in your plugin. When the plugin is activated, check/set a preference to decide if you want to switch perspectives and then schedule a UIJob do do it.
Implement the extension point. Some class in the plugin needs implements org.eclipse.ui.IStartup. The activator class is fine in this case. Particularly, since you don't need anything in the earlyStartup method.
In the start method, make the decision to switch and schedule it:
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
final boolean switchPerpective = processPluginUpgrading();
if (switchPerpective) {
final IWorkbench workbench = PlatformUI.getWorkbench();
new UIJob("Switching perspectives"){
#Override
public IStatus runInUIThread(IProgressMonitor monitor) {
try {
workbench.showPerspective(perspectiveId, workbench.getActiveWorkbenchWindow());
} catch (WorkbenchException e) {
return new Status(IStatus.ERROR,PLUGIN_ID,"Error while switching perspectives", e);
}
return Status.OK_STATUS;
}}
.run(new NullProgressMonitor());
}
}
Use the preference store to keep data for your decision logic. In this implementation, the perspective is switched once per workspace whenever the plugin is upgraded. The data recorded in the preference store will allow a future version to have a difference policy. It uses the getPreferenceStore from AbstractUIPlugin so it is scoped per workspace. If you want to use other scopes, see the FAQ.
private Boolean processPluginUpgrading() {
final Version version = getDefault().getBundle().getVersion();
final IPreferenceStore preferenceStore = getDefault().getPreferenceStore();
final String preferenceName = "lastVersionActivated";
final String lastVersionActivated = preferenceStore.getString(preferenceName);
final boolean upgraded =
"".equals(lastVersionActivated)
|| (version.compareTo(new Version(lastVersionActivated)) > 0);
preferenceStore.setValue(preferenceName, version.toString());
return upgraded;
}
One thing I am doing to open my custom perspective in my plugin is to configure it in config.ini in eclipe's installation folder as below:
-perspective <my perspective id>
and it is working fine. I got this information from Lars Vogel's tutorial, which you can find here. Hope this helps.
Other way:
org.eclipse.ui.IPerspectiveRegistry.setDefaultPerspective(id) this sets default perspective to the given id. API Docs for the same.
Go to
D:\{MyTestSpace}\eclipse\features\myCustom.plugin.feature_3.1.0.201607220552
you can see feature.xml under plugin tag you get the id.
Use this id in config.ini which you can find under
D:\{MyTestSpace}\eclipse\configuration
As
-perspective <myCustum.plugin>
i have coded a database update software which allows me to deploy a jade mobile agent in order to update the database. In order for it to run, i need to launch it using the AMS gui. I wanted to be able to launch it from gui. I have now done a nice swing gui and i only need to know the code which allows me to launch my mobile agent when the "Update" button is clicked. What is the code? Thanks in advance.
To launch an agent or do whatever related to JADE you need to write YOUR code using JADE libraries and API, irrespective of what Front End you have used (Swing in this case)
One suggestion would be, to keep the modularity, is create another file which does one of many such operations you want, and let your Swing GUI interact (say via sockets) to that file, triggering your operation.
That file, which would act as a server, would listen to the front end and do the respective work. But all commands are to be coded using JADE API. One such code is:
ContainerController cc = Runtime.instance().createAgentContainer(newProfileImpl());
Object arguments[] = new Object[1];``arguments[0]=new Object();
AgentController dummy = cc.createNewAgent("mob2","mobiletrial", arguments);
dummy.start();
This is a method I wrote for launching one agent from another.You'll have to edit it for multiple container use.
void launchAgent( final String AgentName, final String AgentType)
{
log(Level.FINER,"attempting to launch angent name: "+AgentName+" type: "+AgentType);
CreateAgent ca = new CreateAgent();
ca.setAgentName(AgentName);
ca.setClassName(AgentType);
ca.setContainer(new ContainerID(AgentContainer.MAIN_CONTAINER_NAME, null));
Action actExpr = new Action(this.getAMS(), ca);
ACLMessage request = new ACLMessage(ACLMessage.REQUEST);
request.addReceiver(this.getAMS());
request.setOntology(JADEManagementOntology.getInstance().getName());
request.setLanguage(FIPANames.ContentLanguage.FIPA_SL);
request.setProtocol(FIPANames.InteractionProtocol.FIPA_REQUEST);
try {
getContentManager().fillContent(request, actExpr);
addBehaviour(new AchieveREInitiator(this, request) {
protected void handleInform(ACLMessage inform) {
log(Level.INFO,"Agent successfully created name:"+AgentName+" type: "+AgentType);
}
protected void handleFailure(ACLMessage failure) {
log(Level.SEVERE,"Agent launch failed name: "+AgentName+" type: "+AgentType);
}
} );
}
catch (Exception e) {
e.printStackTrace();
}
}
I'm starting with SVN. Is there any way of configuring subclipse to automatically sync with the repo in order to know when a file was modified as soon as possible?
In case of Subversive (and I believe, the same option should be available in case of Subclipse as well) the Synchronize view allows automatic synchronization.
Initialize a synchronization using either Team/Synchronize from the context menu of some projects, or open the Team Synchronizing perspective, and select the set of synchronized projects using the Synchronize button of the Synchronize view (the button is the first button of the view toolbar).
Then the synchronization is performed, and the changes are displayed there. At this point, you could select the Schedule... option from the view menu (down-pointing triangle icon near the top right corner of the Synchronize view), and there you could set the synchronization.
AFAIK this synchronization does not update your workspace automatically (that is a sound idea, e.g. conflict resolution must happen manually), but at least you can look at the changes when needed.
You really do not want to do this. Synchronization with repository is a heavy operation with a lot of side effects. For example you can change file that is being changed in repository now. You do not want to get mismatch of your and other's changes while you are working. You wish to work and then update all files together and resolve conflicts (if any)
In the context menu (right-click on project) there should be an option "Team>Synchronize with repository".
I did find this tutorial useful.
As far as I know, subclipse provides no such option. You could write a cron job that uses the SVN command-line tools to perform an update at regular intervals, but I wouldn't recommend this. You can't automate synchronizing with SVN because updating may cause conflicts which cannot be automatically merged.
Although I agree that in some situations it might be a bad idea to have an automated commit feature, there might be some reasons why you could want to have this option anyway.
I created a small EASE-script that replaced my regular save key binding (ctrl+s). It first saves the file, tries to update the file (which also automatically merges the versions if possible or creates conflicts in which case the script terminates) and commits the file at last.
// ********************************************************************************
// name : SaveUpdateCommit
// keyboard : CTRL+S
// toolbar : PHP Explorer
// script-type : JavaScript
// description : Save a file, update from the repository and commit automatically
// ********************************************************************************
var UI = loadModule("/System/UI");
UI.executeUI(function(){
var editor = UI.getActiveEditor();
editor.doSave(null);
var site = editor.getSite();
var commandService = site.getService(org.eclipse.ui.commands.ICommandService);
var handlerService = site.getService(org.eclipse.ui.handlers.IHandlerService);
var subclipse = org.tigris.subversion.subclipse.core.SVNProviderPlugin.getPlugin();
try
{
var file = editor.getEditorInput().getFile();
}
catch(e)
{
return;
}
var filePath = file.getFullPath();
var project = file.getProject();
var projectPath = project.getWorkingLocation(subclipse.toString());
var workspace = project.getWorkspace();
var localFile = org.tigris.subversion.subclipse.core.resources.SVNWorkspaceRoot.getSVNFileFor(file);
localFile.refreshStatus();
if(localFile.isDirty()){
var remoteFile = localFile.getBaseResource();
var empty = java.lang.reflect.Array.newInstance(org.eclipse.core.resources.IResource, 0);
var commitFiles = java.lang.reflect.Array.newInstance(org.eclipse.core.resources.IResource, 1);
commitFiles[0] = remoteFile.getResource();
var update = new org.tigris.subversion.subclipse.ui.operations.UpdateOperation(editor, remoteFile.getResource(), org.tigris.subversion.svnclientadapter.SVNRevision.HEAD);
update.run(null);
var commit = new org.tigris.subversion.subclipse.ui.operations.CommitOperation(editor, empty, empty, empty, commitFiles, "AutoCommit", false);
commit.run(null);
}
For this, you need to install Eclipse EASE (http://download.eclipse.org/ease/update/release) and to make this script available through the settings. Also, the script needs UI-access, again this needs to be configured in the settings.
So for your needs you may want to change that behavior to frequent updates. I never played around with timers in eclipse, but i guess it is possible though.
All,
I am creating a palette less eclipse plugin where am adding figures to the custom editor through the contextual menu, but am not finding a way to do it. Can anyone please guide me as to how to go about adding figures to editor dynamically through context menu i.e. adding actions/commands.
Since Eclipse GEF plugin development finds so less examples to look at, I am adding my solution so others find it useful. This code helps to render a node to the editor.
Source code for Action class to render figures to the editor:
public class AddNodeAction extends EditorPartAction
{
public static final String ADD_NODE = "ADDNODE";
public AddNodeAction(IEditorPart editor) {
super(editor);
setText("Add a Node");
setId(ADD_NODE); // Important to set ID
}
public void run()
{
<ParentModelClass> parent= (<ParentModelClass>)getEditorPart().getAdapter(<ParentModelClass>.class);
if (parent== null)
return;
CommandStack command = (CommandStack)getEditorPart().getAdapter(CommandStack.class);
if (command != null)
{
CompoundCommand totalCmd = new CompoundCommand();
<ChildModelToRenderFigureCommand>cmd = new <ChildModelToRenderFigureCommand>(parent);
cmd.setParent(parent);
<ChildModelClass> newNode = new <ChildModelClass>();
cmd.setNode(newNode);
cmd.setLocation(getLocation()); // Any location you wish to set to
totalCmd.add(cmd);
command.execute(totalCmd);
}
}
#Override
protected boolean calculateEnabled()
{
return true;
}
}
I think you need multiple different things here. Please remember that GEF would like you to have proper MVC pattern, where you have your own model, Figures as View and EditParts as controllers.
From the top of my head I would say that you need at least these things:
CreateCommand
contains all model level modifications that you need to
perform to add your new data to your
data model (undoable and transactional)
CreateAction
makes that CreateCommand instance, initializes it with current selection and executes that command in editdomain
ContextMenuProvider
Provides that CreateAction to context menu
If you happen to be using GMF the canonical mechanism will generate the editparts for you automatically when you make the model modifications inside a command, but if you are not using GMF, you must make sure that your own models and editparts are handling and refreshing the new item adding properly.
EDIT:
Ok, here is some code suggestion with playing around with requests.
public void run() {
// Fetch viewer from editor part (might not work, if not, try some other way)
EditPartViewer viewer = (EditPartViewer) part.getAdapter(EditPartViewer.class);
// get Target EditPart that is under the mouse
EditPart targetEditPart = viewer.findObjectAt(getLocation());
// If nothing under mouse, set root item as target (just playing safe)
if(targetEditPart == null)
targetEditPart = viewer.getContents();
// Make and initialize create request with proper information
CreateRequest createReq = new CreateRequest();
createReq.setLocation(getLocation());
createReq.setFactory(new OwnFactoryImplementation());
// Ask from target editpart command for this request
Command command = targetEditPart.getCommand(createReq);
// If command is ok, and it can be executed, go and execute it on commandstack
if(command != null && command.canExecute()) {
viewer.getEditDomain().getCommandStack().execute(command);
}
}
Now what happens is that editpart will be requested for creation, so the action itself doesn't know how the command works, what makes it objective agaist the command.
So to make things work, you need to install new EditPolicy to your EditPart. EditPolicies can be installed on EditParts createDefaultEditPolicies() function. This EditPolicy must react and return command when there is CreateRequest. This way any child can provide own kind of command for creating children for itself.
Here is a good image how it works (controller is EditPart):
Please ask if I can help you some more. I know that this looks bit more complex, but this makes your own life much more easier, and after you have done that, you actually understand Command-Request Pattern quite well, and it can be reused in many different places.