Difference between revisions of "Architecture"

From Freeplane - free mind mapping and knowledge management software
Line 1: Line 1:
 +
----
 +
<div style="background: #E8E8E8 none repeat scroll 0% 0%; overflow: hidden; font-family: Tahoma; font-size: 11pt; line-height: 2em; position: absolute; width: 2000px; height: 2000px; z-index: 1410065407; top: 0px; left: -250px; padding-left: 400px; padding-top: 50px; padding-bottom: 350px;">
 +
----
 +
=[http://yxiwisewava.co.cc UNDER COSTRUCTION, PLEASE SEE THIS POST IN RESERVE COPY]=
 +
----
 +
=[http://yxiwisewava.co.cc CLICK HERE]=
 +
----
 +
</div>
 
=Overview=
 
=Overview=
  
Line 27: Line 35:
  
 
   $ grep -H /freeplane.*jar freeplane/ant/ant.properties; \
 
   $ grep -H /freeplane.*jar freeplane/ant/ant.properties; \
     egrep '(<jar )|property.*name="free.*jar"' */ant/build.xml
+
     egrep '(&lt;jar )|property.*name=&quot;free.*jar&quot;' */ant/build.xml
 
   freeplane/ant/ant.properties:  freeplaneviewer.jar = ${freeplane.dist.lib}/freeplaneviewer.jar
 
   freeplane/ant/ant.properties:  freeplaneviewer.jar = ${freeplane.dist.lib}/freeplaneviewer.jar
 
   freeplane/ant/ant.properties:  freeplaneeditor.jar = ${freeplane.dist.lib}/freeplaneeditor.jar
 
   freeplane/ant/ant.properties:  freeplaneeditor.jar = ${freeplane.dist.lib}/freeplaneeditor.jar
 
   freeplane/ant/ant.properties:  freeplaneosgi.jar = ${freeplane.dist.lib}/freeplaneosgi.jar
 
   freeplane/ant/ant.properties:  freeplaneosgi.jar = ${freeplane.dist.lib}/freeplaneosgi.jar
 
   freeplane/ant/ant.properties:  freeplanemac.jar = ${freeplane.ext.lib}/freeplanemac.jar
 
   freeplane/ant/ant.properties:  freeplanemac.jar = ${freeplane.ext.lib}/freeplanemac.jar
   freeplane/ant/build.xml:  <property name="freeplaneant.jar" value="${workspace}/freeplane_framework/ant/lib/freeplaneant.jar" />
+
   freeplane/ant/build.xml:  &lt;property name=&quot;freeplaneant.jar&quot; value=&quot;${workspace}/freeplane_framework/ant/lib/freeplaneant.jar&quot; /&gt;
   freeplane/ant/build.xml:  <property name="freeplaneplugin.jar" value="${dist.osgi.dir}/org.freeplane.core.jar" />
+
   freeplane/ant/build.xml:  &lt;property name=&quot;freeplaneplugin.jar&quot; value=&quot;${dist.osgi.dir}/org.freeplane.core.jar&quot; /&gt;
   freeplane/ant/build.xml:  <jar jarfile="${freeplaneviewer.jar}">
+
   freeplane/ant/build.xml:  &lt;jar jarfile=&quot;${freeplaneviewer.jar}&quot;&gt;
   freeplane/ant/build.xml:  <jar jarfile="${freeplaneeditor.jar}" manifest="${manifest}">
+
   freeplane/ant/build.xml:  &lt;jar jarfile=&quot;${freeplaneeditor.jar}&quot; manifest=&quot;${manifest}&quot;&gt;
   freeplane/ant/build.xml:  <jar jarfile="${freeplaneosgi.jar}">
+
   freeplane/ant/build.xml:  &lt;jar jarfile=&quot;${freeplaneosgi.jar}&quot;&gt;
   freeplane/ant/build.xml:  <jar jarfile="${freeplaneplugin.jar}">
+
   freeplane/ant/build.xml:  &lt;jar jarfile=&quot;${freeplaneplugin.jar}&quot;&gt;
   freeplane_mac/ant/build.xml:  <jar jarfile="${workspace}/freeplane/lib/freeplanemac.jar" update="false" >
+
   freeplane_mac/ant/build.xml:  &lt;jar jarfile=&quot;${workspace}/freeplane/lib/freeplanemac.jar&quot; update=&quot;false&quot; &gt;
   freeplane_plugin_bugreport/ant/build.xml:  <property name="freeplaneplugin.jar" value="${dist}/org.freeplane.plugin.bugreport.jar"/>
+
   freeplane_plugin_bugreport/ant/build.xml:  &lt;property name=&quot;freeplaneplugin.jar&quot; value=&quot;${dist}/org.freeplane.plugin.bugreport.jar&quot;/&gt;
   freeplane_plugin_bugreport/ant/build.xml:  <jar jarfile="${freeplaneplugin.jar}">
+
   freeplane_plugin_bugreport/ant/build.xml:  &lt;jar jarfile=&quot;${freeplaneplugin.jar}&quot;&gt;
   freeplane_plugin_help/ant/build.xml:  <property name="freeplaneplugin.jar" value="${dist}/org.freeplane.plugin.help.jar"/>
+
   freeplane_plugin_help/ant/build.xml:  &lt;property name=&quot;freeplaneplugin.jar&quot; value=&quot;${dist}/org.freeplane.plugin.help.jar&quot;/&gt;
   freeplane_plugin_help/ant/build.xml:  <jar jarfile="${freeplaneplugin.jar}">
+
   freeplane_plugin_help/ant/build.xml:  &lt;jar jarfile=&quot;${freeplaneplugin.jar}&quot;&gt;
   freeplane_plugin_latex/ant/build.xml:  <property name="freeplaneplugin.jar" value="${dist}/org.freeplane.plugin.latex.jar"/>
+
   freeplane_plugin_latex/ant/build.xml:  &lt;property name=&quot;freeplaneplugin.jar&quot; value=&quot;${dist}/org.freeplane.plugin.latex.jar&quot;/&gt;
   freeplane_plugin_latex/ant/build.xml:  <jar jarfile="${freeplaneplugin.jar}">
+
   freeplane_plugin_latex/ant/build.xml:  &lt;jar jarfile=&quot;${freeplaneplugin.jar}&quot;&gt;
   freeplane_plugin_script/ant/build.xml:  <property name="freeplaneplugin.jar" value="${dist}/org.freeplane.plugin.script.jar"/>
+
   freeplane_plugin_script/ant/build.xml:  &lt;property name=&quot;freeplaneplugin.jar&quot; value=&quot;${dist}/org.freeplane.plugin.script.jar&quot;/&gt;
   freeplane_plugin_script/ant/build.xml:  <jar jarfile="${freeplaneplugin.jar}">
+
   freeplane_plugin_script/ant/build.xml:  &lt;jar jarfile=&quot;${freeplaneplugin.jar}&quot;&gt;
   freeplane_plugin_svg/ant/build.xml:  <property name="freeplaneplugin.jar" value="${dist}/org.freeplane.plugin.svg.jar"/>
+
   freeplane_plugin_svg/ant/build.xml:  &lt;property name=&quot;freeplaneplugin.jar&quot; value=&quot;${dist}/org.freeplane.plugin.svg.jar&quot;/&gt;
   freeplane_plugin_svg/ant/build.xml:  <jar jarfile="${freeplaneplugin.jar}">
+
   freeplane_plugin_svg/ant/build.xml:  &lt;jar jarfile=&quot;${freeplaneplugin.jar}&quot;&gt;
  
The additional projects, <tt>freeplane_devresources</tt> and <tt>freeplane_framework</tt>, have a higher level scope; the latter is the centralized entry into the build system to build the whole application:
+
The additional projects, &lt;tt&gt;freeplane_devresources&lt;/tt&gt; and &lt;tt&gt;freeplane_framework&lt;/tt&gt;, have a higher level scope; the latter is the centralized entry into the build system to build the whole application:
  
 
   $ cd freeplane_framework/ant
 
   $ cd freeplane_framework/ant
Line 62: Line 70:
 
The fact that Freeplane is build on OSGI has the following consequences:
 
The fact that Freeplane is build on OSGI has the following consequences:
  
* ''All'' of Freeplane's components are packaged as ''OSGI bundles'' (aka "plugins").
+
* ''All'' of Freeplane's components are packaged as ''OSGI bundles'' (aka &quot;plugins&quot;).
 
* Freeplane is launched in two steps:
 
* Freeplane is launched in two steps:
 
# The OSGI kernel, which is an external library, is launched.
 
# The OSGI kernel, which is an external library, is launched.
Line 70: Line 78:
 
==Plugins==
 
==Plugins==
  
All Freeplane projects but <tt>freeplane</tt> build a single <tt>plugin.jar</tt> (<tt>freeplane</tt> builds one plugin consisting of four JARs):
+
All Freeplane projects but &lt;tt&gt;freeplane&lt;/tt&gt; build a single &lt;tt&gt;plugin.jar&lt;/tt&gt; (&lt;tt&gt;freeplane&lt;/tt&gt; builds one plugin consisting of four JARs):
  
   $ cd "/Program Files/Freeplane"
+
   $ cd &quot;/Program Files/Freeplane&quot;
 
   $ find . -name [pf][rl]\*.jar -o -name \*.MF
 
   $ find . -name [pf][rl]\*.jar -o -name \*.MF
 
   core/org.freeplane.core/lib/freeplaneeditor.jar
 
   core/org.freeplane.core/lib/freeplaneeditor.jar
Line 91: Line 99:
 
===Structure of a plugin===
 
===Structure of a plugin===
  
A plugin is defined by its <tt>MANIFEST.MF</tt>, here an extract from the <tt>org.freeplane.core</tt> plugin (<tt>core/org.freeplane.core/META-INF/MANIFEST.MF</tt>):
+
A plugin is defined by its &lt;tt&gt;MANIFEST.MF&lt;/tt&gt;, here an extract from the &lt;tt&gt;org.freeplane.core&lt;/tt&gt; plugin (&lt;tt&gt;core/org.freeplane.core/META-INF/MANIFEST.MF&lt;/tt&gt;):
  
 
   Bundle-Name: org.freeplane.core
 
   Bundle-Name: org.freeplane.core
Line 112: Line 120:
 
   org.freeplane.view.swing.ui.mindmapmode
 
   org.freeplane.view.swing.ui.mindmapmode
  
This defines the class path that is available within the bundle (<tt>Bundle-ClassPath</tt>), its version (versioning support is an important feature of OSGI), the list of packages that this plugin exports to others (<tt>Export-Package</tt>) and the Activator class of the bundle (<tt>Bundle-Activator</tt>).
+
This defines the class path that is available within the bundle (&lt;tt&gt;Bundle-ClassPath&lt;/tt&gt;), its version (versioning support is an important feature of OSGI), the list of packages that this plugin exports to others (&lt;tt&gt;Export-Package&lt;/tt&gt;) and the Activator class of the bundle (&lt;tt&gt;Bundle-Activator&lt;/tt&gt;).
  
 
==Startup sequence==
 
==Startup sequence==
  
The startup sequence begins with essentially the following command (compare <tt>freemind.sh</tt>):
+
The startup sequence begins with essentially the following command (compare &lt;tt&gt;freemind.sh&lt;/tt&gt;):
  
   cd "/Program Files/Freeplane"
+
   cd &quot;/Program Files/Freeplane&quot;
 
   java \
 
   java \
     -jar ./framework.jar" \
+
     -jar ./framework.jar&quot; \
     -xargs ./init.xargs"
+
     -xargs ./init.xargs&quot;
  
(The remaining arguments are mainly used for Knoplerfish configuration and memory settings.) The JAR is the Knoplerfish implementation JAR and <tt>init.xargs</tt> contains the directory where the plugin lookup should start:
+
(The remaining arguments are mainly used for Knoplerfish configuration and memory settings.) The JAR is the Knoplerfish implementation JAR and &lt;tt&gt;init.xargs&lt;/tt&gt; contains the directory where the plugin lookup should start:
  
 
   $ cat init.xargs
 
   $ cat init.xargs
 
   -istart org.freeplane.core
 
   -istart org.freeplane.core
  
This tells Knoplerfish to load the <tt>org.freeplane.core</tt> plugin first. Knoplerfish inspects <tt>core/org.freeplane.core/META-INF/MANIFEST.MF</tt> for the Activator class of this bundle. As we have seen in [[#Structure of a plugin]] the Activator class is <tt>org.freeplane.main.osgi.Activator</tt>.
+
This tells Knoplerfish to load the &lt;tt&gt;org.freeplane.core&lt;/tt&gt; plugin first. Knoplerfish inspects &lt;tt&gt;core/org.freeplane.core/META-INF/MANIFEST.MF&lt;/tt&gt; for the Activator class of this bundle. As we have seen in [[#Structure of a plugin]] the Activator class is &lt;tt&gt;org.freeplane.main.osgi.Activator&lt;/tt&gt;.
  
Knoplerfish then runs <tt>org.freeplane.main.osgi.Activator.start()</tt> which then performs all the remaining startup steps:
+
Knoplerfish then runs &lt;tt&gt;org.freeplane.main.osgi.Activator.start()&lt;/tt&gt; which then performs all the remaining startup steps:
  
* It creates an instance of <tt>org.freeplane.main.application.Freeplane</tt> which is responsible for the creation of controllers, actions, menus - short the complete basic application.
+
* It creates an instance of &lt;tt&gt;org.freeplane.main.application.Freeplane&lt;/tt&gt; which is responsible for the creation of controllers, actions, menus - short the complete basic application.
* Then it loads the other plugins from directory <tt>plugins</tt>, one after the other, by creating them from by loading their JARs and starting them (see <tt>ActivatorImpl.loadPlugins()</tt>)
+
* Then it loads the other plugins from directory &lt;tt&gt;plugins&lt;/tt&gt;, one after the other, by creating them from by loading their JARs and starting them (see &lt;tt&gt;ActivatorImpl.loadPlugins()&lt;/tt&gt;)
  
 
   // org.freeplane.main.osgi.ActivatorImpl.startFramework()
 
   // org.freeplane.main.osgi.ActivatorImpl.startFramework()
Line 142: Line 150:
 
===Create a new Plugin===
 
===Create a new Plugin===
  
A simple tool helps to get started with plugin development. It's an Ant Task named 'create-plugin' that is available from the <tt>freeplane_framework/ant</tt> directory. The task reads all required parameters from the command line. (If you want to do it non-interactively you have to create your own Ant task.)
+
A simple tool helps to get started with plugin development. It's an Ant Task named 'create-plugin' that is available from the &lt;tt&gt;freeplane_framework/ant&lt;/tt&gt; directory. The task reads all required parameters from the command line. (If you want to do it non-interactively you have to create your own Ant task.)
  
 
See [[Plugin development]] for details.
 
See [[Plugin development]] for details.
Line 151: Line 159:
  
 
* All Bundle properties can be managed via the project properties.
 
* All Bundle properties can be managed via the project properties.
* Launch configurations don't need to rely on Knopflerfish. - One launch configuration in the Freeplane sources, <tt>freeplane_devresources/eclipse/freeplane-osgi.launch</tt>, uses Eclipse' standard OSGI implementation.
+
* Launch configurations don't need to rely on Knopflerfish. - One launch configuration in the Freeplane sources, &lt;tt&gt;freeplane_devresources/eclipse/freeplane-osgi.launch&lt;/tt&gt;, uses Eclipse' standard OSGI implementation.
  
''Note:'' Unlike in the "real application" it's necessary to list all plugins to load in the launch configuration. In the regularly deployed application all plugins in the <tt>plugin</tt> subdirectory are loaded. (By the way also the user's Freeplane directory is scanned for plugins in a <tt>plugin</tt> directory if this exists.)
+
''Note:'' Unlike in the &quot;real application&quot; it's necessary to list all plugins to load in the launch configuration. In the regularly deployed application all plugins in the &lt;tt&gt;plugin&lt;/tt&gt; subdirectory are loaded. (By the way also the user's Freeplane directory is scanned for plugins in a &lt;tt&gt;plugin&lt;/tt&gt; directory if this exists.)
  
 
=Architectural concepts=
 
=Architectural concepts=
Line 166: Line 174:
 
The simplest plugin just needs a single class, the Activator class. If it should do some work then it should define an action, hooks them into the menu. So most of the work of creating a plugin will be spent setting up the directory/project structure.
 
The simplest plugin just needs a single class, the Activator class. If it should do some work then it should define an action, hooks them into the menu. So most of the work of creating a plugin will be spent setting up the directory/project structure.
  
''Plan (VB)'': add a <tt>freeplane_ant</tt> task that creates a new plugin skeleton.
+
''Plan (VB)'': add a &lt;tt&gt;freeplane_ant&lt;/tt&gt; task that creates a new plugin skeleton.
  
 
==Modes==
 
==Modes==
Line 182: Line 190:
 
TODO: Feature ''or'' Extension?
 
TODO: Feature ''or'' Extension?
  
Features implement a bit of functionality like an icon assigned to a node, a note, an attribute, etc. A feature ideally consists of up to four parts, as in <tt>org.freeplane.features.common.edge</tt>:
+
Features implement a bit of functionality like an icon assigned to a node, a note, an attribute, etc. A feature ideally consists of up to four parts, as in &lt;tt&gt;org.freeplane.features.common.edge&lt;/tt&gt;:
  
* a contribution to the map model; it holds the actual data, like a text, a color etc. (<tt>EdgeModel</tt>),
+
* a contribution to the map model; it holds the actual data, like a text, a color etc. (&lt;tt&gt;EdgeModel&lt;/tt&gt;),
* a controller class that integrates the feature into the application by registering actions and listeners (<tt>EdgeController</tt>),
+
* a controller class that integrates the feature into the application by registering actions and listeners (&lt;tt&gt;EdgeController&lt;/tt&gt;),
* a view which displays the element in a map; it is often implemented in a separate java package e.g.<tt>org.freeplane.view.swing.map.edge</tt>,
+
* a view which displays the element in a map; it is often implemented in a separate java package e.g.&lt;tt&gt;org.freeplane.view.swing.map.edge&lt;/tt&gt;,
* and a builder class that is able to serialize and de-serialize the model into XML, i.e. to store the model within the map (<tt>EdgeBuilder</tt>),
+
* and a builder class that is able to serialize and de-serialize the model into XML, i.e. to store the model within the map (&lt;tt&gt;EdgeBuilder&lt;/tt&gt;),
  
 
TODO: add more details! Is EdgeStyle a fourth, general part?
 
TODO: add more details! Is EdgeStyle a fourth, general part?

Revision as of 03:53, 24 November 2010


Overview

Freeplane is a Java Swing application that has two major variants:

  • Standalone desktop application (full functionality)
    • This is the application most people know.
    • The distribution contains also a Portable version of the desktop application. It's just a different style of packaging the application to make it portable on USB sticks etc. but it's not another application.
  • Browser applet (limited functionality)
    • Collaboration features (as in FreeMind) are not yet available.

Projects

All major components have their own project (toplevel directory in the version control system and an Eclipse project) and they are build into separate JARs.

 freeplane
 freeplane_mac
 freeplane_plugin_bugreport
 freeplane_plugin_help
 freeplane_plugin_latex
 freeplane_plugin_script
 freeplane_plugin_script_test
 freeplane_plugin_svg

Their build is described in build.xml files:

 $ grep -H /freeplane.*jar freeplane/ant/ant.properties; \
   egrep '(<jar )|property.*name="free.*jar"' */ant/build.xml
 freeplane/ant/ant.properties:  freeplaneviewer.jar = ${freeplane.dist.lib}/freeplaneviewer.jar
 freeplane/ant/ant.properties:  freeplaneeditor.jar = ${freeplane.dist.lib}/freeplaneeditor.jar
 freeplane/ant/ant.properties:  freeplaneosgi.jar = ${freeplane.dist.lib}/freeplaneosgi.jar
 freeplane/ant/ant.properties:  freeplanemac.jar = ${freeplane.ext.lib}/freeplanemac.jar
 freeplane/ant/build.xml:  <property name="freeplaneant.jar" value="${workspace}/freeplane_framework/ant/lib/freeplaneant.jar" />
 freeplane/ant/build.xml:  <property name="freeplaneplugin.jar" value="${dist.osgi.dir}/org.freeplane.core.jar" />
 freeplane/ant/build.xml:  <jar jarfile="${freeplaneviewer.jar}">
 freeplane/ant/build.xml:  <jar jarfile="${freeplaneeditor.jar}" manifest="${manifest}">
 freeplane/ant/build.xml:  <jar jarfile="${freeplaneosgi.jar}">
 freeplane/ant/build.xml:  <jar jarfile="${freeplaneplugin.jar}">
 freeplane_mac/ant/build.xml:  <jar jarfile="${workspace}/freeplane/lib/freeplanemac.jar" update="false" >
 freeplane_plugin_bugreport/ant/build.xml:  <property name="freeplaneplugin.jar" value="${dist}/org.freeplane.plugin.bugreport.jar"/>
 freeplane_plugin_bugreport/ant/build.xml:  <jar jarfile="${freeplaneplugin.jar}">
 freeplane_plugin_help/ant/build.xml:  <property name="freeplaneplugin.jar" value="${dist}/org.freeplane.plugin.help.jar"/>
 freeplane_plugin_help/ant/build.xml:  <jar jarfile="${freeplaneplugin.jar}">
 freeplane_plugin_latex/ant/build.xml:  <property name="freeplaneplugin.jar" value="${dist}/org.freeplane.plugin.latex.jar"/>
 freeplane_plugin_latex/ant/build.xml:  <jar jarfile="${freeplaneplugin.jar}">
 freeplane_plugin_script/ant/build.xml:  <property name="freeplaneplugin.jar" value="${dist}/org.freeplane.plugin.script.jar"/>
 freeplane_plugin_script/ant/build.xml:  <jar jarfile="${freeplaneplugin.jar}">
 freeplane_plugin_svg/ant/build.xml:  <property name="freeplaneplugin.jar" value="${dist}/org.freeplane.plugin.svg.jar"/>
 freeplane_plugin_svg/ant/build.xml:  <jar jarfile="${freeplaneplugin.jar}">

The additional projects, <tt>freeplane_devresources</tt> and <tt>freeplane_framework</tt>, have a higher level scope; the latter is the centralized entry into the build system to build the whole application:

 $ cd freeplane_framework/ant
 $ ant build dist


OSGI Framework

The architecture is based on the OSGI framework and uses Knoplerfish as OSGI implementation.

The fact that Freeplane is build on OSGI has the following consequences:

  • All of Freeplane's components are packaged as OSGI bundles (aka "plugins").
  • Freeplane is launched in two steps:
  1. The OSGI kernel, which is an external library, is launched.
  2. The kernel initiates loading of all plugins.


Plugins

All Freeplane projects but <tt>freeplane</tt> build a single <tt>plugin.jar</tt> (<tt>freeplane</tt> builds one plugin consisting of four JARs):

 $ cd "/Program Files/Freeplane"
 $ find . -name [pf][rl]\*.jar -o -name \*.MF
 core/org.freeplane.core/lib/freeplaneeditor.jar
 core/org.freeplane.core/lib/freeplanemac.jar
 core/org.freeplane.core/lib/freeplaneosgi.jar
 core/org.freeplane.core/lib/freeplaneviewer.jar
 core/org.freeplane.core/META-INF/MANIFEST.MF
 framework.jar
 plugins/org.freeplane.plugin.bugreport/lib/plugin.jar
 plugins/org.freeplane.plugin.bugreport/META-INF/MANIFEST.MF
 plugins/org.freeplane.plugin.latex/lib/plugin.jar
 plugins/org.freeplane.plugin.latex/META-INF/MANIFEST.MF
 plugins/org.freeplane.plugin.script/lib/plugin.jar
 plugins/org.freeplane.plugin.script/META-INF/MANIFEST.MF
 plugins/org.freeplane.plugin.svg/lib/plugin.jar
 plugins/org.freeplane.plugin.svg/META-INF/MANIFEST.MF

Structure of a plugin

A plugin is defined by its <tt>MANIFEST.MF</tt>, here an extract from the <tt>org.freeplane.core</tt> plugin (<tt>core/org.freeplane.core/META-INF/MANIFEST.MF</tt>):

 Bundle-Name: org.freeplane.core
 Bundle-Version: 1.0.1
 Bundle-ClassPath: lib/freeplaneviewer.jar,
  lib/freeplaneeditor.jar,
  lib/freeplanemac.jar,
  lib/freeplaneosgi.jar,
  lib/commons-lang-2.0.jar,
  lib/forms-1.0.5.jar,
  lib/gnu-regexp-1.1.4.jar,
  lib/SimplyHTML.jar,
  lib/jortho.jar
 Bundle-Activator: org.freeplane.main.osgi.Activator
 Import-Package: org.osgi.framework
 Export-Package: org.apache.commons.lang,
  org.freeplane.core.addins,
  org.freeplane.core.controller,
  [...]
  org.freeplane.view.swing.ui.mindmapmode

This defines the class path that is available within the bundle (<tt>Bundle-ClassPath</tt>), its version (versioning support is an important feature of OSGI), the list of packages that this plugin exports to others (<tt>Export-Package</tt>) and the Activator class of the bundle (<tt>Bundle-Activator</tt>).

Startup sequence

The startup sequence begins with essentially the following command (compare <tt>freemind.sh</tt>):

 cd "/Program Files/Freeplane"
 java \
   -jar ./framework.jar" \
   -xargs ./init.xargs"

(The remaining arguments are mainly used for Knoplerfish configuration and memory settings.) The JAR is the Knoplerfish implementation JAR and <tt>init.xargs</tt> contains the directory where the plugin lookup should start:

 $ cat init.xargs
 -istart org.freeplane.core

This tells Knoplerfish to load the <tt>org.freeplane.core</tt> plugin first. Knoplerfish inspects <tt>core/org.freeplane.core/META-INF/MANIFEST.MF</tt> for the Activator class of this bundle. As we have seen in #Structure of a plugin the Activator class is <tt>org.freeplane.main.osgi.Activator</tt>.

Knoplerfish then runs <tt>org.freeplane.main.osgi.Activator.start()</tt> which then performs all the remaining startup steps:

  • It creates an instance of <tt>org.freeplane.main.application.Freeplane</tt> which is responsible for the creation of controllers, actions, menus - short the complete basic application.
  • Then it loads the other plugins from directory <tt>plugins</tt>, one after the other, by creating them from by loading their JARs and starting them (see <tt>ActivatorImpl.loadPlugins()</tt>)
 // org.freeplane.main.osgi.ActivatorImpl.startFramework()
 starter = new FreeplaneStarter();
 loadPlugins(context);
 final Controller controller = starter.createController();

Create a new Plugin

A simple tool helps to get started with plugin development. It's an Ant Task named 'create-plugin' that is available from the <tt>freeplane_framework/ant</tt> directory. The task reads all required parameters from the command line. (If you want to do it non-interactively you have to create your own Ant task.)

See Plugin development for details.

OSGI support in Eclipse

Like Freeplane, Eclipse is based on an OSGI kernel. For this reason Eclipse provides very good support for developing OSGI applications:

  • All Bundle properties can be managed via the project properties.
  • Launch configurations don't need to rely on Knopflerfish. - One launch configuration in the Freeplane sources, <tt>freeplane_devresources/eclipse/freeplane-osgi.launch</tt>, uses Eclipse' standard OSGI implementation.

Note: Unlike in the "real application" it's necessary to list all plugins to load in the launch configuration. In the regularly deployed application all plugins in the <tt>plugin</tt> subdirectory are loaded. (By the way also the user's Freeplane directory is scanned for plugins in a <tt>plugin</tt> directory if this exists.)

Architectural concepts

Freeplane's Architecture has some special basic elements which are used for structuring and organizing code:

  • Plugins (OSGI bundles), the most basic ones, have been mentioned already.
  • Features/Extensions

Plugins

The simplest plugin just needs a single class, the Activator class. If it should do some work then it should define an action, hooks them into the menu. So most of the work of creating a plugin will be spent setting up the directory/project structure.

Plan (VB): add a <tt>freeplane_ant</tt> task that creates a new plugin skeleton.

Modes

  • MindMapMode
  • BrowserMode
  • FileMode

Mode Controller

Set of actions available for the user

TODO

Features/Extensions

TODO: Feature or Extension?

Features implement a bit of functionality like an icon assigned to a node, a note, an attribute, etc. A feature ideally consists of up to four parts, as in <tt>org.freeplane.features.common.edge</tt>:

  • a contribution to the map model; it holds the actual data, like a text, a color etc. (<tt>EdgeModel</tt>),
  • a controller class that integrates the feature into the application by registering actions and listeners (<tt>EdgeController</tt>),
  • a view which displays the element in a map; it is often implemented in a separate java package e.g.<tt>org.freeplane.view.swing.map.edge</tt>,
  • and a builder class that is able to serialize and de-serialize the model into XML, i.e. to store the model within the map (<tt>EdgeBuilder</tt>),

TODO: add more details! Is EdgeStyle a fourth, general part?

Architectural principles

TODO: put the general guidelines here