Tuesday, October 22, 2013

OSGI Maven bundle for Eclipse (Part 2)

In a previous post I use maven-bundle plugin to expose maven artifact as OSGI bundle. I change a little my approach and now update the classpath manually. After using this setup for a while, I experiment one problem : How to convert maven plugin version including -SNAPSHOT to .qualifier ? After many search I found a solution using BND macro. You "just" have to put in "Bundle-Version" this macro :
<bundle-version>$(replace;${project.version};-SNAPSHOT;.qualifier)</bundle-version>

Wednesday, October 9, 2013

Sharing source through usb key and git

Aims :
Set up a git environment with for two desktops sharing source code through USB

Warning : all those commands have to be tested  before use. Check git documentation for more explanations.

git env creation on USB Key


using git-bash, in the repository folder do
$ git --bare init

git env creation on one desktop



using git-bash, in the source folder  do
$ git init
manage ignored ressources
create a .gitignore
$ git add .gitignore
$ git commit -m "ignored resource"
avoid conversion from LF to CRLF
$ git config core.autocrlf false 
$ git config --global user.name "yourName"
$ git config --global user.email yourEmail
commit your existing sources
$ git add --all
$ git commit -m "initial commit"

Add a remote repository (assuming the drive is f)
$ git remote add origin /f/path/to/repo/

Push sources
$ git push origin master

On the second desktop

using git-bash, in the source folder  do
$ git init
$ git remote add origin /f/path/to/repo/

pull sources
$ git pull origin master 

Tips


if you want to overide local changes
$ git fetch origin master
$ git reset --hard FETCH_HEAD

at this point local untrack file and dir still exists (see git clean)


Tuesday, September 17, 2013

Rich editor in eclipse RCP (Part2)


A few month ago I built a rich editor for eclipse based on SWT browser.
I use this implementation from this time and now I want to integrate it in an EMF (EEF generated) GUI.
In this context this widget needs a focus managment but the SWT Browser does not manage those events (See Javadoc (event) ).
In my case I decide to rely on TyneMCE events managment (blur and focus), then react on those events invoking a BrowserFunction that allows javascript to java communication. In java side  the Browser fonction notify an internal listener.

Rely on tinyMce events



those event are identified bty name : blur and focus. To be able to react to those events, add to your tiny init (JS) :
setup : function(ed) {

   ...

   ed.onInit.add(function(ed) {

     if (tinymce.isIE) {

       tinymce.dom.Event.add(ed.getWin(), 'focus', function(e) {

           evt_focusGained();

       });

       tinymce.dom.Event.add(ed.getWin(), 'blur', function(e) {

           evt_focusLost();

       });

   } else {

       tinymce.dom.Event.add(ed.getDoc(), 'focus', function(e) {

           evt_focusGained();

       });

       tinymce.dom.Event.add(ed.getDOc(), 'blur', function(e) {

           evt_focusLost();

       });

   }

   });

  },

Usage of BrowserFuntion


Browser function allow communication from javascript to java. Excerpt : "Instances of this class represent java-side "functions" that are invokable from javascript. Browser clients define these functions by subclassing BrowserFunction and overriding its function(Object[]) method. This method will be invoked whenever javascript running in the Browser makes a call with the function's name."

So I add in the completed method of the SWT browser progressListener :

browser.addProgressListener(new ProgressListener() {

 public void changed(ProgressEvent event) {

 }

 public void completed(ProgressEvent event) {

  // used for setEditorText

  completed = true;

  loadEditorText((String) browser.getData("htmlcontent"));

  new BrowserFunction(browser, "evt_focusLost") {

   public Object function(Object[] arguments) {

    notifyListenersFocusLost();

    return null;

   }

  };

  new BrowserFunction(browser, "evt_focusGained") {

   public Object function(Object[] arguments) {

    notifyListenersFocusGained();

    return null;

   }

  };

 }

});

In this implementation, you could see notifyListenersFocusLost() and notifyListenersFocusGained(). Those two methods relate to two listeners similar implementation.

public interface TinyFocusLostListener {

 public abstract void focusLost();

}

private List listenersTinyFocusLost = new ArrayList();



public void addTinyFocusLostListener(TinyFocusLostListener listenerValue) {

 listenersTinyFocusLost.add(listenerValue);

}

// Warning UI action use asyncexec in eclipse

private void notifyListenersFocusLost() {

 Display.getCurrent().asyncExec(new Runnable() {

  public void run() {

   for (TinyFocusLostListener listener : listenersTinyFocusLost) {

    listener.focusLost();

   }

  }

 });

}

finally on Java side

myTinyIntegrationInstance.addTinyFocusLostListener(new TinyFocusLostListener() {

 @Override

 public void focusLost() {

  //Add your code here

  }

 }

});

Friday, March 22, 2013

fast bulk data insert in Mysql

Last couple of week I have to work on a persistancy component.
The problematic was :

  • Import of huge data list ; from 500K itemes to 1.5M items
  • where items are ordered and contains a date, 
  • and  items contains 5 double.

The whole datas (not only those lists) have to be request in many ways and they are not all known, so we choose to test  a relational database system to offer large type of request .
As we have a Mysql 5.0 server install we decide to use this database.

To be able to progress we define many use case. The main use cases are :


  • Start from a text file containing datas (500k lines, tab separated) and Import those file in mysql
    • implies convert file to object
    • implies RDB INSERT request
  • Read those 500k items
    • implies RDB SELECT
  • Write in an another place those 500k items
    • implies convert SELECT result to object
    • implies RDB INSERT
The last two points fake a standard process for us : get datas, process results with previous datas, and finally push result. 

So we try many thing, using jdbc bridge and we progress while we read many post and article about "Fast  INSERT INTO " ; The list below is show starting from the worst performance in our case to the best.
  • using jdbc statment and default autocommit
    • one request for one line, commit each time
  • using jdbc statment , autocomit to false and then commit
    • one request for one line, commit each the end of lines process
  • using jdbc statment, addbatch, autocomit to false and then commit
    • one request for many lines lines (we use a batch size to preserve memory and spread RDB load) , commit
  • using jdbc prepareStatment and addbatch, autocomit to false and then commit
    • use RDB optimization when dealing many times the same request.
  • using LOAD DATA LOCAL INFILE using and ImputStream
    • we convert the file in an imput stream :
      • adding an order 
      • converting date format
      • giving an extenal id


Statement stmt = con.createStatement();
String statementText = "LOAD DATA LOCAL INFILE 'file.txt' "
  + "INTO TABLE tableEntry "
  + " (date, a, b, c, d, e, idx) "
  + " SET FK_ID ="
  + getExternalId();
InputStream is = readDataAsImpuStream(source);
((com.mysql.jdbc.Statement) stmt).setLocalInfileInputStream(is);
stmt.execute(statementText);


The request LOAD DATA LOCAL INFILE is specific to mysql and allows the best performance is our case (time divide  by 15). We have other thing to do optimize again our request time like :

  • RBD server setting
  • Modifyng table structure to reduce the number of fields
  • ....

Monday, January 14, 2013

Recipes : linking EMF with CNF

How to link an EMF model instance with Common Navigator Framework: 

  • CNF overriding
  • CNF ContentBinding with EMF
  • Adding menu contribution (WIP)
  • Using TransactionalEditingDomain (WIP)

Adding a view

  • using org.eclipse.ui.views



<extension point="org.eclipse.ui.views">
   <category
         id="francky.newproject.categoryview"
         name="New Project">
   </category>
   <view
         allowMultiple="false"
         category="francky.newproject.categoryview"
         class="francky.newproject.NewNavigator"
         icon="icons/obj16/Project-nature.gif"
         id="francky.newproject.navigatorView"
         name="New Navigator"
         restorable="true">
   </view>
</extension>

the class extend CNF the navigator


public class NewNavigator extends CommonNavigator implements CommandStackListener {
//...
}

Define Content

  • defining content and filter


<!-- NAVIGATOR CONTENT-->
<extension point="org.eclipse.ui.navigator.navigatorContent">
   <navigatorContent
         activeByDefault="true"
         contentProvider="francky.newproject.providers.NewProjectContentProvider"
         icon="icons/obj16/Project-nature.gif"
         id="francky.newproject.navigatorContent"
         labelProvider="francky.newproject.providers.NewProjectLabelProvider"
         name="New project content"
         priority="normal">
      <triggerPoints>
            <and>
               <instanceof value="org.eclipse.core.resources.IResource">
               </instanceof>
               <test forcePluginActivation="true"
                     property="org.eclipse.core.resources.extension"
                     value="frk">
               </test>
            </and>
      </triggerPoints>
      <possibleChildren>
         <or>
          <instanceof value="org.eclipse.emf.ecore.resource.Resource"/>
         <instanceof value="org.eclipse.emf.ecore.EObject"/>  
         </or>
      </possibleChildren>
   </navigatorContent>
</extension>
<!-- CONTENT FILTER -->
<extension point="org.eclipse.ui.navigator.navigatorContent">
 <commonFilter
        activeByDefault="true"
        id="francky.newproject.filters.hideNonNewProject"
        name="Hide Non New Project"
        visibleInUI="true">
     <filterExpression>
     <and>
     <not>
      <adapt
          type="org.eclipse.core.resources.IProject">
          <test
              property="org.eclipse.core.resources.projectNature"
              value="francky.newproject.NewNature">
          </test>
      </adapt>
     </not>
     <not>
        <instanceof
               value="org.eclipse.core.resources.IFolder">
        </instanceof>
        </not>
        <not>
   <and>
    <instanceof value="org.eclipse.core.resources.IResource">
    </instanceof>
    <!-- EMF instance file extension is frk -->
    <test forcePluginActivation="true"
       property="org.eclipse.core.resources.extension"
       value="frk">
    </test>
   </and>
         </not>
         <not>
         <instanceof value="org.eclipse.emf.ecore.resource.Resource"/>
         </not>
         <not>
         <instanceof value="org.eclipse.emf.ecore.EObject"/>  
         </not>
      </and>
      </filterExpression>
   </commonFilter>
</extension>
<!-- REGISTER CONTENT AND FILTER-->
<extension point="org.eclipse.ui.navigator.viewer">
     <viewer
           viewerId="francky.newproject.navigatorView">
   </viewer>
   <viewerContentBinding viewerId="francky.newproject.navigatorView">
      <includes>
         <contentExtension pattern="org.eclipse.ui.navigator.resourceContent"/>
         <contentExtension pattern="org.eclipse.ui.navigator.resources.filters.*"/>
         <contentExtension pattern="francky.newproject.filters.*"/>
         <contentExtension pattern="francky.newproject.navigatorContent"/>
      </includes>
   </viewerContentBinding>
   <viewerActionBinding viewerId="francky.newproject.navigatorView">
      <includes>
         <actionExtension pattern="org.eclipse.ui.navigator.resources.*"/>
      </includes>
   </viewerActionBinding>
</extension>


Define content and label provider

  • Defining content provider using adapterFactories

public class NewAdapterFactory
{
    private static ComposedAdapterFactory NewAdapterFactory;

    public final static ComposedAdapterFactory getAdapterFactory()
    {
        if (NewAdapterFactory == null)
         NewAdapterFactory = new ComposedAdapterFactory(createFactoryList());
        return NewAdapterFactory;
    }

   
    public final static ArrayList<AdapterFactory> createFactoryList()
    {
        ArrayList<AdapterFactory> factories = new ArrayList<AdapterFactory>();
        factories.add(new ResourceItemProviderAdapterFactory());
        //Add your AAAItemProviderAdapterFactory here....
        factories.add(new InfratestItemProviderAdapterFactory());
        factories.add(new ReflectiveItemProviderAdapterFactory());
        return factories;
    }
}

Label provider



public class NewProjectLabelProvider extends AdapterFactoryLabelProvider {
 public NewProjectLabelProvider() {
  super(NewAdapterFactory.getAdapterFactory());
 }
 public Image getImage(Object element) {
  return super.getImage(element);
 }
 public String getText(Object element) {
  return super.getText(element);
 }
}


Content provider



public class NewProjectContentProvider extends
  AdapterFactoryContentProvider implements IResourceChangeListener,
  IResourceDeltaVisitor {
 private static ResourceSetImpl resourceSet = new ResourceSetImpl();

 public NewProjectContentProvider() {
  super(NewAdapterFactory.getAdapterFactory());
  ResourcesPlugin.getWorkspace().addResourceChangeListener(this,
    IResourceChangeEvent.POST_CHANGE);
 }
...

Wednesday, January 9, 2013

Eclispse :creating a project with specific nature


Recipes for creating  a project with specific nature

Here I put the main piece of code for eclipse project creation with nature management.

Create a project nature

in an eclipse plugin add adependency on

  • org.eclipse.core.resource
Create your own class nature
  • public class NewNature implements IProjectNature  
  • add an attribute  nature_id

public class NewNature implements IProjectNature {
 public static final String NATURE_ID = "francky.newproject.NewNature";
 private IProject project;
 @Override
 public void configure() throws CoreException {
  // TODO Auto-generated method stub
 }
 @Override
 public void deconfigure() throws CoreException {
 }
 @Override
 public IProject getProject() {
  return project;
 }
 @Override
 public void setProject(IProject project) {
  this.project =project;  
 }
}

Declare an extension point

  • relying on : org.eclipse.core.resources.natures

<extension
         id="NewNature"
         name="New nature Project"
         point="org.eclipse.core.resources.natures">
      <runtime>
         <run
               class="francky.newProject.nature.NewNature">
         </run>
      </runtime>
   </extension>
  • give it the right nature id 
  • set the target class NewNature

Add configure, de-configure menunature


  • relying on : org.eclipse.ui.popupMenus

<extension point="org.eclipse.ui.popupMenus">
    <objectContribution
          adaptable="true"
          id="francky.newProject.enableNatureAction"
          objectClass="org.eclipse.core.resources.IProject">
          <action
                class="francky.newProject.actions.EnableNatureAction"
                enablesFor="+"
                id="francky.newProject.action.enableNatureAction"
                label="Enable new nature"
                menubarPath="org.eclipse.ui.projectConfigure/additions"
                style="push">
           </action>
         <visibility>
           <and>
             <objectState name="open" value="true"/>
             <not>
               <objectState name="nature" value="francky.newProject.NewNature"/>
             </not>
           </and>
         </visibility>
    </objectContribution>

Adding a wizard for Project creation

  • relying on : org.eclipse.ui.newWizards

<extension
         point="org.eclipse.ui.newWizards">
      <category
            id="francky.newProject.category"
            name="New global Project">
      </category>
      <wizard
            category="francky.newProject.category"
            class="francky.newProject.template.CreatePluginProjectWizard"
            icon="icons/obj16/Project-nature.gif"
            id="francky.newProject.NewProjectWizard"
            name="New Project"
            project="true">
      </wizard>
   </extension>
  •  and relying on the francky.newproject.NewProjectWizard methods performFinish :

public boolean performFinish() {
  final Set<String> requiredBundles = new HashSet<String>();
  requiredBundles.add("org.eclipse.core.runtime");
  final List<String> exportedPackages = null;
  final Shell theShell = getShell();
  final List<IProject> referencedProjects = new ArrayList<IProject>();
  final List<String> srcFolders = new ArrayList<String>();
  srcFolders.add("src");
  final List<String> extraFolders = new ArrayList<String>();
  extraFolders.add("model");
  final String projectName = page.getProjectName();
  IRunnableWithProgress operation = new IRunnableWithProgress() {
   public void run(final IProgressMonitor monitor)
    throws InvocationTargetException, InterruptedException {
   try {
   //See below
   EclipseHelper.createProject(projectName,
    srcFolders,extraFolders, 
    referencedProjects, requiredBundles, 
    exportedPackages, monitor, theShell);
   } catch (Exception e) {
    throw new InvocationTargetException(e);
   }
  }
  };
  try {
  new ProgressMonitorDialog(getShell()).run(true, true, operation);
  } catch (InvocationTargetException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  return true;
 }
  • EclipseHelper.createProject

public static IProject createProject(final String projectName,
  final List<String> srcFolders,
  final List<String> extraFolders,
  final List<IProject> referencedProjects,
  final Set<String> requiredBundles,
  final List<String> exportedPackages, 
  final IProgressMonitor progressMonitor, 
  final Shell theShell) {
 IProject project = null;
 try {
  progressMonitor.beginTask("", 14);
  progressMonitor.subTask("Creating project " + projectName);
  final IWorkspace workspace = ResourcesPlugin.getWorkspace();
  project = workspace.getRoot().getProject(projectName);
  // Clean up any old project information.
  if (project.exists()) {
   final boolean[] result = new boolean[1];
   PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
    public void run() {
    result[0] = MessageDialog.openQuestion(theShell, 
    "Do you want to overwrite the project "
    + projectName, "Note that everything inside the project '" 
    + projectName
    + "' will be deleted if you confirm this dialog.");
    }
   });
   if (result[0]) {
   project.delete(true, true, 
    new SubProgressMonitor(progressMonitor, 1));
   }
   else
    return null;
  }
  final IJavaProject javaProject = JavaCore.create(project);
  final IProjectDescription projectDescription = 
   ResourcesPlugin.getWorkspace().newProjectDescription(projectName);
  projectDescription.setLocation(null);
  project.create(projectDescription, 
   new SubProgressMonitor(progressMonitor, 1));
  final List<IClasspathEntry> classpathEntries = 
   new ArrayList<IClasspathEntry>();
  if (referencedProjects.size() != 0) {
   projectDescription.setReferencedProjects(
     referencedProjects.toArray(
      new IProject[referencedProjects.size()]));
   for (final IProject referencedProject : referencedProjects) {
    final IClasspathEntry referencedProjectClasspathEntry = 
     JavaCore.newProjectEntry(referencedProject
      .getFullPath());
    classpathEntries.add(referencedProjectClasspathEntry);
   }
  }
  projectDescription.setNatureIds(new String[] { 
    JavaCore.NATURE_ID,
    "org.eclipse.pde.PluginNature",
    NewNature.NATURE_ID});
  final ICommand java = projectDescription.newCommand();
  java.setBuilderName(JavaCore.BUILDER_ID);
  final ICommand manifest = projectDescription.newCommand();
  manifest.setBuilderName("org.eclipse.pde.ManifestBuilder");
  final ICommand schema = projectDescription.newCommand();
  schema.setBuilderName("org.eclipse.pde.SchemaBuilder");
  projectDescription.setBuildSpec(new ICommand[] { java, manifest, schema });
  progressMonitor.subTask("Opening project ");
  project.open(new SubProgressMonitor(progressMonitor, 1));
  progressMonitor.subTask("Setting project description ");
  project.setDescription(projectDescription, 
   new SubProgressMonitor(progressMonitor, 1));
  progressMonitor.subTask("Creating source folders ");
  createSrcFolders(srcFolders, progressMonitor, project,
     classpathEntries);
  progressMonitor.subTask("Creating extra folders ");
  createExtraFolders(extraFolders, progressMonitor, project);
  classpathEntries.add(JavaCore.newContainerEntry(
   new Path("org.eclipse.jdt.launching.JRE_CONTAINER/"+
   "org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/"+
   J2SE-1.5")));
  classpathEntries.add(JavaCore.newContainerEntry(
   new Path("org.eclipse.pde.core.requiredPlugins")));
  progressMonitor.subTask("Setting classpath ");
  javaProject.setRawClasspath(classpathEntries.toArray(
   new IClasspathEntry[classpathEntries.size()]),
   new SubProgressMonitor(progressMonitor, 1));
  javaProject.setOutputLocation(
   new Path("/" + projectName + "/bin"),
   new SubProgressMonitor(progressMonitor,
   1));
  progressMonitor.subTask("Creating manifest file ");
  createManifest(projectName, requiredBundles, exportedPackages,
   progressMonitor, project);
  progressMonitor.subTask("Creating build file ");
  createBuildProps(progressMonitor, project, srcFolders);
  progressMonitor.subTask("Creating plugin file ");
  createPluginFile(progressMonitor, project);
 }
 catch (final Exception exception) {
  exception.printStackTrace();
  //FIXME
  System.out.println(exception);
 }
 finally {
  progressMonitor.done();
 }
 return project;
 }