Browse files

Added extender chapter code; removed BundleTracker

  • Loading branch information...
1 parent 168b8a7 commit 43a06fe15e127b31f5476f149e147ca76dc39e34 @njbartlett committed Oct 26, 2009
Showing with 484 additions and 141 deletions.
  1. 0 README
  2. +0 −133 common/src/org/osgi/utils/BundleTracker.java
  3. +2 −2 concurrency/.classpath
  4. BIN concurrency/bundles/osgi.cmpn.jar
  5. BIN concurrency/bundles/osgi.cmpn.r4_2.jar
  6. 0 concurrency/{src/org/osgi/book/reader/tutorial → scala_src}/JLabelMailboxCountTracker.scala
  7. +2 −2 example1/.classpath
  8. BIN example1/bundles/osgi.cmpn.jar
  9. BIN example1/bundles/osgi.cmpn.r4_2.jar
  10. +9 −0 extender/.classpath
  11. +2 −0 extender/.gitignore
  12. +17 −0 extender/.project
  13. BIN extender/bundles/osgi.cmpn.r4_2.jar
  14. +3 −0 extender/help_sample.bnd
  15. +3 −0 extender/helpextender.bnd
  16. +5 −0 extender/mbox_svc_extender.bnd
  17. +15 −0 extender/resources/extension_registry/plugin.xml
  18. +5 −0 extender/resources/help_sample/first_steps.html
  19. +4 −0 extender/resources/help_sample/index.properties
  20. +3 −0 extender/runtime/.gitignore
  21. +3 −0 extender/sample_svc_extender.bnd
  22. +58 −0 extender/src/org/osgi/book/extender/service/MailboxServiceExtender.java
  23. +26 −0 extender/src/org/osgi/book/extender/service/MailboxServiceExtenderActivator.java
  24. +18 −0 extender/src/org/osgi/book/extender/service/sample/MyMailbox.java
  25. +105 −0 extender/src/org/osgi/book/help/extender/HelpExtender.java
  26. +30 −0 extender/src/org/osgi/book/help/extender/HelpExtenderActivator.java
  27. +70 −0 extender/src/org/osgi/book/help/extender/HelpExtenderVer1.java
  28. +29 −0 extender/src/org/osgi/book/help/extender/HelpListCommand.java
  29. +17 −0 extender/src/org/osgi/book/help/extender/HelpScannerException.java
  30. +33 −0 extender/src/org/osgi/book/utils/LogTracker.java
  31. +21 −0 extender/src/org/osgi/book/utils/Pair.java
  32. +1 −1 firststeps/.classpath
  33. +2 −2 intro_svcs/.classpath
  34. BIN intro_svcs/bundles/osgi.cmpn.jar
  35. BIN intro_svcs/bundles/osgi.cmpn.r4_2.jar
  36. +1 −1 whiteboard/.classpath
View
0 README
No changes.
View
133 common/src/org/osgi/utils/BundleTracker.java
@@ -1,133 +0,0 @@
-package org.osgi.utils;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.BundleListener;
-import org.osgi.framework.SynchronousBundleListener;
-
-public abstract class BundleTracker {
-
- private final BundleContext context;
- private final Map<String, Bundle> trackedSet
- = new HashMap<String, Bundle>();
-
- private final BundleListener listener =
- new SynchronousBundleListener() {
- public void bundleChanged(BundleEvent event) {
- if (BundleEvent.STARTED == event.getType()) {
- internalAdd(event.getBundle());
- } else if (BundleEvent.STOPPING == event.getType()) {
- internalRemove(event.getBundle());
- }
- }
- };
-
- private boolean isOpen = false;
-
- public BundleTracker(BundleContext context) {
- this.context = context;
- }
-
- /**
- * Open this <code>BundleTracker</code> and begin tracking
- */
- public final void open() {
- synchronized (this) {
- if (isOpen) {
- return;
- } else {
- isOpen = true;
- }
- }
-
- context.addBundleListener(listener);
-
- Bundle[] bundles = context.getBundles();
- for (Bundle bundle : bundles) {
- if (Bundle.ACTIVE == bundle.getState()) {
- internalAdd(bundle);
- }
- }
- }
-
- /**
- * Close this <code>BundleTracker</code> and stop tracking
- */
- public final void close() {
- synchronized (this) {
- if (!isOpen) {
- return;
- } else {
- isOpen = false;
- }
- }
- context.removeBundleListener(listener);
-
- Bundle[] bundles;
- synchronized (trackedSet) {
- bundles = trackedSet.values().toArray(
- new Bundle[trackedSet.size()]);
- }
-
- for (Bundle bundle : bundles) {
- internalRemove(bundle);
- }
- }
-
- /**
- * Return a snapshot of the currently tracked bundles.
- */
- public Bundle[] getBundles() {
- synchronized (trackedSet) {
- Collection<Bundle> bundles = trackedSet.values();
- Bundle[] result = bundles.toArray(
- new Bundle[bundles.size()]);
- return result;
- }
- }
-
- /**
- * Called when a bundle is being added to the
- * <code>BundleTracker</code>. This method does nothing, it is
- * expected to be overridden by concrete subclasses.
- *
- * @param bundle
- */
- protected void addingBundle(Bundle bundle) {
- }
-
- /**
- * Called when a bundle is being removed from the
- * <code>BundleTracker</code> This method does nothing, it is
- * expected to be overridden by concrete subclasses.
- *
- * @param bundle
- */
- protected void removedBundle(Bundle bundle) {
- }
-
- private void internalAdd(Bundle bundle) {
- Bundle prior;
- synchronized (trackedSet) {
- prior = trackedSet.put(bundle.getLocation(), bundle);
- }
- if (prior == null) {
- addingBundle(bundle);
- }
- }
-
- private void internalRemove(Bundle bundle) {
- Bundle removed;
- synchronized (trackedSet) {
- removed = trackedSet.remove(bundle.getLocation());
- }
- if (removed != null) {
- removedBundle(removed);
- }
- }
-}
View
4 concurrency/.classpath
@@ -2,9 +2,9 @@
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
- <classpathentry kind="lib" path="bundles/osgi.cmpn.jar"/>
<classpathentry combineaccessrules="false" kind="src" path="/intro_svcs"/>
<classpathentry combineaccessrules="false" kind="src" path="/dependencies"/>
- <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Equinox"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Equinox 3.5.1"/>
+ <classpathentry kind="lib" path="bundles/osgi.cmpn.r4_2.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
View
BIN concurrency/bundles/osgi.cmpn.jar
Binary file not shown.
View
BIN concurrency/bundles/osgi.cmpn.r4_2.jar
Binary file not shown.
View
0 .../tutorial/JLabelMailboxCountTracker.scala → ...scala_src/JLabelMailboxCountTracker.scala
File renamed without changes.
View
4 example1/.classpath
@@ -2,8 +2,8 @@
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="lib" path="bundles/osgi.cmpn.jar"/>
- <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Equinox"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Equinox 3.5.1"/>
<classpathentry combineaccessrules="false" kind="src" path="/dependencies"/>
+ <classpathentry kind="lib" path="bundles/osgi.cmpn.r4_2.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
View
BIN example1/bundles/osgi.cmpn.jar
Binary file not shown.
View
BIN example1/bundles/osgi.cmpn.r4_2.jar
Binary file not shown.
View
9 extender/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Equinox 3.5.1"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/dependencies"/>
+ <classpathentry kind="lib" path="bundles/osgi.cmpn.r4_2.jar"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
View
2 extender/.gitignore
@@ -0,0 +1,2 @@
+/bin
+/*.jar
View
17 extender/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>extender</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
View
BIN extender/bundles/osgi.cmpn.r4_2.jar
Binary file not shown.
View
3 extender/help_sample.bnd
@@ -0,0 +1,3 @@
+# help_sample.bnd
+Help-Index: docs/index.properties
+Include-Resource: docs=resources/help_sample
View
3 extender/helpextender.bnd
@@ -0,0 +1,3 @@
+update 1# helpextender.bnd
+Private-Package: org.osgi.book.help.extender, org.osgi.book.utils
+Bundle-Activator: org.osgi.book.help.extender.HelpExtenderActivator
View
5 extender/mbox_svc_extender.bnd
@@ -0,0 +1,5 @@
+# mbox_svc_extender.bnd
+Private-Package: org.osgi.book.extender.service,\
+ org.osgi.book.utils
+Bundle-Activator:\
+ org.osgi.book.extender.service.MailboxServiceExtenderActivator
View
15 extender/resources/extension_registry/plugin.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<plugin>
+
+ <extension-point id="org.foo.commands"
+ name="Commands"
+ schema="schema/org.foo.commands.exsd"/>
+
+ <extension point="org.foo.commands">
+ <command id="org.bar.mycommand"
+ class="org.bar.MyCommand">
+ </command>
+ </extension>
+
+</plugin>
View
5 extender/resources/help_sample/first_steps.html
@@ -0,0 +1,5 @@
+<html>
+<head><title>First Steps in OSGi</title></head>
+<body>
+</body>
+</html>
View
4 extender/resources/help_sample/index.properties
@@ -0,0 +1,4 @@
+introduction=Introduction
+first_steps=First Steps in OSGi
+dependencies=Bundle Dependencies
+intro_services=Introduction to Services
View
3 extender/runtime/.gitignore
@@ -0,0 +1,3 @@
+*
+!config.ini
+!.gitignore
View
3 extender/sample_svc_extender.bnd
@@ -0,0 +1,3 @@
+# sample_svc_extender.bnd
+Private-Package: org.osgi.book.extender.service.sample
+Mailbox-ServiceClass: org.osgi.book.extender.service.sample.MyMailbox
View
58 extender/src/org/osgi/book/extender/service/MailboxServiceExtender.java
@@ -0,0 +1,58 @@
+package org.osgi.book.extender.service;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.osgi.book.reader.api.Mailbox;
+import org.osgi.framework.*;
+import org.osgi.service.log.LogService;
+import org.osgi.util.tracker.BundleTracker;
+
+public class MailboxServiceExtender extends BundleTracker {
+
+ private static final String SVC_HEADER = "Mailbox-ServiceClass";
+ private final Map<String, ServiceRegistration> registrations
+ = new ConcurrentHashMap<String, ServiceRegistration>();
+ private final LogService log;
+
+ public MailboxServiceExtender(BundleContext ctx, LogService log) {
+ super(ctx, Bundle.ACTIVE, null);
+ this.log = log;
+ }
+
+ @Override
+ public Object addingBundle(Bundle bundle, BundleEvent ev) {
+ Bundle result = null;
+ String className = (String) bundle.getHeaders().get(SVC_HEADER);
+ if (className != null) {
+ try {
+ Class<?> svcClass = bundle.loadClass(className);
+ if (!Mailbox.class.isAssignableFrom(svcClass)) {
+ log.log(LogService.LOG_ERROR,
+ "Declared class is not an instance of Mailbox");
+ } else {
+ Object instance = svcClass.newInstance();
+ ServiceRegistration reg = bundle.getBundleContext()
+ .registerService(Mailbox.class.getName(), instance,
+ null);
+ registrations.put(bundle.getLocation(), reg);
+ result = bundle;
+ }
+ } catch (ClassNotFoundException e) {
+ log.log(LogService.LOG_ERROR, "Error creating service", e);
+ } catch (InstantiationException e) {
+ log.log(LogService.LOG_ERROR, "Error creating service", e);
+ } catch (IllegalAccessException e) {
+ log.log(LogService.LOG_ERROR, "Error creating service", e);
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public void removedBundle(Bundle bundle, BundleEvent ev, Object ebj) {
+ ServiceRegistration reg;
+ reg = registrations.remove(bundle.getLocation());
+ if (reg != null) reg.unregister();
+ }
+}
View
26 extender/src/org/osgi/book/extender/service/MailboxServiceExtenderActivator.java
@@ -0,0 +1,26 @@
+package org.osgi.book.extender.service;
+
+import org.osgi.book.utils.LogTracker;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class MailboxServiceExtenderActivator
+ implements BundleActivator {
+
+ private volatile LogTracker logTracker;
+ private volatile MailboxServiceExtender extender;
+
+ public void start(BundleContext context) throws Exception {
+ logTracker = new LogTracker(context);
+ logTracker.open();
+
+ extender = new MailboxServiceExtender(context, logTracker);
+ extender.open();
+ }
+
+ public void stop(BundleContext context) throws Exception {
+ extender.close();
+ logTracker.close();
+ }
+
+}
View
18 extender/src/org/osgi/book/extender/service/sample/MyMailbox.java
@@ -0,0 +1,18 @@
+package org.osgi.book.extender.service.sample;
+
+import org.osgi.book.reader.api.*;
+
+public class MyMailbox implements Mailbox {
+
+ public long[] getAllMessages() {
+ return new long[0];
+ }
+ public Message[] getMessages(long[] ids) {
+ return new Message[0];
+ }
+ public long[] getMessagesSince(long id) {
+ return new long[0];
+ }
+ public void markRead(boolean read, long[] ids) {
+ }
+}
View
105 extender/src/org/osgi/book/help/extender/HelpExtender.java
@@ -0,0 +1,105 @@
+package org.osgi.book.help.extender;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.osgi.book.utils.Pair;
+import org.osgi.framework.*;
+import org.osgi.service.log.LogService;
+import org.osgi.util.tracker.BundleTracker;
+
+public class HelpExtender extends BundleTracker {
+
+ private final Map<Long, List<Pair<URL, String>>> documentMap
+ = new ConcurrentHashMap<Long, List<Pair<URL, String>>>();
+ private final LogService log;
+
+ public HelpExtender(BundleContext context, LogService log) {
+ super(context, Bundle.ACTIVE, null);
+ this.log = log;
+ }
+
+ public List<Pair<URL, String>> listHelpDocs() {
+ List<Pair<URL, String>> result = new ArrayList<Pair<URL, String>>();
+ for (List<Pair<URL, String>> list : documentMap.values())
+ result.addAll(list);
+ return result;
+ }
+
+ @Override
+ public Object addingBundle(Bundle bundle, BundleEvent event) {
+ Bundle result = null;
+ long id = bundle.getBundleId();
+ try {
+ List<Pair<URL, String>> docs = scanForHelpDocsWithTitle(bundle);
+ if (!docs.isEmpty()) {
+ documentMap.put(id, docs);
+ result = bundle;
+ }
+ } catch (IOException e) {
+ log.log(LogService.LOG_ERROR, "IO error in bundle "
+ + bundle.getLocation(), e);
+ } catch (HelpScannerException e) {
+ log.log(LogService.LOG_ERROR, "Error in bundle "
+ + bundle.getLocation(), e);
+ }
+ return result;
+ }
+
+ @Override
+ public void removedBundle(Bundle bundle, BundleEvent event, Object obj) {
+ documentMap.remove(bundle.getBundleId());
+ }
+
+ // Omitted: scanForHelpDocsWithTitle method from previous section
+ // ...
+
+ private static final String HELP_INDEX_BUNDLE_HEADER = "Help-Index";
+
+ private List<Pair<URL, String>> scanForHelpDocsWithTitle(
+ Bundle bundle) throws IOException, HelpScannerException {
+ @SuppressWarnings("unchecked")
+ Dictionary<String, String> headers = bundle.getHeaders();
+
+ // Find the index file entry; exit if not found
+ String indexPath = headers.get(HELP_INDEX_BUNDLE_HEADER);
+ if (indexPath == null)
+ return Collections.emptyList();
+ URL indexEntry = bundle.getEntry(indexPath);
+ if (indexEntry == null)
+ throw new HelpScannerException("Entry not found: " + indexPath);
+
+ // Calculate the directory prefix
+ int slashIndex = indexPath.lastIndexOf('/');
+ String prefix = (slashIndex == -1)
+ ? "" : indexPath.substring(0, slashIndex);
+
+ // Load the index file as a Properties object
+ Properties indexProps = new Properties();
+ InputStream stream = null;
+ try {
+ stream = indexEntry.openStream();
+ indexProps.load(stream);
+ } finally {
+ if (stream != null) stream.close();
+ }
+
+ // Iterate through the files
+ List<Pair<URL, String>> result =
+ new ArrayList<Pair<URL, String>>(indexProps.size());
+ Enumeration<?> names = indexProps.propertyNames();
+ while (names.hasMoreElements()) {
+ String name = (String) names.nextElement();
+ String title = indexProps.getProperty(name);
+
+ URL entry = bundle.getEntry(prefix + "/" + name + ".html");
+ if (entry != null) result.add(new Pair<URL, String>(entry, title));
+ }
+ return result;
+ }
+
+
+}
View
30 extender/src/org/osgi/book/help/extender/HelpExtenderActivator.java
@@ -0,0 +1,30 @@
+package org.osgi.book.help.extender;
+
+import org.eclipse.osgi.framework.console.CommandProvider;
+import org.osgi.book.utils.LogTracker;
+import org.osgi.framework.*;
+
+public class HelpExtenderActivator implements BundleActivator {
+
+ private volatile LogTracker log;
+ private volatile HelpExtender extender;
+ private volatile ServiceRegistration cmdSvcReg;
+
+ public void start(BundleContext context) throws Exception {
+ log = new LogTracker(context);
+ log.open();
+ extender = new HelpExtender(context, log);
+ extender.open();
+
+ HelpListCommand command = new HelpListCommand(extender);
+ cmdSvcReg = context.registerService(CommandProvider.class.getName(),
+ command, null);
+ }
+
+ public void stop(BundleContext context) throws Exception {
+ cmdSvcReg.unregister();
+ extender.close();
+ log.close();
+ }
+
+}
View
70 extender/src/org/osgi/book/help/extender/HelpExtenderVer1.java
@@ -0,0 +1,70 @@
+package org.osgi.book.help.extender;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Properties;
+
+import org.osgi.book.utils.Pair;
+import org.osgi.framework.Bundle;
+
+public class HelpExtenderVer1 {
+
+ private List<URL> scanForHelpDocs(Bundle bundle) {
+ List<URL> result;
+ Enumeration<?> entries = bundle.getEntryPaths("help");
+ if (entries != null) {
+ result = new ArrayList<URL>();
+ while (entries.hasMoreElements()) {
+ String entry = (String) entries.nextElement();
+ if (entry.endsWith(".html")) {
+ result.add(bundle.getEntry(entry));
+ }
+ }
+ } else {
+ result = Collections.emptyList();
+ }
+ return result;
+ }
+
+ private List<Pair<URL, String>> scanForHelpDocsWithTitles(
+ Bundle bundle) throws IOException {
+ // Find the index file entry; exit if not found
+ URL indexEntry = bundle.getEntry("help/index.properties");
+ if (indexEntry == null) {
+ return Collections.emptyList();
+ }
+
+ // Load the index file as a Properties object
+ Properties indexProps = new Properties();
+ InputStream stream = null;
+ try {
+ stream = indexEntry.openStream();
+ indexProps.load(stream);
+ } finally {
+ if (stream != null)
+ stream.close();
+ }
+
+ // Iterate through the files
+ List<Pair<URL, String>> result =
+ new ArrayList<Pair<URL, String>>(indexProps.size());
+ Enumeration<?> names = indexProps.propertyNames();
+ while (names.hasMoreElements()) {
+ String name = (String) names.nextElement();
+ String title = indexProps.getProperty(name);
+
+ URL entry = bundle.getEntry("help/" + name + ".html");
+ if (entry != null) {
+ result.add(new Pair<URL, String>(entry, title));
+ }
+ }
+
+ return result;
+ }
+
+}
View
29 extender/src/org/osgi/book/help/extender/HelpListCommand.java
@@ -0,0 +1,29 @@
+package org.osgi.book.help.extender;
+
+import java.net.URL;
+import java.util.List;
+
+import org.eclipse.osgi.framework.console.CommandInterpreter;
+import org.eclipse.osgi.framework.console.CommandProvider;
+import org.osgi.book.utils.Pair;
+
+public class HelpListCommand implements CommandProvider {
+
+ private final HelpExtender extender;
+
+ public HelpListCommand(HelpExtender extender) {
+ this.extender = extender;
+ }
+
+ public String getHelp() {
+ return "\t" + "helpDocs - List currently available help docs";
+ }
+
+ public void _helpDocs(CommandInterpreter ci) {
+ List<Pair<URL,String>> docs = extender.listHelpDocs();
+ ci.println(docs.size() + " document(s) found");
+ for (Pair<URL, String> pair : docs) {
+ ci.println(pair.getSecond() + " (" + pair.getFirst() + ")");
+ }
+ }
+}
View
17 extender/src/org/osgi/book/help/extender/HelpScannerException.java
@@ -0,0 +1,17 @@
+package org.osgi.book.help.extender;
+
+public class HelpScannerException extends Exception {
+
+ public HelpScannerException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public HelpScannerException(String message) {
+ super(message);
+ }
+
+ public HelpScannerException(Throwable cause) {
+ super(cause);
+ }
+
+}
View
33 extender/src/org/osgi/book/utils/LogTracker.java
@@ -0,0 +1,33 @@
+package org.osgi.book.utils;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class LogTracker extends ServiceTracker implements LogService {
+
+ public LogTracker(BundleContext context) {
+ super(context, LogService.class.getName(), null);
+ }
+
+ public void log(int level, String message) {
+ log(null, level, message, null);
+ }
+
+ public void log(int level, String message, Throwable exception) {
+ log(null, level, message, exception);
+ }
+
+ public void log(ServiceReference sr, int level, String message) {
+ log(sr, level, message, null);
+ }
+
+ public void log(ServiceReference sr, int level, String message,
+ Throwable exception) {
+ LogService log = (LogService) getService();
+ if (log != null) {
+ log.log(sr, level, message, exception);
+ }
+ }
+}
View
21 extender/src/org/osgi/book/utils/Pair.java
@@ -0,0 +1,21 @@
+package org.osgi.book.utils;
+
+public class Pair<A, B> {
+ private final A first;
+ private final B second;
+
+ public Pair(A first, B second) {
+ this.first = first;
+ this.second = second;
+ }
+
+ public A getFirst() {
+ return first;
+ }
+
+ public B getSecond() {
+ return second;
+ }
+
+ // Omitted: hashCode, equals and toString implementations
+}
View
2 firststeps/.classpath
@@ -2,6 +2,6 @@
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Equinox"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Equinox 3.5.1"/>
<classpathentry kind="output" path="bin"/>
</classpath>
View
4 intro_svcs/.classpath
@@ -2,8 +2,8 @@
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="lib" path="bundles/osgi.cmpn.jar"/>
- <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Equinox"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Equinox 3.5.1"/>
<classpathentry combineaccessrules="false" kind="src" path="/dependencies"/>
+ <classpathentry kind="lib" path="bundles/osgi.cmpn.r4_2.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
View
BIN intro_svcs/bundles/osgi.cmpn.jar
Binary file not shown.
View
BIN intro_svcs/bundles/osgi.cmpn.r4_2.jar
Binary file not shown.
View
2 whiteboard/.classpath
@@ -3,7 +3,7 @@
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="bundles/osgi.cmpn.jar"/>
- <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Equinox"/>
<classpathentry combineaccessrules="false" kind="src" path="/dependencies"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Equinox 3.5.1"/>
<classpathentry kind="output" path="bin"/>
</classpath>

0 comments on commit 43a06fe

Please sign in to comment.