/[debian]/libjpfcodegen-java/branches/upstream/current/tutorials/basic/index.html
ViewVC logotype

Contents of /libjpfcodegen-java/branches/upstream/current/tutorials/basic/index.html

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1609 - (show annotations)
Sun Mar 1 18:00:34 2009 UTC (12 years, 4 months ago) by gregoa
File MIME type: text/html
File size: 17408 byte(s)
[svn-inject] Installing original source of libjpfcodegen-java
1 <?xml version="1.0" encoding="utf-8"?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
4
5 <head>
6 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7 <title>JPF Code Generator - Basic Tutorial</title>
8 <script type="text/javascript"
9 src="../../resources/website/sh_main.min.js" />
10 <script type="text/javascript" src="../../resources/website/sh_java.js" />
11 <script type="text/javascript"
12 src="../../resources/website/sh_xml.min.js" />
13 <link type="text/css" rel="stylesheet"
14 href="../../resources/website/sh_ide-eclipse.css" />
15 <style type="text/css">
16 /*<![CDATA[*/
17 body {
18 margin: 0;
19 margin-bottom: 20px;
20 padding: 0;
21 background-color: #CCCCCC;
22 font-family: Verdana, Arial, Helvetica, sans-serif;
23 font-size: 10pt;
24 color: #000000;
25 }
26
27 h1,h2,h3,p {
28 margin-top: 10pt;
29 margin-bottom: 3pt;
30 padding-left: 15pt;
31 padding-right: 15pt;
32 }
33
34 h2 {
35 padding-top: 15pt;
36 border-top: solid 1px #999999;
37 }
38
39 .example {
40 margin: 15pt;
41 padding-left: 10pt;
42 padding-right: 10pt;
43 background-color: #EEEEEE;
44 border: solid 1px #999999;
45 color: #000000;
46 }
47
48 .example pre {
49 margin: 10pt;
50 padding: 5pt;
51 border: solid 1px #999999;
52 background-color: #FFFFFF;
53 }
54
55 .example p {
56 padding: 0;
57 }
58
59 dl,ul,ol {
60 margin-top: 3pt;
61 margin-bottom: 3pt;
62 padding-left: 15pt;
63 padding-right: 15pt;
64 }
65
66 dt {
67 margin: 10pt 0 0 0;
68 padding: 0;
69 font-weight: bold;
70 }
71
72 dd {
73 margin: 0;
74 padding: 0;
75 }
76
77 li,img {
78 margin-left: 15pt;
79 }
80
81 a {
82 text-decoration: none;
83 color: #990000;
84 }
85
86 hr {
87 margin-top: 0;
88 margin-bottom: 0;
89 }
90 /*]]>*/
91 </style>
92 </head>
93
94 <body onload="sh_highlightDocument();">
95
96 <h1><a href="http://www.inf.fu-berlin.de/~oezbek/jpf/">JPF Code
97 Generator</a> - Basic Tutorial</h1>
98
99 <h2>Table of Contents</h2>
100 <ol>
101 <li><a href="#intro">Introduction</a></li>
102 <li><a href="#corexml">Creating the Core Plugin's plugin.xml</a></li>
103 <li><a href="#createPlugin">Creating the extending Plugins</a></li>
104 <li><a href="#generateCode">Running the code generator</a></li>
105 <li><a href="#createTheApplication">Creating the Application</a></li>
106 <li><a href="#conclusion">Conclusion</a></li>
107 <li><a href="#contact">Contact</a></li>
108 </ol>
109
110 <h2 id="intro">Introduction</h2>
111
112 <p>This tutorial describes an absolute minimal use-case for JPF and
113 the JPF Code Generator tool. The example system is a stripped-down
114 version of the <a href="http://jpf.sourceforge.net/tutorial.html">JPF
115 Tutorial</a> example. The system consists of three plugins: One core plug-in
116 that displays a tabbed pane and offers an extension-point so that
117 plug-ins can contribute panels on this pane and two plug-ins that
118 provide such panels.</p>
119
120 <div class="example">
121 <p>The system uses the default file structure for a JPF based
122 application:</p>
123 <pre>
124 .
125 |-&gt; src Main application source code
126 \-&gt; plugins Folder for plug-ins
127 |-&gt; core The main plug-in that provides extension-points for others to extend.
128 |-&gt; plugin1 An example plug-in that provides one extension
129 \-&gt; plugin2 Another example plug-in that provides one extension</pre>
130 </div>
131
132 <h2 id="corexml">Creating the Core Plugin's plugin.xml</h2>
133
134 <p>The most important plugin.xml is the one of the core plug-in,
135 since it offers the extension point for the other plug-ins to extend.
136 Since this is a basic tutorial we will only a very basic extension point
137 that requires only two parameters to be defined by an extension. First
138 an extending plug-in should tell us the name of the panel it wants to
139 contribute and then it should provide us with a type that extends <code>java.swing.JPanel</code>,
140 so that we can create an instance of this type to add to the tabbed pane
141 of the main application we want to create.</p>
142
143 <div class="example">
144 <p>The resulting plugin.xml for the com.example.core plug-in looks
145 like this:</p>
146 <pre class="sh_xml">
147 &lt;?xml version="1.0" ?&gt;
148 &lt;!DOCTYPE plugin PUBLIC "-//JPF//Java Plug-in Manifest 1.0" "http://jpf.sourceforge.net/plugin_1_0.dtd"&gt;
149 &lt;plugin id="com.example.core" version="1.0.0"
150 class="com.example.core.CorePlugin"&gt;
151
152 &lt;!-- Since the application code uses the core plug-in
153 we do not provide a runtime reference to the class files. --&gt;
154
155 &lt;!-- In this example, the application provides a single extension point for plug-ins to extend: --&gt;
156 &lt;extension-point id="Panel"&gt;
157 &lt;!-- String parameter with custom-data are used to tell the code-generator
158 that this extension-point parameter is really used for getting objects from plug-ins that
159 implement this extension-point.
160
161 The given class name in custom-data will be used as the return-type of the function "getPanel()"
162 that is generated for this parameter.
163 --&gt;
164 &lt;parameter-def type="string" id="panel"
165 custom-data="javax.swing.JPanel" /&gt;
166 &lt;parameter-def type="string" id="name" /&gt;
167 &lt;/extension-point&gt;
168
169 &lt;/plugin&gt;</pre>
170 <p>The runtime attribute is needed, so that JPF can manage the
171 classpath of our application for us. For more details on this have a
172 look at the <a href="http://jpf.sourceforge.net/tutorial.html">JPF
173 tutorial.</a></p>
174 </div>
175
176 <h2 id="createPlugin">Creating the extending Plugins</h2>
177
178 <p>Once we have defined this extension-point, we can now create
179 plug-ins that extend it. In our case we need to do two things for
180 this...</p>
181
182 <div class="example">
183 <p>...we need to create the actual panel class that we want to
184 contribute to the system (for simplicity this is really a very minimal
185 implementation)...</p>
186 <pre class="sh_java">
187 package com.example.plugin1;
188
189 import java.awt.Label;
190
191 import javax.swing.JPanel;
192
193 public class Plugin1Panel extends JPanel {
194
195 private static final long serialVersionUID = -6420919219685347035L;
196
197 public Plugin1Panel(){
198 this.add(new Label("I am Panel 1!"));
199 }
200 }</pre>
201 <p>...and then we need to create the plugin.xml that will contain an
202 extension:</p>
203 <pre class="sh_xml">
204 &lt;?xml version="1.0" ?&gt;
205 &lt;!DOCTYPE plugin PUBLIC "-//JPF//Java Plug-in Manifest 1.0" "http://jpf.sourceforge.net/plugin_1_0.dtd"&gt;
206 &lt;plugin id="com.example.plugin1" version="1.0.0" class="com.example.plugin1.Plugin1"&gt;
207
208 &lt;requires&gt;
209 &lt;import plugin-id="com.example.core"/&gt;
210 &lt;/requires&gt;
211
212 &lt;runtime&gt;
213 &lt;library type="code" path="build/" id="src"/&gt;
214 &lt;/runtime&gt;
215
216 &lt;extension id="Plugin1Panel" plugin-id="com.example.core" point-id="Panel"&gt;
217 &lt;parameter id="panel" value="com.example.plugin1.Plugin1Panel" /&gt;
218 &lt;parameter id="name" value="Plugin No. 1 Panel" /&gt;
219 &lt;/extension&gt;
220
221 &lt;/plugin&gt;</pre>
222 <p>The plugin.xml for the second plugin is similar.</p>
223 </div>
224
225 <h2 id="generateCode">Running the code generator</h2>
226
227 <p>Using these plugin.xml files, we can now use the JPF Code
228 Generator to create code that will make using the plug-in system very
229 easy.</p>
230
231 <div class="example">
232 <p>Go to directory...</p>
233 <pre>tutorials/basic/</pre>
234 <p>...and run the <code>generate</code> <code>ant</code>-task there:</p>
235 <pre>
236 ant generate
237 </pre></div>
238
239 <p>This will create two classes for each plug-in using the
240 class-attribute in the plugin.xml. We will discuss this only for the
241 interesting case of the CorePlugin (the generated classes Plugin1 and
242 Plugin2 classes are empty at the moment since they don't provide
243 extension points)</p>
244
245 <div class="example">
246 <p>The class that contains the important code parts is <code>com.example.core.generated._CorePlugin.java</code>.
247 As you can see below it contains a method for retrieving all extensions
248 for the extension-point. The extensions then contains methods for
249 accessing the attributes <code>panel</code> and <code>name</code>. Since
250 we defined <code>panel</code> to be a string-parameter with a type as
251 custom-data, the code generator has created a method that returns a
252 singleton instance of the type given in the extending plug-in (in the
253 case of <code>com.example.Plugin1</code> this will be an instance of <code>com.example.plugin1.Plugin1Panel</code>).
254 The name method will return just the string value defined in the
255 plugin.xml of the extending plug-in (for the extension in Plugin1 this
256 will be "Plugin No. 1 Panel").</p>
257 <pre class="sh_java">
258 package com.example.core.generated;
259
260 ...imports...
261
262 /**
263 * Do not modify this file, as it was auto generated and will be overwritten!
264 * User modifications should go in com.example.core.CorePlugin.
265 */
266 public abstract class _CorePlugin extends Plugin {
267
268 public static String getId() {
269 return "com.example.core";
270 }
271
272 static Log log = LogFactory.getLog(_CorePlugin.class);
273
274 public List&lt;PanelExtension&gt; getPanelExtensions() {
275 ExtensionPoint extPoint = getManager().getRegistry().getExtensionPoint(
276 getId(), "Panel");
277 List&lt;PanelExtension&gt; result = new ArrayList&lt;PanelExtension&gt;();
278 for (Extension ext : extPoint.getConnectedExtensions()) {
279 try {
280 result.add(new PanelExtension(getManager().getPlugin(
281 ext.getDeclaringPluginDescriptor().getId()), ext));
282 } catch (PluginLifecycleException e) {
283 log.error("Failed to activate plug-in"
284 + ext.getDeclaringPluginDescriptor().getId(), e);
285 }
286 }
287 return result;
288 }
289
290 public static class PanelExtension extends RuntimeExtension {
291 public PanelExtension(Plugin declaringPlugin, Extension wrapped) {
292 super(declaringPlugin, wrapped);
293 }
294
295 /**
296 * @return A singleton instance of the class parameter or null if the class could not be found!
297 */
298 public javax.swing.JPanel getPanel() {
299 return (javax.swing.JPanel) getClassParameter("panel");
300 }
301
302 public String getName() {
303 return getStringParameter("name");
304 }
305 }
306 }</pre>
307 <p>Since this class will be complete overwritten if you re-run the
308 code generator you should not put any custom code into this class.
309 Rather the code generator has created another class that you can
310 customize, which will not get re-generated if it already exists. This
311 class is the <code>com.example.core.CorePlugin.java</code> and looks as
312 follows:</p>
313
314 <pre class="sh_java">
315 package com.example.core;
316
317 import com.example.core.generated._CorePlugin;
318
319 import org.java.plugin.PluginLifecycleException;
320 import org.java.plugin.PluginManager;
321
322 public class CorePlugin extends _CorePlugin {
323
324 public void doStart(){
325 // TODO: Will be called when plug-in is started.
326 }
327
328 public void doStop(){
329 // TODO: Will be called when plug-in is stopped.
330 }
331
332 /**
333 * Retrieve the Plug-in instance from the given manager.
334 *
335 * @param manager
336 * The manager from which to retrieve the plug-in instance
337 *
338 * @return The requested plug-in or null if not found.
339 */
340 public static CorePlugin getInstance(PluginManager manager) {
341 try {
342 return (CorePlugin) manager
343 .getPlugin(CorePlugin.getId());
344 } catch (PluginLifecycleException e) {
345 return null;
346 } catch (IllegalArgumentException e) {
347 return null;
348 }
349 }
350 }</pre></div>
351
352 <h2 id="createTheApplication">Creating the Application</h2>
353
354 <p>In the main application source folder we can now create the
355 application itself <code>com.example.Main</code>. The application will
356 initialize plug-in system, create the main window with a tabbed pane on
357 it and use the plug-in system to fill this tabbed pane.</p>
358
359 <div class="example">
360 <p>First we need to initialize the plug-in system:</p>
361 <pre class="sh_java">
362 // Create Plugin Manager
363 manager = ObjectFactory.newInstance().createManager();
364
365 // Find plugins and add to registry
366 DefaultPluginsCollector collector = new DefaultPluginsCollector();
367 ExtendedProperties ep = new ExtendedProperties();
368 ep.setProperty("org.java.plugin.boot.pluginsRepositories",
369 "./plugins");
370 try {
371 collector.configure(ep);
372 manager.publishPlugins(collector.collectPluginLocations().toArray(
373 new PluginLocation[] {}));
374 } catch (Exception e) {
375 e.printStackTrace();
376 System.exit(0);
377 }</pre>
378 <p>Then we will create a JFrame to show the tabbed pane:</p>
379 <pre class="sh_java">
380 JFrame frame = new JFrame("JPF Code Generator Basic Tutorial");
381 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
382 frame.setSize(400, 300);
383 frame.setLocation(300, 200);
384
385 JTabbedPane tabbedPane = new JTabbedPane();
386 frame.add(tabbedPane);</pre>
387 <p>Now we want to populate the tabbed pane with the Panels that the
388 plug-ins have contributed</p>
389 <pre class="sh_java">
390 // Use the plugin system to find panels to add to the tabbed pane
391 CorePlugin corePlugin = CorePlugin.getInstance(manager);
392
393 // corePlugin might be null here (for instance if the plug-in is missing)
394 if (corePlugin != null){
395
396 // Now we can get all extensions for the Panel extension point
397 for (PanelExtension extension : corePlugin.getPanelExtensions()){
398
399 // The PanelExtension class then allows easy access to the parameters defined
400 // for this extension-point.
401 JPanel panel = extension.getPanel();
402 String name = extension.getName();
403
404 // panel might be null if an error occurred while creating the object
405 if (panel == null){
406 System.out.println("Error loading panel from extension " + extension.getId());
407 continue;
408 }
409
410 tabbedPane.addTab(name, panel);
411 }
412 }</pre>
413
414 <p>(This paragraph contains some advanced topics, you can safely
415 skip it:) You notice that this style of using a plug-in framework is a
416 little different as the one you get when using the JPF-boot library. In
417 contrast to JPF-boot, where everything is a plug-in and the application
418 is started by starting a dedicated application plug-in, this tutorial
419 here uses the plug-in system from a stand-alone application. I feel that
420 this is a more natural approach, when first getting into contact with
421 plug-in architectures. If you want to achieve a pure plug-in style of
422 programming put both the creation of the JFrame and the hooking up of
423 the panels into the doStart method of the <code>com.example.core.CorePlugin</code>.
424 Another point that is important in this discussion is how to set the
425 classpath. If the core plug-in is used by the main application directly,
426 it also needs to be available on the classpath during building and
427 running the application. This means that the core plugin does not
428 provide a runtime plug-in attribute but instead needs to be on the
429 classpath of the application itself.</p>
430
431 <p>Finally we set this frame to visible:</p>
432 <pre class="sh_java">frame.setVisible(true);</pre>
433 <p>If you put all this code in a class body into the method <code>start()</code>
434 your sample application is done.</p>
435 <pre class="sh_java">
436 package com.example;
437
438 import javax.swing.*;
439 import org.java.plugin.*;
440 import org.java.plugin.util.ExtendedProperties;
441 import com.example.core.CorePlugin;
442 import com.example.core.generated._CorePlugin.PanelExtension;
443
444 public class Main {
445
446 public static void main(final String[] args) {
447 // Move to non-static and swing-thread.
448 SwingUtilities.invokeLater(new Runnable(){
449 public void run() {
450 new Main().start(args);
451 }
452 });
453 }
454
455 PluginManager manager;
456
457 public void start(String[] args) {
458
459 !!Code from above goes here!!
460
461 }
462 }</pre>
463 <p>To run the example application go to the folder...</p>
464 <pre>tutorials/basic/</pre>
465 <p>...and run the <code>ant</code>-task <code>run</code>:</p>
466 <pre>ant run</pre></div>
467
468 <h2 id="conclusion">Conclusion</h2>
469
470 <p>In this tutorial you have learned about the basics of using the
471 Java Plug-in Framework in conjunction with the code generator to easily
472 enable a plug-in system for your java application.</p>
473
474 <p>Key points to remember are:</p>
475 <ul>
476 <li>Create plug-ins that define extension-points, and those than
477 provide extensions for them.</li>
478 <li>Use the JPF Code Generator to generate code for easy access on
479 these extensions and attributes.</li>
480 <li>Start-up the plug-in system using the boiler-plate code
481 described above.</li>
482 <li>As an advanced note: Both styles of using the plug-in
483 framework (from an application and purely plug-in based) are supported
484 by JPF and the code generator.</li>
485 </ul>
486
487 <p>More information on how to use the code generator is provided <a
488 href="../../index.html">in its documentation</a> (for instance if you
489 don't want to use the class attribute to define which class gets
490 generated) and further information about JPF in general is best found on
491 the <a href="http://jpf.sf.net/">JPF Homepage on Sourceforge</a>.</p>
492
493 <h2 id="contact">Contact</h2>
494
495 <p>Copyright (C) Christopher Oezbek (2007) - <a
496 href="mailto:oezi[at]oezi.de">oezi[at]oezi.de</a></p>
497
498 <p>Your <a href="mailto:oezi[at]oezi.de">improvements and
499 suggestions are welcome</a>.</p>
500
501 </body>
502 </html>
503
504

  ViewVC Help
Powered by ViewVC 1.1.26