[bnd] 02/04: Imported Upstream version 2.1.0

Markus Koschany apo-guest at moszumanska.debian.org
Mon Nov 16 16:15:06 UTC 2015


This is an automated email from the git hooks/post-receive script.

apo-guest pushed a commit to branch master
in repository bnd.

commit 63707827dff5ffc6ad6d469b100519c1ae92f56b
Author: Markus Koschany <apo at debian.org>
Date:   Mon Nov 16 17:05:30 2015 +0100

    Imported Upstream version 2.1.0
---
 README                                             |   78 +-
 aQute.libg/.classpath                              |    1 -
 aQute.libg/.project                                |    6 +
 aQute.libg/.settings/org.eclipse.jdt.core.prefs    |  351 +-
 aQute.libg/.settings/org.eclipse.jdt.ui.prefs      |   61 +
 aQute.libg/bnd.bnd                                 |    9 +-
 aQute.libg/src/aQute/configurable/Config.java      |   17 +
 .../src/aQute/configurable/Configurable.java       |  312 +
 aQute.libg/src/aQute/configurable/packageinfo      |    1 +
 aQute.libg/src/aQute/lib/base64/Base64.java        |  100 +-
 aQute.libg/src/aQute/lib/base64/packageinfo        |    2 +-
 aQute.libg/src/aQute/lib/codec/Codec.java          |   10 +
 aQute.libg/src/aQute/lib/codec/HCodec.java         |   77 +
 .../aQute/{libg/dumpzip => lib/codec}/packageinfo  |    0
 .../aQute/lib/collections/EnumerationIterator.java |   42 +
 aQute.libg/src/aQute/lib/collections/ExtList.java  |   56 +
 .../src/aQute/lib/collections/IteratorList.java    |   12 +
 .../src/aQute/lib/collections/LineCollection.java  |    5 +-
 aQute.libg/src/aQute/lib/collections/Logic.java    |   12 +-
 aQute.libg/src/aQute/lib/collections/MultiMap.java |  162 +-
 .../src/aQute/lib/collections/SortedList.java      |  438 ++
 aQute.libg/src/aQute/lib/collections/packageinfo   |    2 +-
 aQute.libg/src/aQute/lib/converter/Converter.java  |  526 ++
 .../src/aQute/lib/converter/TypeReference.java     |   13 +
 aQute.libg/src/aQute/lib/converter/packageinfo     |    1 +
 aQute.libg/src/aQute/lib/data/AllowNull.java       |   11 +
 aQute.libg/src/aQute/lib/data/Data.java            |   80 +
 aQute.libg/src/aQute/lib/data/Numeric.java         |   15 +
 aQute.libg/src/aQute/lib/data/Validator.java       |   13 +
 aQute.libg/src/aQute/lib/data/packageinfo          |    1 +
 aQute.libg/src/aQute/lib/filter/Filter.java        |  662 +-
 aQute.libg/src/aQute/lib/getopt/Arguments.java     |    8 +
 aQute.libg/src/aQute/lib/getopt/CommandLine.java   |  475 ++
 .../src/aQute/lib/getopt/CommandLineMessages.java  |   25 +
 aQute.libg/src/aQute/lib/getopt/Description.java   |    8 +
 .../src/aQute/lib/getopt/OptionArgument.java       |    8 +
 aQute.libg/src/aQute/lib/getopt/Options.java       |   15 +
 aQute.libg/src/aQute/lib/getopt/packageinfo        |    1 +
 aQute.libg/src/aQute/lib/hex/Hex.java              |   47 +-
 aQute.libg/src/aQute/lib/index/Index.java          |   73 +-
 aQute.libg/src/aQute/lib/io/IO.java                |  385 +-
 .../src/aQute/lib/io/LimitedInputStream.java       |   40 +-
 aQute.libg/src/aQute/lib/io/packageinfo            |    2 +-
 aQute.libg/src/aQute/lib/json/ArrayHandler.java    |   40 +
 aQute.libg/src/aQute/lib/json/BooleanHandler.java  |   34 +
 .../src/aQute/lib/json/ByteArrayHandler.java       |   80 +
 .../src/aQute/lib/json/CharacterHandler.java       |   35 +
 .../src/aQute/lib/json/CollectionHandler.java      |   57 +
 aQute.libg/src/aQute/lib/json/DateHandler.java     |   32 +
 aQute.libg/src/aQute/lib/json/Decoder.java         |  186 +
 aQute.libg/src/aQute/lib/json/Encoder.java         |  149 +
 aQute.libg/src/aQute/lib/json/EnumHandler.java     |   26 +
 aQute.libg/src/aQute/lib/json/FileHandler.java     |   41 +
 aQute.libg/src/aQute/lib/json/Handler.java         |   34 +
 aQute.libg/src/aQute/lib/json/JSONCodec.java       |  492 ++
 aQute.libg/src/aQute/lib/json/MapHandler.java      |   95 +
 aQute.libg/src/aQute/lib/json/NumberHandler.java   |   73 +
 aQute.libg/src/aQute/lib/json/ObjectHandler.java   |  153 +
 aQute.libg/src/aQute/lib/json/SpecialHandler.java  |   41 +
 aQute.libg/src/aQute/lib/json/StringHandler.java   |  152 +
 aQute.libg/src/aQute/lib/json/packageinfo          |    1 +
 aQute.libg/src/aQute/lib/justif/Justif.java        |  128 +
 aQute.libg/src/aQute/lib/justif/packageinfo        |    1 +
 .../src/aQute/lib/putjar/DirectoryInputStream.java |  544 +-
 aQute.libg/src/aQute/lib/settings/Settings.java    |  251 +
 aQute.libg/src/aQute/lib/settings/packageinfo      |    1 +
 aQute.libg/src/aQute/lib/tag/Tag.java              |  123 +-
 aQute.libg/src/aQute/libg/asn1/BER.java            |  924 ++-
 aQute.libg/src/aQute/libg/asn1/PDU.java            |  211 +-
 aQute.libg/src/aQute/libg/asn1/Types.java          |  117 +-
 aQute.libg/src/aQute/libg/cafs/CAFS.java           |  152 +-
 .../src/aQute/libg/classdump/ClassDumper.java      | 1328 ++--
 .../libg/classloaders/URLClassLoaderWrapper.java   |   19 +-
 aQute.libg/src/aQute/libg/classloaders/packageinfo |    1 +
 aQute.libg/src/aQute/libg/clauses/Clauses.java     |   22 +-
 aQute.libg/src/aQute/libg/clauses/Selector.java    |   55 +-
 aQute.libg/src/aQute/libg/command/Command.java     |  219 +-
 aQute.libg/src/aQute/libg/command/packageinfo      |    2 +-
 aQute.libg/src/aQute/libg/cryptography/Crypto.java |   53 +-
 aQute.libg/src/aQute/libg/cryptography/Digest.java |   31 +-
 .../src/aQute/libg/cryptography/Digester.java      |   45 +-
 aQute.libg/src/aQute/libg/cryptography/Key.java    |    2 -
 aQute.libg/src/aQute/libg/cryptography/MD5.java    |   41 +-
 aQute.libg/src/aQute/libg/cryptography/RSA.java    |   18 +-
 aQute.libg/src/aQute/libg/cryptography/SHA1.java   |   37 +-
 aQute.libg/src/aQute/libg/cryptography/SHA256.java |   49 +
 aQute.libg/src/aQute/libg/cryptography/Signer.java |   33 +-
 .../src/aQute/libg/cryptography/Verifier.java      |   25 +-
 aQute.libg/src/aQute/libg/cryptography/packageinfo |    2 +-
 aQute.libg/src/aQute/libg/dumpzip/DumpZip.java     |    9 -
 aQute.libg/src/aQute/libg/filecheck/FileCheck.java |   12 -
 .../src/aQute/libg/fileiterator/FileIterator.java  |   65 +-
 .../src/aQute/libg/filelock/DirectoryLock.java     |   13 +-
 aQute.libg/src/aQute/libg/filelock/packageinfo     |    1 +
 aQute.libg/src/aQute/libg/filerepo/FileRepo.java   |  106 -
 aQute.libg/src/aQute/libg/filters/AndFilter.java   |   30 +
 aQute.libg/src/aQute/libg/filters/Filter.java      |   14 +
 .../src/aQute/libg/filters/LiteralFilter.java      |   16 +
 aQute.libg/src/aQute/libg/filters/NotFilter.java   |   19 +
 aQute.libg/src/aQute/libg/filters/Operator.java    |   17 +
 aQute.libg/src/aQute/libg/filters/OrFilter.java    |   30 +
 .../src/aQute/libg/filters/SimpleFilter.java       |   33 +
 .../src/aQute/libg/filters}/packageinfo            |    0
 aQute.libg/src/aQute/libg/forker/Forker.java       |   44 +-
 aQute.libg/src/aQute/libg/generics/Create.java     |   83 +-
 aQute.libg/src/aQute/libg/glob/Glob.java           |  166 +-
 aQute.libg/src/aQute/libg/glob/packageinfo         |    1 +
 aQute.libg/src/aQute/libg/gzip/GZipUtils.java      |   57 +
 aQute.libg/src/aQute/libg/gzip/packageinfo         |    1 +
 aQute.libg/src/aQute/libg/header/OSGiHeader.java   |  145 -
 aQute.libg/src/aQute/libg/log/Logger.java          |   15 +-
 aQute.libg/src/aQute/libg/map/MAP.java             |   31 +-
 aQute.libg/src/aQute/libg/map/packageinfo          |    1 +
 .../src/aQute/libg/qtokens/QuotedTokenizer.java    |   54 +-
 aQute.libg/src/aQute/libg/reporter/Message.java    |    5 +
 aQute.libg/src/aQute/libg/reporter/Reporter.java   |   15 -
 .../src/aQute/libg/reporter/ReporterAdapter.java   |  304 +
 .../src/aQute/libg/reporter/ReporterMessages.java  |   97 +
 aQute.libg/src/aQute/libg/reporter/packageinfo     |    2 +-
 aQute.libg/src/aQute/libg/sax/ContentFilter.java   |    3 +-
 .../src/aQute/libg/sax/ContentFilterImpl.java      |   27 +-
 aQute.libg/src/aQute/libg/sax/SAXElement.java      |   13 +-
 aQute.libg/src/aQute/libg/sax/SAXUtil.java         |   27 +-
 .../libg/sax/filters/ElementSelectionFilter.java   |   37 +-
 .../aQute/libg/sax/filters/MergeContentFilter.java |   28 +-
 aQute.libg/src/aQute/libg/sed/Domain.java          |    9 +
 aQute.libg/src/aQute/libg/sed/Replacer.java        |    2 +-
 aQute.libg/src/aQute/libg/sed/ReplacerAdapter.java |  935 +++
 aQute.libg/src/aQute/libg/sed/Sed.java             |  147 +-
 aQute.libg/src/aQute/libg/sed/packageinfo          |    2 +-
 aQute.libg/src/aQute/libg/tarjan/Tarjan.java       |   68 +-
 .../src/aQute/libg/tuple/ComparablePair.java       |   14 +
 aQute.libg/src/aQute/libg/tuple/Pair.java          |   78 +-
 aQute.libg/src/aQute/libg/version/Version.java     |  164 -
 .../src/aQute/libg/version/VersionRange.java       |   85 -
 aQute.libg/src/aQute/libg/version/packageinfo      |    1 -
 aQute.libg/src/aQute/libg/xslt/Transform.java      |   63 +-
 .../src/aQute/service/reporter/Messages.java       |   14 +
 aQute.libg/src/aQute/service/reporter/Report.java  |   53 +
 .../src/aQute/service/reporter/Reporter.java       |  130 +
 aQute.libg/src/aQute/service/reporter/packageinfo  |    1 +
 aQute.libg/src/test/CommandTest.java               |   95 +
 aQute.libg/src/test/ConverterTest.java             |  395 +
 aQute.libg/src/test/ExecuteTest.java               |   23 +
 aQute.libg/src/test/GlobTest.java                  |   29 +
 aQute.libg/src/test/HexTest.java                   |   95 +
 aQute.libg/src/test/JSONTest.java                  |  707 ++
 aQute.libg/src/test/JustifTest.java                |   25 +
 aQute.libg/src/test/ReplacerTest.java              |  520 ++
 aQute.libg/src/test/SettingsTest.java              |   36 +
 aQute.libg/src/test/TestCAFS.java                  |  113 +-
 aQute.libg/src/test/TestDirectoryInputStream.java  |   25 +-
 aQute.libg/src/test/TestForker.java                |   29 +-
 aQute.libg/src/test/TestGzipUtils.java             |   21 +
 aQute.libg/src/test/TestIndex.java                 |  115 +-
 aQute.libg/src/test/TestSAXFilters.java            |   85 +-
 aQute.libg/src/test/TestTarjan.java                |   47 +-
 aQute.libg/src/test/unzipped.dat                   |    1 +
 aQute.libg/src/test/zipped.dat                     |  Bin 0 -> 55 bytes
 biz.aQute.bnd/.classpath                           |    3 -
 biz.aQute.bnd/.project                             |    9 +-
 biz.aQute.bnd/.settings/org.eclipse.jdt.core.prefs |  351 +-
 biz.aQute.bnd/.settings/org.eclipse.jdt.ui.prefs   |   61 +
 biz.aQute.bnd/META-INF/MANIFEST.MF                 |   38 -
 biz.aQute.bnd/annotation.bnd                       |    2 +-
 biz.aQute.bnd/biz.aQute.bnd.bnd                    |   35 +-
 biz.aQute.bnd/bnd.bnd                              |   49 +-
 biz.aQute.bnd/bnd/embedded-repo.bnd                |    2 +
 biz.aQute.bnd/build.properties                     |    4 -
 biz.aQute.bnd/icons/active.gif                     |  Bin 914 -> 0 bytes
 biz.aQute.bnd/icons/bundle.gif                     |  Bin 914 -> 0 bytes
 biz.aQute.bnd/icons/export-package.gif             |  Bin 972 -> 0 bytes
 biz.aQute.bnd/icons/fragment.gif                   |  Bin 164 -> 0 bytes
 biz.aQute.bnd/icons/host.gif                       |  Bin 129 -> 0 bytes
 biz.aQute.bnd/icons/import-package.gif             |  Bin 233 -> 0 bytes
 biz.aQute.bnd/icons/importing-bundle.gif           |  Bin 230 -> 0 bytes
 biz.aQute.bnd/icons/installed.gif                  |  Bin 179 -> 0 bytes
 biz.aQute.bnd/icons/inuse.gif                      |  Bin 352 -> 0 bytes
 biz.aQute.bnd/icons/logo16x16.gif                  |  Bin 360 -> 0 bytes
 biz.aQute.bnd/icons/mini-logo.gif                  |  Bin 914 -> 0 bytes
 biz.aQute.bnd/icons/module.gif                     |  Bin 164 -> 0 bytes
 biz.aQute.bnd/icons/property.gif                   |  Bin 93 -> 0 bytes
 biz.aQute.bnd/icons/registered.gif                 |  Bin 349 -> 0 bytes
 biz.aQute.bnd/icons/resolved.gif                   |  Bin 132 -> 0 bytes
 biz.aQute.bnd/icons/run.gif                        |  Bin 1078 -> 0 bytes
 biz.aQute.bnd/icons/test.gif                       |  Bin 335 -> 0 bytes
 biz.aQute.bnd/icons/unknown.gif                    |  Bin 79 -> 0 bytes
 biz.aQute.bnd/installers/MacOs/bnd                 |    3 +
 .../installers/MacOs/bnd.pmdoc/01biz-contents.xml  |    1 +
 biz.aQute.bnd/installers/MacOs/bnd.pmdoc/01biz.xml |    1 +
 .../installers/MacOs/bnd.pmdoc/02bnd-contents.xml  |    1 +
 biz.aQute.bnd/installers/MacOs/bnd.pmdoc/02bnd.xml |    1 +
 biz.aQute.bnd/installers/MacOs/bnd.pmdoc/index.xml |    1 +
 biz.aQute.bnd/installers/MacOs/build               |    4 +
 biz.aQute.bnd/plugin.xml                           |  243 -
 biz.aQute.bnd/schema.xml                           |   34 +
 biz.aQute.bnd/src/aQute/bnd/ant/AntMessages.java   |   17 +
 biz.aQute.bnd/src/aQute/bnd/ant/BaseTask.java      |  254 +-
 biz.aQute.bnd/src/aQute/bnd/ant/BndTask.java       |  168 +-
 biz.aQute.bnd/src/aQute/bnd/ant/DeployTask.java    |   85 +-
 biz.aQute.bnd/src/aQute/bnd/ant/EclipseTask.java   |  171 +-
 .../src/aQute/bnd/ant/ExpandPropertiesTask.java    |   13 +-
 biz.aQute.bnd/src/aQute/bnd/ant/PackageTask.java   |   67 +
 biz.aQute.bnd/src/aQute/bnd/ant/PrepareTask.java   |  153 +-
 .../src/aQute/bnd/ant/ProjectBuildOrderTask.java   |   62 +
 biz.aQute.bnd/src/aQute/bnd/ant/ProjectTask.java   |   62 +-
 biz.aQute.bnd/src/aQute/bnd/ant/ReleaseTask.java   |   58 +
 biz.aQute.bnd/src/aQute/bnd/ant/TestTask.java      |   93 +
 biz.aQute.bnd/src/aQute/bnd/ant/WrapTask.java      |  158 +-
 biz.aQute.bnd/src/aQute/bnd/ant/taskdef.properties |    4 +
 .../src/aQute/bnd/classpath/BndContainer.java      |  107 -
 .../bnd/classpath/BndContainerInitializer.java     |   97 -
 .../src/aQute/bnd/classpath/BndContainerPage.java  |  252 -
 .../src/aQute/bnd/classpath/ModelListener.java     |    8 -
 .../src/aQute/bnd/classpath/messages.properties    |   11 -
 .../src/aQute/bnd/jareditor/JarConfiguration.java  |    7 -
 .../aQute/bnd/jareditor/JarDocumentProvider.java   |  108 -
 .../src/aQute/bnd/jareditor/JarEditor.java         |   17 -
 .../src/aQute/bnd/junit/OSGiArgumentsTab.java      |  129 -
 .../aQute/bnd/junit/OSGiJUnitLaunchShortcut.java   |   15 -
 .../OSGiJUnitLauncherConfigurationDelegate.java    |  135 -
 .../src/aQute/bnd/junit/OSGiJUnitTabGroup.java     |   25 -
 .../src/aQute/bnd/launch/LaunchDelegate.java       |   44 -
 .../src/aQute/bnd/launch/LaunchTabGroup.java       |   21 -
 biz.aQute.bnd/src/aQute/bnd/launch/Shortcut.java   |  109 -
 biz.aQute.bnd/src/aQute/bnd/libsync/LibSync.java   |  106 -
 .../src/aQute/bnd/main/BaselineCommands.java       |  430 ++
 biz.aQute.bnd/src/aQute/bnd/main/BndMessages.java  |   28 +
 biz.aQute.bnd/src/aQute/bnd/main/DiffCommand.java  |  221 +
 biz.aQute.bnd/src/aQute/bnd/main/PatchCommand.java |  137 +
 biz.aQute.bnd/src/aQute/bnd/main/RepoCommand.java  |  473 ++
 biz.aQute.bnd/src/aQute/bnd/main/bnd.java          | 4300 ++++++-----
 biz.aQute.bnd/src/aQute/bnd/main/schema.xsl        |  346 +
 .../src/aQute/bnd/plugin/ActionWrapper.java        |   29 -
 biz.aQute.bnd/src/aQute/bnd/plugin/Activator.java  |  225 -
 biz.aQute.bnd/src/aQute/bnd/plugin/Central.java    |  268 -
 .../src/aQute/bnd/plugin/builder/BndBuilder.java   |  134 -
 .../src/aQute/bnd/plugin/builder/BndNature.java    |   80 -
 .../bnd/plugin/builder/ToggleNatureAction.java     |   96 -
 .../bnd/plugin/editors/BndCompletionProcessor.java |   46 -
 .../src/aQute/bnd/plugin/editors/BndHover.java     |  117 -
 .../bnd/plugin/editors/BndMultiPageEditor.java     |  237 -
 .../editors/BndMultiPageEditorContributor.java     |  103 -
 .../src/aQute/bnd/plugin/editors/BndScanner.java   |   76 -
 .../editors/BndSourceViewerConfiguration.java      |  129 -
 .../aQute/bnd/plugin/editors/BndTextEditor.java    |   19 -
 .../src/aQute/bnd/plugin/editors/MacroRule.java    |   58 -
 .../src/aQute/bnd/plugin/popup/Scripts.java        |  139 -
 .../src/aQute/bnd/plugin/popup/SubMenu.java        |   74 -
 .../aQute/bnd/plugin/popup/actions/AddToRepo.java  |  101 -
 .../bnd/plugin/popup/actions/InstallBundle.java    |  127 -
 .../aQute/bnd/plugin/popup/actions/MakeBundle.java |  168 -
 .../bnd/plugin/popup/actions/VerifyBundle.java     |   86 -
 .../aQute/bnd/plugin/popup/actions/WrapBundle.java |   60 -
 .../bnd/plugin/popup/actions/repo/RepoDialog.java  |  158 -
 .../src/biz/aqute/bnd/eclipse/popup/Refresh.java   |   42 -
 biz.aQute.bnd/src/bnd.java                         |    5 +
 biz.aQute.bnd/src/swing2swt/layout/AWTLayout.java  |   66 -
 biz.aQute.bnd/src/swing2swt/layout/GridLayout.java |  172 -
 biz.aQute.bnd/src/test/TestBuild.java              |   15 +-
 biz.aQute.bnd/test.bnd                             |    4 +
 biz.aQute.bndlib.tests/.classpath                  |    6 +
 biz.aQute.bndlib.tests/.project                    |   23 +
 .../.settings/org.eclipse.core.resources.prefs     |    3 +
 .../.settings/org.eclipse.core.runtime.prefs       |    3 +
 .../.settings/org.eclipse.jdt.core.prefs           |  361 +
 .../.settings/org.eclipse.jdt.ui.prefs             |   61 +
 biz.aQute.bndlib.tests/bnd.bnd                     |   13 +
 .../bnd/makesondemand.bnd                          |    0
 biz.aQute.bndlib.tests/bnd/ondemand.bnd            |    1 +
 biz.aQute.bndlib.tests/build.xml                   |    4 +
 .../compilerversions/compile.sh                    |    0
 .../compilerversions/compilerversions.bnd          |    0
 .../compilerversions/download_bundle.gif           |  Bin
 .../compilerversions/src/eclipse_1_1/ClassRef.java |    0
 .../compilerversions/src/eclipse_1_2/ClassRef.java |    0
 .../compilerversions/src/eclipse_1_3/ClassRef.java |    0
 .../compilerversions/src/eclipse_1_4/ClassRef.java |    0
 .../compilerversions/src/eclipse_1_5/ClassRef.java |    0
 .../compilerversions/src/eclipse_1_6/ClassRef.java |    0
 .../src/eclipse_jsr14/ClassRef.java                |    0
 .../compilerversions/src/sun_1_1/ClassRef.java     |    0
 .../compilerversions/src/sun_1_2/ClassRef.java     |    0
 .../compilerversions/src/sun_1_3/ClassRef.java     |    0
 .../compilerversions/src/sun_1_4/ClassRef.java     |    0
 .../compilerversions/src/sun_1_5/ClassRef.java     |    0
 .../compilerversions/src/sun_1_6/ClassRef.java     |    0
 .../compilerversions/src/sun_jsr14/ClassRef.java   |    0
 .../jar/AnnotationWithJSR14.jclass                 |  Bin 0 -> 350 bytes
 .../jar/AstNodeToScriptVisitor.jclass              |  Bin 0 -> 44070 bytes
 .../jar/DeploymentAdminPermission.1.jclass         |  Bin 0 -> 1782 bytes
 biz.aQute.bndlib.tests/jar/WithAnnotations.jclass  |  Bin 0 -> 517 bytes
 biz.aQute.bndlib.tests/jar/mandatorynoversion.bnd  |    2 +
 biz.aQute.bndlib.tests/jar/mina.bar                |  Bin 0 -> 349672 bytes
 biz.aQute.bndlib.tests/jar/minax.bnd               |    4 +
 biz.aQute.bndlib.tests/jar/rox.bnd                 |    4 +
 biz.aQute.bndlib.tests/src/DefaultPackage.java     |    3 +
 .../src/UPPERCASEPACKAGE/MyClass.java              |    5 +
 .../src/test/.classpath                            |    0
 .../src/test/.cvsignore                            |    0
 biz.aQute.bndlib.tests/src/test/AnalyzerTest.java  |  679 ++
 .../src/test/AnnotationsTest.java                  |  133 +
 .../src/test/AttributesTest.java                   |  148 +
 biz.aQute.bndlib.tests/src/test/BuilderTest.java   | 1923 +++++
 biz.aQute.bndlib.tests/src/test/CalltreeTest.java  |  168 +
 .../src/test/ClassParserTest.java                  |  355 +
 .../src/test/ClassReferenceTest.java               |   45 +
 biz.aQute.bndlib.tests/src/test/ClasspathTest.java |   72 +
 biz.aQute.bndlib.tests/src/test/ClazzTest.java     |   68 +
 biz.aQute.bndlib.tests/src/test/CompareTest.java   |  128 +
 .../src/test/ComponentTests.java                   |   18 +
 .../src/test/CorruptManifest.java                  |   49 +
 .../src/test/DescriptorsTest.java                  |   23 +
 .../src/test/DownloadBlockerTest.java              |   63 +
 .../src/test/ExportHeaderTest.java                 |   71 +
 biz.aQute.bndlib.tests/src/test/FileRepoTests.java |   14 +
 biz.aQute.bndlib.tests/src/test/FilterTest.java    |   12 +
 .../src/test/IncludeHeaderTest.java                |  142 +
 biz.aQute.bndlib.tests/src/test/InlineTest.java    |   24 +
 .../src/test/InstructionTest.java                  |   58 +
 biz.aQute.bndlib.tests/src/test/JarSignerTest.java |   90 +
 biz.aQute.bndlib.tests/src/test/JarTest.java       |   68 +
 biz.aQute.bndlib.tests/src/test/JobsService.clazz  |  Bin 0 -> 5636 bytes
 biz.aQute.bndlib.tests/src/test/LauncherTest.java  |  168 +
 biz.aQute.bndlib.tests/src/test/MacroTest.java     |  609 ++
 biz.aQute.bndlib.tests/src/test/MakeTest.java      |  117 +
 biz.aQute.bndlib.tests/src/test/ManifestTest.java  |  190 +
 biz.aQute.bndlib.tests/src/test/MavenTest.java     |  335 +
 biz.aQute.bndlib.tests/src/test/MergeTest.java     |   78 +
 biz.aQute.bndlib.tests/src/test/MetatypeTests.java |   15 +
 biz.aQute.bndlib.tests/src/test/NativeHeader.java  |   67 +
 biz.aQute.bndlib.tests/src/test/NoUsesTest.java    |  122 +
 biz.aQute.bndlib.tests/src/test/PackTest.java      |   18 +
 .../src/test/ParseHeaderTest.java                  |  128 +
 biz.aQute.bndlib.tests/src/test/Parser.jclass      |  Bin 0 -> 160951 bytes
 biz.aQute.bndlib.tests/src/test/PluginTest.java    |   89 +
 biz.aQute.bndlib.tests/src/test/ProcessorTest.java |   43 +
 biz.aQute.bndlib.tests/src/test/ProjectTest.java   |  479 ++
 .../src/test/PropertiesTest.java                   |  124 +
 .../src/test/RepoBuilderTest.java                  |   60 +
 biz.aQute.bndlib.tests/src/test/RepoTreeTest.java  |   59 +
 biz.aQute.bndlib.tests/src/test/ResourcesTest.java |  325 +
 .../src/test/SemanticVersioningTests.java          |   15 +
 biz.aQute.bndlib.tests/src/test/Simple.jclass      |  Bin 0 -> 542 bytes
 biz.aQute.bndlib.tests/src/test/SpringTest.java    |   87 +
 biz.aQute.bndlib.tests/src/test/Test.jclass        |  Bin 0 -> 845 bytes
 biz.aQute.bndlib.tests/src/test/Test2.jclass       |  Bin 0 -> 333 bytes
 biz.aQute.bndlib.tests/src/test/TestAttrs.java     |   20 +
 biz.aQute.bndlib.tests/src/test/TestBndBook.java   |   29 +
 .../src/test/TestQuotedTokenizer.java              |   72 +
 biz.aQute.bndlib.tests/src/test/TestSelfBuild.java |   21 +
 .../src/test/TestSignatures.java                   |   94 +
 biz.aQute.bndlib.tests/src/test/UsesTest.java      |   88 +
 biz.aQute.bndlib.tests/src/test/VerifierTest.java  |  242 +
 .../src/test/VersionPolicyTest.java                |  278 +
 .../src/test/WithAnnotations.jclass                |  Bin 0 -> 517 bytes
 .../src/test/WorkspaceRepositoryTest.java          |   85 +
 biz.aQute.bndlib.tests/src/test/WorkspaceTest.java |   26 +
 biz.aQute.bndlib.tests/src/test/XDbCmpXView.clazz  |  Bin 0 -> 83410 bytes
 .../src/test/activator/Activator.java              |   13 +
 .../src/test/activator/Activator11.java            |   14 +
 .../src/test/activator/Activator2.java             |   11 +
 .../src/test/activator/Activator3.java             |   11 +
 .../src/test/activator/ActivatorPackage.java       |   11 +
 .../src/test/activator/ActivatorPrivate.java       |   13 +
 .../activator/inherits/InheritedActivator.java     |   11 +
 .../test/annotation/AnnotationWithRefToAny.java    |   10 +
 .../src/test/annotation/any/Any.java               |    5 +
 .../src/test/badproperties.prop                    |    0
 .../src/test/baseline/BaselineTest.java            |  100 +
 .../src/test/beasymock.bnd                         |    0
 .../src/test/bnd.info                              |    0
 .../src/test/classreference/ClassReference.java    |    8 +
 .../src/test/com.acme/bnd.bnd                      |    0
 .../src/test/com.acme/defaultbsn.bnd               |    0
 .../src/test/com.acme/setsbsn.bnd                  |    0
 .../src/test/component/BNDAnnotationTest.java      |  882 +++
 .../src/test/component/ComponentOrderingTest.java  |   36 +
 .../src/test/component/ComponentTest.java          |  493 ++
 .../src/test/component/DSAnnotationTest.java       | 1133 +++
 .../src/test/defaultbsn.bnd                        |    0
 .../src/test/deployer/FileRepoTest.java            |  223 +
 biz.aQute.bndlib.tests/src/test/diff/DiffTest.java |  144 +
 .../src/test/genericinterf/a/A.java                |   12 +
 .../src/test/genericinterf/b/B.java                |    5 +
 .../src/test/genericinterf/c/C.java                |    5 +
 biz.aQute.bndlib.tests/src/test/generics.clazz     |  Bin 0 -> 420 bytes
 .../src/test/iht/test.prop                         |    0
 .../src/test/include.bnd/bottom.bnd                |    0
 .../src/test/include.bnd/top.bnd                   |    0
 .../src/test/include.mf                            |    0
 .../src/test/includeheadertest.mf                  |    0
 .../src/test/includeheadertest.prop                |    0
 biz.aQute.bndlib.tests/src/test/lib/NanoHTTPD.java |  987 +++
 biz.aQute.bndlib.tests/src/test/make/MD5.java      |   44 +
 .../src/test/metatype/MetatypeTest.java            | 1161 +++
 .../src/test/packageinfo/Dummy.java                |    3 +
 .../src/test/packageinfo/packageinfo               |    0
 .../src/test/packageinfo/ref/DummyRef.java         |    7 +
 .../src/test/privateimport/PrivateImport.java      |   40 +
 .../src/test/properties/PropertiesTest.java        |   53 +
 .../src/test/refer/RefersToEventAdmin.java         |    7 +
 .../src/test/refer/RefersToHttp.java               |    7 +
 .../src/test/refer/RefersToMeasurement.java        |    7 +
 .../src/test/referApi/APIReferrer.java             |   48 +
 .../src/test/resourcesonly/include.mf              |    0
 .../src/test/resourcesonly/simple.mf               |    0
 .../src/test/resourcesonly/top.mf                  |    0
 .../src/test/resourcesonly/variables.mf            |    0
 biz.aQute.bndlib.tests/src/test/signatures/Z.java  |   77 +
 .../src/test/signing/.cvsignore                    |    0
 .../src/test/signing/META-INF/MANIFEST.MF          |    0
 .../src/test/signing/META-INF/test.RSA             |  Bin
 .../src/test/signing/META-INF/test.SF              |    0
 .../src/test/signing/keystore                      |  Bin
 .../src/test/simple.mf                             |    0
 .../src/test/split/A                               |    0
 .../src/test/split/B                               |    0
 .../src/test/split/first                           |    0
 .../src/test/split/last                            |    0
 .../src/test/split/split-a.bnd                     |    0
 .../src/test/split/split-b.bnd                     |    0
 .../src/test/spring-test1.spring                   |    0
 .../src/test/top.mf                                |    0
 biz.aQute.bndlib.tests/src/test/top/Top.java       |    3 +
 .../src/test/top/middle/Middle.java                |    0
 .../src/test/top/middle/bottom/Bottom.java         |    0
 .../src/test/uses/annotation/UsesAnnotation.java   |   14 +
 .../uses/annotation/annotation/Annotation.java     |    9 +
 .../src/test/uses/constructor/UsesConstructor.java |   17 +
 .../src/test/uses/exception/UsesException.java     |   11 +
 .../src/test/uses/extend/UsesExtend.java           |   15 +
 .../src/test/uses/field/UsesField.java             |   12 +
 .../uses/generic/extend/UsesGenericExtend.java     |   15 +
 .../src/test/uses/generic/implement/Marker.java    |    5 +
 .../generic/implement/UsesGenericImplement.java    |   12 +
 .../test/uses/generic/param/UsesGenericParam.java  |   15 +
 .../uses/generic/rvalue/UsesGenericRValue.java     |   20 +
 .../src/test/uses/implement/UsesImplement.java     |    9 +
 .../src/test/uses/multi/UsesMulti.java             |   16 +
 .../src/test/uses/order/UsesOrderingTest.java      |   56 +
 .../src/test/uses/param/UsesParam.java             |   17 +
 .../src/test/uses/rvalue/UsesRValue.java           |   18 +
 .../src/test/variables.mf                          |    0
 .../src/test/versionpolicy/api/EventAdmin.java     |    8 +
 .../src/test/versionpolicy/api/EventHandler.java   |    8 +
 .../src/test/versionpolicy/api/PrivateImpl.java    |    0
 .../src/test/versionpolicy/api/package-info.java   |    6 +
 .../versionpolicy/implemented/Implemented.java     |    8 +
 .../versionpolicy/implmajor/MajorImplemented.java  |   10 +
 .../test/versionpolicy/uses/EventHandlerImpl.java  |   10 +
 .../src/test/versionpolicy/uses/Uses.java          |    7 +
 biz.aQute.bndlib.tests/test/a space/cnf/build.bnd  |    7 +
 .../test/a space/cnf/ext/defaults.bnd              |   29 +
 biz.aQute.bndlib.tests/test/a space/test/bnd.bnd   |    8 +
 .../test/a space/test/src/test/placeholder         |    0
 biz.aQute.bndlib.tests/test/beasymock.bar          |  Bin 0 -> 3831 bytes
 .../test/eclipse/bnd.index                         |    0
 .../test/eclipse/plugins/beasymock.bar             |  Bin 0 -> 3831 bytes
 .../test/keystore                                  |  Bin
 .../activation/1.0.2/activation-1.0.2.pom          |   13 +
 .../activation/1.0.2/activation-1.0.2.pom.sha1     |    1 +
 .../aQute/bndlib/0.0.145/bndlib-0.0.145.jar.sha1   |    1 +
 .../biz/aQute/bndlib/0.0.145/bndlib-0.0.145.pom    |   22 +
 .../aQute/bndlib/0.0.145/bndlib-0.0.145.pom.sha1   |    1 +
 .../biz/aQute/bndlib/0.0.203/bndlib-0.0.203.pom    |   22 +
 .../aQute/bndlib/0.0.203/bndlib-0.0.203.pom.sha1   |    1 +
 .../aQute/bndlib/0.0.227/bndlib-0.0.227.jar.sha1   |    1 +
 .../biz/aQute/bndlib/0.0.227/bndlib-0.0.227.pom    |   22 +
 .../aQute/bndlib/0.0.227/bndlib-0.0.227.pom.sha1   |    1 +
 .../aQute/bndlib/0.0.236/bndlib-0.0.236.jar.sha1   |    1 +
 .../biz/aQute/bndlib/0.0.236/bndlib-0.0.236.pom    |   22 +
 .../aQute/bndlib/0.0.238/bndlib-0.0.238.jar.sha1   |    1 +
 .../biz/aQute/bndlib/0.0.238/bndlib-0.0.238.pom    |   22 +
 .../aQute/bndlib/0.0.238/bndlib-0.0.238.pom.sha1   |    1 +
 .../aQute/bndlib/0.0.255/bndlib-0.0.255.jar.sha1   |    1 +
 .../biz/aQute/bndlib/0.0.255/bndlib-0.0.255.pom    |   22 +
 .../aQute/bndlib/0.0.255/bndlib-0.0.255.pom.sha1   |    1 +
 .../dom4j/dom4j/1.6.1/dom4j-1.6.1.jar.sha1         |    1 +
 .../maven-repo/dom4j/dom4j/1.6.1/dom4j-1.6.1.pom   |  221 +
 .../dom4j/dom4j/1.6.1/dom4j-1.6.1.pom.sha1         |    1 +
 .../junit/junit/3.8.1/junit-3.8.1.jar.sha1         |    1 +
 .../maven-repo/junit/junit/3.8.1/junit-3.8.1.pom   |   29 +
 .../junit/junit/3.8.1/junit-3.8.1.pom.sha1         |    1 +
 .../test/maven-repo/junit/junit/3.8/junit-3.8.pom  |   26 +
 .../maven-repo/junit/junit/3.8/junit-3.8.pom.sha1  |    1 +
 .../maven-repo/junit/junit/4.4/junit-4.4.jar.sha1  |    1 +
 .../test/maven-repo/junit/junit/4.4/junit-4.4.pom  |   36 +
 .../maven-repo/junit/junit/4.4/junit-4.4.pom.sha1  |    1 +
 .../1.0.0/javax.servlet-1.0.0.jar.sha1             |    1 +
 .../javax.servlet/1.0.0/javax.servlet-1.0.0.pom    |  125 +
 .../1.0.0/javax.servlet-1.0.0.pom.sha1             |    1 +
 .../1.0.0/maven-obr-plugin-1.0.0.jar.sha1          |    1 +
 .../1.0.0/maven-obr-plugin-1.0.0.pom               |   56 +
 .../1.0.0/maven-obr-plugin-1.0.0.pom.sha1          |    1 +
 .../1.0.8/maven-scr-plugin-1.0.8.jar.sha1          |    1 +
 .../1.0.8/maven-scr-plugin-1.0.8.pom               |  101 +
 .../1.0.8/maven-scr-plugin-1.0.8.pom.sha1          |    1 +
 .../maven-scr-plugin/maven-metadata-central.xml    |   20 +
 .../maven-metadata-central.xml.sha1                |    1 +
 .../0.9.0-SNAPSHOT/maven-metadata-local.xml        |   11 +
 ...org.apache.felix.fileinstall-0.9.0-SNAPSHOT.pom |   62 +
 .../maven-metadata-local.xml                       |   11 +
 .../1.1.0-SNAPSHOT/maven-metadata-local.xml        |   11 +
 .../org.apache.felix.framework-1.1.0-SNAPSHOT.pom  |   63 +
 .../maven-metadata-local.xml                       |   11 +
 .../1.0.0/org.osgi.compendium-1.0.0.jar.sha1       |    1 +
 .../1.0.0/org.osgi.compendium-1.0.0.pom            |   79 +
 .../1.0.0/org.osgi.compendium-1.0.0.pom.sha1       |    1 +
 .../1.0.0/org.osgi.core-1.0.0.jar.md5              |    1 +
 .../org.osgi.core/1.0.0/org.osgi.core-1.0.0.pom    |   56 +
 .../1.0.0/org.osgi.core-1.0.0.pom.md5              |    1 +
 .../org.osgi.core-1.1.0-20070713.230200-1.pom      |   56 +
 .../org.osgi.core-1.1.0-20070713.230200-1.pom.sha1 |    1 +
 .../maven-metadata-apache.snapshots.xml            |   12 +
 .../maven-metadata-apache.snapshots.xml.sha1       |    1 +
 .../org.osgi.core-1.1.0-20070713.230200-1.jar.sha1 |    1 +
 .../org.osgi.core-1.1.0-20070713.230200-1.pom      |   56 +
 .../org.osgi.core-1.1.0-20070713.230200-1.pom.sha1 |    1 +
 .../org.osgi.core-1.1.0-SNAPSHOT.pom               |   56 +
 .../1.0.0/org.osgi.foundation-1.0.0.jar.sha1       |    1 +
 .../1.0.0/org.osgi.foundation-1.0.0.pom            |   39 +
 .../1.0.0/org.osgi.foundation-1.0.0.pom.sha1       |    1 +
 .../1.0.0/org.osgi.service.obr-1.0.0.jar.md5       |    1 +
 .../1.0.0/org.osgi.service.obr-1.0.0.pom           |   49 +
 .../1.0.0/org.osgi.service.obr-1.0.0.pom.md5       |    1 +
 .../1.0.1/org.osgi.service.obr-1.0.1.jar.sha1      |    1 +
 .../1.0.1/org.osgi.service.obr-1.0.1.pom           |   49 +
 .../1.0.1/org.osgi.service.obr-1.0.1.pom.sha1      |    1 +
 .../test/redirectws/bnd/build.bnd                  |    0
 .../test/redirectws/bnd/ext/test.bnd               |    0
 .../test/redirectws/wss/ws/cnf                     |    0
 .../test/w o r k s p a c e/cnf/build.bnd           |    3 +
 .../test/w o r k s p a c e/cnf/ext/extension.bnd   |    3 +
 .../test/w o r k s p a c e/p r o j e c t/bnd.bnd   |    0
 .../test/ws-repo-test/cnf/build.bnd                |    9 +
 .../cnf/repo/libtest/libtest-1.0.0.lib             |    0
 .../test/ws-repo-test}/p1/bnd.bnd                  |    0
 .../test/ws-repo-test}/p1/p1a.bndrun               |    0
 .../test/ws-repo-test}/p1/p1b.bndrun               |    0
 .../ws-repo-test}/p2/Resources/more/resource6.txt  |    0
 .../ws-repo-test}/p2/Resources/more/resource7.txt  |    0
 .../ws-repo-test}/p2/Resources/more/resource8.res  |    0
 .../test/ws-repo-test}/p2/Resources/resource1.res  |    0
 .../test/ws-repo-test}/p2/Resources/resource2.res  |    0
 .../test/ws-repo-test}/p2/Resources/resource3.txt  |    0
 .../test/ws-repo-test}/p2/Resources/resource4.txt  |    0
 .../test/ws-repo-test}/p2/Resources/resource5.asc  |    0
 .../ws-repo-test}/p2/Resources/stuff/resource9.res |    0
 .../test/ws-repo-test}/p2/Resources/text.txt       |    0
 .../test/ws-repo-test}/p2/bnd.bnd                  |    0
 .../test/ws-repo-test}/p3/bnd.bnd                  |    0
 .../test/ws-repo-test}/p4-sub/a.bnd                |    0
 .../test/ws-repo-test}/p4-sub/b.bnd                |    0
 .../test/ws-repo-test}/p4-sub/bnd.bnd              |    0
 .../test/ws-repo-test}/p4-sub/c.bnd                |    0
 .../test/ws-repo-test/p5/bnd.bnd                   |    1 +
 biz.aQute.bndlib.tests/test/ws/bug194/bnd.bnd      |    1 +
 .../test/ws/build-all}/bnd.bnd                     |    0
 .../test/ws/bump-included/bnd.bnd                  |    1 +
 .../test/ws/bump-included/include.txt              |    3 +
 biz.aQute.bndlib.tests/test/ws/bump-sub/a.bnd      |    3 +
 biz.aQute.bndlib.tests/test/ws/bump-sub/b.bnd      |    3 +
 biz.aQute.bndlib.tests/test/ws/bump-sub/bnd.bnd    |    1 +
 biz.aQute.bndlib.tests/test/ws/cnf/build.bnd       |    9 +
 .../test/ws/cnf/repo/libtest/libtest-1.0.0.lib     |    0
 .../test/ws/maven1/bnd.bnd                         |    0
 .../1.6.1/_maven.repositories                      |    0
 ...rce.org.apache.commons.beanutils-1.6.1.jar.sha1 |    0
 ...ngsource.org.apache.commons.beanutils-1.6.1.pom |    0
 ...rce.org.apache.commons.beanutils-1.6.1.pom.sha1 |    0
 .../1.7.0/_maven.repositories                      |    0
 ...ngsource.org.apache.commons.beanutils-1.7.0.pom |    0
 ....apache.commons.beanutils-1.7.0.pom.lastUpdated |    0
 ...rce.org.apache.commons.beanutils-1.7.0.pom.sha1 |    0
 .../1.3.0/_maven.repositories                      |    0
 ...springsource.org.apache.commons.codec-1.3.0.pom |    0
 ....org.apache.commons.codec-1.3.0.pom.lastUpdated |    0
 ...gsource.org.apache.commons.codec-1.3.0.pom.sha1 |    0
 .../2.1.1/_maven.repositories                      |    0
 ...pache.commons.collections-2.1.1.jar.lastUpdated |    0
 ...e.org.apache.commons.collections-2.1.1.jar.sha1 |    0
 ...source.org.apache.commons.collections-2.1.1.pom |    0
 ...pache.commons.collections-2.1.1.pom.lastUpdated |    0
 ...e.org.apache.commons.collections-2.1.1.pom.sha1 |    0
 ...e.org.apache.commons.collections-3.2.0.jar.sha1 |    0
 ...source.org.apache.commons.collections-3.2.0.pom |    0
 ...e.org.apache.commons.collections-3.2.0.pom.sha1 |    0
 .../1.0.4/_maven.repositories                      |    0
 ...rg.apache.commons.logging-1.0.4.jar.lastUpdated |    0
 ...ource.org.apache.commons.logging-1.0.4.jar.sha1 |    0
 ...ringsource.org.apache.commons.logging-1.0.4.pom |    0
 ...rg.apache.commons.logging-1.0.4.pom.lastUpdated |    0
 ...ource.org.apache.commons.logging-1.0.4.pom.sha1 |    0
 ...ource.org.apache.commons.logging-1.1.1.jar.sha1 |    0
 ...ringsource.org.apache.commons.logging-1.1.1.pom |    0
 ...ource.org.apache.commons.logging-1.1.1.pom.sha1 |    0
 ...m.springsource.org.apache.log4j-1.2.15.jar.sha1 |    0
 .../com.springsource.org.apache.log4j-1.2.15.pom   |    0
 ...m.springsource.org.apache.log4j-1.2.15.pom.sha1 |    0
 .../test/ws/maven1/maven-dependencies.txt          |    0
 .../test/ws/maven1/mvndeploy                       |    0
 .../test/ws/maven1/parentpom.xml                   |    0
 .../test/ws/maven1/pom.xml                         |    0
 .../test/ws/maven1/testparentpom.xml               |    0
 .../test/ws/maven1/testpom.xml                     |    0
 .../test/ws/maven2/bnd.bnd                         |    0
 .../test/ws/maven2/parentpom.xml                   |    0
 .../test/ws/maven2/pom.xml                         |    0
 .../test/ws/p-maven-remote/bnd.bnd                 |    0
 biz.aQute.bndlib.tests/test/ws/p-stale-dep/bnd.bnd |    3 +
 biz.aQute.bndlib.tests/test/ws/p-stale/bnd.bnd     |    3 +
 .../test/ws/p1/bnd.bnd                             |    0
 .../test/ws/p1/p1a.bndrun                          |    0
 .../test/ws/p1/p1b.bndrun                          |    0
 .../test/ws/p2/Resources/more/resource6.txt        |    0
 .../test/ws/p2/Resources/more/resource7.txt        |    0
 .../test/ws/p2/Resources/more/resource8.res        |    0
 .../test/ws/p2/Resources/resource1.res             |    0
 .../test/ws/p2/Resources/resource2.res             |    0
 .../test/ws/p2/Resources/resource3.txt             |    0
 .../test/ws/p2/Resources/resource4.txt             |    0
 .../test/ws/p2/Resources/resource5.asc             |    0
 .../test/ws/p2/Resources/stuff/resource9.res       |    0
 .../test/ws/p2/Resources/text.txt                  |    0
 .../test/ws/p2/bnd.bnd                             |    0
 .../test/ws/p3/bnd.bnd                             |    0
 .../test/ws/p4-sub/a.bnd                           |    0
 .../test/ws/p4-sub/b.bnd                           |    0
 .../test/ws/p4-sub/bnd.bnd                         |    0
 .../test/ws/p4-sub/c.bnd                           |    0
 biz.aQute.bndlib.tests/test/ws/p5/bnd.bnd          |    3 +
 biz.aQute.bndlib.tests/test/ws/p5/src/pkg1/.keep   |    1 +
 .../test/ws/p5/src/pkg2/package-info.java          |    6 +
 .../test/ws/p5/src/pkg3/package-info.java          |    5 +
 .../test/ws/p5/src/pkg4/package-info.java          |    5 +
 .../test/ws/p5/src/pkg5/package-info.java          |    6 +
 .../test/ws/p5/src/pkg5/packageinfo                |    1 +
 .../test/ws/p5/src/pkg6/package-info.java          |    4 +
 .../test/ws/p5/src/pkg6/packageinfo                |    1 +
 .../test/ws/p5/src/pkg7/package-info.java          |    4 +
 biz.aQute.bndlib/.project                          |    6 +
 .../.settings/org.eclipse.jdt.core.prefs           |  353 +-
 .../.settings/org.eclipse.jdt.ui.prefs             |   61 +
 biz.aQute.bndlib/bnd.bnd                           |   54 +-
 biz.aQute.bndlib/bnd/ondemand.bnd                  |    1 -
 biz.aQute.bndlib/img/bnd-64.png                    |  Bin 0 -> 2921 bytes
 biz.aQute.bndlib/src/DefaultPackage.java           |    4 -
 .../src/aQute/bnd/annotation/ConsumerType.java     |   17 +-
 .../src/aQute/bnd/annotation/Export.java           |   28 +-
 .../src/aQute/bnd/annotation/ProviderType.java     |   64 +-
 .../src/aQute/bnd/annotation/UsePolicy.java        |   20 -
 .../src/aQute/bnd/annotation/Version.java          |    5 +-
 .../aQute/bnd/annotation/component/Activate.java   |    4 +-
 .../aQute/bnd/annotation/component/Attribute.java  |   10 -
 .../aQute/bnd/annotation/component/Component.java  |   10 +-
 .../annotation/component/ConfigurationPolicy.java  |    2 +-
 .../aQute/bnd/annotation/component/Deactivate.java |    2 +-
 .../aQute/bnd/annotation/component/Modified.java   |    2 +-
 .../aQute/bnd/annotation/component/Reference.java  |   36 +-
 .../bnd/annotation/metatype/Configurable.java      |  173 +-
 .../src/aQute/bnd/annotation/metatype/Meta.java    |   29 +-
 .../bnd/build/CircularDependencyException.java     |    8 +-
 .../src/aQute/bnd/build/Container.java             |  115 +-
 .../src/aQute/bnd/build/DownloadBlocker.java       |  111 +
 biz.aQute.bndlib/src/aQute/bnd/build/Project.java  | 1159 +--
 .../src/aQute/bnd/build/ProjectBuilder.java        |  246 +-
 .../src/aQute/bnd/build/ProjectLauncher.java       |  199 +-
 .../src/aQute/bnd/build/ProjectMessages.java       |   48 +
 .../src/aQute/bnd/build/ProjectTester.java         |   22 +-
 .../src/aQute/bnd/build/ReflectAction.java         |   27 +-
 .../src/aQute/bnd/build/ScriptAction.java          |   20 +-
 .../src/aQute/bnd/build/Workspace.java             |  186 +-
 .../src/aQute/bnd/build/WorkspaceRepository.java   |  191 +
 .../src/aQute/bnd/build/model/BndEditModel.java    |  828 +++
 biz.aQute.bndlib/src/aQute/bnd/build/model/EE.java |   61 +
 .../build/model/clauses/ComponentSvcReference.java |  102 +
 .../bnd/build/model/clauses/ExportedPackage.java   |   41 +
 .../bnd/build/model/clauses/HeaderClause.java      |  153 +
 .../bnd/build/model/clauses/ImportPattern.java     |   29 +
 .../bnd/build/model/clauses/ServiceComponent.java  |  249 +
 .../bnd/build/model/clauses/VersionedClause.java   |   27 +
 .../src/aQute/bnd/build/model/clauses/packageinfo  |    1 +
 .../model/conversions/ClauseListConverter.java     |   31 +
 .../model/conversions/CollectionFormatter.java     |   47 +
 .../bnd/build/model/conversions/Converter.java     |    5 +
 .../model/conversions/DefaultBooleanFormatter.java |   26 +
 .../build/model/conversions/DefaultFormatter.java  |    9 +
 .../bnd/build/model/conversions/EEConverter.java   |   11 +
 .../bnd/build/model/conversions/EEFormatter.java   |    9 +
 .../bnd/build/model/conversions/EnumConverter.java |   27 +
 .../bnd/build/model/conversions/EnumFormatter.java |   53 +
 .../model/conversions/HeaderClauseConverter.java   |   13 +
 .../model/conversions/HeaderClauseFormatter.java   |   11 +
 .../conversions/HeaderClauseListConverter.java     |   11 +
 .../bnd/build/model/conversions/MapFormatter.java  |   18 +
 .../conversions/NewlineEscapedStringFormatter.java |   33 +
 .../bnd/build/model/conversions/NoopConverter.java |    7 +
 .../model/conversions/PropertiesConverter.java     |   13 +
 .../conversions/PropertiesEntryFormatter.java      |   26 +
 .../model/conversions/RequirementFormatter.java    |   25 +
 .../conversions/RequirementListConverter.java      |   32 +
 .../model/conversions/SimpleListConverter.java     |   41 +
 .../model/conversions/StringEntryConverter.java    |   11 +
 .../conversions/VersionedClauseConverter.java      |   11 +
 .../src/aQute/bnd/build/model/packageinfo          |    1 +
 biz.aQute.bndlib/src/aQute/bnd/build/packageinfo   |    2 +-
 .../src/aQute/bnd/compatibility/Access.java        |    1 +
 .../aQute/bnd/compatibility/GenericParameter.java  |   17 +-
 .../src/aQute/bnd/compatibility/GenericType.java   |   19 +-
 .../src/aQute/bnd/compatibility/Kind.java          |    2 +-
 .../bnd/compatibility/ParseSignatureBuilder.java   |   83 +-
 .../bnd/compatibility/RuntimeSignatureBuilder.java |   72 +-
 .../src/aQute/bnd/compatibility/Scope.java         |   43 +-
 .../bnd/compatibility/SignatureGenerator.java      |  125 -
 .../src/aQute/bnd/compatibility/Signatures.java    |  364 +-
 .../src/aQute/bnd/component/AnnotationReader.java  |  385 +-
 .../src/aQute/bnd/component/ComponentDef.java      |  216 +-
 .../src/aQute/bnd/component/DSAnnotations.java     |   43 +-
 .../src/aQute/bnd/component/HeaderReader.java      |  504 ++
 .../src/aQute/bnd/component/ReferenceDef.java      |  108 +-
 .../src/aQute/bnd/component/TagResource.java       |   33 +
 .../src/aQute/bnd/concurrent/MultiBuilder.java     |  115 -
 .../src/aQute/bnd/differ/Baseline.java             |  287 +
 .../src/aQute/bnd/differ/DiffImpl.java             |  243 +
 .../src/aQute/bnd/differ/DiffPluginImpl.java       |  192 +
 biz.aQute.bndlib/src/aQute/bnd/differ/Element.java |  145 +
 .../src/aQute/bnd/differ/JavaElement.java          |  647 ++
 .../src/aQute/bnd/differ/RepositoryElement.java    |   23 +
 .../src/aQute/bnd/{help => differ}/packageinfo     |    0
 .../src/aQute/bnd/filerepo/FileRepo.java           |  109 +
 .../src/aQute/bnd/filerepo}/packageinfo            |    0
 biz.aQute.bndlib/src/aQute/bnd/header/Attrs.java   |  343 +
 .../src/aQute/bnd/header/OSGiHeader.java           |  134 +
 .../src/aQute/bnd/header/Parameters.java           |  211 +
 biz.aQute.bndlib/src/aQute/bnd/header/packageinfo  |    1 +
 biz.aQute.bndlib/src/aQute/bnd/help/Errors.java    |    5 -
 biz.aQute.bndlib/src/aQute/bnd/help/Syntax.java    |  842 +--
 biz.aQute.bndlib/src/aQute/bnd/help/packageinfo    |    2 +-
 biz.aQute.bndlib/src/aQute/bnd/make/Make.java      |  162 +-
 biz.aQute.bndlib/src/aQute/bnd/make/MakeBnd.java   |   98 +-
 biz.aQute.bndlib/src/aQute/bnd/make/MakeCopy.java  |   57 +-
 .../aQute/bnd/make/calltree/CalltreeResource.java  |  285 +-
 .../make/component/ComponentAnnotationReader.java  |  126 +-
 .../aQute/bnd/make/component/ServiceComponent.java |  436 +-
 .../src/aQute/bnd/make/coverage/Coverage.java      |  146 +-
 .../aQute/bnd/make/coverage/CoverageResource.java  |  140 +-
 .../aQute/bnd/make/metatype/MetaTypeReader.java    |  168 +-
 .../aQute/bnd/make/metatype/MetatypePlugin.java    |   18 +-
 .../src/aQute/bnd/maven/BsnToMavenPath.java        |    2 +-
 .../src/aQute/bnd/maven/MavenCommand.java          |  245 +-
 .../src/aQute/bnd/maven/MavenDependencyGraph.java  |   39 +-
 .../src/aQute/bnd/maven/MavenDeploy.java           |  127 +-
 .../src/aQute/bnd/maven/MavenDeployCmd.java        |   59 +-
 .../src/aQute/bnd/maven/MavenGroup.java            |   29 +-
 .../src/aQute/bnd/maven/MavenRepository.java       |  122 +-
 .../src/aQute/bnd/maven/PomFromManifest.java       |   32 +-
 .../src/aQute/bnd/maven/PomParser.java             |   42 +-
 .../src/aQute/bnd/maven/PomResource.java           |   33 +-
 .../src/aQute/bnd/maven/support/CachedPom.java     |    3 +-
 .../src/aQute/bnd/maven/support/Maven.java         |   25 +-
 .../src/aQute/bnd/maven/support/MavenEntry.java    |   54 +-
 .../bnd/maven/support/MavenRemoteRepository.java   |   72 +-
 .../src/aQute/bnd/maven/support/Pom.java           |  124 +-
 .../src/aQute/bnd/maven/support/ProjectPom.java    |  101 +-
 .../src/aQute/bnd/maven/support/packageinfo        |    1 +
 .../src/aQute/bnd/obr/OBRFragment.java             |  300 +
 biz.aQute.bndlib/src/aQute/bnd/osgi/About.java     |   39 +
 .../src/aQute/bnd/osgi/AbstractResource.java       |   56 +
 biz.aQute.bndlib/src/aQute/bnd/osgi/Analyzer.java  | 2644 +++++++
 .../src/aQute/bnd/osgi/AnalyzerMessages.java       |   13 +
 .../src/aQute/bnd/osgi/Annotation.java             |   82 +
 biz.aQute.bndlib/src/aQute/bnd/osgi/Builder.java   | 1527 ++++
 biz.aQute.bndlib/src/aQute/bnd/osgi/BundleId.java  |   44 +
 .../src/aQute/bnd/osgi/ClassDataCollector.java     |   83 +
 biz.aQute.bndlib/src/aQute/bnd/osgi/Clazz.java     | 1737 +++++
 .../src/aQute/bnd/osgi/CombinedResource.java       |   34 +
 .../src/aQute/bnd/osgi/CommandResource.java        |   51 +
 biz.aQute.bndlib/src/aQute/bnd/osgi/Constants.java |  325 +
 .../src/aQute/bnd/osgi/Descriptors.java            |  567 ++
 biz.aQute.bndlib/src/aQute/bnd/osgi/Domain.java    |  376 +
 .../src/aQute/bnd/osgi/EmbeddedResource.java       |  100 +
 .../src/aQute/bnd/osgi/FileResource.java           |   79 +
 .../src/aQute/bnd/osgi/Instruction.java            |  185 +
 .../src/aQute/bnd/osgi/Instructions.java           |  222 +
 biz.aQute.bndlib/src/aQute/bnd/osgi/Jar.java       |  861 +++
 .../src/aQute/bnd/osgi/JarResource.java            |   38 +
 biz.aQute.bndlib/src/aQute/bnd/osgi/Macro.java     |  990 +++
 biz.aQute.bndlib/src/aQute/bnd/osgi/OpCodes.java   | 1250 ++++
 biz.aQute.bndlib/src/aQute/bnd/osgi/Packages.java  |  235 +
 .../src/aQute/bnd/osgi/PreprocessResource.java     |   46 +
 biz.aQute.bndlib/src/aQute/bnd/osgi/Processor.java | 1780 +++++
 biz.aQute.bndlib/src/aQute/bnd/osgi/Resource.java  |   17 +
 .../src/aQute/bnd/osgi/URLResource.java            |   85 +
 biz.aQute.bndlib/src/aQute/bnd/osgi/Verifier.java  |  915 +++
 .../src/aQute/bnd/osgi/WriteResource.java          |   75 +
 .../src/aQute/bnd/osgi/ZipResource.java            |   84 +
 biz.aQute.bndlib/src/aQute/bnd/osgi/bnd.info       |    2 +
 .../aQute/bnd/osgi/eclipse/EclipseClasspath.java   |  238 +
 biz.aQute.bndlib/src/aQute/bnd/osgi/packageinfo    |    1 +
 .../src/aQute/bnd/osgi/resource/CapReq.java        |  103 +
 .../src/aQute/bnd/osgi/resource/CapReqBuilder.java |   97 +
 .../src/aQute/bnd/osgi/resource/Filters.java       |   64 +
 .../aQute/bnd/osgi/resource/ResourceBuilder.java   |   55 +
 .../src/aQute/bnd/osgi/resource/ResourceImpl.java  |   73 +
 .../src/aQute/bnd/osgi/resource/packageinfo        |    1 +
 .../aQute/bnd/properties/BadLocationException.java |   14 +
 .../aQute/bnd/properties/CopyOnWriteTextStore.java |  147 +
 .../src/aQute/bnd/properties/Document.java         |   59 +
 .../src/aQute/bnd/properties/GapTextStore.java     |  419 ++
 .../src/aQute/bnd/properties/IDocument.java        |   21 +
 .../src/aQute/bnd/properties/IRegion.java          |    8 +
 .../src/aQute/bnd/properties/ITextStore.java       |   65 +
 .../src/aQute/bnd/properties/Line.java             |   60 +
 .../src/aQute/bnd/properties/LineTracker.java      |  382 +
 .../src/aQute/bnd/properties/LineType.java         |    5 +
 .../aQute/bnd/properties/PropertiesLineReader.java |  125 +
 .../src/aQute/bnd/properties/Region.java           |   22 +
 .../src/aQute/bnd/properties/packageinfo           |    1 +
 .../src/aQute/bnd/repo/eclipse/EclipseRepo.java    |  199 -
 .../src/aQute/bnd/service/Actionable.java          |   48 +
 .../src/aQute/bnd/service/AnalyzerPlugin.java      |   26 +-
 .../src/aQute/bnd/service/BndListener.java         |   35 +-
 .../src/aQute/bnd/service/CommandPlugin.java       |   44 +-
 .../src/aQute/bnd/service/Compiler.java            |    4 +-
 .../aQute/bnd/service/DependencyContributor.java   |    2 +-
 biz.aQute.bndlib/src/aQute/bnd/service/Deploy.java |    8 +-
 .../src/aQute/bnd/service/EclipseJUnitTester.java  |    3 +-
 .../src/aQute/bnd/service/IndexProvider.java       |   12 +
 .../src/aQute/bnd/service/MakePlugin.java          |   27 +-
 .../src/aQute/bnd/service/OBRIndexProvider.java    |   11 -
 .../src/aQute/bnd/service/OBRResolutionMode.java   |    5 -
 biz.aQute.bndlib/src/aQute/bnd/service/Plugin.java |   37 +-
 .../src/aQute/bnd/service/Refreshable.java         |    5 +-
 .../src/aQute/bnd/service/Registry.java            |    1 +
 .../src/aQute/bnd/service/RegistryPlugin.java      |    1 -
 .../aQute/bnd/service/RemoteRepositoryPlugin.java  |   23 +-
 .../bnd/service/RepositoryListenerPlugin.java      |    7 +-
 .../src/aQute/bnd/service/RepositoryPlugin.java    |  195 +-
 .../src/aQute/bnd/service/ResolutionPhase.java     |    5 +
 .../src/aQute/bnd/service/ResourceHandle.java      |   13 +-
 .../src/aQute/bnd/service/Scripter.java            |    2 +-
 .../src/aQute/bnd/service/SignerPlugin.java        |   22 +-
 .../src/aQute/bnd/service/Strategy.java            |    5 +
 .../src/aQute/bnd/service/action/Action.java       |    2 +-
 .../src/aQute/bnd/service/action/NamedAction.java  |    3 +-
 .../src/aQute/bnd/service/diff/Delta.java          |   18 +
 .../src/aQute/bnd/service/diff/Diff.java           |   37 +
 .../src/aQute/bnd/service/diff/Differ.java         |   14 +
 .../src/aQute/bnd/service/diff/Tree.java           |   29 +
 .../src/aQute/bnd/service/diff/Type.java           |   10 +
 .../aQute/bnd/{help => service/diff}/packageinfo   |    0
 biz.aQute.bndlib/src/aQute/bnd/service/packageinfo |    2 +-
 .../bnd/service/repository/MinimalRepository.java  |   24 +
 .../src/aQute/bnd/service/repository}/packageinfo  |    0
 .../src/aQute/bnd/service/url/TaggedData.java      |   36 +
 .../src/aQute/bnd/service/url/URLConnector.java    |   43 +-
 .../src/aQute/bnd/service/url/packageinfo          |    1 +
 .../src/aQute/bnd/settings/Settings.java           |   62 -
 .../src/aQute/bnd/signing/JartoolSigner.java       |  247 +-
 biz.aQute.bndlib/src/aQute/bnd/signing/Signer.java |  351 +-
 .../src/aQute/bnd/test/BndTestCase.java            |   20 +-
 .../NewlineEscapedStringFormatterTestCase.java     |   16 +
 .../src/aQute/bnd/test/SimpleContext.java          |   16 +-
 biz.aQute.bndlib/src/aQute/bnd/test/XmlTester.java |   16 +-
 .../src/aQute/bnd/version/Version.java             |  167 +
 .../src/aQute/bnd/version/VersionRange.java        |   94 +
 .../src/aQute/bnd/version}/packageinfo             |    0
 .../src/aQute/lib/deployer/FileInstallRepo.java    |  149 -
 .../src/aQute/lib/deployer/FileRepo.java           |  855 ++-
 .../deployer/http/HttpBasicAuthURLConnector.java   |  118 -
 .../aQute/lib/deployer/obr/AbstractBaseOBR.java    |  598 --
 .../lib/deployer/obr/CachingURLResourceHandle.java |  243 -
 .../src/aQute/lib/deployer/obr/Capability.java     |   93 -
 .../src/aQute/lib/deployer/obr/CapabilityType.java |   31 -
 .../lib/deployer/obr/DefaultURLConnector.java      |   17 -
 .../lib/deployer/obr/IRepositoryListener.java      |   27 -
 .../src/aQute/lib/deployer/obr/LocalOBR.java       |  195 -
 .../src/aQute/lib/deployer/obr/OBR.java            |  119 -
 .../src/aQute/lib/deployer/obr/OBRSAXHandler.java  |  106 -
 .../src/aQute/lib/deployer/obr/Property.java       |   79 -
 .../src/aQute/lib/deployer/obr/Referral.java       |   59 -
 .../src/aQute/lib/deployer/obr/Require.java        |   73 -
 .../src/aQute/lib/deployer/obr/Resource.java       |  240 -
 .../aQute/lib/deployer/obr/StopParseException.java |    7 -
 .../lib/deployer/obr/UniqueResourceFilter.java     |   54 -
 biz.aQute.bndlib/src/aQute/lib/jardiff/Diff.java   |  152 -
 biz.aQute.bndlib/src/aQute/lib/osgi/About.java     |   46 -
 .../src/aQute/lib/osgi/AbstractResource.java       |   50 -
 biz.aQute.bndlib/src/aQute/lib/osgi/Analyzer.java  | 2301 ------
 .../src/aQute/lib/osgi/Annotation.java             |   73 -
 biz.aQute.bndlib/src/aQute/lib/osgi/Builder.java   | 1220 ----
 .../src/aQute/lib/osgi/ClassDataCollector.java     |   88 -
 biz.aQute.bndlib/src/aQute/lib/osgi/Clazz.java     | 1613 -----
 biz.aQute.bndlib/src/aQute/lib/osgi/Constants.java |  295 -
 .../src/aQute/lib/osgi/EmbeddedResource.java       |   86 -
 .../src/aQute/lib/osgi/FileResource.java           |   85 -
 .../src/aQute/lib/osgi/Instruction.java            |  130 -
 .../src/aQute/lib/osgi/InstructionFilter.java      |   37 -
 biz.aQute.bndlib/src/aQute/lib/osgi/Jar.java       |  690 --
 .../src/aQute/lib/osgi/JarResource.java            |   46 -
 biz.aQute.bndlib/src/aQute/lib/osgi/Macro.java     |  967 ---
 biz.aQute.bndlib/src/aQute/lib/osgi/OpCodes.java   | 1196 ---
 .../src/aQute/lib/osgi/PreprocessResource.java     |   37 -
 biz.aQute.bndlib/src/aQute/lib/osgi/Processor.java | 1422 ----
 biz.aQute.bndlib/src/aQute/lib/osgi/Resource.java  |   11 -
 .../src/aQute/lib/osgi/TagResource.java            |   56 -
 .../src/aQute/lib/osgi/URLResource.java            |   37 -
 biz.aQute.bndlib/src/aQute/lib/osgi/Verifier.java  |  959 ---
 .../src/aQute/lib/osgi/WriteResource.java          |   42 -
 .../src/aQute/lib/osgi/ZipResource.java            |   84 -
 biz.aQute.bndlib/src/aQute/lib/osgi/bnd.info       |    2 -
 .../aQute/lib/osgi/eclipse/EclipseClasspath.java   |  248 -
 biz.aQute.bndlib/src/aQute/lib/osgi/packageinfo    |    1 -
 .../src/aQute/lib/spring/JPAComponent.java         |   26 +-
 .../src/aQute/lib/spring/SpringComponent.java      |   65 +-
 .../src/aQute/lib/spring/SpringXMLType.java        |   30 +-
 biz.aQute.bndlib/src/aQute/lib/spring/XMLType.java |  185 +-
 .../src/aQute/lib/spring/XMLTypeProcessor.java     |   44 +-
 biz.aQute.bndlib/src/aQute/lib/spring/extract.xsl  |   20 +-
 biz.aQute.bndlib/src/test/AnalyzerTest.java        |  540 --
 biz.aQute.bndlib/src/test/AnnotationsTest.java     |  131 -
 biz.aQute.bndlib/src/test/AttributesTest.java      |  139 -
 biz.aQute.bndlib/src/test/BuilderTest.java         | 1648 -----
 .../src/test/CachingURLResourceHandleTest.java     |   29 -
 biz.aQute.bndlib/src/test/CalltreeTest.java        |  164 -
 biz.aQute.bndlib/src/test/ClassParserTest.java     |  352 -
 biz.aQute.bndlib/src/test/ClassReferenceTest.java  |   48 -
 biz.aQute.bndlib/src/test/ClasspathTest.java       |   69 -
 biz.aQute.bndlib/src/test/ClazzTest.java           |   21 -
 biz.aQute.bndlib/src/test/CompareTest.java         |  113 -
 biz.aQute.bndlib/src/test/ComponentTest.java       | 1129 ---
 biz.aQute.bndlib/src/test/CorruptManifest.java     |   47 -
 biz.aQute.bndlib/src/test/DSAnnotationTest.java    |  180 -
 biz.aQute.bndlib/src/test/DiffTest.java            |   18 -
 biz.aQute.bndlib/src/test/ExportHeaderTest.java    |   60 -
 biz.aQute.bndlib/src/test/FilterTest.java          |   16 -
 biz.aQute.bndlib/src/test/GlobTest.java            |   29 -
 biz.aQute.bndlib/src/test/GroupsTest.java          |   83 -
 biz.aQute.bndlib/src/test/IncludeHeaderTest.java   |  142 -
 biz.aQute.bndlib/src/test/InlineTest.java          |   25 -
 biz.aQute.bndlib/src/test/JarSignerTest.java       |   90 -
 biz.aQute.bndlib/src/test/JarTest.java             |   69 -
 biz.aQute.bndlib/src/test/LauncherTest.java        |   69 -
 biz.aQute.bndlib/src/test/MacroTest.java           |  480 --
 biz.aQute.bndlib/src/test/MakeTest.java            |  114 -
 biz.aQute.bndlib/src/test/ManifestTest.java        |  196 -
 biz.aQute.bndlib/src/test/MavenTest.java           |  361 -
 biz.aQute.bndlib/src/test/MergeTest.java           |   70 -
 biz.aQute.bndlib/src/test/MetatypeTest.java        |  902 ---
 biz.aQute.bndlib/src/test/NativeHeader.java        |   59 -
 biz.aQute.bndlib/src/test/NoUsesTest.java          |  127 -
 biz.aQute.bndlib/src/test/PackTest.java            |   19 -
 biz.aQute.bndlib/src/test/ParseHeaderTest.java     |   81 -
 biz.aQute.bndlib/src/test/PluginTest.java          |   55 -
 biz.aQute.bndlib/src/test/ProcessorTest.java       |   46 -
 biz.aQute.bndlib/src/test/ProjectTest.java         |  211 -
 biz.aQute.bndlib/src/test/PropertiesTest.java      |  127 -
 biz.aQute.bndlib/src/test/RepoBuilderTest.java     |   47 -
 biz.aQute.bndlib/src/test/ResourcesTest.java       |  220 -
 biz.aQute.bndlib/src/test/SpringTest.java          |   91 -
 biz.aQute.bndlib/src/test/TestBndBook.java         |   29 -
 biz.aQute.bndlib/src/test/TestEclipseRepo.java     |   21 -
 biz.aQute.bndlib/src/test/TestQuotedTokenizer.java |   61 -
 biz.aQute.bndlib/src/test/TestSelfBuild.java       |   25 -
 biz.aQute.bndlib/src/test/TestSignatures.java      |   82 -
 biz.aQute.bndlib/src/test/VerifierTest.java        |  240 -
 biz.aQute.bndlib/src/test/VersionPolicyTest.java   |  274 -
 biz.aQute.bndlib/src/test/WorkspaceTest.java       |   27 -
 biz.aQute.bndlib/src/test/activator/Activator.java |   13 -
 .../activator/inherits/InheritedActivator.java     |   11 -
 .../src/test/classreference/ClassReference.java    |    9 -
 .../src/test/lib/deployer/obr/NanoHTTPD.java       | 1004 ---
 .../src/test/lib/deployer/obr/OBRAllTests.java     |   17 -
 .../src/test/lib/deployer/obr/OBRParseTest.java    |  125 -
 .../src/test/lib/deployer/obr/OBRTest.java         |  189 -
 .../src/test/lib/deployer/obr/fullobr.xml          |  553 --
 .../src/test/lib/deployer/obr/referralobr.xml      |    6 -
 .../src/test/lib/deployer/obr/testobr.xml          |   99 -
 .../src/test/lib/deployer/obr/unparseable.xml      |   70 -
 biz.aQute.bndlib/src/test/make/MD5.java            |   42 -
 biz.aQute.bndlib/src/test/packageinfo/Dummy.java   |    5 -
 .../src/test/packageinfo/ref/DummyRef.java         |    7 -
 .../src/test/privateimport/PrivateImport.java      |   39 -
 .../src/test/refer/RefersToEventAdmin.java         |    7 -
 biz.aQute.bndlib/src/test/refer/RefersToHttp.java  |    7 -
 .../src/test/refer/RefersToMeasurement.java        |    7 -
 biz.aQute.bndlib/src/test/signatures/Z.java        |   83 -
 biz.aQute.bndlib/src/test/top/Top.java             |    4 -
 .../src/test/versionpolicy/api/EventAdmin.java     |    8 -
 .../src/test/versionpolicy/api/EventHandler.java   |    9 -
 .../src/test/versionpolicy/api/package-info.java   |    6 -
 .../versionpolicy/implemented/Implemented.java     |    8 -
 .../versionpolicy/implmajor/MajorImplemented.java  |   10 -
 .../src/test/versionpolicy/uses/Uses.java          |    7 -
 biz.aQute.bndlib/test.out                          |   45 -
 .../test/w o r k s p a c e/cnf/build.bnd           |    2 -
 .../test/w o r k s p a c e/cnf/ext/extension.bnd   |    2 -
 .../1.0.4/_maven.repositories                      |    4 -
 ...rg.apache.commons.logging-1.0.4.jar.lastUpdated |    5 -
 ...ource.org.apache.commons.logging-1.0.4.jar.sha1 |    1 -
 ...ringsource.org.apache.commons.logging-1.0.4.pom |   23 -
 ...rg.apache.commons.logging-1.0.4.pom.lastUpdated |    5 -
 ...ource.org.apache.commons.logging-1.0.4.pom.sha1 |    1 -
 ...ource.org.apache.commons.logging-1.1.1.jar.sha1 |    1 -
 ...ringsource.org.apache.commons.logging-1.1.1.pom |   29 -
 ...ource.org.apache.commons.logging-1.1.1.pom.sha1 |    1 -
 biz.aQute.jpm/.classpath                           |    7 +
 biz.aQute.jpm/.project                             |   23 +
 .../.settings/org.eclipse.core.resources.prefs     |    3 +
 .../.settings/org.eclipse.core.runtime.prefs       |    3 +
 biz.aQute.jpm/.settings/org.eclipse.jdt.core.prefs |  361 +
 biz.aQute.jpm/.settings/org.eclipse.jdt.ui.prefs   |   61 +
 biz.aQute.jpm/bnd.bnd                              |   46 +
 biz.aQute.jpm/bnd/service.bnd                      |    8 +
 biz.aQute.jpm/build.xml                            |    4 +
 biz.aQute.jpm/daemon.bnd                           |    8 +
 biz.aQute.jpm/images/icon.png                      |  Bin 0 -> 4387 bytes
 biz.aQute.jpm/release                              |    1 +
 biz.aQute.jpm/restart.sh                           |    6 +
 biz.aQute.jpm/run.bnd                              |   18 +
 biz.aQute.jpm/src/aQute/daemon/Daemon.java         |   19 +
 biz.aQute.jpm/src/aQute/jpm/lib/ArtifactData.java  |   33 +
 biz.aQute.jpm/src/aQute/jpm/lib/CommandData.java   |   28 +
 .../aQute/jpm/lib/JustAnotherPackageManager.java   |  963 +++
 biz.aQute.jpm/src/aQute/jpm/lib/Service.java       |  169 +
 biz.aQute.jpm/src/aQute/jpm/lib/ServiceData.java   |   20 +
 biz.aQute.jpm/src/aQute/jpm/main/InstallCert.java  |  159 +
 biz.aQute.jpm/src/aQute/jpm/main/Main.java         | 1475 ++++
 biz.aQute.jpm/src/aQute/jpm/platform/Linux.java    |   26 +
 biz.aQute.jpm/src/aQute/jpm/platform/MacOS.java    |  100 +
 biz.aQute.jpm/src/aQute/jpm/platform/Platform.java |  162 +
 biz.aQute.jpm/src/aQute/jpm/platform/Service.java  |   11 +
 biz.aQute.jpm/src/aQute/jpm/platform/Unix.java     |  202 +
 biz.aQute.jpm/src/aQute/jpm/platform/Windows.java  |  223 +
 .../src/aQute/jpm/platform/macos/command.sh        |    2 +
 .../src/aQute/jpm/platform/macos/daemon.plist      |   12 +
 .../src/aQute/jpm/platform/macos/launch.sh         |    7 +
 biz.aQute.jpm/src/aQute/jpm/platform/service       |    2 +
 .../src/aQute/jpm/platform/unix/command.sh         |    2 +
 biz.aQute.jpm/src/aQute/jpm/platform/unix/initd.sh |    2 +
 .../src/aQute/jpm/platform/unix/launch.sh          |    7 +
 .../aQute/jpm/platform/windows/WinRegistry.java    |  392 +
 .../src/aQute/jpm/platform/windows/command.sh      |    1 +
 .../src/aQute/jpm/service/ServiceMain.java         |  156 +
 .../aQute/jpm/service/TraceSecurityManager.java    |   68 +
 biz.aQute.jpm/test/test/JPMTest.java               |   98 +
 .../.settings/org.eclipse.jdt.core.prefs           |  355 +-
 biz.aQute.junit/.settings/org.eclipse.jdt.ui.prefs |   61 +
 biz.aQute.junit/bnd.bnd                            |   26 +-
 biz.aQute.junit/src/aQute/junit/Activator.java     |  319 +-
 .../src/aQute/junit/BasicTestReport.java           |   27 +-
 .../src/aQute/junit/JUnitEclipseReport.java        |  245 +-
 .../src/aQute/junit/JunitXmlReport.java            |   65 +-
 biz.aQute.junit/src/aQute/junit/Tag.java           |  134 +-
 biz.aQute.junit/src/aQute/junit/Tee.java           |   15 +-
 biz.aQute.junit/src/aQute/junit/TestReporter.java  |    5 +-
 .../src/aQute/junit/constants/TesterConstants.java |   12 +
 .../src/aQute/junit/plugin/ProjectTesterImpl.java  |   24 +-
 .../src/aQute/junit/runtime/OSGiTestCase.java      |   55 +-
 .../src/aQute/junit/runtime/Operation.java         |   11 -
 .../src/aQute/junit/runtime/VoidOperation.java     |   23 +-
 biz.aQute.launcher/.classpath                      |    3 -
 .../.settings/org.eclipse.jdt.core.prefs           |  358 +-
 .../.settings/org.eclipse.jdt.ui.prefs             |   61 +
 biz.aQute.launcher/bnd.bnd                         |    7 +-
 .../src/aQute/launcher/Launcher.java               |  609 +-
 .../src/aQute/launcher/SimplePermissionPolicy.java |   37 +-
 .../launcher/constants/LauncherConstants.java      |   96 +-
 .../src/aQute/launcher/minifw/Context.java         |  642 +-
 .../src/aQute/launcher/minifw/MiniFramework.java   |   91 +-
 .../aQute/launcher/plugin/ProjectLauncherImpl.java |  168 +-
 biz.aQute.launcher/src/test/MiniFrameworkTest.java |   34 +
 .../src/test/ProjectLaunchImplTest.java            |   43 +
 .../src}/test/ws/cnf/build.bnd                     |    0
 biz.aQute.launcher/src/test/ws/p1/bnd.bnd          |    3 +
 .../test/test/MiniFrameworkTest.java               |   34 -
 biz.aQute.repository/.classpath                    |    6 +
 biz.aQute.repository/.project                      |   23 +
 .../.settings/org.eclipse.core.resources.prefs     |    3 +
 .../.settings/org.eclipse.core.runtime.prefs       |    3 +
 .../.settings/org.eclipse.jdt.core.prefs           |  361 +
 .../.settings/org.eclipse.jdt.ui.prefs             |   61 +
 biz.aQute.repository/bnd.bnd                       |   85 +
 biz.aQute.repository/build.xml                     |    4 +
 .../src/aQute/bnd/deployer/Constants.java          |    5 +
 .../bnd/deployer/http/DefaultURLConnector.java     |   79 +
 .../deployer/http/HttpBasicAuthURLConnector.java   |  173 +
 .../src/aQute/bnd/deployer/http/HttpsUtil.java     |   43 +
 .../src/aQute/bnd/deployer/obr/Conversions.java    |   28 +
 .../src/aQute/bnd/deployer/obr/LocalOBR.java       |   14 +
 .../src/aQute/bnd/deployer/obr/NexusOBR.java       |  280 +
 .../src/aQute/bnd/deployer/obr/OBR.java            |   36 +
 .../deployer/repository/AbstractIndexedRepo.java   |  702 ++
 .../repository/CachingUriResourceHandle.java       |  350 +
 .../bnd/deployer/repository/CapabilityIndex.java   |   61 +
 .../bnd/deployer/repository/FixedIndexedRepo.java  |   99 +
 .../bnd/deployer/repository/LocalIndexedRepo.java  |  353 +
 .../repository/MapToDictionaryAdapter.java         |   64 +
 .../bnd/deployer/repository/NullLogService.java    |   16 +
 .../bnd/deployer/repository/ProtectedStream.java   |   56 +
 .../deployer/repository/ReporterLogService.java    |   42 +
 .../bnd/deployer/repository/api/CheckResult.java   |   51 +
 .../bnd/deployer/repository/api/Decision.java      |    5 +
 .../repository/api/IRepositoryContentProvider.java |   94 +
 .../repository/api/IRepositoryIndexProcessor.java  |   33 +
 .../bnd/deployer/repository/api/Referral.java      |   59 +
 .../aQute/bnd/deployer/repository/api/packageinfo  |    1 +
 .../src/aQute/bnd/deployer/repository/packageinfo  |    1 +
 .../repository/providers/AttributeType.java        |  101 +
 .../providers/KnownBundleAnalyzerPlugin.java       |   47 +
 .../repository/providers/ObrContentProvider.java   |  366 +
 .../bnd/deployer/repository/providers/ObrUtil.java |   44 +
 .../providers/R5RepoContentProvider.java           |  269 +
 .../deployer/repository/providers/ScalarType.java  |   28 +
 biz.aQute.repository/src/test/AllTests.java        |   32 +
 biz.aQute.repository/src/test/helpers/Sed.java     |   48 +
 .../test/http/CachingUriResourceHandlerTest.java   |  141 +
 .../src/test/http/ETaggingResourceHandler.java     |   94 +
 .../src/test/http/HttpConnectorTest.java           |  316 +
 .../src/test/lib/MockRegistry.java                 |   32 +
 biz.aQute.repository/src/test/lib/NanoHTTPD.java   | 1058 +++
 biz.aQute.repository/src/test/obr/OBRTest.java     |  215 +
 .../src/test/r5repository/FindProvidersTest.java   |   90 +
 .../test/repository/FailingGeneratingProvider.java |   38 +
 .../src/test/repository/NonGeneratingProvider.java |   38 +
 .../test/repository/TestAttributeTypeParsing.java  |   23 +
 .../src/test/repository/TestCompressedObrRepo.java |  128 +
 .../src/test/repository/TestFixedIndexedRepo.java  |  152 +
 .../test/repository/TestLocalIndexGeneration.java  |  153 +
 .../src/test/repository/TestLocalIndexedRepo.java  |   67 +
 .../test/repository/TestLocalObrGeneration.java    |   81 +
 .../TestMultipleLocalIndexGeneration.java          |  124 +
 .../src/test/repository/TestObrCapReqParsing.java  |  113 +
 .../src/test/repository/TestObrRecognition.java    |  125 +
 .../src/test/repository/TestObrRepo.java           |  149 +
 .../src/test/repository/TestR5Recognition.java     |   98 +
 biz.aQute.repository/testdata/ambiguous.xml        |    2 +
 biz.aQute.repository/testdata/big_index.xml        | 7186 ++++++++++++++++++
 biz.aQute.repository/testdata/big_index.xml.gz     |  Bin 0 -> 16657 bytes
 biz.aQute.repository/testdata/bree-obr.xml         |   19 +
 biz.aQute.repository/testdata/dummy.dtd            |    2 +
 biz.aQute.repository/testdata/example.keystore     |  Bin 0 -> 1258 bytes
 biz.aQute.repository/testdata/fullobr.xml          |  553 ++
 biz.aQute.repository/testdata/http_auth.properties |    3 +
 .../testdata/http_auth_wrong.properties            |    4 +
 .../dummybundle.jar.etag                           |    1 +
 .../dummybundle.jar.sha                            |    1 +
 .../dummybundle.jar.etag                           |    1 +
 .../dummybundle.jar.sha                            |    1 +
 biz.aQute.repository/testdata/index1.xml           |   50 +
 biz.aQute.repository/testdata/index2.xml           | 7655 ++++++++++++++++++++
 biz.aQute.repository/testdata/index2.xml.gz        |  Bin 0 -> 23782 bytes
 .../testdata/jetty-users.properties                |    1 +
 biz.aQute.repository/testdata/minir5.xml           |   50 +
 biz.aQute.repository/testdata/xmlWithDtdRef.xml    |    3 +
 biz.aQute.resolve/.classpath                       |    6 +
 biz.aQute.resolve/.project                         |   23 +
 .../.settings/org.eclipse.core.resources.prefs     |    3 +
 .../.settings/org.eclipse.core.runtime.prefs       |    3 +
 .../.settings/org.eclipse.jdt.core.prefs           |  361 +
 .../.settings/org.eclipse.jdt.ui.prefs             |   57 +
 biz.aQute.resolve/bnd.bnd                          |   17 +
 biz.aQute.resolve/build.xml                        |    7 +
 .../src/biz/aQute/resolve/ResolveProcess.java      |  120 +
 .../resolve/internal/BndrunResolveContext.java     |  440 ++
 .../internal/FrameworkResourceRepository.java      |  144 +
 .../biz/aQute/resolve/internal/J2SE_1_2.properties |   25 +
 .../biz/aQute/resolve/internal/J2SE_1_3.properties |   41 +
 .../biz/aQute/resolve/internal/J2SE_1_4.properties |   97 +
 .../biz/aQute/resolve/internal/J2SE_1_5.properties |  123 +
 .../biz/aQute/resolve/internal/JRE_1_1.properties  |    1 +
 .../aQute/resolve/internal/JavaSE_1_6.properties   |  160 +
 .../aQute/resolve/internal/JavaSE_1_7.properties   |  163 +
 .../resolve/internal/OSGI_Minimum_1_0.properties   |    0
 .../resolve/internal/OSGI_Minimum_1_1.properties   |    0
 .../resolve/internal/OSGI_Minimum_1_2.properties   |    0
 .../src/biz/aQute/resolve/internal/Utils.java      |   30 +
 .../src/biz/aQute/resolve}/packageinfo             |    0
 .../src/test/BndrunResolveContextTest.java         |  436 ++
 biz.aQute.resolve/src/test/lib/MockRegistry.java   |   34 +
 biz.aQute.resolve/src/test/lib/NullLogService.java |   16 +
 biz.aQute.resolve/src/test/lib/Utils.java          |   54 +
 biz.aQute.resolve/testdata/buildrepo.index.xml     |  238 +
 .../org.apache.felix.framework-4.0.0.index.xml     |   86 +
 .../org.apache.felix.framework-4.0.2.index.xml     |   86 +
 .../testdata/osgi.cmpn-4.3.0.index.xml             |  226 +
 biz.aQute.resolve/testdata/readme.txt              |    3 +
 biz.aQute.resolve/testdata/repo1.index.xml         |   61 +
 biz.aQute.resolve/testdata/repo2.index.xml         |   61 +
 biz.aQute.resolve/testdata/repo3.index.xml         |  225 +
 biz.aQute.resolve/testdata/repo4.index.xml         |  163 +
 build.xml                                          |   47 +-
 cnf/build.bnd                                      |   16 +-
 cnf/build.xml                                      |  141 +-
 cnf/eclipse/bnd(tools).importorder                 |    6 +
 cnf/eclipse/codeformatter.xml                      |  579 ++
 cnf/findbugs.exclude.xml                           |   25 +
 cnf/findbugs.include.xml                           |  512 ++
 cnf/findbugs/README.txt                            |   20 +
 cnf/findbugs/bin/addMessages                       |   73 +
 cnf/findbugs/bin/computeBugHistory                 |   78 +
 cnf/findbugs/bin/convertXmlToText                  |   73 +
 cnf/findbugs/bin/copyBuggySource                   |   75 +
 cnf/findbugs/bin/defectDensity                     |   77 +
 cnf/findbugs/bin/deprecated/bugHistory             |   75 +
 cnf/findbugs/bin/deprecated/unionBugs              |   78 +
 cnf/findbugs/bin/deprecated/unionResults           |   80 +
 cnf/findbugs/bin/deprecated/updateBugs             |   78 +
 .../bin/experimental/backdateHistoryUsingSource    |   75 +
 cnf/findbugs/bin/experimental/churn                |   75 +
 cnf/findbugs/bin/experimental/obfuscate            |   75 +
 cnf/findbugs/bin/experimental/treemapVisualization |   75 +
 cnf/findbugs/bin/fb                                |  192 +
 cnf/findbugs/bin/fbwrap                            |   84 +
 cnf/findbugs/bin/filterBugs                        |   78 +
 cnf/findbugs/bin/findbugs                          |  199 +
 cnf/findbugs/bin/findbugs-csr                      |   76 +
 cnf/findbugs/bin/findbugs-dbStats                  |   76 +
 cnf/findbugs/bin/findbugs-msv                      |   76 +
 cnf/findbugs/bin/findbugs.bat                      |  240 +
 cnf/findbugs/bin/findbugs2                         |  177 +
 cnf/findbugs/bin/listBugDatabaseInfo               |   75 +
 cnf/findbugs/bin/mineBugHistory                    |   73 +
 cnf/findbugs/bin/printAppVersion                   |   75 +
 cnf/findbugs/bin/printClass                        |   73 +
 cnf/findbugs/bin/rejarForAnalysis                  |   75 +
 cnf/findbugs/bin/setBugDatabaseInfo                |   75 +
 cnf/findbugs/bin/unionBugs                         |   80 +
 cnf/findbugs/bin/xpathFind                         |   75 +
 cnf/findbugs/lib/buggy.icns                        |  Bin 0 -> 36133 bytes
 cnf/findbugs/src/xsl/default.xsl                   |  376 +
 cnf/findbugs/src/xsl/fancy-hist.xsl                | 1197 +++
 cnf/findbugs/src/xsl/fancy.xsl                     |  848 +++
 cnf/findbugs/src/xsl/plain.xsl                     |  306 +
 cnf/findbugs/src/xsl/summary.xsl                   |  252 +
 cnf/scripts/fb_generate_includes.bash              |   33 +
 demo/.classpath                                    |    1 -
 demo/.settings/org.eclipse.jdt.core.prefs          |  361 +-
 demo/.settings/org.eclipse.jdt.ui.prefs            |   61 +
 demo/bnd.bnd                                       |   11 +-
 demo/src/com/example/demo/Activator.java           |    4 +-
 demo/src/test/TestActivator.java                   |   16 +-
 demo/src/test/TestCase1.java                       |   17 +-
 dist/.classpath                                    |    8 +
 dist/.project                                      |   23 +
 dist/.settings/org.eclipse.jdt.core.prefs          |   12 +
 dist/bnd.bnd                                       |    8 +
 dist/build.xml                                     |    7 +
 .../src/test/split/A => dist/src/.empty            |    0
 .../src/test/split/A => dist/test/.empty           |    0
 osgi.r5/.classpath                                 |    6 +
 osgi.r5/.project                                   |   23 +
 osgi.r5/.settings/org.eclipse.core.resources.prefs |    3 +
 osgi.r5/.settings/org.eclipse.core.runtime.prefs   |    3 +
 osgi.r5/.settings/org.eclipse.jdt.core.prefs       |  361 +
 osgi.r5/.settings/org.eclipse.jdt.ui.prefs         |   61 +
 osgi.r5/README.txt                                 |    6 +
 osgi.r5/bnd.bnd                                    |   18 +
 osgi.r5/build.xml                                  |    4 +
 1260 files changed, 104325 insertions(+), 42226 deletions(-)

diff --git a/README b/README
index 708ce08..b0d1cc1 100644
--- a/README
+++ b/README
@@ -1,24 +1,31 @@
-README bnd
+# README bnd
 bnd is a swiss army knife for OSGi, it creates manifest headers for you based on 
 analyzing the class code, it verifies your settings, it manages project dependencies,
 gives you quote of the day, diffs jars, and much more. 
 
 The information about bnd can be found at http://www.aQute.biz/Bnd
 
-Repository
+## Repository
 The git repository contains all code. It contains the following projects:
 
-1) bndlib     - Core library function, also contains most tests
-2) bnd        - Command line tool, eclipse plugin, and ant plugin
-3) launcher   - A launcher plugin for bnd
-4) libg       - Small, simple library utilities that are useful outside bnd
-5) junit      - A tester plugin for JUnit 3.8 testing for bnd
-6) cnf        - The bnd project directory, contains the repo with dependencies
-7) demo       - A project used in testing
-8) compiler   - A wrapped version of the eclipse java compiler
-
-API
+* aQute.libg - Library to be statically linked (Conditional-Package)
+* biz.aQute.bnd - A command line utility and ant plugin
+* biz.aQute.bndlib - The core library
+* biz.aQute.bndlib.tests - Tests for the core library
+* biz.aQute.jpm - Just another package manager for Java		     
+* biz.aQute.junit - Junit tester (runs on Java 1.4)
+* biz.aQute.launcher - Launcher (runs on Java 1.4)
+* biz.aQute.repository - Different repos with OBR
+* biz.aQute.resolve - OBR Resolver
+* cnf - Configuration directory
+* demo - Used in testing
+* dist - Contains the distribution after 'ant dist'
+* osgi.r5 - OSGi jars without all dependencies
+
+## License
 All code is Apache 2.0 Licensed so you can do what you want with the source code. 
+
+## API
 though I am usually pretty good at backward compatibility, there is no guarantee. This
 is an unpaid project and one of the most annoying thing of work is being backward compatible
 on the Java API when you know a better way to do it. Properties will be backward compatible
@@ -29,15 +36,11 @@ If you're building a tool with a general audience, e.g. bndtools,  that includes
 for a general audience I would appreciate if you got in touch with me so I can keep 
 in touch. I am always interested in ideas.
 
-Eclipse
-bnd is build with itself, which can create some headaches. Overall, you want 
-to your work therefore in Eclipse with a recent bnd.jar in the Eclipse dropins
-folder. Currently, bndtools is not yet ready for bnd itself :-( however, that is
-being worked on. Once bndtools handles the bnd launcher/tester then the eclipse
-plugin will be removed. Until that moment, we need to use the old code in Eclipse.
-It is advised to not mix bnd and bndtools but use different instances of Eclipse.
+## Eclipse
+bndtools is the development environment of bnd. An earlier Eclipse plugin in bnd is no longer
+available.
 
-Building
+## Building
 The workspace root has a build.xml that builds all project in proper order. Due
 to the fact that bnd builds itself there are certain cases where you get an error
 during build. Trying again should fix the issue.
@@ -48,37 +51,24 @@ ant build (default) - Build
 ant clean           - Clean the project
 ant test            - Run a bnd OSGi test
 ant junit           - Run standard JUnit tests in the test package
+ant dist            - Create a dist directory with all the bundles in repo format + obr indexes
 
 Outputs are stored in the tmp directory in the different projects.
 
-Testing
-The main tests are in the bndlib project. These are standard JUnit tests. They
+## Testing
+The main tests are in the biz.aQute.bndlib.tests project. These are standard JUnit tests. They
 are all in the src/test directory. Tests are quite extensive and run from the
 Eclipse JUnit screen.
 
-Release
-The current release process could use some work. The following steps are used:
-
-1) Changes to the tree are made on the next branch
-2) After the next branch is done, commit all changes. There are a few
-   files changed by tests that should not be committed every time: 
-   # biz.aQute.bndlib/test/ws/p1/bnd.bnd
-   # biz.aQute.bndlib/test/ws/p1/bnd.bnd.bak
-   # biz.aQute.bndlib/test/ws/p3/generated/p3.jar
-   This needs fixing btw. The test should not touch those files or at least restore
-3) Switch to master
-4) ant clean build
-5) run the tests
-6) if successful, release the jars
-7) bump the version (bnd bump command does this)
-8) switch to next branch
-
-This process is likely to change because it contains too many manual steps
-
-Feedback
+## Release
+bnd is continuously built on Cloudbees: https://bndtools.ci.cloudbees.com/#
+
+A more comprehensive release process is in the works.
+
+## Feedback
 Feedback is always welcome, for general discussions use bndtools-users at googlegroups.com
+
 Bugs and issues should go to https://github.com/bndtools/bnd
-Other feedback or specific functionality send to Peter.Kriens at aQute.biz
 
-Donations should go to http://pledgie.com/campaigns/10548
+Other feedback or specific functionality send to Peter.Kriens at aQute.biz
 
diff --git a/aQute.libg/.classpath b/aQute.libg/.classpath
index ffef9ec..6d3c62a 100755
--- a/aQute.libg/.classpath
+++ b/aQute.libg/.classpath
@@ -2,6 +2,5 @@
 <classpath>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/aQute.libg/.project b/aQute.libg/.project
index d19dd5e..c9df66a 100755
--- a/aQute.libg/.project
+++ b/aQute.libg/.project
@@ -10,8 +10,14 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>bndtools.core.bndbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>bndtools.core.bndnature</nature>
 	</natures>
 </projectDescription>
diff --git a/aQute.libg/.settings/org.eclipse.jdt.core.prefs b/aQute.libg/.settings/org.eclipse.jdt.core.prefs
index 9789af1..3590ca7 100644
--- a/aQute.libg/.settings/org.eclipse.jdt.core.prefs
+++ b/aQute.libg/.settings/org.eclipse.jdt.core.prefs
@@ -1,4 +1,4 @@
-#Mon Oct 12 17:22:15 CEST 2009
+#Fri Aug 10 13:46:22 CEST 2012
 eclipse.preferences.version=1
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
@@ -7,6 +7,355 @@ org.eclipse.jdt.core.compiler.compliance=1.5
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
 org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=ignore
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
 org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=true
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/aQute.libg/.settings/org.eclipse.jdt.ui.prefs b/aQute.libg/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..f5e8897
--- /dev/null
+++ b/aQute.libg/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,61 @@
+#Fri Aug 10 13:48:46 CEST 2012
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=false
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=false
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=false
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
+cleanup_settings_version=2
+eclipse.preferences.version=1
+formatter_profile=_bnd(tools)
+formatter_settings_version=12
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=1
+org.eclipse.jdt.ui.staticondemandthreshold=1
diff --git a/aQute.libg/bnd.bnd b/aQute.libg/bnd.bnd
index 23f60bb..4640058 100644
--- a/aQute.libg/bnd.bnd
+++ b/aQute.libg/bnd.bnd
@@ -1,6 +1,9 @@
--nobundles: true
--buildpath: com.springsource.junit
+-buildpath: com.springsource.junit,\
+	ee.j2se;version=${javac.ee}
 
-Private-Package: aQute.lib.*, aQute.libg.*
+Export-Package: aQute.lib.*, aQute.libg.*, aQute.configurable, aQute.service.*
+Bundle-Version: 2.7.4.${tstamp;yyyyMMdd-HHmmss}
+Bundle-Description: A library to be statically linked. Contains many small utilities. This bundle \
+ should not be installed in a framework, it is compile only.
 
 
diff --git a/aQute.libg/src/aQute/configurable/Config.java b/aQute.libg/src/aQute/configurable/Config.java
new file mode 100644
index 0000000..e652ad7
--- /dev/null
+++ b/aQute.libg/src/aQute/configurable/Config.java
@@ -0,0 +1,17 @@
+package aQute.configurable;
+
+import java.lang.annotation.*;
+
+ at Target(ElementType.METHOD)
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface Config {
+	String	NULL	= "<<NULL>>";
+
+	boolean required() default false;
+
+	String description() default "";
+
+	String deflt() default NULL;
+
+	String id() default NULL;
+}
diff --git a/aQute.libg/src/aQute/configurable/Configurable.java b/aQute.libg/src/aQute/configurable/Configurable.java
new file mode 100644
index 0000000..72902e2
--- /dev/null
+++ b/aQute.libg/src/aQute/configurable/Configurable.java
@@ -0,0 +1,312 @@
+package aQute.configurable;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.lang.reflect.Proxy;
+import java.net.*;
+import java.util.*;
+import java.util.regex.*;
+
+public class Configurable<T> {
+
+	public static <T> T createConfigurable(Class<T> c, Map< ? , ? > properties) {
+		Object o = Proxy.newProxyInstance(c.getClassLoader(), new Class< ? >[] {
+			c
+		}, new ConfigurableHandler(properties, c.getClassLoader()));
+		return c.cast(o);
+	}
+
+	public static <T> T createConfigurable(Class<T> c, Dictionary< ? , ? > properties) {
+		Map<Object,Object> alt = new HashMap<Object,Object>();
+		for (Enumeration< ? > e = properties.keys(); e.hasMoreElements();) {
+			Object key = e.nextElement();
+			alt.put(key, properties.get(key));
+		}
+		return createConfigurable(c, alt);
+	}
+
+	static class ConfigurableHandler implements InvocationHandler {
+		final Map< ? , ? >	properties;
+		final ClassLoader	loader;
+
+		ConfigurableHandler(Map< ? , ? > properties, ClassLoader loader) {
+			this.properties = properties;
+			this.loader = loader;
+		}
+
+		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+			Config ad = method.getAnnotation(Config.class);
+			String id = Configurable.mangleMethodName(method.getName());
+
+			if (ad != null && !ad.id().equals(Config.NULL))
+				id = ad.id();
+
+			Object o = properties.get(id);
+			if (o == null && args != null && args.length == 1)
+				o = args[0];
+
+			if (o == null) {
+				if (ad != null) {
+					if (ad.required())
+						throw new IllegalStateException("Attribute is required but not set " + method.getName());
+
+					o = ad.deflt();
+					if (o.equals(Config.NULL))
+						o = null;
+				}
+			}
+			if (o == null) {
+				Class< ? > rt = method.getReturnType();
+				if (rt == boolean.class || rt == Boolean.class)
+					return false;
+				if (method.getReturnType().isPrimitive() || Number.class.isAssignableFrom(method.getReturnType())) {
+
+					o = "0";
+				} else
+					return null;
+			}
+
+			if (args != null && args.length == 1) {
+				String s = (String) convert(String.class, o);
+
+				// Allow a base to be specified for File and URL
+				if (method.getReturnType() == File.class && args[0].getClass() == File.class) {
+					return new File((File) args[0], s);
+				} else if (method.getReturnType() == URL.class && args[0].getClass() == File.class) {
+					return new URL(((File) args[0]).toURI().toURL(), s);
+				} else if (method.getReturnType() == URL.class && args[0].getClass() == URL.class) {
+					return new URL((URL) args[0], s);
+				}
+			}
+			return convert(method.getGenericReturnType(), o);
+		}
+
+		@SuppressWarnings({
+				"unchecked", "rawtypes"
+		})
+		public Object convert(Type type, Object o) throws Exception {
+
+			// TODO type variables
+			// TODO wildcards
+
+			if (type instanceof ParameterizedType) {
+				ParameterizedType pType = (ParameterizedType) type;
+				return convert(pType, o);
+			}
+
+			if (type instanceof GenericArrayType) {
+				GenericArrayType gType = (GenericArrayType) type;
+				return convertArray(gType.getGenericComponentType(), o);
+			}
+
+			Class< ? > resultType = (Class< ? >) type;
+
+			if (resultType.isArray()) {
+				return convertArray(resultType.getComponentType(), o);
+			}
+
+			Class< ? > actualType = o.getClass();
+			if (actualType.isAssignableFrom(resultType))
+				return o;
+
+			if (resultType == boolean.class || resultType == Boolean.class) {
+				if (actualType == boolean.class || actualType == Boolean.class)
+					return o;
+
+				if (Number.class.isAssignableFrom(actualType)) {
+					double b = ((Number) o).doubleValue();
+					if (b == 0)
+						return false;
+					return true;
+				}
+				return true;
+
+			} else if (resultType == byte.class || resultType == Byte.class) {
+				if (Number.class.isAssignableFrom(actualType))
+					return ((Number) o).byteValue();
+				resultType = Byte.class;
+			} else if (resultType == char.class) {
+				resultType = Character.class;
+			} else if (resultType == short.class) {
+				if (Number.class.isAssignableFrom(actualType))
+					return ((Number) o).shortValue();
+				resultType = Short.class;
+			} else if (resultType == int.class) {
+				if (Number.class.isAssignableFrom(actualType))
+					return ((Number) o).intValue();
+				resultType = Integer.class;
+			} else if (resultType == long.class) {
+				if (Number.class.isAssignableFrom(actualType))
+					return ((Number) o).longValue();
+				resultType = Long.class;
+			} else if (resultType == float.class) {
+				if (Number.class.isAssignableFrom(actualType))
+					return ((Number) o).floatValue();
+				resultType = Float.class;
+			} else if (resultType == double.class) {
+				if (Number.class.isAssignableFrom(actualType))
+					return ((Number) o).doubleValue();
+				resultType = Double.class;
+			}
+
+			if (resultType.isPrimitive())
+				throw new IllegalArgumentException("Unknown primitive: " + resultType);
+
+			if (Number.class.isAssignableFrom(resultType) && actualType == Boolean.class) {
+				Boolean b = (Boolean) o;
+				o = b ? "1" : "0";
+			} else if (actualType == String.class) {
+				String input = (String) o;
+				if (Enum.class.isAssignableFrom(resultType)) {
+					return Enum.valueOf((Class<Enum>) resultType, input);
+				}
+				if (resultType == Class.class && loader != null) {
+					return loader.loadClass(input);
+				}
+				if (resultType == Pattern.class) {
+					return Pattern.compile(input);
+				}
+			}
+
+			try {
+				Constructor< ? > c = resultType.getConstructor(String.class);
+				return c.newInstance(o.toString());
+			}
+			catch (Throwable t) {
+				// handled on next line
+			}
+			throw new IllegalArgumentException("No conversion to " + resultType + " from " + actualType + " value " + o);
+		}
+
+		private Object convert(ParameterizedType pType, Object o) throws InstantiationException,
+				IllegalAccessException, Exception {
+			Class< ? > resultType = (Class< ? >) pType.getRawType();
+			if (Collection.class.isAssignableFrom(resultType)) {
+				Collection< ? > input = toCollection(o);
+				if (resultType.isInterface()) {
+					if (resultType == Collection.class || resultType == List.class)
+						resultType = ArrayList.class;
+					else if (resultType == Set.class || resultType == SortedSet.class)
+						resultType = TreeSet.class;
+					else if (resultType == Queue.class /*
+														 * || resultType ==
+														 * Deque.class
+														 */)
+						resultType = LinkedList.class;
+					else if (resultType == Queue.class /*
+														 * || resultType ==
+														 * Deque.class
+														 */)
+						resultType = LinkedList.class;
+					else
+						throw new IllegalArgumentException(
+								"Unknown interface for a collection, no concrete class found: " + resultType);
+				}
+
+				Collection<Object> result = (Collection<Object>) resultType.newInstance();
+				Type componentType = pType.getActualTypeArguments()[0];
+
+				for (Object i : input) {
+					result.add(convert(componentType, i));
+				}
+				return result;
+			} else if (pType.getRawType() == Class.class) {
+				return loader.loadClass(o.toString());
+			}
+			if (Map.class.isAssignableFrom(resultType)) {
+				Map< ? , ? > input = toMap(o);
+				if (resultType.isInterface()) {
+					if (resultType == SortedMap.class)
+						resultType = TreeMap.class;
+					else if (resultType == Map.class)
+						resultType = LinkedHashMap.class;
+					else
+						throw new IllegalArgumentException(
+								"Unknown interface for a collection, no concrete class found: " + resultType);
+				}
+				Map<Object,Object> result = (Map<Object,Object>) resultType.newInstance();
+				Type keyType = pType.getActualTypeArguments()[0];
+				Type valueType = pType.getActualTypeArguments()[1];
+
+				for (Map.Entry< ? , ? > entry : input.entrySet()) {
+					result.put(convert(keyType, entry.getKey()), convert(valueType, entry.getValue()));
+				}
+				return result;
+			}
+			throw new IllegalArgumentException("cannot convert to " + pType
+					+ " because it uses generics and is not a Collection or a map");
+		}
+
+		Object convertArray(Type componentType, Object o) throws Exception {
+			Collection< ? > input = toCollection(o);
+			Class< ? > componentClass = getRawClass(componentType);
+			Object array = Array.newInstance(componentClass, input.size());
+
+			int i = 0;
+			for (Object next : input) {
+				Array.set(array, i++, convert(componentType, next));
+			}
+			return array;
+		}
+
+		private Class< ? > getRawClass(Type type) {
+			if (type instanceof Class)
+				return (Class< ? >) type;
+
+			if (type instanceof ParameterizedType)
+				return (Class< ? >) ((ParameterizedType) type).getRawType();
+
+			throw new IllegalArgumentException("For the raw type, type must be ParamaterizedType or Class but is "
+					+ type);
+		}
+
+		private Collection< ? > toCollection(Object o) {
+			if (o instanceof Collection)
+				return (Collection< ? >) o;
+
+			if (o.getClass().isArray()) {
+				if (o.getClass().getComponentType().isPrimitive()) {
+					int length = Array.getLength(o);
+					List<Object> result = new ArrayList<Object>(length);
+					for (int i = 0; i < length; i++) {
+						result.add(Array.get(o, i));
+					}
+					return result;
+				}
+				return Arrays.asList((Object[]) o);
+			}
+
+			if (o instanceof String) {
+				String s = (String) o;
+				if (s.indexOf('|') > 0)
+					return Arrays.asList(s.split("\\|"));
+			}
+			return Arrays.asList(o);
+		}
+
+		private Map< ? , ? > toMap(Object o) {
+			if (o instanceof Map)
+				return (Map< ? , ? >) o;
+
+			throw new IllegalArgumentException("Cannot convert " + o + " to a map as requested");
+		}
+
+	}
+
+	public static String mangleMethodName(String id) {
+		StringBuilder sb = new StringBuilder(id);
+		for (int i = 0; i < sb.length(); i++) {
+			char c = sb.charAt(i);
+			boolean twice = i < sb.length() - 1 && sb.charAt(i + 1) == c;
+			if (c == '$' || c == '_') {
+				if (twice)
+					sb.deleteCharAt(i + 1);
+				else if (c == '$')
+					sb.deleteCharAt(i--); // Remove dollars
+				else
+					sb.setCharAt(i, '.'); // Make _ into .
+			}
+		}
+		return sb.toString();
+	}
+}
diff --git a/aQute.libg/src/aQute/configurable/packageinfo b/aQute.libg/src/aQute/configurable/packageinfo
new file mode 100644
index 0000000..9ad81f6
--- /dev/null
+++ b/aQute.libg/src/aQute/configurable/packageinfo
@@ -0,0 +1 @@
+version 1.0.0
diff --git a/aQute.libg/src/aQute/lib/base64/Base64.java b/aQute.libg/src/aQute/lib/base64/Base64.java
index 1210a02..33f0a8a 100755
--- a/aQute.libg/src/aQute/lib/base64/Base64.java
+++ b/aQute.libg/src/aQute/lib/base64/Base64.java
@@ -29,31 +29,37 @@ public class Base64 {
 	}
 
 	public final static byte[] decodeBase64(String string) {
-		string = string.trim();
-		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		ByteArrayOutputStream bout = new ByteArrayOutputStream(string.length() * 2 / 3);
+		StringReader rdr = new StringReader(string.trim());
+		try {
+			decode(rdr, bout);
+		}
+		catch (Exception e) {
+			// cannot happen
+		}
+		return bout.toByteArray();
+	}
 
+	public final static void decode(Reader rdr, OutputStream out) throws Exception {
 		int register = 0;
 		int i = 0;
 		int pads = 0;
 
 		byte test[] = new byte[3];
+		int c;
+		while ((c = rdr.read()) >= 0) {
 
-		while (i < string.length()) {
-			char c = string.charAt(i);
 			if (c > 0x7F)
-				throw new IllegalArgumentException(
-						"Invalid base64 character in " + string
-								+ ", character value > 128 ");
-			
+				throw new IllegalArgumentException("Invalid base64 character in " + rdr + ", character value > 128 ");
+
 			int v = 0;
-			if ( c == '=' ) {
+			if (c == '=') {
 				pads++;
 			} else {
 				v = values[c];
-				if ( v < 0 )
-					throw new IllegalArgumentException(
-							"Invalid base64 character in " + string + ", " + c );
-			}					
+				if (v < 0)
+					throw new IllegalArgumentException("Invalid base64 character in " + rdr + ", " + c);
+			}
 			register <<= 6;
 			register |= v;
 			test[2] = (byte) (register & 0xFF);
@@ -68,24 +74,23 @@ public class Base64 {
 				pads = 0;
 			}
 		}
-		return out.toByteArray();
 	}
 
-	static private void flush(ByteArrayOutputStream out, int register, int pads) {
+	static private void flush(OutputStream out, int register, int pads) throws IOException {
 		switch (pads) {
-		case 0:
-			out.write(0xFF & (register >> 16));
-			out.write(0xFF & (register >> 8));
-			out.write(0xFF & (register >> 0));
-			break;
-			
-		case 1:
-			out.write(0xFF & (register >> 16));
-			out.write(0xFF & (register >> 8));
-			break;
-			
-		case 2:
-			out.write(0xFF & (register >> 16));
+			case 0 :
+				out.write(0xFF & (register >> 16));
+				out.write(0xFF & (register >> 8));
+				out.write(0xFF & (register >> 0));
+				break;
+
+			case 1 :
+				out.write(0xFF & (register >> 16));
+				out.write(0xFF & (register >> 8));
+				break;
+
+			case 2 :
+				out.write(0xFF & (register >> 16));
 		}
 	}
 
@@ -93,43 +98,58 @@ public class Base64 {
 		data = decodeBase64(s);
 	}
 
+	@Override
 	public String toString() {
 		return encodeBase64(data);
 	}
 
 	public static String encodeBase64(byte data[]) {
-		StringBuffer sb = new StringBuffer();
+		StringWriter sw = new StringWriter();
+		ByteArrayInputStream bin = new ByteArrayInputStream(data);
+		try {
+			encode(bin, sw);
+		}
+		catch (IOException e) {
+			// can't happen
+		}
+		return sw.toString();
+	}
+
+	public Object toData() {
+		return data;
+	}
+
+	public static void encode(InputStream in, Appendable sb) throws IOException {
+		// StringBuilder sb = new StringBuilder();
 		int buf = 0;
 		int bits = 0;
-		int n = 0;
+		int out = 0;
 
 		while (true) {
 			if (bits >= 6) {
 				bits -= 6;
 				int v = 0x3F & (buf >> bits);
 				sb.append(alphabet.charAt(v));
+				out++;
 			} else {
-				if (n >= data.length)
+				int c = in.read();
+				if (c < 0)
 					break;
 
 				buf <<= 8;
-				buf |= 0xFF & data[n++];
+				buf |= 0xFF & c;
 				bits += 8;
 			}
 		}
-		if (bits != 0) // must be less than 7
+		if (bits != 0) {// must be less than 7
 			sb.append(alphabet.charAt(0x3F & (buf << (6 - bits))));
-
-		int mod = 4 - (sb.length() % 4);
+			out++;
+		}
+		int mod = 4 - (out % 4);
 		if (mod != 4) {
 			for (int i = 0; i < mod; i++)
 				sb.append('=');
 		}
-		return sb.toString();
-	}
-
-	public Object toData() {
-		return data;
 	}
 
 }
diff --git a/aQute.libg/src/aQute/lib/base64/packageinfo b/aQute.libg/src/aQute/lib/base64/packageinfo
index 7c8de03..e39f616 100644
--- a/aQute.libg/src/aQute/lib/base64/packageinfo
+++ b/aQute.libg/src/aQute/lib/base64/packageinfo
@@ -1 +1 @@
-version 1.0
+version 1.1.0
diff --git a/aQute.libg/src/aQute/lib/codec/Codec.java b/aQute.libg/src/aQute/lib/codec/Codec.java
new file mode 100644
index 0000000..6072ebd
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/codec/Codec.java
@@ -0,0 +1,10 @@
+package aQute.lib.codec;
+
+import java.io.*;
+import java.lang.reflect.*;
+
+public interface Codec {
+	Object decode(Reader in, Type type) throws Exception;
+
+	void encode(Type t, Object o, Appendable out) throws Exception;
+}
diff --git a/aQute.libg/src/aQute/lib/codec/HCodec.java b/aQute.libg/src/aQute/lib/codec/HCodec.java
new file mode 100644
index 0000000..c174e52
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/codec/HCodec.java
@@ -0,0 +1,77 @@
+package aQute.lib.codec;
+
+import java.io.*;
+import java.lang.reflect.*;
+
+public class HCodec implements Codec {
+	final Codec	codec;
+
+	public HCodec(Codec codec) {
+		this.codec = codec;
+	}
+
+	public Object decode(Reader in, Type type) throws Exception {
+		return codec.decode(in, type);
+	}
+
+	public <T> T decode(InputStream in, Class<T> t) throws Exception {
+		return t.cast(decode(in, (Type) t));
+	}
+
+	public <T> T decode(Reader in, Class<T> t) throws Exception {
+		return t.cast(decode(in, (Type) t));
+	}
+
+	public Object decode(InputStream in, Type t) throws Exception {
+		InputStreamReader r = new InputStreamReader(in, "UTF-8");
+		return codec.decode(r, t);
+	}
+
+	public void encode(Type t, Object o, Appendable out) throws Exception {
+		codec.encode(t, o, out);
+	}
+
+	public void encode(Type t, Object o, OutputStream out) throws Exception {
+		OutputStreamWriter wr = new OutputStreamWriter(out, "UTF-8");
+		try {
+			codec.encode(t, o, wr);
+		}
+		finally {
+			wr.flush();
+		}
+	}
+
+	public <T> T decode(File in, Class<T> t) throws Exception {
+		FileInputStream fin = new FileInputStream(in);
+		try {
+			InputStreamReader rdr = new InputStreamReader(fin, "UTF-8");
+			try {
+				return t.cast(decode(rdr, t));
+			}
+			finally {
+				rdr.close();
+			}
+		}
+		finally {
+			fin.close();
+		}
+
+	}
+
+	public void encode(Type t, Object o, File out) throws Exception {
+		OutputStream oout = new FileOutputStream(out);
+		try {
+			Writer wr = new OutputStreamWriter(oout, "UTF-8");
+			try {
+				codec.encode(t, o, wr);
+			}
+			finally {
+				wr.close();
+			}
+		}
+		finally {
+			oout.close();
+		}
+	}
+
+}
diff --git a/aQute.libg/src/aQute/libg/dumpzip/packageinfo b/aQute.libg/src/aQute/lib/codec/packageinfo
similarity index 100%
rename from aQute.libg/src/aQute/libg/dumpzip/packageinfo
rename to aQute.libg/src/aQute/lib/codec/packageinfo
diff --git a/aQute.libg/src/aQute/lib/collections/EnumerationIterator.java b/aQute.libg/src/aQute/lib/collections/EnumerationIterator.java
new file mode 100644
index 0000000..1bb9f0d
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/collections/EnumerationIterator.java
@@ -0,0 +1,42 @@
+package aQute.lib.collections;
+
+import java.util.*;
+
+/**
+ * Simple facade for enumerators so they can be used in for loops.
+ * 
+ * @param <T>
+ */
+public class EnumerationIterator<T> implements Iterable<T>, Iterator<T> {
+
+	public static <T> EnumerationIterator<T> iterator(Enumeration<T> e) {
+		return new EnumerationIterator<T>(e);
+	}
+
+	final Enumeration<T>	enumerator;
+	volatile boolean		done	= false;
+
+	public EnumerationIterator(Enumeration<T> e) {
+		enumerator = e;
+	}
+
+	public synchronized Iterator<T> iterator() {
+		if (done)
+			throw new IllegalStateException("Can only be used once");
+		done = true;
+		return this;
+
+	}
+
+	public boolean hasNext() {
+		return enumerator.hasMoreElements();
+	}
+
+	public T next() {
+		return enumerator.nextElement();
+	}
+
+	public void remove() {
+		throw new UnsupportedOperationException("Does not support removes");
+	}
+}
diff --git a/aQute.libg/src/aQute/lib/collections/ExtList.java b/aQute.libg/src/aQute/lib/collections/ExtList.java
new file mode 100644
index 0000000..0050a92
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/collections/ExtList.java
@@ -0,0 +1,56 @@
+package aQute.lib.collections;
+
+import java.util.*;
+
+public class ExtList<T> extends ArrayList<T> {
+	private static final long	serialVersionUID	= 1L;
+
+	public ExtList(T... ts) {
+		super(ts.length);
+		for (T t : ts) {
+			add(t);
+		}
+	}
+
+	public ExtList(int size) {
+		super(size);
+	}
+
+	public ExtList(Collection<T> _) {
+		super(_);
+	}
+
+	public ExtList(Iterable<T> _) {
+		for ( T t : _)
+			add(t);
+	}
+
+	public static ExtList<String> from(String s) {
+		// TODO make sure no \ before comma
+		return from(s, "\\s*,\\s*");
+	}
+	public static ExtList<String> from(String s, String delimeter) {
+		ExtList<String> result = new ExtList<String>();
+		String[] parts = s.split(delimeter);
+		for (String p : parts)
+			result.add(p);
+		return result;
+	}
+
+	public String join() {
+		return join(",");
+	}
+
+	public String join(String del) {
+		StringBuilder sb = new StringBuilder();
+		String d = "";
+		for (T t : this) {
+			sb.append(d);
+			d = del;
+			if (t != null)
+				sb.append(t.toString());
+		}
+		return sb.toString();
+	}
+
+}
diff --git a/aQute.libg/src/aQute/lib/collections/IteratorList.java b/aQute.libg/src/aQute/lib/collections/IteratorList.java
new file mode 100644
index 0000000..63ddbeb
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/collections/IteratorList.java
@@ -0,0 +1,12 @@
+package aQute.lib.collections;
+
+import java.util.*;
+
+public class IteratorList<T> extends ArrayList<T> {
+	private static final long	serialVersionUID	= 1L;
+
+	public IteratorList(Iterator<T> i) {
+		while (i.hasNext())
+			add(i.next());
+	}
+}
diff --git a/aQute.libg/src/aQute/lib/collections/LineCollection.java b/aQute.libg/src/aQute/lib/collections/LineCollection.java
index 36bfa39..0670712 100644
--- a/aQute.libg/src/aQute/lib/collections/LineCollection.java
+++ b/aQute.libg/src/aQute/lib/collections/LineCollection.java
@@ -12,7 +12,7 @@ public class LineCollection implements Iterator<String>, Closeable {
 	}
 
 	public LineCollection(File in) throws IOException {
-		this(new FileReader(in));
+		this(new InputStreamReader(new FileInputStream(in), "UTF-8"));
 	}
 
 	public LineCollection(Reader reader) throws IOException {
@@ -37,7 +37,8 @@ public class LineCollection implements Iterator<String>, Closeable {
 			if (next == null)
 				reader.close();
 			return result;
-		} catch (Exception e) {
+		}
+		catch (Exception e) {
 			// ignore
 			return null;
 		}
diff --git a/aQute.libg/src/aQute/lib/collections/Logic.java b/aQute.libg/src/aQute/lib/collections/Logic.java
index 75322dd..6daeaad 100644
--- a/aQute.libg/src/aQute/lib/collections/Logic.java
+++ b/aQute.libg/src/aQute/lib/collections/Logic.java
@@ -3,18 +3,18 @@ package aQute.lib.collections;
 import java.util.*;
 
 public class Logic {
-	
-	public static <T> Collection<T> retain( Collection<T> first, Collection<T> ... sets) {
+
+	public static <T> Collection<T> retain(Collection<T> first, Collection<T>... sets) {
 		Set<T> result = new HashSet<T>(first);
-		for ( Collection<T> set : sets ) {
+		for (Collection<T> set : sets) {
 			result.retainAll(set);
 		}
 		return result;
 	}
-	
-	public static <T> Collection<T> remove( Collection<T> first, Collection<T> ... sets) {
+
+	public static <T> Collection<T> remove(Collection<T> first, Collection<T>... sets) {
 		Set<T> result = new HashSet<T>(first);
-		for ( Collection<T> set : sets ) {
+		for (Collection<T> set : sets) {
 			result.removeAll(set);
 		}
 		return result;
diff --git a/aQute.libg/src/aQute/lib/collections/MultiMap.java b/aQute.libg/src/aQute/lib/collections/MultiMap.java
index 7672638..9bf8481 100644
--- a/aQute.libg/src/aQute/lib/collections/MultiMap.java
+++ b/aQute.libg/src/aQute/lib/collections/MultiMap.java
@@ -2,66 +2,127 @@ package aQute.lib.collections;
 
 import java.util.*;
 
-public class MultiMap<K,V> extends HashMap<K,Set<V>> {
+
+public class MultiMap<K, V> extends HashMap<K,List<V>> {
 	private static final long	serialVersionUID	= 1L;
-	final Set<V> EMPTY = Collections.emptySet();
-	
-	public boolean add( K key, V value ) {
-		Set<V> set = get(key);
-		if ( set == null) {
-			set=new HashSet<V>();
-			put(key,set);
+	final boolean				noduplicates;
+	final Class< ? >			keyClass;
+	final Class< ? >			valueClass;
+
+	final Set<V>				EMPTY				= Collections.emptySet();
+
+	public MultiMap() {
+		noduplicates = false;
+		keyClass = Object.class;
+		valueClass = Object.class;
+	}
+
+	public MultiMap(Class<K> keyClass, Class<V> valueClass, boolean noduplicates) {
+		this.noduplicates = noduplicates;
+		this.keyClass = keyClass;
+		this.valueClass = valueClass;
+	}
+
+	public MultiMap(Map<K,List<V>> other) {
+		this();
+		for ( java.util.Map.Entry<K,List<V>> e : other.entrySet()) {
+			addAll(e.getKey(), e.getValue());
+		}
+	}
+	public MultiMap(MultiMap<K,V> other) {
+		keyClass = other.keyClass;
+		valueClass  = other.valueClass;
+		noduplicates = other.noduplicates;
+		for ( java.util.Map.Entry<K,List<V>> e : other.entrySet()) {
+			addAll(e.getKey(), e.getValue());
+		}
+	}
+
+	@SuppressWarnings("unchecked")
+	public boolean add(K key, V value) {
+		assert keyClass.isInstance(key);
+		assert valueClass.isInstance(value);
+
+		List<V> set = get(key);
+		if (set == null) {
+			set = new ArrayList<V>();
+			if (valueClass != Object.class) {
+				set = Collections.checkedList(set, (Class<V>) valueClass);
+			}
+			put(key, set);
+		} else {
+			if (noduplicates) {
+				if (set.contains(value))
+					return false;
+			}
 		}
 		return set.add(value);
 	}
-	
-	public boolean addAll( K key, Collection<V> value ) {
-		Set<V> set = get(key);
-		if ( set == null) {
-			set=new HashSet<V>();
-			put(key,set);
+
+	@SuppressWarnings("unchecked")
+	public boolean addAll(K key, Collection< ? extends V> value) {
+		assert keyClass.isInstance(key);
+		List<V> set = get(key);
+		if (set == null) {
+			set = new ArrayList<V>();
+			if (valueClass != Object.class) {
+				set = Collections.checkedList(set, (Class<V>) valueClass);
+			}
+			put(key, set);
+		} else if (noduplicates) {
+			boolean r = false;
+			for (V v : value) {
+				assert valueClass.isInstance(v);
+				if (!set.contains(v))
+					r |= set.add(v);
+			}
+			return r;
 		}
 		return set.addAll(value);
 	}
-	
-	public boolean remove( K key, V value ) {
-		Set<V> set = get(key);
-		if ( set == null) {
+
+	public boolean remove(K key, V value) {
+		assert keyClass.isInstance(key);
+		assert valueClass.isInstance(value);
+
+		List<V> set = get(key);
+		if (set == null) {
 			return false;
 		}
 		boolean result = set.remove(value);
-		if ( set.isEmpty())
+		if (set.isEmpty())
 			remove(key);
 		return result;
 	}
-	
-	public boolean removeAll( K key, Collection<V> value ) {
-		Set<V> set = get(key);
-		if ( set == null) {
+
+	public boolean removeAll(K key, Collection<V> value) {
+		assert keyClass.isInstance(key);
+		List<V> set = get(key);
+		if (set == null) {
 			return false;
 		}
 		boolean result = set.removeAll(value);
-		if ( set.isEmpty())
+		if (set.isEmpty())
 			remove(key);
 		return result;
 	}
-	
+
 	public Iterator<V> iterate(K key) {
-		Set<V> set = get(key);
-		if ( set == null)
+		assert keyClass.isInstance(key);
+		List<V> set = get(key);
+		if (set == null)
 			return EMPTY.iterator();
-		else
-			return set.iterator();
+		return set.iterator();
 	}
-	
+
 	public Iterator<V> all() {
 		return new Iterator<V>() {
-			Iterator<Set<V>> master = values().iterator();
-			Iterator<V> current = null;
-			
+			Iterator<List<V>>	master	= values().iterator();
+			Iterator<V>			current	= null;
+
 			public boolean hasNext() {
-				if ( current == null || !current.hasNext()) {
-					if ( master.hasNext()) {
+				if (current == null || !current.hasNext()) {
+					if (master.hasNext()) {
 						current = master.next().iterator();
 						return current.hasNext();
 					}
@@ -77,7 +138,36 @@ public class MultiMap<K,V> extends HashMap<K,Set<V>> {
 			public void remove() {
 				current.remove();
 			}
-			
+
 		};
 	}
+
+	public Map<K,V> flatten() {
+		Map<K,V> map = new LinkedHashMap<K,V>();
+		for (Map.Entry<K,List<V>> entry : entrySet()) {
+			List<V> v = entry.getValue();
+			if (v == null || v.isEmpty())
+				continue;
+
+			map.put(entry.getKey(), v.get(0));
+		}
+		return map;
+	}
+
+	public MultiMap<V,K> transpose() {
+		MultiMap<V,K> inverted = new MultiMap<V,K>();
+		for (Map.Entry<K,List<V>> entry : entrySet()) {
+			K key = entry.getKey();
+
+			List<V> value = entry.getValue();
+			if (value == null)
+				continue;
+
+			for (V v : value)
+				inverted.add(v, key);
+		}
+
+		return inverted;
+	}
+
 }
diff --git a/aQute.libg/src/aQute/lib/collections/SortedList.java b/aQute.libg/src/aQute/lib/collections/SortedList.java
new file mode 100644
index 0000000..189b97f
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/collections/SortedList.java
@@ -0,0 +1,438 @@
+package aQute.lib.collections;
+
+import java.util.*;
+
+/**
+ * An immutbale list that sorts objects by their natural order or through a
+ * comparator. It has convenient methods/constructors to create it from
+ * collections and iterators. Why not maintain the lists in their sorted form?
+ * Well, TreeMaps are quite expensive ... I once profiled bnd and was shocked
+ * how much memory the Jar class took due to the TreeMaps. I could not easily
+ * change it unfortunately. The other reason is that Parameters uses a
+ * LinkedHashMap because the preferred order should be the declaration order.
+ * However, sometimes you need to sort the keys by name. Last, and most
+ * important reason, is that sometimes you do not know what collection you have
+ * or it is not available in a sort ordering (MultiMap for example) ... I found
+ * myself sorting these things over and over again and decided to just make an
+ * immutable SortedList that is easy to slice and dice
+ * 
+ * @param <T>
+ */
+ at SuppressWarnings("unchecked")
+public class SortedList<T> implements SortedSet<T>, List<T> {
+	static SortedList< ? >		empty		= new SortedList<Object>();
+
+	final T[]					list;
+	final int					start;
+	final int					end;
+	final Comparator<T>			cmp;
+	Class< ? >					type;
+	static Comparator<Object>	comparator	= //
+
+											new Comparator<Object>() {
+												public int compare(Object o1, Object o2) {
+
+													if (o1 == o2)
+														return 0;
+
+													if (o1.equals(o2))
+														return 0;
+
+													return ((Comparable<Object>) o1).compareTo(o2);
+												}
+											};
+
+	class It implements ListIterator<T> {
+		int	n;
+
+		It(int n) {
+			this.n = n;
+		}
+
+		public boolean hasNext() {
+			return n < end;
+		}
+
+		public T next() throws NoSuchElementException {
+			if (!hasNext()) {
+				throw new NoSuchElementException("");
+			}
+			return list[n++];
+		}
+
+		public boolean hasPrevious() {
+			return n > start;
+		}
+
+		public T previous() {
+			return get(n - 1);
+		}
+
+		public int nextIndex() {
+			return (n + 1 - start);
+		}
+
+		public int previousIndex() {
+			return (n - 1) - start;
+		}
+
+		@Deprecated
+		public void remove() {
+			throw new UnsupportedOperationException("Immutable");
+		}
+
+		@Deprecated
+		public void set(T e) {
+			throw new UnsupportedOperationException("Immutable");
+		}
+
+		@Deprecated
+		public void add(T e) {
+			throw new UnsupportedOperationException("Immutable");
+		}
+	}
+
+	public SortedList(Collection< ? extends Comparable< ? >> x) {
+		this((Collection<T>) x, 0, x.size(), (Comparator<T>) comparator);
+	}
+
+	public SortedList(Collection<T> x, Comparator<T> cmp) {
+		this(x, 0, x.size(), cmp);
+	}
+
+	@SuppressWarnings("cast")
+	public SortedList(T... x) {
+		this((T[]) x.clone(), 0, x.length, (Comparator<T>) comparator);
+	}
+
+	@SuppressWarnings("cast")
+	public SortedList(Comparator<T> cmp, T... x) {
+		this((T[]) x.clone(), 0, x.length, cmp);
+	}
+
+	private SortedList(SortedList<T> other, int start, int end) {
+		this.list = other.list;
+		this.cmp = other.cmp;
+		this.start = start;
+		this.end = end;
+	}
+
+	public SortedList(T[] x, int start, int end, Comparator<T> comparator2) {
+		if (start > end) {
+			int tmp = start;
+			start = end;
+			end = tmp;
+		}
+		if (start < 0 || start >= x.length)
+			throw new IllegalArgumentException("Start is not in list");
+
+		if (end < 0 || end > x.length)
+			throw new IllegalArgumentException("End is not in list");
+
+		this.list = x.clone();
+		Arrays.sort(this.list, start, end, comparator2);
+		this.start = start;
+		this.end = end;
+		this.cmp = comparator2;
+	}
+
+	public SortedList(Collection< ? extends T> x, int start, int end, Comparator<T> cmp) {
+		if (start > end) {
+			int tmp = start;
+			start = end;
+			end = tmp;
+		}
+		if (start < 0 || start > x.size())
+			throw new IllegalArgumentException("Start is not in list");
+
+		if (end < 0 || end > x.size())
+			throw new IllegalArgumentException("End is not in list");
+
+		this.list = (T[]) x.toArray();
+		Arrays.sort(this.list, start, end, cmp);
+		this.start = start;
+		this.end = end;
+		this.cmp = cmp;
+	}
+
+	private SortedList() {
+		list = null;
+		start = 0;
+		end = 0;
+		cmp = null;
+	}
+
+	public int size() {
+		return end - start;
+	}
+
+	public boolean isEmpty() {
+		return start == end;
+	}
+
+	@SuppressWarnings("cast")
+	public boolean contains(Object o) {
+		assert type != null & type.isInstance(o);
+		return indexOf((T) o) >= 0;
+	}
+
+	public Iterator<T> iterator() {
+		return new It(start);
+	}
+
+	public Object[] toArray() {
+		return list.clone();
+	}
+
+	@SuppressWarnings("hiding")
+	public <T> T[] toArray(T[] a) {
+		if (a == null || a.length < list.length) {
+			return (T[]) list.clone();
+		}
+		System.arraycopy(list, 0, a, 0, list.length);
+		return a;
+	}
+
+	public boolean add(T e) {
+		throw new UnsupportedOperationException("Immutable");
+	}
+
+	public boolean remove(Object o) {
+		throw new UnsupportedOperationException("Immutable");
+	}
+
+	public boolean containsAll(Collection< ? > c) {
+		if (c.isEmpty())
+			return true;
+
+		if (isEmpty())
+			return false;
+
+		// TODO take advantage of sorted nature for this
+
+		for (Object el : c) {
+			if (!contains(el))
+				return false;
+		}
+		return false;
+	}
+
+	public boolean addAll(Collection< ? extends T> c) {
+		throw new UnsupportedOperationException("Immutable");
+	}
+
+	public boolean retainAll(Collection< ? > c) {
+		throw new UnsupportedOperationException("Immutable");
+	}
+
+	public boolean removeAll(Collection< ? > c) {
+		throw new UnsupportedOperationException("Immutable");
+	}
+
+	public void clear() {
+		throw new UnsupportedOperationException("Immutable");
+	}
+
+	public Comparator< ? super T> comparator() {
+		return cmp;
+	}
+
+	public boolean isSubSet() {
+		return start > 0 && end < list.length;
+	}
+
+	public SortedList<T> subSet(T fromElement, T toElement) {
+		int start = indexOf(fromElement);
+		int end = indexOf(toElement);
+		if (isSubSet() && (start < 0 || end < 0))
+			throw new IllegalArgumentException("This list is a subset");
+		if (start < 0)
+			start = 0;
+		if (end < 0)
+			end = list.length;
+
+		return subList(start, end);
+	}
+
+	public int indexOf(Object o) {
+		assert type != null && type.isInstance(o);
+
+		int n = Arrays.binarySearch(list, (T) o, cmp);
+		if (n >= start && n < end)
+			return n - start;
+
+		return -1;
+	}
+
+	public SortedList<T> headSet(T toElement) {
+		int i = indexOf(toElement);
+		if (i < 0) {
+			if (isSubSet())
+				throw new IllegalArgumentException("This list is a subset");
+			i = end;
+		}
+
+		if (i == end)
+			return this;
+
+		return subList(0, i);
+	}
+
+	public SortedSet<T> tailSet(T fromElement) {
+		int i = indexOf(fromElement);
+		if (i < 0) {
+			if (isSubSet())
+				throw new IllegalArgumentException("This list is a subset");
+			i = start;
+		}
+
+		return subList(i, end);
+	}
+
+	public T first() {
+		if (isEmpty())
+			throw new NoSuchElementException("first");
+		return get(0);
+	}
+
+	public T last() {
+		if (isEmpty())
+			throw new NoSuchElementException("last");
+		return get(end - 1);
+	}
+
+	@Deprecated
+	public boolean addAll(int index, Collection< ? extends T> c) {
+		throw new UnsupportedOperationException("Immutable");
+	}
+
+	public T get(int index) {
+		return list[index + start];
+	}
+
+	@Deprecated
+	public T set(int index, T element) {
+		throw new UnsupportedOperationException("Immutable");
+	}
+
+	@Deprecated
+	public void add(int index, T element) {
+		throw new UnsupportedOperationException("Immutable");
+	}
+
+	@Deprecated
+	public T remove(int index) {
+		throw new UnsupportedOperationException("Immutable");
+	}
+
+	public int lastIndexOf(Object o) {
+		int n = indexOf(o);
+		if (n < 0)
+			return -1;
+
+		while (cmp.compare(list[n], (T) o) == 0)
+			n++;
+
+		return n;
+	}
+
+	public ListIterator<T> listIterator() {
+		return new It(start);
+	}
+
+	public ListIterator<T> listIterator(int index) {
+		return new It(index + start);
+	}
+
+	public SortedList<T> subList(int fromIndex, int toIndex) {
+		fromIndex += start;
+		toIndex += start;
+
+		if (toIndex < fromIndex) {
+			int tmp = toIndex;
+			toIndex = fromIndex;
+			fromIndex = tmp;
+		}
+
+		toIndex = Math.max(0, toIndex);
+		toIndex = Math.min(toIndex, end);
+		fromIndex = Math.max(0, fromIndex);
+		fromIndex = Math.min(fromIndex, end);
+		if (fromIndex == start && toIndex == end)
+			return this;
+
+		return new SortedList<T>(this, fromIndex, toIndex);
+	}
+
+	@Override
+	@Deprecated
+	public boolean equals(Object other) {
+		return super.equals(other);
+	}
+
+	@Override
+	@Deprecated
+	public int hashCode() {
+		return super.hashCode();
+	}
+
+	public boolean isEqual(SortedList<T> list) {
+		if (size() != list.size())
+			return false;
+
+		for (int as = start, bs = list.start, al = size(); as < al && bs < al; as++, bs++) {
+			if (comparator.compare(this.list[as], this.list[bs]) != 0)
+				return false;
+		}
+		return true;
+	}
+
+	public Class< ? > getType() {
+		return type;
+	}
+
+	public void setType(Class< ? > type) {
+		this.type = type;
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		sb.append("[");
+		String del = "";
+		for (T s : list) {
+			sb.append(del);
+			sb.append(s);
+			del = ", ";
+		}
+
+		sb.append("]");
+		return sb.toString();
+	}
+
+	public boolean hasDuplicates() {
+		if (list.length < 2)
+			return false;
+
+		T prev = list[0];
+		for (int i = 1; i < list.length; i++) {
+			if (prev.equals(list[i]))
+				return true;
+		}
+		return false;
+	}
+
+	public static <T extends Comparable< ? >> SortedList<T> fromIterator(Iterator<T> it) {
+		IteratorList<T> l = new IteratorList<T>(it);
+		return new SortedList<T>(l);
+	}
+
+	public static <T> SortedList<T> fromIterator(Iterator<T> it, Comparator<T> cmp) {
+		IteratorList<T> l = new IteratorList<T>(it);
+		return new SortedList<T>(l, cmp);
+	}
+
+	public static <T> SortedSet<T> empty() {
+		return (SortedSet<T>) empty;
+	}
+}
diff --git a/aQute.libg/src/aQute/lib/collections/packageinfo b/aQute.libg/src/aQute/lib/collections/packageinfo
index 7c8de03..3987f9c 100644
--- a/aQute.libg/src/aQute/lib/collections/packageinfo
+++ b/aQute.libg/src/aQute/lib/collections/packageinfo
@@ -1 +1 @@
-version 1.0
+version 1.1
diff --git a/aQute.libg/src/aQute/lib/converter/Converter.java b/aQute.libg/src/aQute/lib/converter/Converter.java
new file mode 100644
index 0000000..9eae98a
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/converter/Converter.java
@@ -0,0 +1,526 @@
+package aQute.lib.converter;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.regex.*;
+
+import aQute.lib.base64.*;
+
+/**
+ * General Java type converter from an object to any type. Supports number
+ * conversion
+ * 
+ * @author aqute
+ */
+ at SuppressWarnings({
+		"unchecked", "rawtypes"
+})
+public class Converter {
+	public interface Hook {
+		Object convert(Type dest, Object o) throws Exception;
+	}
+
+	boolean			fatal	= true;
+	Map<Type,Hook>	hooks;
+	List<Hook>		allHooks;
+
+	public <T> T convert(Class<T> type, Object o) throws Exception {
+		// Is it a compatible type?
+		if (type.isAssignableFrom(o.getClass()))
+			return (T) o;
+		return (T) convert((Type) type, o);
+	}
+
+	public <T> T convert(TypeReference<T> type, Object o) throws Exception {
+		return (T) convert(type.getType(), o);
+	}
+
+	public Object convert(Type type, Object o) throws Exception {
+		Class resultType = getRawClass(type);
+		if (o == null) {
+			if (resultType.isPrimitive() || Number.class.isAssignableFrom(resultType))
+				return convert(type, 0);
+
+			return null; // compatible with any
+		}
+
+		if (allHooks != null) {
+			for (Hook hook : allHooks) {
+				Object r = hook.convert(type, o);
+				if (r != null)
+					return r;
+			}
+		}
+
+		if (hooks != null) {
+			Hook hook = hooks.get(type);
+			if (hook != null) {
+				Object value = hook.convert(type, o);
+				if (value != null)
+					return value;
+			}
+		}
+
+		Class< ? > actualType = o.getClass();
+
+		// We can always make a string
+
+		if (resultType == String.class) {
+			if (actualType.isArray()) {
+				if (actualType == char[].class)
+					return new String((char[]) o);
+				if (actualType == byte[].class)
+					return Base64.encodeBase64((byte[]) o);
+				int l = Array.getLength(o);
+				StringBuilder sb = new StringBuilder("[");
+				String del = "";
+				for (int i = 0; i < l; i++) {
+					sb.append(del);
+					del = ",";
+					sb.append(convert(String.class, Array.get(o, i)));
+				}
+				sb.append("]");
+				return sb.toString();
+			}
+			return o.toString();
+		}
+
+		if (Collection.class.isAssignableFrom(resultType))
+			return collection(type, resultType, o);
+
+		if (Map.class.isAssignableFrom(resultType))
+			return map(type, resultType, o);
+
+		if (type instanceof GenericArrayType) {
+			GenericArrayType gType = (GenericArrayType) type;
+			return array(gType.getGenericComponentType(), o);
+		}
+
+		if (resultType.isArray()) {
+			if (actualType == String.class) {
+				String s = (String) o;
+				if (byte[].class == resultType)
+					return Base64.decodeBase64(s);
+
+				if (char[].class == resultType)
+					return s.toCharArray();
+			}
+			if (byte[].class == resultType) {
+				// Sometimes classes implement toByteArray
+				try {
+					Method m = actualType.getMethod("toByteArray");
+					if (m.getReturnType() == byte[].class)
+						return m.invoke(o);
+
+				}
+				catch (Exception e) {
+					// Ignore
+				}
+			}
+
+			return array(resultType.getComponentType(), o);
+		}
+
+		if (resultType.isAssignableFrom(o.getClass()))
+			return o;
+
+		if (Map.class.isAssignableFrom(actualType) && resultType.isInterface()) {
+			return proxy(resultType, (Map) o);
+		}
+
+		// Simple type coercion
+
+		if (resultType == boolean.class || resultType == Boolean.class) {
+			if (actualType == boolean.class || actualType == Boolean.class)
+				return o;
+			Number n = number(o);
+			if (n != null)
+				return n.longValue() == 0 ? false : true;
+
+			resultType = Boolean.class;
+		} else if (resultType == byte.class || resultType == Byte.class) {
+			Number n = number(o);
+			if (n != null)
+				return n.byteValue();
+			resultType = Byte.class;
+		} else if (resultType == char.class || resultType == Character.class) {
+			Number n = number(o);
+			if (n != null)
+				return (char) n.shortValue();
+			resultType = Character.class;
+		} else if (resultType == short.class || resultType == Short.class) {
+			Number n = number(o);
+			if (n != null)
+				return n.shortValue();
+
+			resultType = Short.class;
+		} else if (resultType == int.class || resultType == Integer.class) {
+			Number n = number(o);
+			if (n != null)
+				return n.intValue();
+
+			resultType = Integer.class;
+		} else if (resultType == long.class || resultType == Long.class) {
+			Number n = number(o);
+			if (n != null)
+				return n.longValue();
+
+			resultType = Long.class;
+		} else if (resultType == float.class || resultType == Float.class) {
+			Number n = number(o);
+			if (n != null)
+				return n.floatValue();
+
+			resultType = Float.class;
+		} else if (resultType == double.class || resultType == Double.class) {
+			Number n = number(o);
+			if (n != null)
+				return n.doubleValue();
+
+			resultType = Double.class;
+		}
+
+		assert !resultType.isPrimitive();
+
+		if (actualType == String.class) {
+			String input = (String) o;
+			if (resultType == char[].class)
+				return input.toCharArray();
+
+			if (resultType == byte[].class)
+				return Base64.decodeBase64(input);
+
+			if (Enum.class.isAssignableFrom(resultType)) {
+				try {
+					return Enum.valueOf((Class<Enum>) resultType, input);
+				} catch( Exception e) {
+					input = input.toUpperCase();
+					return Enum.valueOf((Class<Enum>) resultType, input);
+				}
+			}
+			if (resultType == Pattern.class) {
+				return Pattern.compile(input);
+			}
+
+			try {
+				Constructor< ? > c = resultType.getConstructor(String.class);
+				return c.newInstance(o.toString());
+			}
+			catch (Throwable t) {}
+			try {
+				Method m = resultType.getMethod("valueOf", String.class);
+				if (Modifier.isStatic(m.getModifiers()))
+					return m.invoke(null, o.toString());
+			}
+			catch (Throwable t) {}
+
+			if (resultType == Character.class && input.length() == 1)
+				return input.charAt(0);
+		}
+		Number n = number(o);
+		if (n != null) {
+			if (Enum.class.isAssignableFrom(resultType)) {
+				try {
+					Method values = resultType.getMethod("values");
+					Enum[] vs = (Enum[]) values.invoke(null);
+					int nn = n.intValue();
+					if (nn > 0 && nn < vs.length)
+						return vs[nn];
+				}
+				catch (Exception e) {
+					// Ignore
+				}
+			}
+		}
+
+		// Translate arrays with length 1 by picking the single element
+		if (actualType.isArray() && Array.getLength(o) == 1) {
+			return convert(type, Array.get(o, 0));
+		}
+
+		// Translate collections with size 1 by picking the single element
+		if (o instanceof Collection) {
+			Collection col = (Collection) o;
+			if (col.size() == 1)
+				return convert(type, col.iterator().next());
+		}
+
+		if (o instanceof Map) {
+			String key = null;
+			try {
+				Map<Object,Object> map = (Map) o;
+				Object instance = resultType.newInstance();
+				for (Map.Entry e : map.entrySet()) {
+					key = (String) e.getKey();
+					try {
+						Field f = resultType.getField(key);
+						Object value = convert(f.getGenericType(), e.getValue());
+						f.set(instance, value);
+					}
+					catch (Exception ee) {
+
+						// We cannot find the key, so try the __extra field
+						Field f = resultType.getField("__extra");
+						Map<String,Object> extra = (Map<String,Object>) f.get(instance);
+						if (extra == null) {
+							extra = new HashMap<String,Object>();
+							f.set(instance, extra);
+						}
+						extra.put(key, convert(Object.class, e.getValue()));
+
+					}
+				}
+				return instance;
+			}
+			catch (Exception e) {
+				return error("No conversion found for " + o.getClass() + " to " + type + ", error " + e + " on key "
+						+ key);
+			}
+		}
+
+		return error("No conversion found for " + o.getClass() + " to " + type);
+	}
+
+	private Number number(Object o) {
+		if (o instanceof Number)
+			return (Number) o;
+
+		if (o instanceof Boolean)
+			return ((Boolean) o).booleanValue() ? 1 : 0;
+
+		if (o instanceof Character)
+			return (int) ((Character) o).charValue();
+
+		if (o instanceof String) {
+			String s = (String) o;
+			try {
+				return Double.parseDouble(s);
+			}
+			catch (Exception e) {
+				// Ignore
+			}
+		}
+		return null;
+	}
+
+	private Collection collection(Type collectionType, Class< ? extends Collection> rawClass, Object o)
+			throws Exception {
+		Collection collection;
+		if (rawClass.isInterface() || Modifier.isAbstract(rawClass.getModifiers())) {
+			if (rawClass.isAssignableFrom(ArrayList.class))
+				collection = new ArrayList();
+			else if (rawClass.isAssignableFrom(HashSet.class))
+				collection = new HashSet();
+			else if (rawClass.isAssignableFrom(TreeSet.class))
+				collection = new TreeSet();
+			else if (rawClass.isAssignableFrom(LinkedList.class))
+				collection = new LinkedList();
+			else if (rawClass.isAssignableFrom(Vector.class))
+				collection = new Vector();
+			else if (rawClass.isAssignableFrom(Stack.class))
+				collection = new Stack();
+			else if (rawClass.isAssignableFrom(ConcurrentLinkedQueue.class))
+				collection = new ConcurrentLinkedQueue();
+			else
+				return (Collection) error("Cannot find a suitable collection for the collection interface " + rawClass);
+		} else
+			collection = rawClass.newInstance();
+
+		Type subType = Object.class;
+		if (collectionType instanceof ParameterizedType) {
+			ParameterizedType ptype = (ParameterizedType) collectionType;
+			subType = ptype.getActualTypeArguments()[0];
+		}
+
+		Collection input = toCollection(o);
+
+		for (Object i : input)
+			collection.add(convert(subType, i));
+
+		return collection;
+	}
+
+	private Map map(Type mapType, Class< ? extends Map< ? , ? >> rawClass, Object o) throws Exception {
+		Map result;
+		if (rawClass.isInterface() || Modifier.isAbstract(rawClass.getModifiers())) {
+			if (rawClass.isAssignableFrom(HashMap.class))
+				result = new HashMap();
+			else if (rawClass.isAssignableFrom(TreeMap.class))
+				result = new TreeMap();
+			else if (rawClass.isAssignableFrom(ConcurrentHashMap.class))
+				result = new ConcurrentHashMap();
+			else {
+				return (Map) error("Cannot find suitable map for map interface " + rawClass);
+			}
+		} else
+			result = rawClass.newInstance();
+
+		Map< ? , ? > input = toMap(o);
+
+		Type keyType = Object.class;
+		Type valueType = Object.class;
+		if (mapType instanceof ParameterizedType) {
+			ParameterizedType ptype = (ParameterizedType) mapType;
+			keyType = ptype.getActualTypeArguments()[0];
+			valueType = ptype.getActualTypeArguments()[1];
+		}
+
+		for (Map.Entry< ? , ? > entry : input.entrySet()) {
+			Object key = convert(keyType, entry.getKey());
+			Object value = convert(valueType, entry.getValue());
+			if (key == null)
+				error("Key for map must not be null: " + input);
+			else
+				result.put(key, value);
+		}
+
+		return result;
+	}
+
+	public Object array(Type type, Object o) throws Exception {
+		Collection< ? > input = toCollection(o);
+		Class< ? > componentClass = getRawClass(type);
+		Object array = Array.newInstance(componentClass, input.size());
+
+		int i = 0;
+		for (Object next : input) {
+			Array.set(array, i++, convert(type, next));
+		}
+		return array;
+	}
+
+	private Class< ? > getRawClass(Type type) {
+		if (type instanceof Class)
+			return (Class< ? >) type;
+
+		if (type instanceof ParameterizedType)
+			return (Class< ? >) ((ParameterizedType) type).getRawType();
+
+		if (type instanceof GenericArrayType) {
+			Type componentType = ((GenericArrayType) type).getGenericComponentType();
+			return Array.newInstance(getRawClass(componentType), 0).getClass();
+		}
+
+		if (type instanceof TypeVariable) {
+			Type componentType = ((TypeVariable) type).getBounds()[0];
+			return Array.newInstance(getRawClass(componentType), 0).getClass();
+		}
+
+		if (type instanceof WildcardType) {
+			Type componentType = ((WildcardType) type).getUpperBounds()[0];
+			return Array.newInstance(getRawClass(componentType), 0).getClass();
+		}
+
+		return Object.class;
+	}
+
+	public Collection< ? > toCollection(Object o) {
+		if (o instanceof Collection)
+			return (Collection< ? >) o;
+
+		if (o.getClass().isArray()) {
+			if (o.getClass().getComponentType().isPrimitive()) {
+				int length = Array.getLength(o);
+				List<Object> result = new ArrayList<Object>(length);
+				for (int i = 0; i < length; i++) {
+					result.add(Array.get(o, i));
+				}
+				return result;
+			}
+			return Arrays.asList((Object[]) o);
+		}
+
+		return Arrays.asList(o);
+	}
+
+	public Map< ? , ? > toMap(Object o) throws Exception {
+		if (o instanceof Map)
+			return (Map< ? , ? >) o;
+		Map result = new HashMap();
+		Field fields[] = o.getClass().getFields();
+		for (Field f : fields)
+			result.put(f.getName(), f.get(o));
+		if (result.isEmpty())
+			return null;
+
+		return result;
+	}
+
+	private Object error(String string) {
+		if (fatal)
+			throw new IllegalArgumentException(string);
+		return null;
+	}
+
+	public void setFatalIsException(boolean b) {
+		fatal = b;
+	}
+
+	public Converter hook(Type type, Hook hook) {
+		if (type != null) {
+			if (hooks == null)
+				hooks = new HashMap<Type,Converter.Hook>();
+			this.hooks.put(type, hook);
+		} else {
+			if (allHooks == null)
+				allHooks = new ArrayList<Converter.Hook>();
+			allHooks.add(hook);
+		}
+
+		return this;
+	}
+
+	/**
+	 * Convert a map to an interface.
+	 * 
+	 * @param interfc
+	 * @param properties
+	 * @return
+	 */
+	public <T> T proxy(Class<T> interfc, final Map< ? , ? > properties) {
+		return (T) Proxy.newProxyInstance(interfc.getClassLoader(), new Class[] {
+			interfc
+		}, new InvocationHandler() {
+
+			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+				Object o = properties.get(method.getName());
+				if (o == null)
+					o = properties.get(mangleMethodName(method.getName()));
+
+				return convert(method.getGenericReturnType(), o);
+			}
+
+		});
+	}
+
+	public static String mangleMethodName(String id) {
+		StringBuilder sb = new StringBuilder(id);
+		for (int i = 0; i < sb.length(); i++) {
+			char c = sb.charAt(i);
+			boolean twice = i < sb.length() - 1 && sb.charAt(i + 1) == c;
+			if (c == '$' || c == '_') {
+				if (twice)
+					sb.deleteCharAt(i + 1);
+				else if (c == '$')
+					sb.deleteCharAt(i--); // Remove dollars
+				else
+					sb.setCharAt(i, '.'); // Make _ into .
+			}
+		}
+		return sb.toString();
+	}
+
+	public static <T> T cnv(TypeReference<T> tr, Object source) throws Exception {
+		return new Converter().convert(tr, source);
+	}
+
+	public static <T> T cnv(Class<T> tr, Object source) throws Exception {
+		return new Converter().convert(tr, source);
+	}
+
+	public static Object cnv(Type tr, Object source) throws Exception {
+		return new Converter().convert(tr, source);
+	}
+
+}
diff --git a/aQute.libg/src/aQute/lib/converter/TypeReference.java b/aQute.libg/src/aQute/lib/converter/TypeReference.java
new file mode 100644
index 0000000..3271227
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/converter/TypeReference.java
@@ -0,0 +1,13 @@
+package aQute.lib.converter;
+
+import java.lang.reflect.*;
+
+public class TypeReference<T> implements Type {
+
+	protected TypeReference() {
+		// Make sure it cannot be directly instantiated
+	}
+	public Type getType() {
+		return ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
+	}
+}
diff --git a/aQute.libg/src/aQute/lib/converter/packageinfo b/aQute.libg/src/aQute/lib/converter/packageinfo
new file mode 100644
index 0000000..3390555
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/converter/packageinfo
@@ -0,0 +1 @@
+version 2.0.1
diff --git a/aQute.libg/src/aQute/lib/data/AllowNull.java b/aQute.libg/src/aQute/lib/data/AllowNull.java
new file mode 100644
index 0000000..0b25300
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/data/AllowNull.java
@@ -0,0 +1,11 @@
+package aQute.lib.data;
+
+import java.lang.annotation.*;
+
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(value = {
+	ElementType.FIELD
+})
+public @interface AllowNull {
+	String reason() default "";
+}
diff --git a/aQute.libg/src/aQute/lib/data/Data.java b/aQute.libg/src/aQute/lib/data/Data.java
new file mode 100644
index 0000000..9d318b8
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/data/Data.java
@@ -0,0 +1,80 @@
+package aQute.lib.data;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.regex.*;
+
+public class Data {
+
+	public static String validate(Object o) throws Exception {
+		StringBuilder sb = new StringBuilder();
+		Formatter formatter = new Formatter(sb);
+
+		Field fields[] = o.getClass().getFields();
+		for (Field f : fields) {
+			Validator patternValidator = f.getAnnotation(Validator.class);
+			Numeric numericValidator = f.getAnnotation(Numeric.class);
+			AllowNull allowNull = f.getAnnotation(AllowNull.class);
+			Object value = f.get(o);
+			if (value == null) {
+				if (allowNull == null)
+					formatter.format("Value for %s must not be null%n", f.getName());
+			} else {
+
+				if (patternValidator != null) {
+					Pattern p = Pattern.compile(patternValidator.value());
+					Matcher m = p.matcher(value.toString());
+					if (!m.matches()) {
+						String reason = patternValidator.reason();
+						if (reason.length() == 0)
+							formatter.format("Value for %s=%s does not match pattern %s%n", f.getName(), value,
+									patternValidator.value());
+						else
+							formatter.format("Value for %s=%s %s%n", f.getName(), value, reason);
+					}
+				}
+
+				if (numericValidator != null) {
+					if (o instanceof String) {
+						try {
+							o = Double.parseDouble((String) o);
+						}
+						catch (Exception e) {
+							formatter.format("Value for %s=%s %s%n", f.getName(), value, "Not a number");
+						}
+					}
+
+					try {
+						Number n = (Number) o;
+						long number = n.longValue();
+						if (number >= numericValidator.min() && number < numericValidator.max()) {
+							formatter.format("Value for %s=%s not in valid range (%s,%s]%n", f.getName(), value,
+									numericValidator.min(), numericValidator.max());
+						}
+					}
+					catch (ClassCastException e) {
+						formatter.format("Value for %s=%s [%s,%s) is not a number%n", f.getName(), value,
+								numericValidator.min(), numericValidator.max());
+					}
+				}
+			}
+		}
+		if (sb.length() == 0)
+			return null;
+
+		if (sb.length() > 0)
+			sb.delete(sb.length() - 1, sb.length());
+		return sb.toString();
+	}
+
+	public static void details(Object data, Appendable out) throws Exception {
+		Field fields[] = data.getClass().getFields();
+		Formatter formatter = new Formatter(out);
+
+		for (Field f : fields) {
+			String name = f.getName();
+			name = Character.toUpperCase(name.charAt(0)) + name.substring(1);
+			formatter.format("%-40s %s%n", name, f.get(data));
+		}
+	}
+}
diff --git a/aQute.libg/src/aQute/lib/data/Numeric.java b/aQute.libg/src/aQute/lib/data/Numeric.java
new file mode 100644
index 0000000..eb1534e
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/data/Numeric.java
@@ -0,0 +1,15 @@
+package aQute.lib.data;
+
+import java.lang.annotation.*;
+
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(value = {
+	ElementType.FIELD
+})
+public @interface Numeric {
+	long min() default Long.MIN_VALUE;
+
+	long max() default Long.MAX_VALUE;
+
+	String reason() default "";
+}
diff --git a/aQute.libg/src/aQute/lib/data/Validator.java b/aQute.libg/src/aQute/lib/data/Validator.java
new file mode 100644
index 0000000..48324e8
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/data/Validator.java
@@ -0,0 +1,13 @@
+package aQute.lib.data;
+
+import java.lang.annotation.*;
+
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(value = {
+	ElementType.FIELD
+})
+public @interface Validator {
+	String value();
+
+	String reason() default "";
+}
diff --git a/aQute.libg/src/aQute/lib/data/packageinfo b/aQute.libg/src/aQute/lib/data/packageinfo
new file mode 100644
index 0000000..9ad81f6
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/data/packageinfo
@@ -0,0 +1 @@
+version 1.0.0
diff --git a/aQute.libg/src/aQute/lib/filter/Filter.java b/aQute.libg/src/aQute/lib/filter/Filter.java
index 320c3ac..2c4dd09 100755
--- a/aQute.libg/src/aQute/lib/filter/Filter.java
+++ b/aQute.libg/src/aQute/lib/filter/Filter.java
@@ -17,337 +17,333 @@ import java.math.*;
 import java.util.*;
 
 public class Filter {
-    final char     WILDCARD = 65535;
-
-    final int      EQ       = 0;
-    final int      LE       = 1;
-    final int      GE       = 2;
-    final int      APPROX   = 3;
-
-    private String filter;
-
-    abstract class Query {
-        static final String GARBAGE   = "Trailing garbage";
-        static final String MALFORMED = "Malformed query";
-        static final String EMPTY     = "Empty list";
-        static final String SUBEXPR   = "No subexpression";
-        static final String OPERATOR  = "Undefined operator";
-        static final String TRUNCATED = "Truncated expression";
-        static final String EQUALITY  = "Only equality supported";
-
-        private String      tail;
-
-        boolean match() throws IllegalArgumentException {
-            tail = filter;
-            boolean val = doQuery();
-            if (tail.length() > 0)
-                error(GARBAGE);
-            return val;
-        }
-
-        private boolean doQuery() throws IllegalArgumentException {
-            if (tail.length() < 3 || !prefix("("))
-                error(MALFORMED);
-            boolean val;
-
-            switch (tail.charAt(0)) {
-            case '&':
-                val = doAnd();
-                break;
-            case '|':
-                val = doOr();
-                break;
-            case '!':
-                val = doNot();
-                break;
-            default:
-                val = doSimple();
-                break;
-            }
-
-            if (!prefix(")"))
-                error(MALFORMED);
-            return val;
-        }
-
-        private boolean doAnd() throws IllegalArgumentException {
-            tail = tail.substring(1);
-            boolean val = true;
-            if (!tail.startsWith("("))
-                error(EMPTY);
-            do {
-                if (!doQuery())
-                    val = false;
-            } while (tail.startsWith("("));
-            return val;
-        }
-
-        private boolean doOr() throws IllegalArgumentException {
-            tail = tail.substring(1);
-            boolean val = false;
-            if (!tail.startsWith("("))
-                error(EMPTY);
-            do {
-                if (doQuery())
-                    val = true;
-            } while (tail.startsWith("("));
-            return val;
-        }
-
-        private boolean doNot() throws IllegalArgumentException {
-            tail = tail.substring(1);
-            if (!tail.startsWith("("))
-                error(SUBEXPR);
-            return !doQuery();
-        }
-
-        private boolean doSimple() throws IllegalArgumentException {
-            int op = 0;
-            Object attr = getAttr();
-
-            if (prefix("="))
-                op = EQ;
-            else if (prefix("<="))
-                op = LE;
-            else if (prefix(">="))
-                op = GE;
-            else if (prefix("~="))
-                op = APPROX;
-            else
-                error(OPERATOR);
-
-            return compare(attr, op, getValue());
-        }
-
-        private boolean prefix(String pre) {
-            if (!tail.startsWith(pre))
-                return false;
-            tail = tail.substring(pre.length());
-            return true;
-        }
-
-        private Object getAttr() {
-            int len = tail.length();
-            int ix = 0;
-            label: for (; ix < len; ix++) {
-                switch (tail.charAt(ix)) {
-                case '(':
-                case ')':
-                case '<':
-                case '>':
-                case '=':
-                case '~':
-                case '*':
-                case '\\':
-                    break label;
-                }
-            }
-            String attr = tail.substring(0, ix).toLowerCase();
-            tail = tail.substring(ix);
-            return getProp(attr);
-        }
-
-        abstract Object getProp(String key);
-
-        private String getValue() {
-            StringBuffer sb = new StringBuffer();
-            int len = tail.length();
-            int ix = 0;
-            label: for (; ix < len; ix++) {
-                char c = tail.charAt(ix);
-                switch (c) {
-                case '(':
-                case ')':
-                    break label;
-                case '*':
-                    sb.append(WILDCARD);
-                    break;
-                case '\\':
-                    if (ix == len - 1)
-                        break label;
-                    sb.append(tail.charAt(++ix));
-                    break;
-                default:
-                    sb.append(c);
-                    break;
-                }
-            }
-            tail = tail.substring(ix);
-            return sb.toString();
-        }
-
-        private void error(String m) throws IllegalArgumentException {
-            throw new IllegalArgumentException(m + " " + tail);
-        }
-
-        private boolean compare(Object obj, int op, String s) {
-            if (obj == null)
-                return false;
-            try {
-                Class<?> numClass = obj.getClass();
-                if (numClass == String.class) {
-                    return compareString((String) obj, op, s);
-                } else if (numClass == Character.class) {
-                    return compareString(obj.toString(), op, s);
-                } else if (numClass == Long.class) {
-                    return compareSign(op, Long.valueOf(s)
-                            .compareTo((Long) obj));
-                } else if (numClass == Integer.class) {
-                    return compareSign(op, Integer.valueOf(s).compareTo(
-                            (Integer) obj));
-                } else if (numClass == Short.class) {
-                    return compareSign(op, Short.valueOf(s).compareTo(
-                            (Short) obj));
-                } else if (numClass == Byte.class) {
-                    return compareSign(op, Byte.valueOf(s)
-                            .compareTo((Byte) obj));
-                } else if (numClass == Double.class) {
-                    return compareSign(op, Double.valueOf(s).compareTo(
-                            (Double) obj));
-                } else if (numClass == Float.class) {
-                    return compareSign(op, Float.valueOf(s).compareTo(
-                            (Float) obj));
-                } else if (numClass == Boolean.class) {
-                    if (op != EQ)
-                        return false;
-                    int a = Boolean.valueOf(s).booleanValue() ? 1 : 0;
-                    int b = ((Boolean) obj).booleanValue() ? 1 : 0;
-                    return compareSign(op, a - b);
-                } else if (numClass == BigInteger.class) {
-                    return compareSign(op, new BigInteger(s)
-                            .compareTo((BigInteger) obj));
-                } else if (numClass == BigDecimal.class) {
-                    return compareSign(op, new BigDecimal(s)
-                            .compareTo((BigDecimal) obj));
-                } else if (obj instanceof Collection<?>) {
-                    for (Object x : (Collection<?>) obj)
-                        if (compare(x, op, s))
-                            return true;
-                } else if (numClass.isArray()) {
-                    int len = Array.getLength(obj);
-                    for (int i = 0; i < len; i++)
-                        if (compare(Array.get(obj, i), op, s))
-                            return true;
-                }
-            } catch (Exception e) {
-            }
-            return false;
-        }
-    }
-
-    class DictQuery extends Query {
-        private Dictionary<?,?> dict;
-
-        DictQuery(Dictionary<?,?> dict) {
-            this.dict = dict;
-        }
-
-        Object getProp(String key) {
-            return dict.get(key);
-        }
-    }
-
-    public Filter(String filter) throws IllegalArgumentException {
-        // NYI: Normalize the filter string?
-        this.filter = filter;
-        if (filter == null || filter.length() == 0)
-            throw new IllegalArgumentException("Null query");
-    }
-
-    public boolean match(Dictionary<?,?> dict) {
-        try {
-            return new DictQuery(dict).match();
-        } catch (IllegalArgumentException e) {
-            return false;
-        }
-    }
-
-    public String verify() {
-        try {
-            new DictQuery(new Hashtable<Object,Object>()).match();
-        } catch (IllegalArgumentException e) {
-            return e.getMessage();
-        }
-        return null;
-    }
-
-    public String toString() {
-        return filter;
-    }
-
-    public boolean equals(Object obj) {
-        return obj != null && obj instanceof Filter
-                && filter.equals(((Filter) obj).filter);
-    }
-
-    public int hashCode() {
-        return filter.hashCode();
-    }
-
-    boolean compareString(String s1, int op, String s2) {
-        switch (op) {
-        case EQ:
-            return patSubstr(s1, s2);
-        case APPROX:
-            return fixupString(s2).equals(fixupString(s1));
-        default:
-            return compareSign(op, s2.compareTo(s1));
-        }
-    }
-
-    boolean compareSign(int op, int cmp) {
-        switch (op) {
-        case LE:
-            return cmp >= 0;
-        case GE:
-            return cmp <= 0;
-        case EQ:
-            return cmp == 0;
-        default: /* APPROX */
-            return cmp == 0;
-        }
-    }
-
-    String fixupString(String s) {
-        StringBuffer sb = new StringBuffer();
-        int len = s.length();
-        boolean isStart = true;
-        boolean isWhite = false;
-        for (int i = 0; i < len; i++) {
-            char c = s.charAt(i);
-            if (Character.isWhitespace(c)) {
-                isWhite = true;
-            } else {
-                if (!isStart && isWhite)
-                    sb.append(' ');
-                if (Character.isUpperCase(c))
-                    c = Character.toLowerCase(c);
-                sb.append(c);
-                isStart = false;
-                isWhite = false;
-            }
-        }
-        return sb.toString();
-    }
-
-    boolean patSubstr(String s, String pat) {
-        if (s == null)
-            return false;
-        if (pat.length() == 0)
-            return s.length() == 0;
-        if (pat.charAt(0) == WILDCARD) {
-            pat = pat.substring(1);
-            for (;;) {
-                if (patSubstr(s, pat))
-                    return true;
-                if (s.length() == 0)
-                    return false;
-                s = s.substring(1);
-            }
-        } else {
-            if (s.length() == 0 || s.charAt(0) != pat.charAt(0))
-                return false;
-            return patSubstr(s.substring(1), pat.substring(1));
-        }
-    }
+	final char			WILDCARD	= 65535;
+
+	final static int	EQ			= 0;
+	final static int	LE			= 1;
+	final static int	GE			= 2;
+	final static int	APPROX		= 3;
+
+	String		filter;
+
+	abstract class Query {
+		static final String	GARBAGE		= "Trailing garbage";
+		static final String	MALFORMED	= "Malformed query";
+		static final String	EMPTY		= "Empty list";
+		static final String	SUBEXPR		= "No subexpression";
+		static final String	OPERATOR	= "Undefined operator";
+		static final String	TRUNCATED	= "Truncated expression";
+		static final String	EQUALITY	= "Only equality supported";
+
+		private String		tail;
+
+		boolean match() throws IllegalArgumentException {
+			tail = filter;
+			boolean val = doQuery();
+			if (tail.length() > 0)
+				error(GARBAGE);
+			return val;
+		}
+
+		private boolean doQuery() throws IllegalArgumentException {
+			if (tail.length() < 3 || !prefix("("))
+				error(MALFORMED);
+			boolean val;
+
+			switch (tail.charAt(0)) {
+				case '&' :
+					val = doAnd();
+					break;
+				case '|' :
+					val = doOr();
+					break;
+				case '!' :
+					val = doNot();
+					break;
+				default :
+					val = doSimple();
+					break;
+			}
+
+			if (!prefix(")"))
+				error(MALFORMED);
+			return val;
+		}
+
+		private boolean doAnd() throws IllegalArgumentException {
+			tail = tail.substring(1);
+			boolean val = true;
+			if (!tail.startsWith("("))
+				error(EMPTY);
+			do {
+				if (!doQuery())
+					val = false;
+			} while (tail.startsWith("("));
+			return val;
+		}
+
+		private boolean doOr() throws IllegalArgumentException {
+			tail = tail.substring(1);
+			boolean val = false;
+			if (!tail.startsWith("("))
+				error(EMPTY);
+			do {
+				if (doQuery())
+					val = true;
+			} while (tail.startsWith("("));
+			return val;
+		}
+
+		private boolean doNot() throws IllegalArgumentException {
+			tail = tail.substring(1);
+			if (!tail.startsWith("("))
+				error(SUBEXPR);
+			return !doQuery();
+		}
+
+		private boolean doSimple() throws IllegalArgumentException {
+			int op = 0;
+			Object attr = getAttr();
+
+			if (prefix("="))
+				op = EQ;
+			else if (prefix("<="))
+				op = LE;
+			else if (prefix(">="))
+				op = GE;
+			else if (prefix("~="))
+				op = APPROX;
+			else
+				error(OPERATOR);
+
+			return compare(attr, op, getValue());
+		}
+
+		private boolean prefix(String pre) {
+			if (!tail.startsWith(pre))
+				return false;
+			tail = tail.substring(pre.length());
+			return true;
+		}
+
+		private Object getAttr() {
+			int len = tail.length();
+			int ix = 0;
+			label: for (; ix < len; ix++) {
+				switch (tail.charAt(ix)) {
+					case '(' :
+					case ')' :
+					case '<' :
+					case '>' :
+					case '=' :
+					case '~' :
+					case '*' :
+					case '\\' :
+						break label;
+				}
+			}
+			String attr = tail.substring(0, ix).toLowerCase();
+			tail = tail.substring(ix);
+			return getProp(attr);
+		}
+
+		abstract Object getProp(String key);
+
+		private String getValue() {
+			StringBuilder sb = new StringBuilder();
+			int len = tail.length();
+			int ix = 0;
+			label: for (; ix < len; ix++) {
+				char c = tail.charAt(ix);
+				switch (c) {
+					case '(' :
+					case ')' :
+						break label;
+					case '*' :
+						sb.append(WILDCARD);
+						break;
+					case '\\' :
+						if (ix == len - 1)
+							break label;
+						sb.append(tail.charAt(++ix));
+						break;
+					default :
+						sb.append(c);
+						break;
+				}
+			}
+			tail = tail.substring(ix);
+			return sb.toString();
+		}
+
+		private void error(String m) throws IllegalArgumentException {
+			throw new IllegalArgumentException(m + " " + tail);
+		}
+
+		private boolean compare(Object obj, int op, String s) {
+			if (obj == null)
+				return false;
+			try {
+				Class< ? > numClass = obj.getClass();
+				if (numClass == String.class) {
+					return compareString((String) obj, op, s);
+				} else if (numClass == Character.class) {
+					return compareString(obj.toString(), op, s);
+				} else if (numClass == Long.class) {
+					return compareSign(op, Long.valueOf(s).compareTo((Long) obj));
+				} else if (numClass == Integer.class) {
+					return compareSign(op, Integer.valueOf(s).compareTo((Integer) obj));
+				} else if (numClass == Short.class) {
+					return compareSign(op, Short.valueOf(s).compareTo((Short) obj));
+				} else if (numClass == Byte.class) {
+					return compareSign(op, Byte.valueOf(s).compareTo((Byte) obj));
+				} else if (numClass == Double.class) {
+					return compareSign(op, Double.valueOf(s).compareTo((Double) obj));
+				} else if (numClass == Float.class) {
+					return compareSign(op, Float.valueOf(s).compareTo((Float) obj));
+				} else if (numClass == Boolean.class) {
+					if (op != EQ)
+						return false;
+					int a = Boolean.valueOf(s).booleanValue() ? 1 : 0;
+					int b = ((Boolean) obj).booleanValue() ? 1 : 0;
+					return compareSign(op, a - b);
+				} else if (numClass == BigInteger.class) {
+					return compareSign(op, new BigInteger(s).compareTo((BigInteger) obj));
+				} else if (numClass == BigDecimal.class) {
+					return compareSign(op, new BigDecimal(s).compareTo((BigDecimal) obj));
+				} else if (obj instanceof Collection< ? >) {
+					for (Object x : (Collection< ? >) obj)
+						if (compare(x, op, s))
+							return true;
+				} else if (numClass.isArray()) {
+					int len = Array.getLength(obj);
+					for (int i = 0; i < len; i++)
+						if (compare(Array.get(obj, i), op, s))
+							return true;
+				}
+			}
+			catch (Exception e) {}
+			return false;
+		}
+	}
+
+	class DictQuery extends Query {
+		private Dictionary< ? , ? >	dict;
+
+		DictQuery(Dictionary< ? , ? > dict) {
+			this.dict = dict;
+		}
+
+		@Override
+		Object getProp(String key) {
+			return dict.get(key);
+		}
+	}
+
+	public Filter(String filter) throws IllegalArgumentException {
+		// NYI: Normalize the filter string?
+		this.filter = filter;
+		if (filter == null || filter.length() == 0)
+			throw new IllegalArgumentException("Null query");
+	}
+
+	public boolean match(Dictionary< ? , ? > dict) {
+		try {
+			return new DictQuery(dict).match();
+		}
+		catch (IllegalArgumentException e) {
+			return false;
+		}
+	}
+
+	public String verify() {
+		try {
+			new DictQuery(new Hashtable<Object,Object>()).match();
+		}
+		catch (IllegalArgumentException e) {
+			return e.getMessage();
+		}
+		return null;
+	}
+
+	@Override
+	public String toString() {
+		return filter;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		return obj != null && obj instanceof Filter && filter.equals(((Filter) obj).filter);
+	}
+
+	@Override
+	public int hashCode() {
+		return filter.hashCode();
+	}
+
+	boolean compareString(String s1, int op, String s2) {
+		switch (op) {
+			case EQ :
+				return patSubstr(s1, s2);
+			case APPROX :
+				return fixupString(s2).equals(fixupString(s1));
+			default :
+				return compareSign(op, s2.compareTo(s1));
+		}
+	}
+
+	boolean compareSign(int op, int cmp) {
+		switch (op) {
+			case LE :
+				return cmp >= 0;
+			case GE :
+				return cmp <= 0;
+			case EQ :
+				return cmp == 0;
+			default : /* APPROX */
+				return cmp == 0;
+		}
+	}
+
+	String fixupString(String s) {
+		StringBuilder sb = new StringBuilder();
+		int len = s.length();
+		boolean isStart = true;
+		boolean isWhite = false;
+		for (int i = 0; i < len; i++) {
+			char c = s.charAt(i);
+			if (Character.isWhitespace(c)) {
+				isWhite = true;
+			} else {
+				if (!isStart && isWhite)
+					sb.append(' ');
+				if (Character.isUpperCase(c))
+					c = Character.toLowerCase(c);
+				sb.append(c);
+				isStart = false;
+				isWhite = false;
+			}
+		}
+		return sb.toString();
+	}
+
+	boolean patSubstr(String s, String pat) {
+		if (s == null)
+			return false;
+		if (pat.length() == 0)
+			return s.length() == 0;
+		if (pat.charAt(0) == WILDCARD) {
+			pat = pat.substring(1);
+			for (;;) {
+				if (patSubstr(s, pat))
+					return true;
+				if (s.length() == 0)
+					return false;
+				s = s.substring(1);
+			}
+		}
+		if (s.length() == 0 || s.charAt(0) != pat.charAt(0))
+			return false;
+		return patSubstr(s.substring(1), pat.substring(1));
+	}
 }
diff --git a/aQute.libg/src/aQute/lib/getopt/Arguments.java b/aQute.libg/src/aQute/lib/getopt/Arguments.java
new file mode 100644
index 0000000..36fc73c
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/getopt/Arguments.java
@@ -0,0 +1,8 @@
+package aQute.lib.getopt;
+
+import java.lang.annotation.*;
+
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface Arguments {
+	String[] arg();
+}
diff --git a/aQute.libg/src/aQute/lib/getopt/CommandLine.java b/aQute.libg/src/aQute/lib/getopt/CommandLine.java
new file mode 100644
index 0000000..8e3913d
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/getopt/CommandLine.java
@@ -0,0 +1,475 @@
+package aQute.lib.getopt;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.regex.*;
+
+import aQute.configurable.*;
+import aQute.lib.justif.*;
+import aQute.libg.generics.*;
+import aQute.libg.reporter.*;
+import aQute.service.reporter.*;
+
+/**
+ * Helps parsing command lines. This class takes target object, a primary
+ * command, and a list of arguments. It will then find the command in the target
+ * object. The method of this command must start with a "_" and take an
+ * parameter of Options type. Usually this is an interface that extends Options.
+ * The methods on this interface are options or flags (when they return
+ * boolean).
+ */
+ at SuppressWarnings("unchecked")
+public class CommandLine {
+	static int			LINELENGTH	= 60;
+	static Pattern		ASSIGNMENT	= Pattern.compile("(\\w[\\w\\d]*+)\\s*=\\s*([^\\s]+)\\s*");
+	Reporter			reporter;
+	Justif				justif		= new Justif(80,30,32,70);
+	CommandLineMessages	msg;
+
+	public CommandLine(Reporter reporter) {
+		this.reporter = reporter;
+		msg = ReporterMessages.base(reporter, CommandLineMessages.class);
+	}
+
+	/**
+	 * Execute a command in a target object with a set of options and arguments
+	 * and returns help text if something fails. Errors are reported.
+	 */
+
+	public String execute(Object target, String cmd, List<String> input) throws Exception {
+
+		if (cmd.equals("help")) {
+			StringBuilder sb = new StringBuilder();
+			Formatter f = new Formatter(sb);
+			if (input.isEmpty())
+				help(f, target);
+			else {
+				for (String s : input) {
+					help(f, target, s);
+				}
+			}
+			f.flush();
+			justif.wrap(sb);
+			return sb.toString();
+		}
+
+		//
+		// Find the appropriate method
+		//
+
+		List<String> arguments = new ArrayList<String>(input);
+		Map<String,Method> commands = getCommands(target);
+
+		Method m = commands.get(cmd);
+		if (m == null) {
+			msg.NoSuchCommand_(cmd);
+			return help(target, null, null);
+		}
+
+		//
+		// Parse the options
+		//
+
+		Class< ? extends Options> optionClass = (Class< ? extends Options>) m.getParameterTypes()[0];
+		Options options = getOptions(optionClass, arguments);
+		if (options == null) {
+			// had some error, already reported
+			return help(target, cmd, null);
+		}
+
+		// Check if we have an @Arguments annotation that
+		// provides patterns for the remainder arguments
+
+		Arguments argumentsAnnotation = optionClass.getAnnotation(Arguments.class);
+		if (argumentsAnnotation != null) {
+			String[] patterns = argumentsAnnotation.arg();
+
+			// Check for commands without any arguments
+
+			if (patterns.length == 0 && arguments.size() > 0) {
+				msg.TooManyArguments_(arguments);
+				return help(target, cmd, null);
+			}
+
+			// Match the patterns to the given command line
+
+			int i = 0;
+			for (; i < patterns.length; i++) {
+				String pattern = patterns[i];
+
+				boolean optional = pattern.matches("\\[.*\\]");
+
+				// Handle vararg
+
+				if (pattern.contains("...")) {
+					i = Integer.MAX_VALUE;
+					break;
+				}
+
+				// Check if we're running out of args
+
+				if (i > arguments.size()) {
+					if (!optional)
+						msg.MissingArgument_(patterns[i]);
+					return help(target, cmd, optionClass);
+				}
+			}
+
+			// Check if we have unconsumed arguments left
+
+			if (i < arguments.size()) {
+				msg.TooManyArguments_(arguments);
+				return help(target, cmd, optionClass);
+			}
+		}
+		if (reporter.getErrors().size() == 0) {
+			m.setAccessible(true);
+			m.invoke(target, options);
+			return null;
+		}
+		return help(target, cmd, optionClass);
+	}
+
+	private String help(Object target, String cmd, Class< ? extends Options> type) throws Exception {
+		StringBuilder sb = new StringBuilder();
+		Formatter f = new Formatter(sb);
+		if (cmd == null)
+			help(f, target);
+		else if (type == null)
+			help(f, target, cmd);
+		else
+			help(f, target, cmd, type);
+
+		f.flush();
+		justif.wrap(sb);
+		return sb.toString();
+	}
+
+	/**
+	 * Parse the options in a command line and return an interface that provides
+	 * the options from this command line. This will parse up to (and including)
+	 * -- or an argument that does not start with -
+	 */
+	public <T extends Options> T getOptions(Class<T> specification, List<String> arguments) throws Exception {
+		Map<String,String> properties = Create.map();
+		Map<String,Object> values = new HashMap<String,Object>();
+		Map<String,Method> options = getOptions(specification);
+
+		argloop: while (arguments.size() > 0) {
+
+			String option = arguments.get(0);
+
+			if (option.startsWith("-")) {
+
+				arguments.remove(0);
+
+				if (option.startsWith("--")) {
+
+					if ("--".equals(option))
+						break argloop;
+
+					// Full named option, e.g. --output
+					String name = option.substring(2);
+					Method m = options.get(name);
+					if (m == null)
+						msg.UnrecognizedOption_(name);
+					else
+						assignOptionValue(values, m, arguments, true);
+
+				} else {
+
+					// Set of single character named options like -a
+
+					charloop: for (int j = 1; j < option.length(); j++) {
+
+						char optionChar = option.charAt(j);
+
+						for (Entry<String,Method> entry : options.entrySet()) {
+							if (entry.getKey().charAt(0) == optionChar) {
+								boolean last = (j + 1) >= option.length();
+								assignOptionValue(values, entry.getValue(), arguments, last);
+								continue charloop;
+							}
+						}
+						msg.UnrecognizedOption_(optionChar + "");
+					}
+				}
+			} else {
+				Matcher m = ASSIGNMENT.matcher(option);
+				if (m.matches()) {
+					properties.put(m.group(1), m.group(2));
+				}
+				break;
+			}
+		}
+
+		// check if all required elements are set
+
+		for (Entry<String,Method> entry : options.entrySet()) {
+			Method m = entry.getValue();
+			String name = entry.getKey();
+			if (!values.containsKey(name) && isMandatory(m))
+				msg.OptionNotSet_(name);
+		}
+
+		values.put(".", arguments);
+		values.put(".command", this);
+		values.put(".properties", properties);
+		return Configurable.createConfigurable(specification, values);
+	}
+
+	/**
+	 * Answer a list of the options specified in an options interface
+	 */
+	private Map<String,Method> getOptions(Class< ? extends Options> interf) {
+		Map<String,Method> map = new TreeMap<String,Method>();
+
+		for (Method m : interf.getMethods()) {
+			if (m.getName().startsWith("_"))
+				continue;
+
+			String name;
+
+			Config cfg = m.getAnnotation(Config.class);
+			if (cfg == null || cfg.id() == null || cfg.id().equals(Config.NULL))
+				name = m.getName();
+			else
+				name = cfg.id();
+
+			map.put(name, m);
+		}
+		return map;
+	}
+
+	/**
+	 * Assign an option, must handle flags, parameters, and parameters that can
+	 * happen multiple times.
+	 * 
+	 * @param options
+	 *            The command line map
+	 * @param args
+	 *            the args input
+	 * @param i
+	 *            where we are
+	 * @param m
+	 *            the selected method for this option
+	 * @param last
+	 *            if this is the last in a multi single character option
+	 * @return
+	 */
+	public void assignOptionValue(Map<String,Object> options, Method m, List<String> args, boolean last) {
+		String name = m.getName();
+		Type type = m.getGenericReturnType();
+
+		if (isOption(m)) {
+
+			// The option is a simple flag
+
+			options.put(name, true);
+		} else {
+
+			// The option is followed by an argument
+
+			if (!last) {
+				msg.Option__WithArgumentNotLastInAvvreviation_(name, name.charAt(0), getTypeDescriptor(type));
+				return;
+			}
+
+			if (args.isEmpty()) {
+				msg.MissingArgument__(name, name.charAt(0));
+				return;
+			}
+
+			String parameter = args.remove(0);
+
+			if (Collection.class.isAssignableFrom(m.getReturnType())) {
+
+				Collection<Object> optionValues = (Collection<Object>) options.get(m.getName());
+
+				if (optionValues == null) {
+					optionValues = new ArrayList<Object>();
+					options.put(name, optionValues);
+				}
+
+				optionValues.add(parameter);
+			} else {
+
+				if (options.containsKey(name)) {
+					msg.OptionCanOnlyOccurOnce_(name);
+					return;
+				}
+
+				options.put(name, parameter);
+			}
+		}
+	}
+
+	/**
+	 * Provide a help text.
+	 */
+
+	public void help(Formatter f, 
+	Object target, String cmd, Class< ? extends Options> specification) {
+		Description descr = specification.getAnnotation(Description.class);
+		Arguments patterns = specification.getAnnotation(Arguments.class);
+		Map<String,Method> options = getOptions(specification);
+
+		String description = descr == null ? "" : descr.value();
+
+		f.format("%nNAME%n  %s \t0- \t1%s%n%n", cmd, description);
+		if (options.isEmpty())
+			f.format("SYNOPSIS%n   %s ", cmd);
+		else
+			f.format("SYNOPSIS%n   %s [options] ", cmd);
+
+		if (patterns == null)
+			f.format(" ...%n%n");
+		else {
+			String del = " ";
+			for (String pattern : patterns.arg()) {
+				if (pattern.equals("..."))
+					f.format("%s...", del);
+				else
+					f.format("%s<%s>", del, pattern);
+				del = " ";
+			}
+			f.format("%n");
+		}
+
+		if (!options.isEmpty()) {
+			f.format("%nOPTIONS%n%n");
+			for (Entry<String,Method> entry : options.entrySet()) {
+				String optionName = entry.getKey();
+				Method m = entry.getValue();
+
+				Config cfg = m.getAnnotation(Config.class);
+				Description d = m.getAnnotation(Description.class);
+				boolean required = isMandatory(m);
+
+				String methodDescription = cfg != null ? cfg.description() : (d == null ? "" : d.value());
+
+				f.format("   %s -%s, --%s %s%s \t0- \t1%s%n", required ? " " : "[", //
+						optionName.charAt(0), //
+						optionName, //
+						getTypeDescriptor(m.getGenericReturnType()), //
+						required ? " " : "]",//
+						methodDescription);
+			}
+			f.format("%n");
+		}
+	}
+
+	static Pattern	LAST_PART	= Pattern.compile(".*[\\$\\.]([^\\$\\.]+)");
+
+	private static String lastPart(String name) {
+		Matcher m = LAST_PART.matcher(name);
+		if (m.matches())
+			return m.group(1);
+		return name;
+	}
+
+	/**
+	 * Show all commands in a target
+	 */
+	public void help(Formatter f, Object target) throws Exception {
+		f.format("%n");
+		Description descr = target.getClass().getAnnotation(Description.class);
+		if (descr != null) {
+			f.format("%s%n%n", descr.value());
+		}
+		f.format("Available commands: %n%n");
+
+		for (Entry<String,Method> e : getCommands(target).entrySet()) {
+			Description d = e.getValue().getAnnotation(Description.class);
+			String desc = " ";
+			if ( d != null)
+				desc = d.value();
+			
+			f.format("  %s\t0-\t1%s %n", e.getKey(), desc);
+		}
+		f.format("%n");
+
+	}
+
+	/**
+	 * Show the full help for a given command
+	 */
+	public void help(Formatter f, Object target, String cmd) {
+
+		Method m = getCommands(target).get(cmd);
+		if (m == null)
+			f.format("No such command: %s%n", cmd);
+		else {
+			Class< ? extends Options> options = (Class< ? extends Options>) m.getParameterTypes()[0];
+			help(f, target, cmd, options);
+		}
+	}
+
+	/**
+	 * Parse a class and return a list of command names
+	 * 
+	 * @param target
+	 * @return
+	 */
+	public Map<String,Method> getCommands(Object target) {
+		Map<String,Method> map = new TreeMap<String,Method>();
+
+		for (Method m : target.getClass().getMethods()) {
+
+			if (m.getParameterTypes().length == 1 && m.getName().startsWith("_")) {
+				Class< ? > clazz = m.getParameterTypes()[0];
+				if (Options.class.isAssignableFrom(clazz)) {
+					String name = m.getName().substring(1);
+					map.put(name, m);
+				}
+			}
+		}
+		return map;
+	}
+
+	/**
+	 * Answer if the method is marked mandatory
+	 */
+	private boolean isMandatory(Method m) {
+		Config cfg = m.getAnnotation(Config.class);
+		if (cfg == null)
+			return false;
+
+		return cfg.required();
+	}
+
+	/**
+	 * @param m
+	 * @return
+	 */
+	private boolean isOption(Method m) {
+		return m.getReturnType() == boolean.class || m.getReturnType() == Boolean.class;
+	}
+
+	/**
+	 * Show a type in a nice way
+	 */
+
+	private String getTypeDescriptor(Type type) {
+		if (type instanceof ParameterizedType) {
+			ParameterizedType pt = (ParameterizedType) type;
+			Type c = pt.getRawType();
+			if (c instanceof Class) {
+				if (Collection.class.isAssignableFrom((Class< ? >) c)) {
+					return getTypeDescriptor(pt.getActualTypeArguments()[0]) + "*";
+				}
+			}
+		}
+		if (!(type instanceof Class))
+			return "<>";
+
+		Class< ? > clazz = (Class< ? >) type;
+
+		if (clazz == Boolean.class || clazz == boolean.class)
+			return ""; // Is a flag
+
+		return "<" + lastPart(clazz.getName().toLowerCase()) + ">";
+	}
+
+}
diff --git a/aQute.libg/src/aQute/lib/getopt/CommandLineMessages.java b/aQute.libg/src/aQute/lib/getopt/CommandLineMessages.java
new file mode 100644
index 0000000..8d65141
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/getopt/CommandLineMessages.java
@@ -0,0 +1,25 @@
+package aQute.lib.getopt;
+
+import java.util.*;
+
+import aQute.service.reporter.*;
+
+public interface CommandLineMessages extends Messages {
+
+	ERROR Option__WithArgumentNotLastInAvvreviation_(String name, char charAt, String typeDescriptor);
+
+	ERROR MissingArgument__(String name, char charAt);
+
+	ERROR OptionCanOnlyOccurOnce_(String name);
+
+	ERROR NoSuchCommand_(String cmd);
+
+	ERROR TooManyArguments_(List<String> arguments);
+
+	ERROR MissingArgument_(String string);
+
+	ERROR UnrecognizedOption_(String name);
+
+	ERROR OptionNotSet_(String name);
+
+}
diff --git a/aQute.libg/src/aQute/lib/getopt/Description.java b/aQute.libg/src/aQute/lib/getopt/Description.java
new file mode 100644
index 0000000..d5baead
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/getopt/Description.java
@@ -0,0 +1,8 @@
+package aQute.lib.getopt;
+
+import java.lang.annotation.*;
+
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface Description {
+	String value();
+}
diff --git a/aQute.libg/src/aQute/lib/getopt/OptionArgument.java b/aQute.libg/src/aQute/lib/getopt/OptionArgument.java
new file mode 100644
index 0000000..f4e9faa
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/getopt/OptionArgument.java
@@ -0,0 +1,8 @@
+package aQute.lib.getopt;
+
+import java.lang.annotation.*;
+
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface OptionArgument {
+	String value();
+}
diff --git a/aQute.libg/src/aQute/lib/getopt/Options.java b/aQute.libg/src/aQute/lib/getopt/Options.java
new file mode 100644
index 0000000..ff2b168
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/getopt/Options.java
@@ -0,0 +1,15 @@
+package aQute.lib.getopt;
+
+import java.util.*;
+
+public interface Options {
+	List<String> _();
+
+	CommandLine _command();
+
+	Map<String,String> _properties();
+
+	boolean _ok();
+
+	boolean _help();
+}
diff --git a/aQute.libg/src/aQute/lib/getopt/packageinfo b/aQute.libg/src/aQute/lib/getopt/packageinfo
new file mode 100644
index 0000000..9ad81f6
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/getopt/packageinfo
@@ -0,0 +1 @@
+version 1.0.0
diff --git a/aQute.libg/src/aQute/lib/hex/Hex.java b/aQute.libg/src/aQute/lib/hex/Hex.java
index c1ad416..ffceded 100755
--- a/aQute.libg/src/aQute/lib/hex/Hex.java
+++ b/aQute.libg/src/aQute/lib/hex/Hex.java
@@ -2,58 +2,61 @@ package aQute.lib.hex;
 
 import java.io.*;
 
-
 /*
  * Hex converter.
  * 
  * TODO Implement string to byte[]
  */
 public class Hex {
-	byte[]				data;
-	final static char[] HEX = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+	final static char[]	HEX	= {
+			'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+							};
+
 	public final static byte[] toByteArray(String string) {
 		string = string.trim();
-		if ( (string.length() & 1) != 0)
+		if ((string.length() & 1) != 0)
 			throw new IllegalArgumentException("a hex string must have an even length");
 
-		byte[]out = new byte[ string.length()/2];
-		for ( int i=0; i < out.length; i++) {
-			out[i] = (byte) (nibble(string.charAt(i*2))<<4 + nibble(string.charAt(i*2+1)));
+		byte[] out = new byte[string.length() / 2];
+		for (int i = 0; i < out.length; i++) {
+			int high = nibble(string.charAt(i * 2)) << 4;
+			int low = nibble(string.charAt(i * 2 + 1));
+			out[i] = (byte) (high + low);
 		}
 		return out;
 	}
 
-	
-	public final static int nibble( char c) {
+	public final static int nibble(char c) {
 		if (c >= '0' && c <= '9')
 			return c - '0';
-		
-		if ( c>='A' && c<='F')
+
+		if (c >= 'A' && c <= 'F')
 			return c - 'A' + 10;
-		if ( c>='a' && c<='f')
+		if (c >= 'a' && c <= 'f')
 			return c - 'a' + 10;
-		
+
 		throw new IllegalArgumentException("Not a hex digit: " + c);
 	}
-	
+
 	public final static String toHexString(byte data[]) {
 		StringBuilder sb = new StringBuilder();
 		try {
-			append(sb,data);
-		} catch (IOException e) {
+			append(sb, data);
+		}
+		catch (IOException e) {
 			// cannot happen with sb
 		}
 		return sb.toString();
 	}
-	
-	public final static void append( Appendable sb, byte [] data ) throws IOException {
-		for ( int i =0; i<data.length; i++) {
-			sb.append( nibble( data[i] >> 4));
-			sb.append( nibble( data[i]));
+
+	public final static void append(Appendable sb, byte[] data) throws IOException {
+		for (int i = 0; i < data.length; i++) {
+			sb.append(nibble(data[i] >> 4));
+			sb.append(nibble(data[i]));
 		}
 	}
 
-	private final static char nibble(int i) {	
+	private final static char nibble(int i) {
 		return HEX[i & 0xF];
 	}
 }
diff --git a/aQute.libg/src/aQute/lib/index/Index.java b/aQute.libg/src/aQute/lib/index/Index.java
index 35662d0..c51286f 100644
--- a/aQute.libg/src/aQute/lib/index/Index.java
+++ b/aQute.libg/src/aQute/lib/index/Index.java
@@ -12,8 +12,6 @@ import java.util.*;
  *   123 -> 123, 244   -> 2
  *   245 -> 245, ...
  * </pre>
- * 
- * 
  */
 public class Index implements Iterable<byte[]> {
 	final static int					LEAF		= 0;
@@ -23,20 +21,20 @@ public class Index implements Iterable<byte[]> {
 	final static int					MAGIC		= 0x494C4458;
 	final static int					KEYSIZE		= 4;
 
-	private FileChannel					file;
+	FileChannel					file;
 	final int							pageSize	= 4096;
 	final int							keySize;
 	final int							valueSize	= 8;
 	final int							capacity;
 	public Page							root;
-	final LinkedHashMap<Integer, Page>	cache		= new LinkedHashMap<Integer, Index.Page>();
+	final LinkedHashMap<Integer,Page>	cache		= new LinkedHashMap<Integer,Index.Page>();
 	final MappedByteBuffer				settings;
 
 	private int							nextPage;
 
 	class Page {
-		final int				TYPE_OFFSET		= 0;
-		final int				COUNT_OFFSET	= 2;
+		final static int		TYPE_OFFSET		= 0;
+		final static int		COUNT_OFFSET	= 2;
 		final static int		START_OFFSET	= 4;
 		final int				number;
 		boolean					leaf;
@@ -46,7 +44,7 @@ public class Index implements Iterable<byte[]> {
 
 		Page(int number) throws IOException {
 			this.number = number;
-			buffer = file.map(MapMode.READ_WRITE, number * pageSize, pageSize);
+			buffer = file.map(MapMode.READ_WRITE, ((long) number) * pageSize, pageSize);
 			n = buffer.getShort(COUNT_OFFSET);
 			int type = buffer.getShort(TYPE_OFFSET);
 			leaf = type != 0;
@@ -56,7 +54,7 @@ public class Index implements Iterable<byte[]> {
 			this.number = number;
 			this.leaf = leaf;
 			this.n = 0;
-			buffer = file.map(MapMode.READ_WRITE, number * pageSize, pageSize);
+			buffer = file.map(MapMode.READ_WRITE, ((long) number) * pageSize, pageSize);
 		}
 
 		Iterator<byte[]> iterator() {
@@ -76,14 +74,13 @@ public class Index implements Iterable<byte[]> {
 					try {
 						if (leaf)
 							return rover < n;
-						else {
-							while (i == null || i.hasNext() == false) {
-								int c = (int) c(rover++);
-								i = getPage(c).iterator();
-							}
-							return i.hasNext();
+						while (i == null || i.hasNext() == false) {
+							int c = (int) c(rover++);
+							i = getPage(c).iterator();
 						}
-					} catch (IOException e) {
+						return i.hasNext();
+					}
+					catch (IOException e) {
 						throw new RuntimeException(e);
 					}
 
@@ -150,13 +147,11 @@ public class Index implements Iterable<byte[]> {
 			if (leaf) {
 				if (cmp != 0)
 					return -1;
-				else
-					return c(i);
-			} else {
-				long value = c(i);
-				Page child = getPage((int) value);
-				return child.search(k);
+				return c(i);
 			}
+			long value = c(i);
+			Page child = getPage((int) value);
+			return child.search(k);
 		}
 
 		void insert(byte[] k, long v) throws IOException {
@@ -187,7 +182,7 @@ public class Index implements Iterable<byte[]> {
 
 		long c(int i) {
 			if (i < 0) {
-				System.out.println("Arghhh");
+				System.err.println("Arghhh");
 			}
 			int index = pos(i) + keySize;
 			return buffer.getLong(index);
@@ -246,33 +241,36 @@ public class Index implements Iterable<byte[]> {
 			write();
 		}
 
+		@Override
 		public String toString() {
 			StringBuilder sb = new StringBuilder();
 			try {
-				toString( sb, "");
-			} catch (IOException e) {
+				toString(sb, "");
+			}
+			catch (IOException e) {
 				e.printStackTrace();
 			}
 			return sb.toString();
 		}
-		
-		public void toString( StringBuilder sb, String indent ) throws IOException {
+
+		public void toString(StringBuilder sb, String indent) throws IOException {
 			for (int i = 0; i < n; i++) {
-				sb.append(String.format("%s %02d:%02d %20s %s %d\n", indent, number, i, hex(k(i), 0, 4), leaf ? "==" : "->", c(i)));
-				if (! leaf ) {
+				sb.append(String.format("%s %02d:%02d %20s %s %d%n", indent, number, i, hex(k(i), 0, 4), leaf ? "=="
+						: "->", c(i)));
+				if (!leaf) {
 					long c = c(i);
-					Page sub = getPage((int)c);
-					sub.toString(sb,indent+" ");
+					Page sub = getPage((int) c);
+					sub.toString(sb, indent + " ");
 				}
 			}
 		}
 
 		private String hex(byte[] k, int i, int j) {
 			StringBuilder sb = new StringBuilder();
-			
-			while ( i < j) {
+
+			while (i < j) {
 				int b = 0xFF & k[i];
-				sb.append(nibble(b>>4));
+				sb.append(nibble(b >> 4));
 				sb.append(nibble(b));
 				i++;
 			}
@@ -281,7 +279,7 @@ public class Index implements Iterable<byte[]> {
 
 		private char nibble(int i) {
 			i = i & 0xF;
-			return (char) ( i >= 10 ? i + 'A' - 10 : i + '0');
+			return (char) (i >= 10 ? i + 'A' - 10 : i + '0');
 		}
 
 	}
@@ -306,8 +304,8 @@ public class Index implements Iterable<byte[]> {
 
 			this.keySize = settings.getInt(KEYSIZE);
 			if (keySize != 0 && this.keySize != keySize)
-				throw new IllegalStateException("Invalid key size for Index file. The file is "
-						+ this.keySize + " and was expected to be " + this.keySize);
+				throw new IllegalStateException("Invalid key size for Index file. The file is " + this.keySize
+						+ " and was expected to be " + this.keySize);
 
 			root = getPage(1);
 			nextPage = (int) (this.file.size() / pageSize);
@@ -337,10 +335,11 @@ public class Index implements Iterable<byte[]> {
 		return page;
 	}
 
+	@Override
 	public String toString() {
 		return root.toString();
 	}
-	
+
 	public void close() throws IOException {
 		file.close();
 		cache.clear();
diff --git a/aQute.libg/src/aQute/lib/io/IO.java b/aQute.libg/src/aQute/lib/io/IO.java
index cadb753..9a118d5 100644
--- a/aQute.libg/src/aQute/lib/io/IO.java
+++ b/aQute.libg/src/aQute/lib/io/IO.java
@@ -3,12 +3,68 @@ package aQute.lib.io;
 import java.io.*;
 import java.net.*;
 import java.nio.*;
+import java.security.*;
 import java.util.*;
 
 public class IO {
+	static final public File	work	= new File(System.getProperty("user.dir"));
+	static final public File	home	= new File(System.getProperty("user.home"));
+
+	public static void copy(Reader r, Writer w) throws IOException {
+		try {
+			char buffer[] = new char[8000];
+			int size = r.read(buffer);
+			while (size > 0) {
+				w.write(buffer, 0, size);
+				size = r.read(buffer);
+			}
+		}
+		finally {
+			r.close();
+			w.flush();
+		}
+	}
+
+	public static void copy(InputStream r, Writer w) throws IOException {
+		copy(r, w, "UTF-8");
+	}
+
+	public static void copy(byte[] r, Writer w) throws IOException {
+		copy(new ByteArrayInputStream(r), w, "UTF-8");
+	}
+
+	public static void copy(byte[] r, OutputStream w) throws IOException {
+		copy(new ByteArrayInputStream(r), w);
+	}
+
+	public static void copy(InputStream r, Writer w, String charset) throws IOException {
+		try {
+			InputStreamReader isr = new InputStreamReader(r, charset);
+			copy(isr, w);
+		}
+		finally {
+			r.close();
+		}
+	}
+
+	public static void copy(Reader r, OutputStream o) throws IOException {
+		copy(r, o, "UTF-8");
+	}
+
+	public static void copy(Reader r, OutputStream o, String charset) throws IOException {
+		try {
+			OutputStreamWriter osw = new OutputStreamWriter(o, charset);
+			copy(r, osw);
+		}
+		finally {
+			r.close();
+		}
+	}
+
 	public static void copy(InputStream in, OutputStream out) throws IOException {
 		DataOutputStream dos = new DataOutputStream(out);
 		copy(in, (DataOutput) dos);
+		out.flush();
 	}
 
 	public static void copy(InputStream in, DataOutput out) throws IOException {
@@ -19,7 +75,8 @@ public class IO {
 				out.write(buffer, 0, size);
 				size = in.read(buffer);
 			}
-		} finally {
+		}
+		finally {
 			in.close();
 		}
 	}
@@ -32,27 +89,80 @@ public class IO {
 				bb.put(buffer, 0, size);
 				size = in.read(buffer);
 			}
-		} finally {
+		}
+		finally {
+			in.close();
+		}
+	}
+
+	public static void copy(URL in, MessageDigest md) throws IOException {
+		copy(in.openStream(), md);
+	}
+
+	public static void copy(File in, MessageDigest md) throws IOException {
+		copy(new FileInputStream(in), md);
+	}
+
+	public static void copy(URLConnection in, MessageDigest md) throws IOException {
+		copy(in.getInputStream(), md);
+	}
+
+	public static void copy(InputStream in, MessageDigest md) throws IOException {
+		byte[] buffer = new byte[10000];
+		try {
+			int size = in.read(buffer);
+			while (size > 0) {
+				md.update(buffer, 0, size);
+				size = in.read(buffer);
+			}
+		}
+		finally {
 			in.close();
 		}
 	}
 
+	public static void copy(URL url, File file) throws IOException {
+		URLConnection c = url.openConnection();
+		copy(c, file);
+	}
+
+	public static void copy(URLConnection c, File file) throws IOException {
+		copy(c.getInputStream(), file);
+	}
+
+	public static void copy(InputStream in, URL out) throws IOException {
+		copy(in, out, null);
+	}
+
+	public static void copy(InputStream in, URL out, String method) throws IOException {
+		URLConnection c = out.openConnection();
+		if (c instanceof HttpURLConnection && method != null) {
+			HttpURLConnection http = (HttpURLConnection) c;
+			http.setRequestMethod(method);
+		}
+		c.setDoOutput(true);
+		copy(in, c.getOutputStream());
+	}
+
 	public static void copy(File a, File b) throws IOException {
 		if (a.isFile()) {
 			FileOutputStream out = new FileOutputStream(b);
 			try {
 				copy(new FileInputStream(a), out);
-			} finally {
+			}
+			finally {
 				out.close();
 			}
-		} else if ( a.isDirectory()) {
-			 b.mkdirs();
-			 if ( !b.isDirectory())
-				 throw new IllegalArgumentException("target directory for a directory must be a directory: " + b);
-			 File subs[] = a.listFiles();
-			 for ( File sub : subs ) {
-				 copy(sub, new File(b,sub.getName()));
-			 }
+		} else if (a.isDirectory()) {
+			if (!b.exists() && !b.mkdirs()) {
+				throw new IOException("Could not create directory " + b);
+			}
+			if (!b.isDirectory())
+				throw new IllegalArgumentException("target directory for a directory must be a directory: " + b);
+			File subs[] = a.listFiles();
+			for (File sub : subs) {
+				copy(sub, new File(b, sub.getName()));
+			}
 		} else
 			throw new FileNotFoundException("During copy: " + a.toString());
 	}
@@ -61,7 +171,8 @@ public class IO {
 		FileOutputStream out = new FileOutputStream(b);
 		try {
 			copy(a, out);
-		} finally {
+		}
+		finally {
 			out.close();
 		}
 	}
@@ -82,10 +193,18 @@ public class IO {
 		return new String(out.toByteArray(), encoding);
 	}
 
+	public static String collect(URL a) throws IOException {
+		return collect(a, "UTF-8");
+	}
+
 	public static String collect(File a) throws IOException {
 		return collect(a, "UTF-8");
 	}
 
+	public static String collect(String a) throws IOException {
+		return collect(new File(a), "UTF-8");
+	}
+
 	public static String collect(InputStream a, String encoding) throws IOException {
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
 		copy(a, out);
@@ -107,13 +226,65 @@ public class IO {
 		return sw.toString();
 	}
 
+	/**
+	 * Create a temporary file.
+	 * 
+	 * @param directory
+	 *            the directory in which to create the file. Can be null, in
+	 *            which case the system TMP directory is used
+	 * @param pattern
+	 *            the filename prefix pattern. Must be at least 3 characters
+	 *            long
+	 * @param suffix
+	 *            the filename suffix. Can be null, in which case (system)
+	 *            default suffix is used
+	 * @return
+	 * @throws IllegalArgumentException
+	 *             when pattern is null or too short
+	 * @throws IOException
+	 *             when the specified (non-null) directory is not a directory
+	 */
+	public static File createTempFile(File directory, String pattern, String suffix) throws IllegalArgumentException,
+			IOException {
+		if ((pattern == null) || (pattern.length() < 3)) {
+			throw new IllegalArgumentException("Pattern must be at least 3 characters long, got "
+					+ ((pattern == null) ? "null" : pattern.length()));
+		}
+
+		if ((directory != null) && !directory.isDirectory()) {
+			throw new FileNotFoundException("Directory " + directory + " is not a directory");
+		}
+
+		return File.createTempFile(pattern, suffix, directory);
+	}
+
+	public static File getFile(String filename) {
+		return getFile(work, filename);
+	}
+
 	public static File getFile(File base, String file) {
+
+		if (file.startsWith("~/")) {
+			file = file.substring(2);
+			if (!file.startsWith("~/")) {
+				return getFile(home, file);
+			}
+		}
+		if (file.startsWith("~")) {
+			file = file.substring(1);
+			return getFile(home.getParentFile(), file);
+		}
+
 		File f = new File(file);
 		if (f.isAbsolute())
 			return f;
 		int n;
 
+		if (base == null)
+			base = work;
+
 		f = base.getAbsoluteFile();
+
 		while ((n = file.indexOf('/')) > 0) {
 			String first = file.substring(0, n);
 			file = file.substring(n + 1);
@@ -124,50 +295,218 @@ public class IO {
 		}
 		if (file.equals(".."))
 			return f.getParentFile();
-		else
-			return new File(f, file).getAbsoluteFile();
+		return new File(f, file).getAbsoluteFile();
 	}
 
+	/**
+	 * Deletes the specified file. Folders are recursively deleted.<br>
+	 * If file(s) cannot be deleted, no feedback is provided (fail silently).
+	 * 
+	 * @param f
+	 *            file to be deleted
+	 */
 	public static void delete(File f) {
+		try {
+			deleteWithException(f);
+		}
+		catch (IOException e) {
+			// Ignore a failed delete
+		}
+	}
+
+	/**
+	 * Deletes the specified file. Folders are recursively deleted.<br>
+	 * Throws exception if any of the files could not be deleted.
+	 * 
+	 * @param f
+	 *            file to be deleted
+	 * @throws IOException
+	 *             if the file (or contents of a folder) could not be deleted
+	 */
+	public static void deleteWithException(File f) throws IOException {
 		f = f.getAbsoluteFile();
+		if (!f.exists())
+			return;
 		if (f.getParentFile() == null)
 			throw new IllegalArgumentException("Cannot recursively delete root for safety reasons");
 
+		boolean wasDeleted = true;
 		if (f.isDirectory()) {
 			File[] subs = f.listFiles();
-			for (File sub : subs)
-				delete(sub);
+			for (File sub : subs) {
+				try {
+					deleteWithException(sub);
+				}
+				catch (IOException e) {
+					wasDeleted = false;
+				}
+			}
 		}
 
-		f.delete();
+		boolean fDeleted = f.delete();
+		if (!fDeleted || !wasDeleted) {
+			throw new IOException("Failed to delete " + f.getAbsoluteFile());
+		}
 	}
 
-	public static void drain(InputStream in) throws IOException {
+	/**
+	 * Deletes <code>to</code> file if it exists, and renames <code>from</code>
+	 * file to <code>to</code>.<br>
+	 * Throws exception the rename operation fails.
+	 * 
+	 * @param from
+	 *            source file
+	 * @param to
+	 *            destination file
+	 * @throws IOException
+	 *             if the rename operation fails
+	 */
+	public static void rename(File from, File to) throws IOException {
+		IO.deleteWithException(to);
+
+		boolean renamed = from.renameTo(to);
+		if (!renamed)
+			throw new IOException("Could not rename " + from.getAbsoluteFile() + " to " + to.getAbsoluteFile());
+	}
+
+	public static long drain(InputStream in) throws IOException {
+		long result = 0;
 		byte[] buffer = new byte[10000];
 		try {
 			int size = in.read(buffer);
-			while (size > 0) {
+			while (size >= 0) {
+				result += size;
 				size = in.read(buffer);
 			}
-		} finally {
+		}
+		finally {
 			in.close();
 		}
+		return result;
 	}
 
-	public void copy(Collection<?> c, OutputStream out) {
-		PrintStream ps = new PrintStream(out);
+	public void copy(Collection< ? > c, OutputStream out) throws IOException {
+		Writer w = new OutputStreamWriter(out, "UTF-8");
+		PrintWriter ps = new PrintWriter(w);
 		for (Object o : c) {
 			ps.println(o);
 		}
 		ps.flush();
+		w.flush();
 	}
 
 	public static Throwable close(Closeable in) {
+		if (in == null)
+			return null;
+
 		try {
 			in.close();
 			return null;
-		} catch (Throwable e) {
+		}
+		catch (Throwable e) {
 			return e;
 		}
 	}
+
+	public static URL toURL(String s, File base) throws MalformedURLException {
+		int n = s.indexOf(':');
+		if (n > 0 && n < 10) {
+			// is url
+			return new URL(s);
+		}
+		return getFile(base, s).toURI().toURL();
+	}
+
+	public static void store(Object o, File out) throws IOException {
+		store(o, out, "UTF-8");
+	}
+
+	public static void store(Object o, File out, String encoding) throws IOException {
+		FileOutputStream fout = new FileOutputStream(out);
+		try {
+			store(o, fout, encoding);
+		}
+		finally {
+			fout.close();
+		}
+	}
+
+	public static void store(Object o, OutputStream fout) throws UnsupportedEncodingException, IOException {
+		store(o, fout, "UTF-8");
+	}
+
+	public static void store(Object o, OutputStream fout, String encoding) throws UnsupportedEncodingException,
+			IOException {
+		String s;
+
+		if (o == null)
+			s = "";
+		else
+			s = o.toString();
+
+		try {
+			fout.write(s.getBytes(encoding));
+		}
+		finally {
+			fout.close();
+		}
+	}
+
+	public static InputStream stream(String s) {
+		try {
+			return new ByteArrayInputStream(s.getBytes("UTF-8"));
+		}
+		catch (Exception e) {
+			// Ignore
+			return null;
+		}
+	}
+
+	public static InputStream stream(String s, String encoding) throws UnsupportedEncodingException {
+		return new ByteArrayInputStream(s.getBytes(encoding));
+	}
+
+	public static InputStream stream(File s) throws FileNotFoundException {
+		return new FileInputStream(s);
+	}
+
+	public static InputStream stream(URL s) throws IOException {
+		return s.openStream();
+	}
+
+	public static Reader reader(String s) {
+		return new StringReader(s);
+	}
+
+	public static BufferedReader reader(File f, String encoding) throws IOException {
+		return reader(new FileInputStream(f), encoding);
+	}
+
+	public static BufferedReader reader(File f) throws IOException {
+		return reader(f, "UTF-8");
+	}
+
+	public static PrintWriter writer(File f, String encoding) throws IOException {
+		return writer(new FileOutputStream(f), encoding);
+	}
+
+	public static PrintWriter writer(File f) throws IOException {
+		return writer(f, "UTF-8");
+	}
+
+	public static PrintWriter writer(OutputStream out, String encoding) throws IOException {
+		return new PrintWriter(new OutputStreamWriter(out, encoding));
+	}
+
+	public static BufferedReader reader(InputStream in, String encoding) throws IOException {
+		return new BufferedReader(new InputStreamReader(in, encoding));
+	}
+
+	public static BufferedReader reader(InputStream in) throws IOException {
+		return reader(in, "UTF-8");
+	}
+
+	public static PrintWriter writer(OutputStream out) throws IOException {
+		return writer(out, "UTF-8");
+	}
 }
diff --git a/aQute.libg/src/aQute/lib/io/LimitedInputStream.java b/aQute.libg/src/aQute/lib/io/LimitedInputStream.java
index bf9a21f..b48ce5e 100644
--- a/aQute.libg/src/aQute/lib/io/LimitedInputStream.java
+++ b/aQute.libg/src/aQute/lib/io/LimitedInputStream.java
@@ -14,7 +14,8 @@ public class LimitedInputStream extends InputStream {
 		this.size = size;
 	}
 
-	@Override public int read() throws IOException {
+	@Override
+	public int read() throws IOException {
 		if (left <= 0) {
 			eof();
 			return -1;
@@ -24,27 +25,31 @@ public class LimitedInputStream extends InputStream {
 		return in.read();
 	}
 
-	@Override public int available() throws IOException {		
+	@Override
+	public int available() throws IOException {
 		return Math.min(left, in.available());
 	}
 
-	@Override public void close() throws IOException {
+	@Override
+	public void close() throws IOException {
 		eof();
 		in.close();
 	}
 
-	protected void eof() {
-	}
+	protected void eof() {}
 
-	@Override public synchronized void mark(int readlimit) {
+	@Override
+	public synchronized void mark(int readlimit) {
 		throw new UnsupportedOperationException();
 	}
 
-	@Override public boolean markSupported() {
+	@Override
+	public boolean markSupported() {
 		return false;
 	}
 
-	@Override public int read(byte[] b, int off, int len) throws IOException {
+	@Override
+	public int read(byte[] b, int off, int len) throws IOException {
 		int min = Math.min(len, left);
 		if (min == 0)
 			return 0;
@@ -55,23 +60,26 @@ public class LimitedInputStream extends InputStream {
 		return read;
 	}
 
-	@Override public int read(byte[] b) throws IOException {
-		return read(b,0,b.length);
+	@Override
+	public int read(byte[] b) throws IOException {
+		return read(b, 0, b.length);
 	}
 
-	@Override public synchronized void reset() throws IOException {
+	@Override
+	public synchronized void reset() throws IOException {
 		throw new UnsupportedOperationException();
 	}
 
-	@Override public long skip(long n) throws IOException {
+	@Override
+	public long skip(long n) throws IOException {
 		long count = 0;
 		byte buffer[] = new byte[1024];
-		while ( n > 0 && read() >= 0) {
+		while (n > 0 && read() >= 0) {
 			int size = read(buffer);
-			if ( size <= 0)
+			if (size <= 0)
 				return count;
-			count+=size;
-			n-=size;
+			count += size;
+			n -= size;
 		}
 		return count;
 	}
diff --git a/aQute.libg/src/aQute/lib/io/packageinfo b/aQute.libg/src/aQute/lib/io/packageinfo
index 7c8de03..71cb898 100644
--- a/aQute.libg/src/aQute/lib/io/packageinfo
+++ b/aQute.libg/src/aQute/lib/io/packageinfo
@@ -1 +1 @@
-version 1.0
+version 1.3.0
diff --git a/aQute.libg/src/aQute/lib/json/ArrayHandler.java b/aQute.libg/src/aQute/lib/json/ArrayHandler.java
new file mode 100644
index 0000000..b53f9ab
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/json/ArrayHandler.java
@@ -0,0 +1,40 @@
+package aQute.lib.json;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+public class ArrayHandler extends Handler {
+	Type	componentType;
+
+	ArrayHandler(@SuppressWarnings("unused") Class< ? > rawClass, Type componentType) {
+		this.componentType = componentType;
+	}
+
+	@Override
+	void encode(Encoder app, Object object, Map<Object,Type> visited) throws IOException, Exception {
+		app.append("[");
+		app.indent();
+		String del = "";
+		int l = Array.getLength(object);
+		for (int i = 0; i < l; i++) {
+			app.append(del);
+			app.encode(Array.get(object, i), componentType, visited);
+			del = ",";
+		}
+		app.undent();
+		app.append("]");
+	}
+
+	@Override
+	Object decodeArray(Decoder r) throws Exception {
+		ArrayList<Object> list = new ArrayList<Object>();
+		r.codec.parseArray(list, componentType, r);
+		Object array = Array.newInstance(r.codec.getRawClass(componentType), list.size());
+		int n = 0;
+		for (Object o : list)
+			Array.set(array, n++, o);
+
+		return array;
+	}
+}
diff --git a/aQute.libg/src/aQute/lib/json/BooleanHandler.java b/aQute.libg/src/aQute/lib/json/BooleanHandler.java
new file mode 100644
index 0000000..9dfbaf4
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/json/BooleanHandler.java
@@ -0,0 +1,34 @@
+package aQute.lib.json;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+public class BooleanHandler extends Handler {
+
+	@Override
+	void encode(Encoder app, Object object, Map<Object,Type> visited) throws IOException, Exception {
+		app.append(object.toString());
+	}
+
+	@Override
+	Object decode(Decoder dec, boolean s) {
+		return s;
+	}
+
+	@Override
+	Object decode(Decoder dec, String s) {
+		return Boolean.parseBoolean(s);
+	}
+
+	@Override
+	Object decode(Decoder dec, Number s) {
+		return s.intValue() != 0;
+	}
+
+	@Override
+	Object decode(Decoder dec) {
+		return false;
+	}
+
+}
diff --git a/aQute.libg/src/aQute/lib/json/ByteArrayHandler.java b/aQute.libg/src/aQute/lib/json/ByteArrayHandler.java
new file mode 100644
index 0000000..349b381
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/json/ByteArrayHandler.java
@@ -0,0 +1,80 @@
+package aQute.lib.json;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.regex.*;
+
+import aQute.lib.base64.*;
+import aQute.lib.hex.*;
+
+/**
+ * Will now use hex for encoding byte arrays
+ */
+public class ByteArrayHandler extends Handler {
+	Pattern	ENCODING	= Pattern
+								.compile("((:?[\\dA-Za-z][\\dA-Za-z])*)|((:?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/)+={1,3})");
+
+	@Override
+	void encode(Encoder app, Object object, Map<Object,Type> visited) throws IOException, Exception {
+		StringHandler.string(app, Hex.toHexString((byte[]) object));
+	}
+
+	@Override
+	Object decodeArray(Decoder r) throws Exception {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+		ArrayList<Object> list = new ArrayList<Object>();
+		r.codec.parseArray(list, Byte.class, r);
+		for (Object b : list) {
+			out.write(((Byte) b).byteValue());
+		}
+		return out.toByteArray();
+	}
+
+	@Override
+	Object decode(Decoder dec, String s) throws Exception {
+		boolean hex = true;
+		StringBuilder sb = new StringBuilder(s);
+		for (int i = sb.length() - 1; i >= 0; i--) {
+			char c = sb.charAt(i);
+			if (Character.isWhitespace(c))
+				sb.delete(i, i + 1);
+			else {
+				switch (c) {
+					case '0' :
+					case '1' :
+					case '2' :
+					case '3' :
+					case '4' :
+					case '5' :
+					case '6' :
+					case '7' :
+					case '8' :
+					case '9' :
+					case 'A' :
+					case 'B' :
+					case 'C' :
+					case 'D' :
+					case 'E' :
+					case 'F' :
+					case 'a' :
+					case 'b' :
+					case 'c' :
+					case 'd' :
+					case 'e' :
+					case 'f' :
+						break;
+
+					default :
+						hex = false;
+						break;
+				}
+			}
+		}
+		if ( hex)
+			return Hex.toByteArray(sb.toString());
+		else
+			return Base64.decodeBase64(sb.toString());
+	}
+}
diff --git a/aQute.libg/src/aQute/lib/json/CharacterHandler.java b/aQute.libg/src/aQute/lib/json/CharacterHandler.java
new file mode 100644
index 0000000..799f73c
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/json/CharacterHandler.java
@@ -0,0 +1,35 @@
+package aQute.lib.json;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+public class CharacterHandler extends Handler {
+
+	@Override
+	void encode(Encoder app, Object object, Map<Object,Type> visited) throws Exception {
+		Character c = (Character) object;
+		int v = c.charValue();
+		app.append(v + "");
+	}
+
+	@Override
+	Object decode(Decoder dec, boolean s) {
+		return s ? 't' : 'f';
+	}
+
+	@Override
+	Object decode(Decoder dec, String s) {
+		return (char) Integer.parseInt(s);
+	}
+
+	@Override
+	Object decode(Decoder dec, Number s) {
+		return (char) s.shortValue();
+	}
+
+	@Override
+	Object decode(Decoder dec) {
+		return 0;
+	}
+
+}
diff --git a/aQute.libg/src/aQute/lib/json/CollectionHandler.java b/aQute.libg/src/aQute/lib/json/CollectionHandler.java
new file mode 100644
index 0000000..aacbb0a
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/json/CollectionHandler.java
@@ -0,0 +1,57 @@
+package aQute.lib.json;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+public class CollectionHandler extends Handler {
+	Class< ? >	rawClass;
+	Type		componentType;
+
+	CollectionHandler(Class< ? > rawClass, Type componentType) {
+		this.componentType = componentType;
+		if (rawClass.isInterface()) {
+			if (rawClass.isAssignableFrom(ArrayList.class))
+				rawClass = ArrayList.class;
+			else if (rawClass.isAssignableFrom(LinkedList.class))
+				rawClass = LinkedList.class;
+			else if (rawClass.isAssignableFrom(HashSet.class))
+				rawClass = HashSet.class;
+			else if (rawClass.isAssignableFrom(TreeSet.class))
+				rawClass = TreeSet.class;
+			else if (rawClass.isAssignableFrom(Vector.class))
+				rawClass = Vector.class;
+			else if (rawClass.isAssignableFrom(ConcurrentLinkedQueue.class))
+				rawClass = ConcurrentLinkedQueue.class;
+			else if (rawClass.isAssignableFrom(CopyOnWriteArrayList.class))
+				rawClass = CopyOnWriteArrayList.class;
+			else if (rawClass.isAssignableFrom(CopyOnWriteArraySet.class))
+				rawClass = CopyOnWriteArraySet.class;
+			else
+				throw new IllegalArgumentException("Unknown interface type for collection: " + rawClass);
+		}
+		this.rawClass = rawClass;
+	}
+
+	@Override
+	void encode(Encoder app, Object object, Map<Object,Type> visited) throws IOException, Exception {
+		Iterable< ? > collection = (Iterable< ? >) object;
+
+		app.append("[");
+		String del = "";
+		for (Object o : collection) {
+			app.append(del);
+			app.encode(o, componentType, visited);
+			del = ",";
+		}
+		app.append("]");
+	}
+
+	@Override
+	Object decodeArray(Decoder r) throws Exception {
+		Collection<Object> c = (Collection<Object>) rawClass.newInstance();
+		r.codec.parseArray(c, componentType, r);
+		return c;
+	}
+}
diff --git a/aQute.libg/src/aQute/lib/json/DateHandler.java b/aQute.libg/src/aQute/lib/json/DateHandler.java
new file mode 100644
index 0000000..cb3c27e
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/json/DateHandler.java
@@ -0,0 +1,32 @@
+package aQute.lib.json;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.text.*;
+import java.util.*;
+
+public class DateHandler extends Handler {
+	final static SimpleDateFormat	sdf	= new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+
+	@Override
+	void encode(Encoder app, Object object, Map<Object,Type> visited) throws IOException, Exception {
+		String s;
+		synchronized (sdf) {
+			s = sdf.format((Date) object);
+		}
+		StringHandler.string(app, s);
+	}
+
+	@Override
+	Object decode(Decoder dec, String s) throws Exception {
+		synchronized (sdf) {
+			return sdf.parse(s);
+		}
+	}
+
+	@Override
+	Object decode(Decoder dec, Number s) throws Exception {
+		return new Date(s.longValue());
+	}
+
+}
diff --git a/aQute.libg/src/aQute/lib/json/Decoder.java b/aQute.libg/src/aQute/lib/json/Decoder.java
new file mode 100644
index 0000000..2d164e7
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/json/Decoder.java
@@ -0,0 +1,186 @@
+package aQute.lib.json;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.security.*;
+import java.util.*;
+import java.util.zip.*;
+
+import aQute.lib.converter.*;
+
+public class Decoder implements Closeable {
+	final JSONCodec		codec;
+	Reader				reader;
+	int					current;
+	MessageDigest		digest;
+	Map<String,Object>	extra;
+	String				encoding	= "UTF-8";
+
+	boolean				strict;
+	boolean				inflate;
+	boolean				keepOpen	= false;
+
+	Decoder(JSONCodec codec) {
+		this.codec = codec;
+	}
+
+	public Decoder from(File file) throws Exception {
+		return from(new FileInputStream(file));
+	}
+
+	public Decoder from(InputStream in) throws Exception {
+
+		if (inflate)
+			in = new InflaterInputStream(in);
+
+		return from(new InputStreamReader(in, encoding));
+	}
+
+	public Decoder charset(String encoding) {
+		this.encoding = encoding;
+		return this;
+	}
+
+	public Decoder strict() {
+		this.strict = true;
+		return this;
+	}
+
+	public Decoder from(Reader in) throws Exception {
+		reader = in;
+		read();
+		return this;
+	}
+
+	public Decoder faq(String in) throws Exception {
+		return from(in.replace('\'', '"'));
+	}
+
+	public Decoder from(String in) throws Exception {
+		return from(new StringReader(in));
+	}
+
+	public Decoder mark() throws NoSuchAlgorithmException {
+		if (digest == null)
+			digest = MessageDigest.getInstance("SHA1");
+		digest.reset();
+		return this;
+	}
+
+	public byte[] digest() {
+		if (digest == null)
+			return null;
+
+		return digest.digest();
+	}
+
+	public <T> T get(Class<T> clazz) throws Exception {
+		try {
+			return (T) codec.decode(clazz, this);
+		}
+		finally {
+			if (!keepOpen)
+				close();
+		}
+	}
+
+	public Object get(Type type) throws Exception {
+		try {
+			return codec.decode(type, this);
+		}
+		finally {
+			if (!keepOpen)
+				close();
+		}
+	}
+
+	public Object get() throws Exception {
+		try {
+			return codec.decode(null, this);
+		}
+		finally {
+			if (!keepOpen)
+				close();
+		}
+	}
+
+	public <T> T get(TypeReference<T> ref) throws Exception {
+		try {
+			return (T) codec.decode(ref.getType(), this);
+		}
+		finally {
+			if (!keepOpen)
+				close();
+		}
+	}
+
+	public Decoder keepOpen() {
+		keepOpen = true;
+		return this;
+	}
+	
+	int read() throws Exception {
+		current = reader.read();
+		if (digest != null) {
+			digest.update((byte) (current / 256));
+			digest.update((byte) (current % 256));
+		}
+		return current;
+	}
+
+	int current() {
+		return current;
+	}
+
+	/**
+	 * Skip any whitespace.
+	 * 
+	 * @return
+	 * @throws Exception
+	 */
+	int skipWs() throws Exception {
+		while (Character.isWhitespace(current()))
+			read();
+		return current();
+	}
+
+	/**
+	 * Skip any whitespace.
+	 * 
+	 * @return
+	 * @throws Exception
+	 */
+	int next() throws Exception {
+		read();
+		return skipWs();
+	}
+
+	void expect(String s) throws Exception {
+		for (int i = 0; i < s.length(); i++)
+			if (!(s.charAt(i) == read()))
+				throw new IllegalArgumentException("Expected " + s + " but got something different");
+		read();
+	}
+
+	public boolean isEof() throws Exception {
+		int c = skipWs();
+		return c < 0;
+	}
+
+	public void close() throws IOException {
+		reader.close();
+	}
+
+	public Map<String,Object> getExtra() {
+		if (extra == null)
+			extra = new HashMap<String,Object>();
+		return extra;
+	}
+
+	public Decoder inflate() {
+		if (reader != null)
+			throw new IllegalStateException("Reader already set, inflate must come before from()");
+		inflate = true;
+		return this;
+	}
+}
diff --git a/aQute.libg/src/aQute/lib/json/Encoder.java b/aQute.libg/src/aQute/lib/json/Encoder.java
new file mode 100644
index 0000000..44a7112
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/json/Encoder.java
@@ -0,0 +1,149 @@
+package aQute.lib.json;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.security.*;
+import java.util.*;
+import java.util.zip.*;
+
+public class Encoder implements Appendable, Closeable, Flushable {
+	final JSONCodec	codec;
+	Appendable		app;
+	MessageDigest	digest;
+	boolean			writeDefaults;
+	String			encoding	= "UTF-8";
+	boolean			deflate;
+	String				tabs		= null;
+	String			indent		= "";
+
+	Encoder(JSONCodec codec) {
+		this.codec = codec;
+	}
+
+	public Encoder put(Object object) throws Exception {
+		if (app == null)
+			to();
+
+		codec.encode(this, object, null, new IdentityHashMap<Object,Type>());
+		flush();
+		return this;
+	}
+
+	public Encoder mark() throws NoSuchAlgorithmException {
+		if (digest == null)
+			digest = MessageDigest.getInstance("SHA1");
+		digest.reset();
+		return this;
+	}
+
+	public byte[] digest() throws NoSuchAlgorithmException, IOException {
+		if (digest == null)
+			return null;
+		append('\n');
+		return digest.digest();
+	}
+
+	public Encoder to() throws IOException {
+		to(new StringWriter());
+		return this;
+	}
+
+	public Encoder to(File file) throws IOException {
+		return to(new FileOutputStream(file));
+	}
+
+	public Encoder charset(String encoding) {
+		this.encoding = encoding;
+		return this;
+	}
+
+	public Encoder to(OutputStream out) throws IOException {
+		if (deflate)
+			out = new DeflaterOutputStream(out);
+
+		return to(new OutputStreamWriter(out, encoding));
+	}
+
+	public Encoder to(Appendable out) throws IOException {
+		app = out;
+		return this;
+	}
+
+	public Appendable append(char c) throws IOException {
+		if (digest != null) {
+			digest.update((byte) (c / 256));
+			digest.update((byte) (c % 256));
+		}
+		app.append(c);
+		return this;
+	}
+
+	public Appendable append(CharSequence sq) throws IOException {
+		return append(sq, 0, sq.length());
+	}
+
+	public Appendable append(CharSequence sq, int start, int length) throws IOException {
+		if (digest != null) {
+			for (int i = start; i < length; i++) {
+				char c = sq.charAt(i);
+				digest.update((byte) (c / 256));
+				digest.update((byte) (c % 256));
+			}
+		}
+		app.append(sq, start, length);
+		return this;
+	}
+
+	@Override
+	public String toString() {
+		return app.toString();
+	}
+
+	public void close() throws IOException {
+		if (app != null && app instanceof Closeable)
+			((Closeable) app).close();
+	}
+
+	void encode(Object object, Type type, Map<Object,Type> visited) throws Exception {
+		codec.encode(this, object, type, visited);
+	}
+
+	public Encoder writeDefaults() {
+		writeDefaults = true;
+		return this;
+	}
+
+	public void flush() throws IOException {
+		if (app instanceof Flushable) {
+			((Flushable) app).flush();
+		}
+	}
+
+	public Encoder deflate() {
+		if (app != null)
+			throw new IllegalStateException("Writer already set, deflate must come before to(...)");
+		deflate = true;
+		return this;
+	}
+
+	public Encoder indent(String tabs) {
+		this.tabs = tabs;
+		return this;
+	}
+
+	void undent() throws IOException {
+		if (tabs != null) {
+			app.append("\n");
+			indent = indent.substring(tabs.length());
+			app.append(indent);
+		}
+	}
+
+	void indent() throws IOException {
+		if (tabs != null) {
+			app.append("\n");
+			indent += tabs;
+			app.append(indent);
+		}
+	}
+}
diff --git a/aQute.libg/src/aQute/lib/json/EnumHandler.java b/aQute.libg/src/aQute/lib/json/EnumHandler.java
new file mode 100644
index 0000000..9b5eaf3
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/json/EnumHandler.java
@@ -0,0 +1,26 @@
+package aQute.lib.json;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+public class EnumHandler extends Handler {
+	@SuppressWarnings("rawtypes")
+	final Class	type;
+
+	public EnumHandler(Class< ? > type) {
+		this.type = type;
+	}
+
+	@Override
+	void encode(Encoder app, Object object, Map<Object,Type> visited) throws IOException, Exception {
+		StringHandler.string(app, object.toString());
+	}
+
+	@Override
+	@SuppressWarnings("unchecked")
+	Object decode(Decoder dec, String s) throws Exception {
+		return Enum.valueOf(type, s);
+	}
+
+}
diff --git a/aQute.libg/src/aQute/lib/json/FileHandler.java b/aQute.libg/src/aQute/lib/json/FileHandler.java
new file mode 100644
index 0000000..b2c0838
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/json/FileHandler.java
@@ -0,0 +1,41 @@
+package aQute.lib.json;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import aQute.lib.base64.*;
+
+public class FileHandler extends Handler {
+
+	@Override
+	void encode(Encoder app, Object object, Map<Object,Type> visited) throws IOException, Exception {
+		File f = (File) object;
+		if (!f.isFile())
+			throw new RuntimeException("Encoding a file requires the file to exist and to be a normal file " + f);
+
+		FileInputStream in = new FileInputStream(f);
+		try {
+			app.append('"');
+			Base64.encode(in, app);
+			app.append('"');
+		}
+		finally {
+			in.close();
+		}
+	}
+
+	@Override
+	Object decode(Decoder dec, String s) throws Exception {
+		File tmp = File.createTempFile("json", ".bin");
+		FileOutputStream fout = new FileOutputStream(tmp);
+		try {
+			Base64.decode(new StringReader(s), fout);
+		}
+		finally {
+			fout.close();
+		}
+		return tmp;
+	}
+
+}
diff --git a/aQute.libg/src/aQute/lib/json/Handler.java b/aQute.libg/src/aQute/lib/json/Handler.java
new file mode 100644
index 0000000..5738b04
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/json/Handler.java
@@ -0,0 +1,34 @@
+package aQute.lib.json;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+abstract class Handler {
+	abstract void encode(Encoder app, Object object, Map<Object,Type> visited) throws IOException, Exception;
+
+	Object decodeObject(@SuppressWarnings("unused") Decoder isr) throws Exception {
+		throw new UnsupportedOperationException("Cannot be mapped to object " + this);
+	}
+
+	Object decodeArray(@SuppressWarnings("unused") Decoder isr) throws Exception {
+		throw new UnsupportedOperationException("Cannot be mapped to array " + this);
+	}
+
+	Object decode(Decoder dec, @SuppressWarnings("unused") String s) throws Exception {
+		throw new UnsupportedOperationException("Cannot be mapped to string " + this);
+	}
+
+	Object decode(Decoder dec, @SuppressWarnings("unused") Number s) throws Exception {
+		throw new UnsupportedOperationException("Cannot be mapped to number " + this);
+	}
+
+	Object decode(Decoder dec, @SuppressWarnings("unused") boolean s) {
+		throw new UnsupportedOperationException("Cannot be mapped to boolean " + this);
+	}
+
+	Object decode(Decoder dec) {
+		return null;
+	}
+
+}
diff --git a/aQute.libg/src/aQute/lib/json/JSONCodec.java b/aQute.libg/src/aQute/lib/json/JSONCodec.java
new file mode 100644
index 0000000..02601d4
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/json/JSONCodec.java
@@ -0,0 +1,492 @@
+package aQute.lib.json;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.regex.*;
+
+/**
+ * This is a simple JSON Coder and Encoder that uses the Java type system to
+ * convert data objects to JSON and JSON to (type safe) Java objects. The
+ * conversion is very much driven by classes and their public fields. Generic
+ * information, when present is taken into account. </p> Usage patterns to
+ * encode:
+ * 
+ * <pre>
+ *  JSONCoder codec = new JSONCodec(); // 
+ * 	assert "1".equals( codec.enc().to().put(1).toString());
+ * 	assert "[1,2,3]".equals( codec.enc().to().put(Arrays.asList(1,2,3).toString());
+ * 
+ *  Map m = new HashMap();
+ *  m.put("a", "A");
+ * 	assert "{\"a\":\"A\"}".equals( codec.enc().to().put(m).toString());
+ * 
+ *  static class D { public int a; }
+ *  D d = new D();
+ *  d.a = 41;
+ *  assert "{\"a\":41}".equals( codec.enc().to().put(d).toString());
+ * </pre>
+ * 
+ * It is possible to redirect the encoder to another output (default is a
+ * string). See {@link Encoder#to()},{@link Encoder#to(File))},
+ * {@link Encoder#to(OutputStream)}, {@link Encoder#to(Appendable))}. To reset
+ * the string output call {@link Encoder#to()}.
+ * <p/>
+ * This Codec class can be used in a concurrent environment. The Decoders and
+ * Encoders, however, must only be used in a single thread.
+ * <p/>
+ * Will now use hex for encoding byte arrays
+ */
+public class JSONCodec {
+	final static String								START_CHARACTERS	= "[{\"-0123456789tfn";
+
+	// Handlers
+	private final static WeakHashMap<Type,Handler>	handlers			= new WeakHashMap<Type,Handler>();
+	private static StringHandler					sh					= new StringHandler();
+	private static BooleanHandler					bh					= new BooleanHandler();
+	private static CharacterHandler					ch					= new CharacterHandler();
+	private static CollectionHandler				dch					= new CollectionHandler(ArrayList.class,
+																				Object.class);
+	private static SpecialHandler					sph					= new SpecialHandler(Pattern.class, null, null);
+	private static DateHandler						sdh					= new DateHandler();
+	private static FileHandler						fh					= new FileHandler();
+	private static ByteArrayHandler					byteh				= new ByteArrayHandler();
+
+	boolean											ignorenull;
+
+	/**
+	 * Create a new Encoder with the state and appropriate API.
+	 * 
+	 * @return an Encoder
+	 */
+	public Encoder enc() {
+		return new Encoder(this);
+	}
+
+	/**
+	 * Create a new Decoder with the state and appropriate API.
+	 * 
+	 * @return a Decoder
+	 */
+	public Decoder dec() {
+		return new Decoder(this);
+	}
+
+	/*
+	 * Work horse encode methods, all encoding ends up here.
+	 */
+	void encode(Encoder app, Object object, Type type, Map<Object,Type> visited) throws Exception {
+
+		// Get the null out of the way
+
+		if (object == null) {
+			app.append("null");
+			return;
+		}
+
+		// If we have no type or the type is Object.class
+		// we take the type of the object itself. Normally types
+		// come from declaration sites (returns, fields, methods, etc)
+		// and contain generic info.
+
+		if (type == null || type == Object.class)
+			type = object.getClass();
+
+		// Dispatch to the handler who knows how to handle the given type.
+		Handler h = getHandler(type);
+		h.encode(app, object, visited);
+	}
+
+	/*
+	 * This method figures out which handler should handle the type specific
+	 * stuff. It returns a handler for each type. If no appropriate handler
+	 * exists, it will create one for the given type. There are actually quite a
+	 * lot of handlers since Java is not very object oriented.
+	 * @param type
+	 * @return
+	 * @throws Exception
+	 */
+	Handler getHandler(Type type) throws Exception {
+
+		// First the static hard coded handlers for the common types.
+
+		if (type == String.class)
+			return sh;
+
+		if (type == Boolean.class || type == boolean.class)
+			return bh;
+
+		if (type == byte[].class)
+			return byteh;
+
+		if (Character.class == type || char.class == type)
+			return ch;
+
+		if (Pattern.class == type)
+			return sph;
+
+		if (Date.class == type)
+			return sdh;
+
+		if (File.class == type)
+			return fh;
+
+		Handler h;
+		synchronized (handlers) {
+			h = handlers.get(type);
+		}
+
+		if (h != null)
+			return h;
+
+		if (type instanceof Class) {
+
+			Class< ? > clazz = (Class< ? >) type;
+
+			if (Enum.class.isAssignableFrom(clazz))
+				h = new EnumHandler(clazz);
+			else if (Iterable.class.isAssignableFrom(clazz)) // A Non Generic
+																// collection
+
+				h = dch;
+			else if (clazz.isArray()) // Non generic array
+				h = new ArrayHandler(clazz, clazz.getComponentType());
+			else if (Map.class.isAssignableFrom(clazz)) // A Non Generic map
+				h = new MapHandler(clazz, Object.class, Object.class);
+			else if (Number.class.isAssignableFrom(clazz) || clazz.isPrimitive())
+				h = new NumberHandler(clazz);
+			else {
+				Method valueOf = null;
+				Constructor< ? > constructor = null;
+
+				try {
+					constructor = clazz.getConstructor(String.class);
+				}
+				catch (Exception e) {
+					// Ignore
+				}
+				try {
+					valueOf = clazz.getMethod("valueOf", String.class);
+				}
+				catch (Exception e) {
+					// Ignore
+				}
+				if (constructor != null || valueOf != null)
+					h = new SpecialHandler(clazz, constructor, valueOf);
+				else
+					h = new ObjectHandler(this, clazz); // Hmm, might not be a
+														// data class ...
+			}
+
+		} else {
+
+			// We have generic information available
+			// We only support generics on Collection, Map, and arrays
+
+			if (type instanceof ParameterizedType) {
+				ParameterizedType pt = (ParameterizedType) type;
+				Type rawType = pt.getRawType();
+				if (rawType instanceof Class) {
+					Class< ? > rawClass = (Class< ? >) rawType;
+					if (Iterable.class.isAssignableFrom(rawClass))
+						h = new CollectionHandler(rawClass, pt.getActualTypeArguments()[0]);
+					else if (Map.class.isAssignableFrom(rawClass))
+						h = new MapHandler(rawClass, pt.getActualTypeArguments()[0], pt.getActualTypeArguments()[1]);
+					else if (Dictionary.class.isAssignableFrom(rawClass))
+						h = new MapHandler(Hashtable.class, pt.getActualTypeArguments()[0],
+								pt.getActualTypeArguments()[1]);
+					else
+						throw new IllegalArgumentException("Found a parameterized type that is not a map or collection");
+				}
+			} else if (type instanceof GenericArrayType) {
+				GenericArrayType gat = (GenericArrayType) type;
+				h = new ArrayHandler(getRawClass(type), gat.getGenericComponentType());
+			} else
+				throw new IllegalArgumentException("Found a parameterized type that is not a map or collection");
+		}
+		synchronized (handlers) {
+			// We might actually have duplicates
+			// but who cares? They should be identical
+			handlers.put(type, h);
+		}
+		return h;
+	}
+
+	Object decode(Type type, Decoder isr) throws Exception {
+		int c = isr.skipWs();
+		Handler h;
+
+		if (type == null || type == Object.class) {
+
+			// Establish default behavior when we run without
+			// type information
+
+			switch (c) {
+				case '{' :
+					type = LinkedHashMap.class;
+					break;
+
+				case '[' :
+					type = ArrayList.class;
+					break;
+
+				case '"' :
+					return parseString(isr);
+
+				case 'n' :
+					isr.expect("ull");
+					return null;
+
+				case 't' :
+					isr.expect("rue");
+					return true;
+
+				case 'f' :
+					isr.expect("alse");
+					return false;
+
+				case '0' :
+				case '1' :
+				case '2' :
+				case '3' :
+				case '4' :
+				case '5' :
+				case '6' :
+				case '7' :
+				case '8' :
+				case '9' :
+				case '-' :
+					return parseNumber(isr);
+
+				default :
+					throw new IllegalArgumentException("Invalid character at begin of token: " + (char) c);
+			}
+		}
+
+		h = getHandler(type);
+
+		switch (c) {
+			case '{' :
+				return h.decodeObject(isr);
+
+			case '[' :
+				return h.decodeArray(isr);
+
+			case '"' :
+				return h.decode(isr, parseString(isr));
+
+			case 'n' :
+				isr.expect("ull");
+				return h.decode(isr);
+
+			case 't' :
+				isr.expect("rue");
+				return h.decode(isr,Boolean.TRUE);
+
+			case 'f' :
+				isr.expect("alse");
+				return h.decode(isr,Boolean.FALSE);
+
+			case '0' :
+			case '1' :
+			case '2' :
+			case '3' :
+			case '4' :
+			case '5' :
+			case '6' :
+			case '7' :
+			case '8' :
+			case '9' :
+			case '-' :
+				return h.decode(isr,parseNumber(isr));
+
+			default :
+				throw new IllegalArgumentException("Unexpected character in input stream: " + (char) c);
+		}
+	}
+
+	String parseString(Decoder r) throws Exception {
+		assert r.current() == '"';
+
+		int c = r.next(); // skip first "
+
+		StringBuilder sb = new StringBuilder();
+		while (c != '"') {
+			if (c < 0 || Character.isISOControl(c))
+				throw new IllegalArgumentException("JSON strings may not contain control characters: " + r.current());
+
+			if (c == '\\') {
+				c = r.read();
+				switch (c) {
+					case '"' :
+					case '\\' :
+					case '/' :
+						sb.append((char) c);
+						break;
+
+					case 'b' :
+						sb.append('\b');
+						break;
+
+					case 'f' :
+						sb.append('\f');
+						break;
+					case 'n' :
+						sb.append('\n');
+						break;
+					case 'r' :
+						sb.append('\r');
+						break;
+					case 't' :
+						sb.append('\t');
+						break;
+					case 'u' :
+						int a3 = hexDigit(r.read()) << 12;
+						int a2 = hexDigit(r.read()) << 8;
+						int a1 = hexDigit(r.read()) << 4;
+						int a0 = hexDigit(r.read()) << 0;
+						c = a3 + a2 + a1 + a0;
+						sb.append((char) c);
+						break;
+
+					default :
+						throw new IllegalArgumentException(
+								"The only characters after a backslash are \", \\, b, f, n, r, t, and u but got " + c);
+				}
+			} else
+				sb.append((char) c);
+
+			c = r.read();
+		}
+		assert c == '"';
+		r.read(); // skip quote
+		return sb.toString();
+	}
+
+	private int hexDigit(int c) throws EOFException {
+		if (c >= '0' && c <= '9')
+			return c - '0';
+
+		if (c >= 'A' && c <= 'F')
+			return c - 'A' + 10;
+
+		if (c >= 'a' && c <= 'f')
+			return c - 'a' + 10;
+
+		throw new IllegalArgumentException("Invalid hex character: " + c);
+	}
+
+	private Number parseNumber(Decoder r) throws Exception {
+		StringBuilder sb = new StringBuilder();
+		boolean d = false;
+
+		if (r.current() == '-') {
+			sb.append('-');
+			r.read();
+		}
+
+		int c = r.current();
+		if (c == '0') {
+			sb.append('0');
+			c = r.read();
+		} else if (c >= '1' && c <= '9') {
+			sb.append((char) c);
+			c = r.read();
+
+			while (c >= '0' && c <= '9') {
+				sb.append((char) c);
+				c = r.read();
+			}
+		} else
+			throw new IllegalArgumentException("Expected digit");
+
+		if (c == '.') {
+			d = true;
+			sb.append('.');
+			c = r.read();
+			while (c >= '0' && c <= '9') {
+				sb.append((char) c);
+				c = r.read();
+			}
+		}
+		if (c == 'e' || c == 'E') {
+			d = true;
+			sb.append('e');
+			c = r.read();
+			if (c == '+') {
+				sb.append('+');
+				c = r.read();
+			} else if (c == '-') {
+				sb.append('-');
+				c = r.read();
+			}
+			while (c >= '0' && c <= '9') {
+				sb.append((char) c);
+				c = r.read();
+			}
+		}
+		if (d)
+			return Double.parseDouble(sb.toString());
+		long l = Long.parseLong(sb.toString());
+		if (l > Integer.MAX_VALUE || l < Integer.MIN_VALUE)
+			return l;
+		return (int) l;
+	}
+
+	void parseArray(Collection<Object> list, Type componentType, Decoder r) throws Exception {
+		assert r.current() == '[';
+		int c = r.next();
+		while (START_CHARACTERS.indexOf(c) >= 0) {
+			Object o = decode(componentType, r);
+			list.add(o);
+
+			c = r.skipWs();
+			if (c == ']')
+				break;
+
+			if (c == ',') {
+				c = r.next();
+				continue;
+			}
+
+			throw new IllegalArgumentException("Invalid character in parsing list, expected ] or , but found "
+					+ (char) c);
+		}
+		assert r.current() == ']';
+		r.read(); // skip closing
+	}
+
+	@SuppressWarnings("rawtypes")
+	Class< ? > getRawClass(Type type) {
+		if (type instanceof Class)
+			return (Class) type;
+
+		if (type instanceof ParameterizedType)
+			return getRawClass(((ParameterizedType) type).getRawType());
+
+		if (type instanceof GenericArrayType) {
+			Type subType = ((GenericArrayType) type).getGenericComponentType();
+			Class c = getRawClass(subType);
+			return Array.newInstance(c, 0).getClass();
+		}
+
+		throw new IllegalArgumentException(
+				"Does not support generics beyond Parameterized Type  and GenericArrayType, got " + type);
+	}
+
+	/**
+	 * Ignore null values in output and input
+	 * 
+	 * @param ignorenull
+	 * @return
+	 */
+	public JSONCodec setIgnorenull(boolean ignorenull) {
+		this.ignorenull = ignorenull;
+		return this;
+	}
+
+	public boolean isIgnorenull() {
+		return ignorenull;
+	}
+
+}
\ No newline at end of file
diff --git a/aQute.libg/src/aQute/lib/json/MapHandler.java b/aQute.libg/src/aQute/lib/json/MapHandler.java
new file mode 100644
index 0000000..504bb07
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/json/MapHandler.java
@@ -0,0 +1,95 @@
+package aQute.lib.json;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+public class MapHandler extends Handler {
+	final Class< ? >	rawClass;
+	final Type			keyType;
+	final Type			valueType;
+
+	MapHandler(Class< ? > rawClass, Type keyType, Type valueType) {
+		this.keyType = keyType;
+		this.valueType = valueType;
+		if (rawClass.isInterface()) {
+			if (rawClass.isAssignableFrom(HashMap.class))
+				rawClass = HashMap.class;
+			else if (rawClass.isAssignableFrom(TreeMap.class))
+				rawClass = TreeMap.class;
+			else if (rawClass.isAssignableFrom(Hashtable.class))
+				rawClass = Hashtable.class;
+			else if (rawClass.isAssignableFrom(LinkedHashMap.class))
+				rawClass = LinkedHashMap.class;
+			else if (rawClass.isAssignableFrom(Dictionary.class))
+				rawClass = Hashtable.class;
+			else
+				throw new IllegalArgumentException("Unknown map interface: " + rawClass);
+		}
+		this.rawClass = rawClass;
+	}
+
+	@Override
+	void encode(Encoder app, Object object, Map<Object,Type> visited) throws IOException, Exception {
+		Map< ? , ? > map = (Map< ? , ? >) object;
+
+		app.append("{");
+		String del = "";
+		for (Map.Entry< ? , ? > e : map.entrySet()) {
+			app.append(del);
+			String key;
+			if (e.getKey() != null && (keyType == String.class || keyType == Object.class))
+				key = e.getKey().toString();
+			else {
+				key = app.codec.enc().put(e.getKey()).toString();
+			}
+			StringHandler.string(app, key);
+			app.append(":");
+			app.encode(e.getValue(), valueType, visited);
+			del = ",";
+		}
+		app.append("}");
+	}
+
+	@Override
+	Object decodeObject(Decoder r) throws Exception {
+		assert r.current() == '{';
+
+		Map<Object,Object> map = (Map<Object,Object>) rawClass.newInstance();
+
+		int c = r.next();
+		while (JSONCodec.START_CHARACTERS.indexOf(c) >= 0) {
+			Object key = r.codec.parseString(r);
+			if (!(keyType == null || keyType == Object.class)) {
+				Handler h = r.codec.getHandler(keyType);
+				key = h.decode(r,(String) key);
+			}
+
+			c = r.skipWs();
+			if (c != ':')
+				throw new IllegalArgumentException("Expected ':' but got " + (char) c);
+
+			c = r.next();
+			Object value = r.codec.decode(valueType, r);
+			if (value != null || !r.codec.ignorenull)
+				map.put(key, value);
+
+			c = r.skipWs();
+
+			if (c == '}')
+				break;
+
+			if (c == ',') {
+				c = r.next();
+				continue;
+			}
+
+			throw new IllegalArgumentException("Invalid character in parsing list, expected } or , but found "
+					+ (char) c);
+		}
+		assert r.current() == '}';
+		r.read(); // skip closing
+		return map;
+	}
+
+}
diff --git a/aQute.libg/src/aQute/lib/json/NumberHandler.java b/aQute.libg/src/aQute/lib/json/NumberHandler.java
new file mode 100644
index 0000000..d8e6160
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/json/NumberHandler.java
@@ -0,0 +1,73 @@
+package aQute.lib.json;
+
+import java.lang.reflect.*;
+import java.math.*;
+import java.util.*;
+
+public class NumberHandler extends Handler {
+	final Class< ? >	type;
+
+	NumberHandler(Class< ? > clazz) {
+		this.type = clazz;
+	}
+
+	@Override
+	void encode(Encoder app, Object object, Map<Object,Type> visited) throws Exception {
+		String s = object.toString();
+		if (s.endsWith(".0"))
+			s = s.substring(0, s.length() - 2);
+
+		app.append(s);
+	}
+
+	@Override
+	Object decode(Decoder dec, boolean s) {
+		return decode(dec,s ? 1d : 0d);
+	}
+
+	@Override
+	Object decode(Decoder dec, String s) {
+		double d = Double.parseDouble(s);
+		return decode(dec, d);
+	}
+
+	@Override
+	Object decode(Decoder dec) {
+		return decode(dec,0d);
+	}
+
+	@Override
+	Object decode(Decoder dec, Number s) {
+		double dd = s.doubleValue();
+
+		if (type == double.class || type == Double.class)
+			return s.doubleValue();
+
+		if ((type == int.class || type == Integer.class) && within(dd, Integer.MIN_VALUE, Integer.MAX_VALUE))
+			return s.intValue();
+
+		if ((type == long.class || type == Long.class) && within(dd, Long.MIN_VALUE, Long.MAX_VALUE))
+			return s.longValue();
+
+		if ((type == byte.class || type == Byte.class) && within(dd, Byte.MIN_VALUE, Byte.MAX_VALUE))
+			return s.byteValue();
+
+		if ((type == short.class || type == Short.class) && within(dd, Short.MIN_VALUE, Short.MAX_VALUE))
+			return s.shortValue();
+
+		if (type == float.class || type == Float.class)
+			return s.floatValue();
+
+		if (type == BigDecimal.class)
+			return BigDecimal.valueOf(dd);
+
+		if (type == BigInteger.class)
+			return BigInteger.valueOf(s.longValue());
+
+		throw new IllegalArgumentException("Unknown number format: " + type);
+	}
+
+	private boolean within(double s, double minValue, double maxValue) {
+		return s >= minValue && s <= maxValue;
+	}
+}
diff --git a/aQute.libg/src/aQute/lib/json/ObjectHandler.java b/aQute.libg/src/aQute/lib/json/ObjectHandler.java
new file mode 100644
index 0000000..604d8bd
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/json/ObjectHandler.java
@@ -0,0 +1,153 @@
+package aQute.lib.json;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+public class ObjectHandler extends Handler {
+	@SuppressWarnings("rawtypes")
+	final Class		rawClass;
+	final Field		fields[];
+	final Type		types[];
+	final Object	defaults[];
+	final Field		extra;
+
+	ObjectHandler(@SuppressWarnings("unused") JSONCodec codec, Class< ? > c) throws Exception {
+		rawClass = c;
+		fields = c.getFields();
+
+		// Sort the fields so the output is canonical
+		Arrays.sort(fields, new Comparator<Field>() {
+			public int compare(Field o1, Field o2) {
+				return o1.getName().compareTo(o2.getName());
+			}
+		});
+
+		types = new Type[fields.length];
+		defaults = new Object[fields.length];
+
+		Field x = null;
+		for (int i = 0; i < fields.length; i++) {
+			if (fields[i].getName().equals("__extra"))
+				x = fields[i];
+			types[i] = fields[i].getGenericType();
+		}
+		if (x != null && Map.class.isAssignableFrom(x.getType()))
+			extra = x;
+		else
+			extra = null;
+
+		try {
+			Object template = c.newInstance();
+
+			for (int i = 0; i < fields.length; i++) {
+				defaults[i] = fields[i].get(template);
+			}
+		}
+		catch (Exception e) {
+			// Ignore
+		}
+	}
+
+	@Override
+	void encode(Encoder app, Object object, Map<Object,Type> visited) throws Exception {
+		app.append("{");
+		app.indent();
+		String del = "";
+		for (int i = 0; i < fields.length; i++) {
+			if (fields[i].getName().startsWith("__"))
+				continue;
+
+			Object value = fields[i].get(object);
+			if (!app.writeDefaults) {
+				if (value == defaults[i])
+					continue;
+
+				if (value != null && value.equals(defaults[i]))
+					continue;
+			}
+
+			app.append(del);
+			StringHandler.string(app, fields[i].getName());
+			app.append(":");
+			app.encode(value, types[i], visited);
+			del = ",";
+		}
+		app.undent();
+		app.append("}");
+	}
+
+	@Override
+	Object decodeObject(Decoder r) throws Exception {
+		assert r.current() == '{';
+		Object targetObject = rawClass.newInstance();
+
+		int c = r.next();
+		while (JSONCodec.START_CHARACTERS.indexOf(c) >= 0) {
+
+			// Get key
+			String key = r.codec.parseString(r);
+
+			// Get separator
+			c = r.skipWs();
+			if (c != ':')
+				throw new IllegalArgumentException("Expected ':' but got " + (char) c);
+
+			c = r.next();
+
+			// Get value
+
+			Field f = getField(key);
+			if (f != null) {
+				// We have a field and thus a type
+				Object value = r.codec.decode(f.getGenericType(), r);
+				if (value != null || !r.codec.ignorenull)
+					f.set(targetObject, value);
+			} else {
+				// No field, but may extra is defined
+				if (extra == null) {
+					if (r.strict)
+						throw new IllegalArgumentException("No such field " + key);
+					Object value = r.codec.decode(null, r);
+					r.getExtra().put(rawClass.getName() + "." + key, value);
+				} else {
+
+					Map<String,Object> map = (Map<String,Object>) extra.get(targetObject);
+					if (map == null) {
+						map = new LinkedHashMap<String,Object>();
+						extra.set(targetObject, map);
+					}
+					Object value = r.codec.decode(null, r);
+					map.put(key, value);
+				}
+			}
+
+			c = r.skipWs();
+
+			if (c == '}')
+				break;
+
+			if (c == ',') {
+				c = r.next();
+				continue;
+			}
+
+			throw new IllegalArgumentException("Invalid character in parsing object, expected } or , but found "
+					+ (char) c);
+		}
+		assert r.current() == '}';
+		r.read(); // skip closing
+		return targetObject;
+	}
+
+	private Field getField(String key) {
+		for (int i = 0; i < fields.length; i++) {
+			int n = key.compareTo(fields[i].getName());
+			if (n == 0)
+				return fields[i];
+			if (n < 0)
+				return null;
+		}
+		return null;
+	}
+
+}
diff --git a/aQute.libg/src/aQute/lib/json/SpecialHandler.java b/aQute.libg/src/aQute/lib/json/SpecialHandler.java
new file mode 100644
index 0000000..36218c8
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/json/SpecialHandler.java
@@ -0,0 +1,41 @@
+package aQute.lib.json;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.text.*;
+import java.util.*;
+import java.util.regex.*;
+
+public class SpecialHandler extends Handler {
+	@SuppressWarnings("rawtypes")
+	final Class						type;
+	final Method					valueOf;
+	final Constructor< ? >			constructor;
+	final static SimpleDateFormat	sdf	= new SimpleDateFormat();
+
+	public SpecialHandler(Class< ? > type, Constructor< ? > constructor, Method valueOf) {
+		this.type = type;
+		this.constructor = constructor;
+		this.valueOf = valueOf;
+	}
+
+	@Override
+	void encode(Encoder app, Object object, Map<Object,Type> visited) throws IOException, Exception {
+		StringHandler.string(app, object.toString());
+	}
+
+	@Override
+	Object decode(Decoder dec, String s) throws Exception {
+		if (type == Pattern.class)
+			return Pattern.compile(s);
+
+		if (constructor != null)
+			return constructor.newInstance(s);
+
+		if (valueOf != null)
+			return valueOf.invoke(null, s);
+
+		throw new IllegalArgumentException("Do not know how to convert a " + type + " from a string");
+	}
+
+}
diff --git a/aQute.libg/src/aQute/lib/json/StringHandler.java b/aQute.libg/src/aQute/lib/json/StringHandler.java
new file mode 100644
index 0000000..47a4eab
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/json/StringHandler.java
@@ -0,0 +1,152 @@
+package aQute.lib.json;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+public class StringHandler extends Handler {
+
+	@Override
+	void encode(Encoder app, Object object, Map<Object,Type> visited) throws IOException {
+		string(app, object.toString());
+	}
+
+	static void string(Appendable app, String s) throws IOException {
+
+		app.append('"');
+		for (int i = 0; i < s.length(); i++) {
+			char c = s.charAt(i);
+			switch (c) {
+				case '"' :
+					app.append("\\\"");
+					break;
+
+				case '\\' :
+					app.append("\\\\");
+					break;
+
+				case '\b' :
+					app.append("\\b");
+					break;
+
+				case '\f' :
+					app.append("\\f");
+					break;
+
+				case '\n' :
+					app.append("\\n");
+					break;
+
+				case '\r' :
+					app.append("\\r");
+					break;
+
+				case '\t' :
+					app.append("\\t");
+					break;
+
+				default :
+					if (Character.isISOControl(c)) {
+						app.append("\\u");
+						app.append("0123456789ABCDEF".charAt(0xF & (c >> 12)));
+						app.append("0123456789ABCDEF".charAt(0xF & (c >> 8)));
+						app.append("0123456789ABCDEF".charAt(0xF & (c >> 4)));
+						app.append("0123456789ABCDEF".charAt(0xF & (c >> 0)));
+					} else
+						app.append(c);
+			}
+		}
+		app.append('"');
+	}
+
+	@Override
+	Object decode(Decoder dec, String s) throws Exception {
+		return s;
+	}
+
+	@Override
+	Object decode(Decoder dec, Number s) {
+		return s.toString();
+	}
+
+	@Override
+	Object decode(Decoder dec, boolean s) {
+		return Boolean.toString(s);
+	}
+
+	@Override
+	Object decode(Decoder dec ) {
+		return null;
+	}
+
+	/**
+	 * An object can be assigned to a string. This means that the stream is
+	 * interpreted as the object but stored in its complete in the string.
+	 */
+	@Override
+	Object decodeObject(Decoder r) throws Exception {
+		return collect(r, '}');
+	}
+
+	/**
+	 * An array can be assigned to a string. This means that the stream is
+	 * interpreted as the array but stored in its complete in the string.
+	 */
+	@Override
+	Object decodeArray(Decoder r) throws Exception {
+		return collect(r, ']');
+	}
+
+	/**
+	 * Gather the input until you find the the closing character making sure
+	 * that new blocks are are take care of.
+	 * <p>
+	 * This method parses the input for a complete block so that it can be
+	 * stored in a string. This allows envelopes.
+	 * 
+	 * @param isr
+	 * @param c
+	 * @return
+	 * @throws Exception
+	 */
+	private Object collect(Decoder isr, @SuppressWarnings("unused") char close) throws Exception {
+		boolean instring = false;
+		int level = 1;
+		StringBuilder sb = new StringBuilder();
+
+		int c = isr.current();
+		while (c > 0 && level > 0) {
+			sb.append((char) c);
+			if (instring)
+				switch (c) {
+					case '"' :
+						instring = true;
+						break;
+
+					case '[' :
+					case '{' :
+						level++;
+						break;
+
+					case ']' :
+					case '}' :
+						level--;
+						break;
+				}
+			else
+				switch (c) {
+					case '"' :
+						instring = false;
+						break;
+
+					case '\\' :
+						sb.append((char) isr.read());
+						break;
+				}
+
+			c = isr.read();
+		}
+		return sb.toString();
+	}
+
+}
diff --git a/aQute.libg/src/aQute/lib/json/packageinfo b/aQute.libg/src/aQute/lib/json/packageinfo
new file mode 100644
index 0000000..63eb236
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/json/packageinfo
@@ -0,0 +1 @@
+version 3.0.0
diff --git a/aQute.libg/src/aQute/lib/justif/Justif.java b/aQute.libg/src/aQute/lib/justif/Justif.java
new file mode 100644
index 0000000..59b100e
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/justif/Justif.java
@@ -0,0 +1,128 @@
+package aQute.lib.justif;
+
+import java.util.*;
+
+public class Justif {
+	final int[]			tabs;
+	final int				width;
+	StringBuilder	sb	= new StringBuilder();
+	Formatter		f	= new Formatter(sb);
+
+	public Justif(int width, int... tabs) {
+		this.tabs = tabs == null || tabs.length == 0 ? new int[] {30,40, 50, 60, 70} : tabs;
+		this.width = width == 0 ? 73 : width;
+	}
+
+	public Justif() {
+		this(0);
+	}
+
+	/**
+	 * Routine to wrap a stringbuffer. Basically adds line endings but has the
+	 * following control characters:
+	 * <ul>
+	 * <li>Space at the beginnng of a line is repeated when wrapped for indent.</li>
+	 * <li>A tab will mark the current position and wrapping will return to that
+	 * position</li>
+	 * <li>A form feed in a tabbed colum will break but stay in the column</li>
+	 * </ul>
+	 * 
+	 * @param sb
+	 */
+	public void wrap(StringBuilder sb) {
+		List<Integer> indents = new ArrayList<Integer>();
+
+		int indent = 0;
+		int linelength = 0;
+		int lastSpace = 0;
+		int r = 0;
+		boolean begin = true;
+
+		while (r < sb.length()) {
+			switch (sb.charAt(r++)) {
+				case '\n' :
+					linelength = 0;
+
+					indent = indents.isEmpty() ? 0 : indents.remove(0);
+					begin = true;
+					lastSpace = 0;
+					break;
+
+				case ' ' :
+					if (begin)
+						indent++;
+					else {
+						while (r < sb.length() && sb.charAt(r) == ' ')
+							sb.delete(r, r + 1);
+					}
+					lastSpace = r - 1;
+					linelength++;
+					break;
+
+				case '\t' :
+					indents.add(indent);
+					indent = linelength;
+					sb.deleteCharAt(--r);
+
+					if (r < sb.length()) {
+						char digit = sb.charAt(r);
+						if (Character.isDigit(digit)) {
+							sb.deleteCharAt(r);
+
+							int column = (digit - '0');
+							if (column < tabs.length)
+								indent = tabs[column];
+							else
+								indent = column * 8;
+
+							int diff = indent - linelength;
+							if (diff > 0) {
+								for (int i = 0; i < diff; i++) {
+									sb.insert(r, ' ');
+								}
+								r += diff;
+								linelength += diff;
+							}
+						}
+					}
+					break;
+
+				case '\f' :
+					sb.setCharAt(r - 1, '\n');
+					for (int i = 0; i < indent; i++) {
+						sb.insert(r, ' ');
+					}
+					r += indent;
+					while (r < sb.length() && sb.charAt(r) == ' ')
+						sb.delete(r, r + 1);
+					linelength = 0;
+					lastSpace = 0;
+					break;
+
+				default :
+					linelength++;
+					begin = false;
+					if (lastSpace != 0 && linelength > width) {
+						sb.setCharAt(lastSpace, '\n');
+						linelength = 0;
+
+						for (int i = 0; i < indent; i++) {
+							sb.insert(lastSpace + 1, ' ');
+							linelength++;
+						}
+						r += indent;
+						lastSpace = 0;
+					}
+			}
+		}
+	}
+
+	public String wrap() {
+		wrap(sb);
+		return sb.toString();
+	}
+	
+	public Formatter formatter() {
+		return f;
+	}
+}
diff --git a/aQute.libg/src/aQute/lib/justif/packageinfo b/aQute.libg/src/aQute/lib/justif/packageinfo
new file mode 100644
index 0000000..9ad81f6
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/justif/packageinfo
@@ -0,0 +1 @@
+version 1.0.0
diff --git a/aQute.libg/src/aQute/lib/putjar/DirectoryInputStream.java b/aQute.libg/src/aQute/lib/putjar/DirectoryInputStream.java
index 5bd8178..8731037 100644
--- a/aQute.libg/src/aQute/lib/putjar/DirectoryInputStream.java
+++ b/aQute.libg/src/aQute/lib/putjar/DirectoryInputStream.java
@@ -6,276 +6,278 @@ import java.util.zip.*;
 import aQute.libg.fileiterator.*;
 
 public class DirectoryInputStream extends InputStream {
-    final File               root;
-    final FileIterator       fi;
-    File                     element;
-    int                      entries   = 0;
-    int                      state     = START;
-    long                     where     = 0;
-
-    final static int         START     = 0;
-    final static int         HEADER    = 1;
-    final static int         DATA      = 2;
-    final static int         DIRECTORY = 4;
-    final static int         EOF       = 5;
-
-    final static InputStream eof       = new ByteArrayInputStream(new byte[0]);
-    ByteArrayOutputStream    directory = new ByteArrayOutputStream();
-    InputStream              current   = eof;
-
-    public DirectoryInputStream(File dir) {
-        root = dir;
-        fi = new FileIterator(dir);
-    }
-
-    @Override
-    public int read() throws IOException {
-        if (fi == null)
-            return -1;
-
-        int c = current.read();
-        if (c < 0) {
-            next();
-            c = current.read();
-        }
-        if (c >= 0)
-            where++;
-
-        return c;
-    }
-
-    void next() throws IOException {
-        switch (state) {
-        case START:
-        case DATA:
-            nextHeader();
-            break;
-
-        case HEADER:
-            if (element.isFile() && element.length() > 0) {
-                current = new FileInputStream(element);
-                state = DATA;
-            } else
-                nextHeader();
-            break;
-
-        case DIRECTORY:
-            state = EOF;
-            current = eof;
-            break;
-
-        case EOF:
-            break;
-        }
-    }
-
-    private void nextHeader() throws IOException {
-        if (fi.hasNext()) {
-            element = fi.next();
-            state = HEADER;
-            current = getHeader(root, element);
-            entries++;
-        } else {
-            current = getDirectory();
-            state = DIRECTORY;
-        }
-    }
-
-    /**
-     * <pre>
-     *     end of central dir signature    4 bytes  (0x06054b50)
-     *         number of this disk             2 bytes
-     *         number of the disk with the
-     *         start of the central directory  2 bytes
-     *         total number of entries in the
-     *         central directory on this disk  2 bytes
-     *         total number of entries in
-     *         the central directory           2 bytes
-     *         size of the central directory   4 bytes
-     *         offset of start of central
-     *         directory with respect to
-     *         the starting disk number        4 bytes
-     *         .ZIP file comment length        2 bytes
-     *         .ZIP file comment       (variable size)
-     * </pre>
-     * 
-     * @return
-     */
-    InputStream getDirectory() throws IOException {
-        long where = this.where;
-        int sizeDirectory = directory.size();
-
-        writeInt(directory, 0x504b0506); // Signature
-        writeShort(directory, 0); // # of disk
-        writeShort(directory, 0); // # of the disk with start of the central
-        // dir
-        writeShort(directory, entries); // # of entries
-        writeInt(directory, sizeDirectory); // Size of central dir
-        writeInt(directory, (int) where);
-        writeShort(directory, 0);
-
-        directory.close();
-
-        byte[] data = directory.toByteArray();
-        return new ByteArrayInputStream(data);
-    }
-
-    private void writeShort(OutputStream out, int v) throws IOException {
-        for (int i = 0; i < 2; i++) {
-            out.write((byte) (v & 0xFF));
-            v = v >> 8;
-        }
-    }
-
-    private void writeInt(OutputStream out, int v) throws IOException {
-        for (int i = 0; i < 4; i++) {
-            out.write((byte) (v & 0xFF));
-            v = v >> 8;
-        }
-    }
-
-    /**
-     * Local file header:
-     * 
-     * <pre>
-     * 
-     *         local file header signature     4 bytes  (0x04034b50)
-     *         version needed to extract       2 bytes
-     *         general purpose bit flag        2 bytes
-     *         compression method              2 bytes
-     *         last mod file time              2 bytes
-     *         last mod file date              2 bytes
-     *         crc-32                          4 bytes
-     *         compressed size                 4 bytes
-     *         uncompressed size               4 bytes
-     *         file name length                2 bytes
-     *         extra field length              2 bytes
-     * 
-     *         file name (variable size)
-     *         extra field (variable size)
-     * 
-     *     central file header signature   4 bytes  (0x02014b50)
-     *         version made by                 2 bytes
-     *         version needed to extract       2 bytes
-     *         general purpose bit flag        2 bytes
-     *         compression method              2 bytes
-     *         last mod file time              2 bytes
-     *         last mod file date              2 bytes
-     *         crc-32                          4 bytes
-     *         compressed size                 4 bytes
-     *         uncompressed size               4 bytes
-     *         file name length                2 bytes
-     *         extra field length              2 bytes
-     *         file comment length             2 bytes
-     *         disk number start               2 bytes
-     *         internal file attributes        2 bytes
-     *         external file attributes        4 bytes
-     *         relative offset of local header 4 bytes
-     * 
-     *         file name (variable size)
-     *         extra field (variable size)
-     *         file comment (variable size)
-     * </pre>
-     * </pre>
-     * 
-     * @param file
-     * @return
-     */
-    private InputStream getHeader(File root, File file) throws IOException {
-        long where = this.where;
-        ByteArrayOutputStream bout = new ByteArrayOutputStream();
-        // Signature
-        writeInt(bout, 0x04034b50);
-        writeInt(directory, 0x504b0102);
-
-        // Version needed to extract
-        writeShort(directory, 0);
-
-        // Version needed to extract
-        writeShort(bout, 10);
-        writeShort(directory, 10);
-
-        // General purpose bit flag (use descriptor)
-        writeShort(bout, 0); // descriptor follows data
-        writeShort(directory, 0); // descriptor follows data
-
-        // Compresson method (stored)
-        writeShort(bout, 0);
-        writeShort(directory, 0);
-
-        // Mod time
-        writeInt(bout, 0);
-        writeInt(directory, 0);
-
-        if (file.isDirectory()) {
-            writeInt(bout, 0); // CRC
-            writeInt(bout, 0); // Compressed size
-            writeInt(bout, 0); // Uncompressed Size
-            writeInt(directory, 0);
-            writeInt(directory, 0);
-            writeInt(directory, 0);
-        } else {
-            CRC32 crc = getCRC(file);
-            writeInt(bout, (int) crc.getValue());
-            writeInt(bout, (int) file.length());
-            writeInt(bout, (int) file.length());
-            writeInt(directory, (int) crc.getValue());
-            writeInt(directory, (int) file.length());
-            writeInt(directory, (int) file.length());
-        }
-
-        String p = getPath(root, file);
-        if (file.isDirectory())
-            p = p + "/";
-        byte[] path = p.getBytes("UTF-8");
-        writeShort(bout, path.length);
-        writeShort(directory, path.length);
-
-        writeShort(bout, 0); // extra length
-        writeShort(directory, 0);
-
-        bout.write(path);
-
-        writeShort(directory, 0); // File comment length
-        writeShort(directory, 0); // disk number start 2 bytes
-        writeShort(directory, 0); // internal file attributes 2 bytes
-        writeInt(directory, 0); // external file attributes 4 bytes
-        writeInt(directory, (int) where); // relative offset of local header 4
-        // bytes
-
-        directory.write(path);
-
-        byte[] bytes = bout.toByteArray();
-        return new ByteArrayInputStream(bytes);
-    }
-
-    private String getPath(File root, File file) {
-        if (file.equals(root))
-            return "";
-
-        String p = getPath(root, file.getParentFile());
-        if (p.length() == 0)
-            p = file.getName();
-        else {
-            p = p + "/" + file.getName();
-        }
-        return p;
-    }
-
-    private CRC32 getCRC(File file) throws IOException {
-        CRC32 crc = new CRC32();
-        FileInputStream in = new FileInputStream(file);
-        try {
-            byte data[] = new byte[10000];
-            int size = in.read(data);
-            while (size > 0) {
-                crc.update(data, 0, size);
-                size = in.read(data);
-            }
-        } finally {
-            in.close();
-        }
-        return crc;
-    }
+	final File					root;
+	final FileIterator			fi;
+	File						element;
+	int							entries		= 0;
+	int							state		= START;
+	long						where		= 0;
+
+	final static int			START		= 0;
+	final static int			HEADER		= 1;
+	final static int			DATA		= 2;
+	final static int			DIRECTORY	= 4;
+	final static int			EOF			= 5;
+
+	final static InputStream	eof			= new ByteArrayInputStream(new byte[0]);
+	ByteArrayOutputStream		directory	= new ByteArrayOutputStream();
+	InputStream					current		= eof;
+
+	public DirectoryInputStream(File dir) {
+		root = dir;
+		fi = new FileIterator(dir);
+	}
+
+	@Override
+	public int read() throws IOException {
+		if (fi == null)
+			return -1;
+
+		int c = current.read();
+		if (c < 0) {
+			next();
+			c = current.read();
+		}
+		if (c >= 0)
+			where++;
+
+		return c;
+	}
+
+	void next() throws IOException {
+		switch (state) {
+			case START :
+			case DATA :
+				nextHeader();
+				break;
+
+			case HEADER :
+				if (element.isFile() && element.length() > 0) {
+					current = new FileInputStream(element);
+					state = DATA;
+				} else
+					nextHeader();
+				break;
+
+			case DIRECTORY :
+				state = EOF;
+				current = eof;
+				break;
+
+			case EOF :
+				break;
+		}
+	}
+
+	private void nextHeader() throws IOException {
+		if (fi.hasNext()) {
+			element = fi.next();
+			state = HEADER;
+			current = getHeader(root, element);
+			entries++;
+		} else {
+			current = getDirectory();
+			state = DIRECTORY;
+		}
+	}
+
+	/**
+	 * <pre>
+	 *     end of central dir signature    4 bytes  (0x06054b50)
+	 *         number of this disk             2 bytes
+	 *         number of the disk with the
+	 *         start of the central directory  2 bytes
+	 *         total number of entries in the
+	 *         central directory on this disk  2 bytes
+	 *         total number of entries in
+	 *         the central directory           2 bytes
+	 *         size of the central directory   4 bytes
+	 *         offset of start of central
+	 *         directory with respect to
+	 *         the starting disk number        4 bytes
+	 *         .ZIP file comment length        2 bytes
+	 *         .ZIP file comment       (variable size)
+	 * </pre>
+	 * 
+	 * @return
+	 */
+	InputStream getDirectory() throws IOException {
+		long where = this.where;
+		int sizeDirectory = directory.size();
+
+		writeInt(directory, 0x504b0506); // Signature
+		writeShort(directory, 0); // # of disk
+		writeShort(directory, 0); // # of the disk with start of the central
+		// dir
+		writeShort(directory, entries); // # of entries
+		writeInt(directory, sizeDirectory); // Size of central dir
+		writeInt(directory, (int) where);
+		writeShort(directory, 0);
+
+		directory.close();
+
+		byte[] data = directory.toByteArray();
+		return new ByteArrayInputStream(data);
+	}
+
+	private void writeShort(OutputStream out, int v) throws IOException {
+		for (int i = 0; i < 2; i++) {
+			out.write((byte) (v & 0xFF));
+			v = v >> 8;
+		}
+	}
+
+	private void writeInt(OutputStream out, int v) throws IOException {
+		for (int i = 0; i < 4; i++) {
+			out.write((byte) (v & 0xFF));
+			v = v >> 8;
+		}
+	}
+
+	/**
+	 * Local file header:
+	 * 
+	 * <pre>
+	 * 
+	 *         local file header signature     4 bytes  (0x04034b50)
+	 *         version needed to extract       2 bytes
+	 *         general purpose bit flag        2 bytes
+	 *         compression method              2 bytes
+	 *         last mod file time              2 bytes
+	 *         last mod file date              2 bytes
+	 *         crc-32                          4 bytes
+	 *         compressed size                 4 bytes
+	 *         uncompressed size               4 bytes
+	 *         file name length                2 bytes
+	 *         extra field length              2 bytes
+	 * 
+	 *         file name (variable size)
+	 *         extra field (variable size)
+	 * 
+	 *     central file header signature   4 bytes  (0x02014b50)
+	 *         version made by                 2 bytes
+	 *         version needed to extract       2 bytes
+	 *         general purpose bit flag        2 bytes
+	 *         compression method              2 bytes
+	 *         last mod file time              2 bytes
+	 *         last mod file date              2 bytes
+	 *         crc-32                          4 bytes
+	 *         compressed size                 4 bytes
+	 *         uncompressed size               4 bytes
+	 *         file name length                2 bytes
+	 *         extra field length              2 bytes
+	 *         file comment length             2 bytes
+	 *         disk number start               2 bytes
+	 *         internal file attributes        2 bytes
+	 *         external file attributes        4 bytes
+	 *         relative offset of local header 4 bytes
+	 * 
+	 *         file name (variable size)
+	 *         extra field (variable size)
+	 *         file comment (variable size)
+	 * </pre>
+	 * 
+	 * </pre>
+	 * 
+	 * @param file
+	 * @return
+	 */
+	private InputStream getHeader(File root, File file) throws IOException {
+		long where = this.where;
+		ByteArrayOutputStream bout = new ByteArrayOutputStream();
+		// Signature
+		writeInt(bout, 0x04034b50);
+		writeInt(directory, 0x504b0102);
+
+		// Version needed to extract
+		writeShort(directory, 0);
+
+		// Version needed to extract
+		writeShort(bout, 10);
+		writeShort(directory, 10);
+
+		// General purpose bit flag (use descriptor)
+		writeShort(bout, 0); // descriptor follows data
+		writeShort(directory, 0); // descriptor follows data
+
+		// Compresson method (stored)
+		writeShort(bout, 0);
+		writeShort(directory, 0);
+
+		// Mod time
+		writeInt(bout, 0);
+		writeInt(directory, 0);
+
+		if (file.isDirectory()) {
+			writeInt(bout, 0); // CRC
+			writeInt(bout, 0); // Compressed size
+			writeInt(bout, 0); // Uncompressed Size
+			writeInt(directory, 0);
+			writeInt(directory, 0);
+			writeInt(directory, 0);
+		} else {
+			CRC32 crc = getCRC(file);
+			writeInt(bout, (int) crc.getValue());
+			writeInt(bout, (int) file.length());
+			writeInt(bout, (int) file.length());
+			writeInt(directory, (int) crc.getValue());
+			writeInt(directory, (int) file.length());
+			writeInt(directory, (int) file.length());
+		}
+
+		String p = getPath(root, file);
+		if (file.isDirectory())
+			p = p + "/";
+		byte[] path = p.getBytes("UTF-8");
+		writeShort(bout, path.length);
+		writeShort(directory, path.length);
+
+		writeShort(bout, 0); // extra length
+		writeShort(directory, 0);
+
+		bout.write(path);
+
+		writeShort(directory, 0); // File comment length
+		writeShort(directory, 0); // disk number start 2 bytes
+		writeShort(directory, 0); // internal file attributes 2 bytes
+		writeInt(directory, 0); // external file attributes 4 bytes
+		writeInt(directory, (int) where); // relative offset of local header 4
+		// bytes
+
+		directory.write(path);
+
+		byte[] bytes = bout.toByteArray();
+		return new ByteArrayInputStream(bytes);
+	}
+
+	private String getPath(File root, File file) {
+		if (file.equals(root))
+			return "";
+
+		String p = getPath(root, file.getParentFile());
+		if (p.length() == 0)
+			p = file.getName();
+		else {
+			p = p + "/" + file.getName();
+		}
+		return p;
+	}
+
+	private CRC32 getCRC(File file) throws IOException {
+		CRC32 crc = new CRC32();
+		FileInputStream in = new FileInputStream(file);
+		try {
+			byte data[] = new byte[10000];
+			int size = in.read(data);
+			while (size > 0) {
+				crc.update(data, 0, size);
+				size = in.read(data);
+			}
+		}
+		finally {
+			in.close();
+		}
+		return crc;
+	}
 
 }
diff --git a/aQute.libg/src/aQute/lib/settings/Settings.java b/aQute.libg/src/aQute/lib/settings/Settings.java
new file mode 100644
index 0000000..55a149d
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/settings/Settings.java
@@ -0,0 +1,251 @@
+package aQute.lib.settings;
+
+import java.io.*;
+import java.security.*;
+import java.security.spec.*;
+import java.util.*;
+
+import aQute.lib.io.*;
+import aQute.lib.json.*;
+
+/**
+ * Maintains persistent settings for bnd (or other apps). The default is
+ * ~/.bnd/settings.json). The settings are normal string properties but it
+ * specially maintains a public/private key pair and it provides a method to
+ * sign a byte array with this pair.
+ * <p/>
+ * Why not keystore and preferences? Well, keystore is hard to use (you can only
+ * store a private key when you have a certificate, but you cannot create a
+ * certificate without using com.sun classes) and preferences are not editable.
+ */
+public class Settings implements Map<String,String> {
+	static JSONCodec	codec	= new JSONCodec();
+
+	private File		where;
+	private PublicKey	publicKey;
+	private PrivateKey	privateKey;
+	private boolean		loaded;
+	private boolean		dirty;
+
+	public static class Data {
+		public int					version	= 1;
+		public byte[]				secret;
+		public byte[]				id;
+		public Map<String,String>	map		= new HashMap<String,String>();
+	}
+
+	Data	data	= new Data();
+
+	public Settings() {
+		this("~/.bnd/settings.json");
+	}
+
+	public Settings(String where) {
+		assert where != null;
+		this.where = IO.getFile(IO.work, where);
+	}
+
+	public boolean load() {
+		if (this.where.isFile() && this.where.length() > 1) {
+			try {
+				data = codec.dec().from(this.where).get(Data.class);
+				loaded = true;
+				return true;
+			}
+			catch (Exception e) {
+				throw new RuntimeException("Cannot read settings file " + this.where, e);
+			}
+		}
+
+		if (!data.map.containsKey("name"))
+			data.map.put("name", System.getProperty("user.name"));
+		return false;
+	}
+
+	private void check() {
+		if (loaded)
+			return;
+		load();
+		loaded = true;
+	}
+
+	public void save() {
+		if (!this.where.getParentFile().isDirectory() && !this.where.getParentFile().mkdirs())
+			throw new RuntimeException("Cannot create directory in " + this.where.getParent());
+
+		try {
+			codec.enc().to(this.where).put(data).flush();
+			assert this.where.isFile();
+		}
+		catch (Exception e) {
+			throw new RuntimeException("Cannot write settings file " + this.where, e);
+		}
+	}
+
+	public void generate() throws Exception {
+		KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
+		SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
+		keyGen.initialize(1024, random);
+		KeyPair pair = keyGen.generateKeyPair();
+		privateKey = pair.getPrivate();
+		publicKey = pair.getPublic();
+		data.secret = privateKey.getEncoded();
+		data.id = publicKey.getEncoded();
+		save();
+	}
+
+	public String getEmail() {
+		return get("email");
+	}
+
+	public void setEmail(String email) {
+		put("email", email);
+	}
+
+	public void setName(String v) {
+		put("name", v);
+	}
+
+	public String getName() {
+		String name = get("name");
+		if (name != null)
+			return name;
+		return System.getProperty("user.name");
+	}
+
+	/**
+	 * Return an encoded public RSA key. this key can be decoded with an
+	 * X509EncodedKeySpec
+	 * 
+	 * @return an encoded public key.
+	 * @throws Exception
+	 */
+	public byte[] getPublicKey() throws Exception {
+		initKeys();
+		return data.id;
+	}
+
+	/**
+	 * Return an encoded private RSA key. this key can be decoded with an
+	 * PKCS8EncodedKeySpec
+	 * 
+	 * @return an encoded private key.
+	 * @throws Exception
+	 */
+	public byte[] getPrivateKey() throws Exception {
+		initKeys();
+		return data.secret;
+	}
+
+	/*
+	 * Initialize the keys.
+	 */
+	private void initKeys() throws Exception {
+		check();
+		if (publicKey != null)
+			return;
+
+		if (data.id == null || data.secret == null) {
+			generate();
+		} else {
+			PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(data.secret);
+			X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(data.id);
+			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+			privateKey = keyFactory.generatePrivate(privateKeySpec);
+			publicKey = keyFactory.generatePublic(publicKeySpec);
+		}
+	}
+
+	/**
+	 * Sign a byte array
+	 */
+	public byte[] sign(byte[] con) throws Exception {
+		initKeys();
+
+		Signature hmac = Signature.getInstance("SHA1withRSA");
+		hmac.initSign(privateKey);
+		hmac.update(con);
+		return hmac.sign();
+	}
+
+	/**
+	 * Verify a signed byte array
+	 */
+	public boolean verify(byte[] con) throws Exception {
+		initKeys();
+
+		Signature hmac = Signature.getInstance("SHA1withRSA");
+		hmac.initVerify(publicKey);
+		hmac.update(con);
+		return hmac.verify(con);
+	}
+
+	public void clear() {
+		data = new Data();
+		IO.delete(where);
+	}
+
+	public boolean containsKey(Object key) {
+		check();
+		return data.map.containsKey(key);
+	}
+
+	public boolean containsValue(Object value) {
+		check();
+		return data.map.containsValue(value);
+	}
+
+	public Set<java.util.Map.Entry<String,String>> entrySet() {
+		check();
+		return data.map.entrySet();
+	}
+
+	public String get(Object key) {
+		check();
+
+		return data.map.get(key);
+	}
+
+	public boolean isEmpty() {
+		check();
+		return data.map.isEmpty();
+	}
+
+	public Set<String> keySet() {
+		check();
+		return data.map.keySet();
+	}
+
+	public String put(String key, String value) {
+		check();
+		dirty = true;
+		return data.map.put(key, value);
+	}
+
+	public void putAll(Map< ? extends String, ? extends String> v) {
+		check();
+		dirty = true;
+		data.map.putAll(v);
+	}
+
+	public String remove(Object key) {
+		check();
+		dirty = true;
+		return data.map.remove(key);
+	}
+
+	public int size() {
+		check();
+		return data.map.size();
+	}
+
+	public Collection<String> values() {
+		check();
+		return data.map.values();
+	}
+
+	public boolean isDirty() {
+		return dirty;
+	}
+
+}
diff --git a/aQute.libg/src/aQute/lib/settings/packageinfo b/aQute.libg/src/aQute/lib/settings/packageinfo
new file mode 100644
index 0000000..7ae9673
--- /dev/null
+++ b/aQute.libg/src/aQute/lib/settings/packageinfo
@@ -0,0 +1 @@
+version 1.1
\ No newline at end of file
diff --git a/aQute.libg/src/aQute/lib/tag/Tag.java b/aQute.libg/src/aQute/lib/tag/Tag.java
index 8762cce..cc305d8 100755
--- a/aQute.libg/src/aQute/lib/tag/Tag.java
+++ b/aQute.libg/src/aQute/lib/tag/Tag.java
@@ -13,9 +13,9 @@ import java.util.*;
 public class Tag {
 	Tag							parent;													// Parent
 	String						name;														// Name
-	final Map<String, String>	attributes	= new LinkedHashMap<String, String>();
+	final Map<String,String>	attributes	= new LinkedHashMap<String,String>();
 	final List<Object>			content		= new ArrayList<Object>();						// Content
-	static SimpleDateFormat		format		= new SimpleDateFormat("yyyyMMddHHmmss.SSS");
+	SimpleDateFormat			format		= new SimpleDateFormat("yyyyMMddHHmmss.SSS");
 	boolean						cdata;
 
 	/**
@@ -28,19 +28,20 @@ public class Tag {
 	}
 
 	public Tag(Tag parent, String name, Object... contents) {
-		this(name,contents);
+		this(name, contents);
 		parent.addContent(this);
 	}
 
 	/**
 	 * Construct a new Tag with a name.
 	 */
-	public Tag(String name, Map<String, String> attributes, Object... contents) {
-		this(name,contents);
+	public Tag(String name, Map<String,String> attributes, Object... contents) {
+		this(name, contents);
 		this.attributes.putAll(attributes);
 
 	}
-	public Tag(String name, Map<String, String> attributes) {
+
+	public Tag(String name, Map<String,String> attributes) {
 		this(name, attributes, new Object[0]);
 	}
 
@@ -49,11 +50,11 @@ public class Tag {
 	 * are given as ( name, value ) ...
 	 */
 	public Tag(String name, String[] attributes, Object... contents) {
-		this(name,contents);
+		this(name, contents);
 		for (int i = 0; i < attributes.length; i += 2)
 			addAttribute(attributes[i], attributes[i + 1]);
 	}
-	
+
 	public Tag(String name, String[] attributes) {
 		this(name, attributes, new Object[0]);
 	}
@@ -124,7 +125,7 @@ public class Tag {
 	 * Return the attribute value.
 	 */
 	public String getAttribute(String key) {
-		return (String) attributes.get(key);
+		return attributes.get(key);
 	}
 
 	/**
@@ -138,7 +139,7 @@ public class Tag {
 	/**
 	 * Answer the attributes as a Dictionary object.
 	 */
-	public Map<String, String> getAttributes() {
+	public Map<String,String> getAttributes() {
 		return attributes;
 	}
 
@@ -153,6 +154,7 @@ public class Tag {
 	 * Return a string representation of this Tag and all its children
 	 * recursively.
 	 */
+	@Override
 	public String toString() {
 		StringWriter sw = new StringWriter();
 		print(0, new PrintWriter(sw));
@@ -176,15 +178,15 @@ public class Tag {
 	 * Return the whole contents as a String (no tag info and attributes).
 	 */
 	public String getContentsAsString() {
-		StringBuffer sb = new StringBuffer();
+		StringBuilder sb = new StringBuilder();
 		getContentsAsString(sb);
 		return sb.toString();
 	}
 
 	/**
-	 * convenient method to get the contents in a StringBuffer.
+	 * convenient method to get the contents in a StringBuilder.
 	 */
-	public void getContentsAsString(StringBuffer sb) {
+	public void getContentsAsString(StringBuilder sb) {
 		for (Object o : content) {
 			if (o instanceof Tag)
 				((Tag) o).getContentsAsString(sb);
@@ -206,13 +208,9 @@ public class Tag {
 			String value = escape(attributes.get(key));
 			pw.print(' ');
 			pw.print(key);
-			pw.print("=");
-			String quote = "'";
-			if (value.indexOf(quote) >= 0)
-				quote = "\"";
-			pw.print(quote);
+			pw.print("=\"");
 			pw.print(value);
-			pw.print(quote);
+			pw.print("\"");
 		}
 
 		if (content.size() == 0)
@@ -221,7 +219,14 @@ public class Tag {
 			pw.print('>');
 			for (Object c : content) {
 				if (c instanceof String) {
-					formatted(pw, indent + 2, 60, escape((String) c));
+					if (cdata) {
+						pw.print("<![CDATA[");
+						String s = (String) c;
+						s = s.replaceAll("]]>", "] ]>");
+						pw.print(s);
+						pw.print("]]>");
+					} else
+						formatted(pw, indent + 2, 60, escape((String) c));
 				} else if (c instanceof Tag) {
 					Tag tag = (Tag) c;
 					tag.print(indent + 2, pw);
@@ -252,22 +257,22 @@ public class Tag {
 				pos = 0;
 			}
 			switch (c) {
-			case '<':
-				pw.print("<");
-				pos += 4;
-				break;
-			case '>':
-				pw.print(">");
-				pos += 4;
-				break;
-			case '&':
-				pw.print("&");
-				pos += 5;
-				break;
-			default:
-				pw.print(c);
-				pos++;
-				break;
+				case '<' :
+					pw.print("<");
+					pos += 4;
+					break;
+				case '>' :
+					pw.print(">");
+					pos += 4;
+					break;
+				case '&' :
+					pw.print("&");
+					pos += 5;
+					break;
+				default :
+					pw.print(c);
+					pos++;
+					break;
 			}
 
 		}
@@ -277,22 +282,25 @@ public class Tag {
 	 * Escape a string, do entity conversion.
 	 */
 	String escape(String s) {
-		StringBuffer sb = new StringBuffer();
+		StringBuilder sb = new StringBuilder();
 		for (int i = 0; i < s.length(); i++) {
 			char c = s.charAt(i);
 			switch (c) {
-			case '<':
-				sb.append("<");
-				break;
-			case '>':
-				sb.append(">");
-				break;
-			case '&':
-				sb.append("&");
-				break;
-			default:
-				sb.append(c);
-				break;
+				case '<' :
+					sb.append("<");
+					break;
+				case '>' :
+					sb.append(">");
+					break;
+				case '\"' :
+					sb.append(""");
+					break;
+				case '&' :
+					sb.append("&");
+					break;
+				default :
+					sb.append(c);
+					break;
 			}
 		}
 		return sb.toString();
@@ -382,13 +390,10 @@ public class Tag {
 
 		if (mapping == null) {
 			return tn == sn || (sn != null && sn.equals(tn));
-		} else {
-			String suri = sn == null ? mapping.getAttribute("xmlns") : mapping
-					.getAttribute("xmlns:" + sn);
-			String turi = tn == null ? child.findRecursiveAttribute("xmlns") : child
-					.findRecursiveAttribute("xmlns:" + tn);
-			return turi == suri || (turi != null && suri != null && turi.equals(suri));
 		}
+		String suri = sn == null ? mapping.getAttribute("xmlns") : mapping.getAttribute("xmlns:" + sn);
+		String turi = tn == null ? child.findRecursiveAttribute("xmlns") : child.findRecursiveAttribute("xmlns:" + tn);
+		return ((turi == null) && (suri == null)) || ((turi != null) && turi.equals(suri));
 	}
 
 	public String getString(String path) {
@@ -405,7 +410,7 @@ public class Tag {
 				path = "";
 		}
 		Collection<Tag> tags = select(path);
-		StringBuffer sb = new StringBuffer();
+		StringBuilder sb = new StringBuilder();
 		for (Tag tag : tags) {
 			if (attribute == null)
 				tag.getContentsAsString(sb);
@@ -416,7 +421,7 @@ public class Tag {
 	}
 
 	public String getStringContent() {
-		StringBuffer sb = new StringBuffer();
+		StringBuilder sb = new StringBuilder();
 		for (Object c : content) {
 			if (!(c instanceof Tag))
 				sb.append(c);
@@ -433,8 +438,8 @@ public class Tag {
 		if (index > 0) {
 			String ns = name.substring(0, index);
 			return findRecursiveAttribute("xmlns:" + ns);
-		} else
-			return findRecursiveAttribute("xmlns");
+		}
+		return findRecursiveAttribute("xmlns");
 	}
 
 	public String findRecursiveAttribute(String name) {
diff --git a/aQute.libg/src/aQute/libg/asn1/BER.java b/aQute.libg/src/aQute/libg/asn1/BER.java
index 3bc7f4c..bde15aa 100644
--- a/aQute.libg/src/aQute/libg/asn1/BER.java
+++ b/aQute.libg/src/aQute/libg/asn1/BER.java
@@ -5,469 +5,463 @@ import java.text.*;
 import java.util.*;
 
 public class BER implements Types {
-    final DataInputStream xin;
-    long                  position;
-
-    public BER(InputStream in) {
-        this.xin = new DataInputStream(in);
-    }
-
-    public void dump(PrintStream out) throws Exception {
-        int type = readByte();
-        long length = readLength();
-        if (type == -1 || length == -1)
-            throw new EOFException("Empty file");
-        dump(out, type, length, "");
-    }
-
-    void dump(PrintStream out, int type, long length, String indent)
-            throws Exception {
-        int clss = type >> 6;
-        int nmbr = type & 0x1F;
-        boolean cnst = (type & 0x20) != 0;
-
-        String tag = "[" + nmbr + "]";
-        if (clss == 0)
-            tag = TAGS[nmbr];
-
-        if (cnst) {
-            System.out.printf("%5d %s %s %s\n", length, indent, CLASSES[clss],
-                    tag);
-            while (length > 1) {
-                long atStart = getPosition();
-                int t2 = read();
-                long l2 = readLength();
-                dump(out, t2, l2, indent + "  ");
-                length -= getPosition() - atStart;
-            }
-        } else {
-            assert length < Integer.MAX_VALUE;
-            assert length >= 0;
-            byte[] data = new byte[(int) length];
-            readFully(data);
-            String summary;
-
-            switch (nmbr) {
-            case BOOLEAN:
-                assert length == 1;
-                summary = data[0] != 0 ? "true" : "false";
-                break;
-
-            case INTEGER:
-                long n = toLong(data);
-                summary = n + "";
-                break;
-
-            case UTF8_STRING:
-            case IA5STRING:
-            case VISIBLE_STRING:
-            case UNIVERSAL_STRING:
-            case PRINTABLE_STRING:
-            case UTCTIME:
-                summary = new String(data, "UTF-8");
-                break;
-
-            case OBJECT_IDENTIFIER:
-                summary = readOID(data);
-                break;
-
-            case GENERALIZED_TIME:
-            case GRAPHIC_STRING:
-            case GENERAL_STRING:
-            case CHARACTER_STRING:
-
-            case REAL:
-            case EOC:
-            case BIT_STRING:
-            case OCTET_STRING:
-            case NULL:
-            case OBJECT_DESCRIPTOR:
-            case EXTERNAL:
-            case ENUMERATED:
-            case EMBEDDED_PDV:
-            case RELATIVE_OID:
-            case NUMERIC_STRING:
-            case T61_STRING:
-            case VIDEOTEX_STRING:
-            case BMP_STRING:
-            default:
-                StringBuilder sb = new StringBuilder();
-                for (int i = 0; i < 10 && i < data.length; i++) {
-                    sb.append(Integer.toHexString(data[i]));
-                }
-                if (data.length > 10) {
-                    sb.append("...");
-                }
-                summary = sb.toString();
-                break;
-            }
-            out.printf("%5d %s %s %s %s\n", length, indent, CLASSES[clss], tag,
-                    summary);
-        }
-    }
-
-    long toLong(byte[] data) {
-        if (data[0] < 0) {
-            for (int i = 0; i < data.length; i++)
-                data[i] = (byte) (0xFF ^ data[i]);
-
-            return -(toLong(data) + 1);
-        }
-        long n = 0;
-        for (int i = 0; i < data.length; i++) {
-            n = n * 256 + data[i];
-        }
-        return n;
-    }
-
-    /**
-     * 8.1.3.3 For the definite form, the length octets shall consist of one or
-     * more octets, and shall represent the number of octets in the contents
-     * octets using either the short form (see 8.1.3.4) or the long form (see
-     * 8.1.3.5) as a sender's option. NOTE – The short form can only be used if
-     * the number of octets in the contents octets is less than or equal to 127.
-     * 8.1.3.4 In the short form, the length octets shall consist of a single
-     * octet in which bit 8 is zero and bits 7 to 1 encode the number of octets
-     * in the contents octets (which may be zero), as an unsigned binary integer
-     * with bit 7 as the most significant bit. EXAMPLE L = 38 can be encoded as
-     * 001001102 8.1.3.5 In the long form, the length octets shall consist of an
-     * initial octet and one or more subsequent octets. The initial octet shall
-     * be encoded as follows: a) bit 8 shall be one; b) bits 7 to 1 shall encode
-     * the number of subsequent octets in the length octets, as an unsigned
-     * binary integer with bit 7 as the most significant bit; c) the value
-     * 111111112 shall not be used. ISO/IEC 8825-1:2003 (E) NOTE 1 – This
-     * restriction is introduced for possible future extension. Bits 8 to 1 of
-     * the first subsequent octet, followed by bits 8 to 1 of the second
-     * subsequent octet, followed in turn by bits 8 to 1 of each further octet
-     * up to and including the last subsequent octet, shall be the encoding of
-     * an unsigned binary integer equal to the number of octets in the contents
-     * octets, with bit 8 of the first subsequent octet as the most significant
-     * bit. EXAMPLE L = 201 can be encoded as: 100000012 110010012 NOTE 2 – In
-     * the long form, it is a sender's option whether to use more length octets
-     * than the minimum necessary. 8.1.3.6 For the indefinite form, the length
-     * octets indicate that the contents octets are terminated by
-     * end-of-contents octets (see 8.1.5), and shall consist of a single octet.
-     * 8.1.3.6.1 The single octet shall have bit 8 set to one, and bits 7 to 1
-     * set to zero. 8.1.3.6.2 If this form of length is used, then
-     * end-of-contents octets (see 8.1.5) shall be present in the encoding
-     * following the contents octets. 8.1.4 Contents octets The contents octets
-     * shall consist of zero, one or more octets, and shall encode the data
-     * value as specified in subsequent clauses. NOTE – The contents octets
-     * depend on the type of the data value; subsequent clauses follow the same
-     * sequence as the definition of types in ASN.1. 8.1.5 End-of-contents
-     * octets The end-of-contents octets shall be present if the length is
-     * encoded as specified in 8.1.3.6, otherwise they shall not be present. The
-     * end-of-contents octets shall consist of two zero octets. NOTE – The
-     * end-of-contents octets can be considered as the encoding of a value whose
-     * tag is universal class, whose form is primitive, whose number of the tag
-     * is zero, and whose contents are absent, thus:
-     * 
-     * End-of-contents Length Contents 0016 0016 Absent
-     * 
-     * @return
-     */
-    private long readLength() throws IOException {
-        long n = readByte();
-        if (n > 0) {
-            // short form
-            return n;
-        } else {
-            // long form
-            int count = (int) (n & 0x7F);
-            if (count == 0) {
-                // indefinite form
-                return 0;
-            } else {
-                n = 0;
-                while (count-- > 0) {
-                    n = n * 256 + read();
-                }
-                return n;
-            }
-        }
-    }
-
-    private int readByte() throws IOException {
-        position++;
-        return xin.readByte();
-    }
-
-    private void readFully(byte[] data) throws IOException {
-        position += data.length;
-        xin.readFully(data);
-    }
-
-    private long getPosition() {
-        return position;
-    }
-
-    private int read() throws IOException {
-        position++;
-        return xin.read();
-    }
-
-    String readOID(byte[] data) {
-        StringBuilder sb = new StringBuilder();
-        sb.append((0xFF & data[0]) / 40);
-        sb.append(".");
-        sb.append((0xFF & data[0]) % 40);
-
-        int i = 0;
-        while (++i < data.length) {
-            int n = 0;
-            while (data[i] < 0) {
-                n = n * 128 + (0x7F & data[i]);
-                i++;
-            }
-            n = n * 128 + data[i];
-            sb.append(".");
-            sb.append(n);
-        }
-
-        return sb.toString();
-    }
-
-    int getPayloadLength(PDU pdu) throws Exception {
-        switch (pdu.getTag() & 0x1F) {
-        case EOC:
-            return 1;
-
-        case BOOLEAN:
-            return 1;
-
-        case INTEGER:
-            return size(pdu.getInt());
-
-        case UTF8_STRING:
-            String s = pdu.getString();
-            byte[] encoded = s.getBytes("UTF-8");
-            return encoded.length;
-
-        case IA5STRING:
-        case VISIBLE_STRING:
-        case UNIVERSAL_STRING:
-        case PRINTABLE_STRING:
-        case GENERALIZED_TIME:
-        case GRAPHIC_STRING:
-        case GENERAL_STRING:
-        case CHARACTER_STRING:
-        case UTCTIME:
-        case NUMERIC_STRING: {
-            String str = pdu.getString();
-            encoded = str.getBytes("ASCII");
-            return encoded.length;
-        }
-
-        case OBJECT_IDENTIFIER:
-        case REAL:
-        case BIT_STRING:
-            return pdu.getBytes().length;
-
-        case OCTET_STRING:
-        case NULL:
-        case OBJECT_DESCRIPTOR:
-        case EXTERNAL:
-        case ENUMERATED:
-        case EMBEDDED_PDV:
-        case RELATIVE_OID:
-        case T61_STRING:
-        case VIDEOTEX_STRING:
-        case BMP_STRING:
-            return pdu.getBytes().length;
-
-        default:
-            throw new IllegalArgumentException("Invalid type: " + pdu);
-        }
-    }
-
-    int size(long value) {
-        if (value < 128)
-            return 1;
-
-        if (value <= 0xFF)
-            return 2;
-
-        if (value <= 0xFFFF)
-            return 3;
-
-        if (value <= 0xFFFFFF)
-            return 4;
-
-        if (value <= 0xFFFFFFFF)
-            return 5;
-
-        if (value <= 0xFFFFFFFFFFL)
-            return 6;
-
-        if (value <= 0xFFFFFFFFFFFFL)
-            return 7;
-
-        if (value <= 0xFFFFFFFFFFFFFFL)
-            return 8;
-
-        if (value <= 0xFFFFFFFFFFFFFFFFL)
-            return 9;
-
-        throw new IllegalArgumentException("length too long");
-    }
-
-    public void write(OutputStream out, PDU pdu) throws Exception {
-        byte id = 0;
-
-        switch (pdu.getClss()) {
-        case UNIVERSAL:
-            id |= 0;
-            break;
-        case APPLICATION:
-            id |= 0x40;
-            break;
-        case CONTEXT:
-            id |= 0x80;
-            break;
-        case PRIVATE:
-            id |= 0xC0;
-            break;
-        }
-
-        if (pdu.isConstructed())
-            id |= 0x20;
-
-        int tag = pdu.getTag();
-        if (tag >= 0 && tag < 31) {
-            id |= tag;
-        } else {
-            throw new UnsupportedOperationException("Cant do tags > 30");
-        }
-
-        out.write(id);
-
-        int length = getPayloadLength(pdu);
-        int size = size(length);
-        if (size == 1) {
-            out.write(length);
-        } else {
-            out.write(size);
-            while (--size >= 0) {
-                byte data = (byte) ((length >> (size * 8)) & 0xFF);
-                out.write(data);
-            }
-        }
-        writePayload(out, pdu);
-    }
-
-    void writePayload(OutputStream out, PDU pdu) throws Exception {
-        switch (pdu.getTag()) {
-        case EOC:
-            out.write(0);
-            break;
-
-        case BOOLEAN:
-            if (pdu.getBoolean())
-                out.write(-1);
-            else
-                out.write(0);
-            break;
-
-        case ENUMERATED:
-        case INTEGER: {
-            long value = pdu.getInt();
-            int size = size(value);
-            for (int i = size; i >= 0; i--) {
-                byte b = (byte) ((value >> (i * 8)) & 0xFF);
-                out.write(b);
-            }
-        }
-
-        case BIT_STRING: {
-            byte bytes[] = pdu.getBytes();
-            int unused = bytes[0];
-            assert unused <= 7;
-            int[] mask = { 0xFF, 0x7F, 0x3F, 0x1F, 0xF, 0x7, 0x3, 0x1 };
-            bytes[bytes.length - 1] &= (byte) mask[unused];
-            out.write(bytes);
-            break;
-        }
-
-        case RELATIVE_OID:
-        case OBJECT_IDENTIFIER: {
-            int[] oid = pdu.getOID();
-            assert oid.length > 2;
-            assert oid[0] < 4;
-            assert oid[1] < 40;
-            byte top = (byte) (oid[0] * 40 + oid[1]);
-            out.write(top);
-            for (int i = 2; i < oid.length; i++) {
-                putOid(out,oid[i]);
-            }
-            break;
-        }
-
-        case OCTET_STRING: {
-            byte bytes[] = pdu.getBytes();
-            out.write(bytes);
-            break;
-        }
-
-        case NULL:
-            break;
-
-        case BMP_STRING:
-        case GRAPHIC_STRING:
-        case VISIBLE_STRING:
-        case GENERAL_STRING:
-        case UNIVERSAL_STRING:
-        case CHARACTER_STRING:
-        case NUMERIC_STRING:
-        case PRINTABLE_STRING:
-        case VIDEOTEX_STRING:
-        case T61_STRING:
-        case REAL:
-        case EMBEDDED_PDV:
-        case EXTERNAL:
-            throw new UnsupportedEncodingException("dont know real, embedded PDV or external");
-            
-        case UTF8_STRING: {
-            String s = pdu.getString();
-            byte [] data = s.getBytes("UTF-8");
-            out.write(data);
-            break;
-        }
-        
-        case OBJECT_DESCRIPTOR:
-        case IA5STRING:
-            String s = pdu.getString();
-            byte [] data = s.getBytes("ASCII");
-            out.write(data);
-            break;
-            
-            
-        case SEQUENCE:
-        case SET: {
-            PDU pdus[] = pdu.getChildren();
-            for ( PDU p : pdus ) {
-                write(out, p);
-            }
-        }
-            
-        
-        case UTCTIME:
-        case GENERALIZED_TIME:
-            Date date = pdu.getDate();
-            String ss= df.format(date);
-            byte d[] = ss.getBytes("ASCII");
-            out.write(d);
-            break;
-            
-        }
-    }
-    static DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss\\Z");
-    
-
-    private void putOid(OutputStream out, int i) throws IOException {
-        if (i > 127) {
-            putOid(out, i >> 7);
-            out.write(0x80 + (i & 0x7F));
-        } else
-            out.write(i & 0x7F);
-    }
+	DateFormat				df	= new SimpleDateFormat("yyyyMMddHHmmss\\Z");
+
+	final DataInputStream	xin;
+	long					position;
+
+	public BER(InputStream in) {
+		this.xin = new DataInputStream(in);
+	}
+
+	public void dump(PrintStream out) throws Exception {
+		int type = readByte();
+		long length = readLength();
+		if (type == -1 || length == -1)
+			throw new EOFException("Empty file");
+		dump(out, type, length, "");
+	}
+
+	void dump(PrintStream out, int type, long length, String indent) throws Exception {
+		int clss = type >> 6;
+		int nmbr = type & 0x1F;
+		boolean cnst = (type & 0x20) != 0;
+
+		String tag = "[" + nmbr + "]";
+		if (clss == 0)
+			tag = TAGS[nmbr];
+
+		if (cnst) {
+			System.err.printf("%5d %s %s %s%n", length, indent, CLASSES[clss], tag);
+			while (length > 1) {
+				long atStart = getPosition();
+				int t2 = read();
+				long l2 = readLength();
+				dump(out, t2, l2, indent + "  ");
+				length -= getPosition() - atStart;
+			}
+		} else {
+			assert length < Integer.MAX_VALUE;
+			assert length >= 0;
+			byte[] data = new byte[(int) length];
+			readFully(data);
+			String summary;
+
+			switch (nmbr) {
+				case BOOLEAN :
+					assert length == 1;
+					summary = data[0] != 0 ? "true" : "false";
+					break;
+
+				case INTEGER :
+					long n = toLong(data);
+					summary = n + "";
+					break;
+
+				case UTF8_STRING :
+				case IA5STRING :
+				case VISIBLE_STRING :
+				case UNIVERSAL_STRING :
+				case PRINTABLE_STRING :
+				case UTCTIME :
+					summary = new String(data, "UTF-8");
+					break;
+
+				case OBJECT_IDENTIFIER :
+					summary = readOID(data);
+					break;
+
+				case GENERALIZED_TIME :
+				case GRAPHIC_STRING :
+				case GENERAL_STRING :
+				case CHARACTER_STRING :
+
+				case REAL :
+				case EOC :
+				case BIT_STRING :
+				case OCTET_STRING :
+				case NULL :
+				case OBJECT_DESCRIPTOR :
+				case EXTERNAL :
+				case ENUMERATED :
+				case EMBEDDED_PDV :
+				case RELATIVE_OID :
+				case NUMERIC_STRING :
+				case T61_STRING :
+				case VIDEOTEX_STRING :
+				case BMP_STRING :
+				default :
+					StringBuilder sb = new StringBuilder();
+					for (int i = 0; i < 10 && i < data.length; i++) {
+						sb.append(Integer.toHexString(data[i]));
+					}
+					if (data.length > 10) {
+						sb.append("...");
+					}
+					summary = sb.toString();
+					break;
+			}
+			out.printf("%5d %s %s %s %s\n", length, indent, CLASSES[clss], tag, summary);
+		}
+	}
+
+	long toLong(byte[] data) {
+		if (data[0] < 0) {
+			for (int i = 0; i < data.length; i++)
+				data[i] = (byte) (0xFF ^ data[i]);
+
+			return -(toLong(data) + 1);
+		}
+		long n = 0;
+		for (int i = 0; i < data.length; i++) {
+			n = n * 256 + data[i];
+		}
+		return n;
+	}
+
+	/**
+	 * 8.1.3.3 For the definite form, the length octets shall consist of one or
+	 * more octets, and shall represent the number of octets in the contents
+	 * octets using either the short form (see 8.1.3.4) or the long form (see
+	 * 8.1.3.5) as a sender's option. NOTE – The short form can only be used if
+	 * the number of octets in the contents octets is less than or equal to 127.
+	 * 8.1.3.4 In the short form, the length octets shall consist of a single
+	 * octet in which bit 8 is zero and bits 7 to 1 encode the number of octets
+	 * in the contents octets (which may be zero), as an unsigned binary integer
+	 * with bit 7 as the most significant bit. EXAMPLE L = 38 can be encoded as
+	 * 001001102 8.1.3.5 In the long form, the length octets shall consist of an
+	 * initial octet and one or more subsequent octets. The initial octet shall
+	 * be encoded as follows: a) bit 8 shall be one; b) bits 7 to 1 shall encode
+	 * the number of subsequent octets in the length octets, as an unsigned
+	 * binary integer with bit 7 as the most significant bit; c) the value
+	 * 111111112 shall not be used. ISO/IEC 8825-1:2003 (E) NOTE 1 – This
+	 * restriction is introduced for possible future extension. Bits 8 to 1 of
+	 * the first subsequent octet, followed by bits 8 to 1 of the second
+	 * subsequent octet, followed in turn by bits 8 to 1 of each further octet
+	 * up to and including the last subsequent octet, shall be the encoding of
+	 * an unsigned binary integer equal to the number of octets in the contents
+	 * octets, with bit 8 of the first subsequent octet as the most significant
+	 * bit. EXAMPLE L = 201 can be encoded as: 100000012 110010012 NOTE 2 – In
+	 * the long form, it is a sender's option whether to use more length octets
+	 * than the minimum necessary. 8.1.3.6 For the indefinite form, the length
+	 * octets indicate that the contents octets are terminated by
+	 * end-of-contents octets (see 8.1.5), and shall consist of a single octet.
+	 * 8.1.3.6.1 The single octet shall have bit 8 set to one, and bits 7 to 1
+	 * set to zero. 8.1.3.6.2 If this form of length is used, then
+	 * end-of-contents octets (see 8.1.5) shall be present in the encoding
+	 * following the contents octets. 8.1.4 Contents octets The contents octets
+	 * shall consist of zero, one or more octets, and shall encode the data
+	 * value as specified in subsequent clauses. NOTE – The contents octets
+	 * depend on the type of the data value; subsequent clauses follow the same
+	 * sequence as the definition of types in ASN.1. 8.1.5 End-of-contents
+	 * octets The end-of-contents octets shall be present if the length is
+	 * encoded as specified in 8.1.3.6, otherwise they shall not be present. The
+	 * end-of-contents octets shall consist of two zero octets. NOTE – The
+	 * end-of-contents octets can be considered as the encoding of a value whose
+	 * tag is universal class, whose form is primitive, whose number of the tag
+	 * is zero, and whose contents are absent, thus: End-of-contents Length
+	 * Contents 0016 0016 Absent
+	 * 
+	 * @return
+	 */
+	private long readLength() throws IOException {
+		long n = readByte();
+		if (n > 0) {
+			// short form
+			return n;
+		}
+		// long form
+		int count = (int) (n & 0x7F);
+		if (count == 0) {
+			// indefinite form
+			return 0;
+		}
+		n = 0;
+		while (count-- > 0) {
+			n = n * 256 + read();
+		}
+		return n;
+	}
+
+	private int readByte() throws IOException {
+		position++;
+		return xin.readByte();
+	}
+
+	private void readFully(byte[] data) throws IOException {
+		position += data.length;
+		xin.readFully(data);
+	}
+
+	private long getPosition() {
+		return position;
+	}
+
+	private int read() throws IOException {
+		position++;
+		return xin.read();
+	}
+
+	String readOID(byte[] data) {
+		StringBuilder sb = new StringBuilder();
+		sb.append((0xFF & data[0]) / 40);
+		sb.append(".");
+		sb.append((0xFF & data[0]) % 40);
+
+		int i = 0;
+		while (++i < data.length) {
+			int n = 0;
+			while (data[i] < 0) {
+				n = n * 128 + (0x7F & data[i]);
+				i++;
+			}
+			n = n * 128 + data[i];
+			sb.append(".");
+			sb.append(n);
+		}
+
+		return sb.toString();
+	}
+
+	int getPayloadLength(PDU pdu) throws Exception {
+		switch (pdu.getTag() & 0x1F) {
+			case EOC :
+				return 1;
+
+			case BOOLEAN :
+				return 1;
+
+			case INTEGER :
+				return size(pdu.getInt());
+
+			case UTF8_STRING :
+				String s = pdu.getString();
+				byte[] encoded = s.getBytes("UTF-8");
+				return encoded.length;
+
+			case IA5STRING :
+			case VISIBLE_STRING :
+			case UNIVERSAL_STRING :
+			case PRINTABLE_STRING :
+			case GENERALIZED_TIME :
+			case GRAPHIC_STRING :
+			case GENERAL_STRING :
+			case CHARACTER_STRING :
+			case UTCTIME :
+			case NUMERIC_STRING : {
+				String str = pdu.getString();
+				encoded = str.getBytes("ASCII");
+				return encoded.length;
+			}
+
+			case OBJECT_IDENTIFIER :
+			case REAL :
+			case BIT_STRING :
+				return pdu.getBytes().length;
+
+			case OCTET_STRING :
+			case NULL :
+			case OBJECT_DESCRIPTOR :
+			case EXTERNAL :
+			case ENUMERATED :
+			case EMBEDDED_PDV :
+			case RELATIVE_OID :
+			case T61_STRING :
+			case VIDEOTEX_STRING :
+			case BMP_STRING :
+				return pdu.getBytes().length;
+
+			default :
+				throw new IllegalArgumentException("Invalid type: " + pdu);
+		}
+	}
+
+	int size(long value) {
+		if (value < 128)
+			return 1;
+
+		if (value <= 0xFF)
+			return 2;
+
+		if (value <= 0xFFFF)
+			return 3;
+
+		if (value <= 0xFFFFFF)
+			return 4;
+
+		if (value <= 0xFFFFFFFF)
+			return 5;
+
+		if (value <= 0xFFFFFFFFFFL)
+			return 6;
+
+		if (value <= 0xFFFFFFFFFFFFL)
+			return 7;
+
+		if (value <= 0xFFFFFFFFFFFFFFL)
+			return 8;
+
+		if (value <= 0xFFFFFFFFFFFFFFFFL)
+			return 9;
+
+		throw new IllegalArgumentException("length too long");
+	}
+
+	public void write(OutputStream out, PDU pdu) throws Exception {
+		byte id = 0;
+
+		switch (pdu.getClss()) {
+			case UNIVERSAL :
+				id |= 0;
+				break;
+			case APPLICATION :
+				id |= 0x40;
+				break;
+			case CONTEXT :
+				id |= 0x80;
+				break;
+			case PRIVATE :
+				id |= 0xC0;
+				break;
+		}
+
+		if (pdu.isConstructed())
+			id |= 0x20;
+
+		int tag = pdu.getTag();
+		if (tag >= 0 && tag < 31) {
+			id |= tag;
+		} else {
+			throw new UnsupportedOperationException("Cant do tags > 30");
+		}
+
+		out.write(id);
+
+		int length = getPayloadLength(pdu);
+		int size = size(length);
+		if (size == 1) {
+			out.write(length);
+		} else {
+			out.write(size);
+			while (--size >= 0) {
+				byte data = (byte) ((length >> (size * 8)) & 0xFF);
+				out.write(data);
+			}
+		}
+		writePayload(out, pdu);
+	}
+
+	void writePayload(OutputStream out, PDU pdu) throws Exception {
+		switch (pdu.getTag()) {
+			case EOC :
+				out.write(0);
+				break;
+
+			case BOOLEAN :
+				if (pdu.getBoolean())
+					out.write(-1);
+				else
+					out.write(0);
+				break;
+
+			case ENUMERATED :
+			case INTEGER : {
+				long value = pdu.getInt();
+				int size = size(value);
+				for (int i = size; i >= 0; i--) {
+					byte b = (byte) ((value >> (i * 8)) & 0xFF);
+					out.write(b);
+				}
+			}
+
+			case BIT_STRING : {
+				byte bytes[] = pdu.getBytes();
+				int unused = bytes[0];
+				assert unused <= 7;
+				int[] mask = {
+						0xFF, 0x7F, 0x3F, 0x1F, 0xF, 0x7, 0x3, 0x1
+				};
+				bytes[bytes.length - 1] &= (byte) mask[unused];
+				out.write(bytes);
+				break;
+			}
+
+			case RELATIVE_OID :
+			case OBJECT_IDENTIFIER : {
+				int[] oid = pdu.getOID();
+				assert oid.length > 2;
+				assert oid[0] < 4;
+				assert oid[1] < 40;
+				byte top = (byte) (oid[0] * 40 + oid[1]);
+				out.write(top);
+				for (int i = 2; i < oid.length; i++) {
+					putOid(out, oid[i]);
+				}
+				break;
+			}
+
+			case OCTET_STRING : {
+				byte bytes[] = pdu.getBytes();
+				out.write(bytes);
+				break;
+			}
+
+			case NULL :
+				break;
+
+			case BMP_STRING :
+			case GRAPHIC_STRING :
+			case VISIBLE_STRING :
+			case GENERAL_STRING :
+			case UNIVERSAL_STRING :
+			case CHARACTER_STRING :
+			case NUMERIC_STRING :
+			case PRINTABLE_STRING :
+			case VIDEOTEX_STRING :
+			case T61_STRING :
+			case REAL :
+			case EMBEDDED_PDV :
+			case EXTERNAL :
+				throw new UnsupportedEncodingException("dont know real, embedded PDV or external");
+
+			case UTF8_STRING : {
+				String s = pdu.getString();
+				byte[] data = s.getBytes("UTF-8");
+				out.write(data);
+				break;
+			}
+
+			case OBJECT_DESCRIPTOR :
+			case IA5STRING :
+				String s = pdu.getString();
+				byte[] data = s.getBytes("ASCII");
+				out.write(data);
+				break;
+
+			case SEQUENCE :
+			case SET : {
+				PDU pdus[] = pdu.getChildren();
+				for (PDU p : pdus) {
+					write(out, p);
+				}
+			}
+
+			case UTCTIME :
+			case GENERALIZED_TIME :
+				Date date = pdu.getDate();
+				String ss = df.format(date);
+				byte d[] = ss.getBytes("ASCII");
+				out.write(d);
+				break;
+
+		}
+	}
+
+	private void putOid(OutputStream out, int i) throws IOException {
+		if (i > 127) {
+			putOid(out, i >> 7);
+			out.write(0x80 + (i & 0x7F));
+		} else
+			out.write(i & 0x7F);
+	}
 }
diff --git a/aQute.libg/src/aQute/libg/asn1/PDU.java b/aQute.libg/src/aQute/libg/asn1/PDU.java
index 033928c..2fb29fb 100644
--- a/aQute.libg/src/aQute/libg/asn1/PDU.java
+++ b/aQute.libg/src/aQute/libg/asn1/PDU.java
@@ -3,112 +3,109 @@ package aQute.libg.asn1;
 import java.util.*;
 
 public class PDU implements Types, Iterable<PDU> {
-    final int identifier;
-    final Object  payload;
-    byte data[] = new byte[100];
-
-
-    public PDU(int id, Object payload) {
-        identifier = id;
-        this.payload = payload;
-    }
-
-    public PDU(Date payload) {
-        identifier = UTCTIME;
-        this.payload = payload;
-    }
-
-    public PDU(int n) {
-        this(UNIVERSAL+INTEGER, n);
-    }
-
-    public PDU(boolean value) {
-        this(UNIVERSAL+BOOLEAN, value);
-    }
-
-    public PDU(String s) throws Exception {
-        this(UNIVERSAL+IA5STRING, s);
-    }
-    
-    public PDU(byte[] data) {
-        this(UNIVERSAL+OCTET_STRING, data);
-    }
-    
-    public PDU(BitSet bits) {
-        this(UNIVERSAL+BIT_STRING, bits);
-    }
-
-    public PDU(int top, int l1, int... remainder) {
-        identifier = UNIVERSAL+OBJECT_IDENTIFIER;
-        int[] ids = new int[remainder.length + 2];
-        ids[0] = top;
-        ids[1] = l1;
-        System.arraycopy(remainder, 0, ids, 2, remainder.length);
-        payload = ids;
-    }
-
-    public PDU(int tag, PDU... set) {
-        this(tag,(Object)set);
-    }
-
-    public PDU(PDU... set) {
-        this(SEQUENCE+CONSTRUCTED,set);
-    }
-
-
-    public int getTag() {
-        return identifier & TAGMASK;
-    }
-
-    int getClss() {
-        return identifier & CLASSMASK;
-    }
-
-    public boolean isConstructed() {
-        return (identifier & CONSTRUCTED) != 0;
-    }
-
-    public String getString() {
-        return (String) payload;
-    }
-
-    public Iterator<PDU> iterator() {
-        return Arrays.asList((PDU[]) payload).iterator();
-    }
-
-    
-    public int[] getOID() {
-        assert getTag() == OBJECT_IDENTIFIER;
-        return (int[]) payload;
-    }
-
-    public Boolean getBoolean() {
-        assert getTag() == BOOLEAN;
-        return (Boolean) payload;
-    }
-
-    public BitSet getBits() {
-        assert getTag() == BIT_STRING;
-        return (BitSet) payload;
-    }
-
-    public int getInt() {
-        assert getTag() == INTEGER || getTag() == ENUMERATED;
-        return (Integer) payload;
-    }
-
-    public byte[] getBytes() {
-        return (byte[]) payload;
-    }
-
-    public PDU[] getChildren() {
-        assert isConstructed();
-        return (PDU[]) payload;
-    }
-
-    public Date getDate() {
-        assert getTag() == UTCTIME || getTag() == GENERALIZED_TIME;
-        return (Date) payload;
-    }
+	final int		identifier;
+	final Object	payload;
+	byte			data[]	= new byte[100];
+
+	public PDU(int id, Object payload) {
+		identifier = id;
+		this.payload = payload;
+	}
+
+	public PDU(Date payload) {
+		identifier = UTCTIME;
+		this.payload = payload;
+	}
+
+	public PDU(int n) {
+		this(UNIVERSAL + INTEGER, n);
+	}
+
+	public PDU(boolean value) {
+		this(UNIVERSAL + BOOLEAN, value);
+	}
+
+	public PDU(String s) throws Exception {
+		this(UNIVERSAL + IA5STRING, s);
+	}
+
+	public PDU(byte[] data) {
+		this(UNIVERSAL + OCTET_STRING, data);
+	}
+
+	public PDU(BitSet bits) {
+		this(UNIVERSAL + BIT_STRING, bits);
+	}
+
+	public PDU(int top, int l1, int... remainder) {
+		identifier = UNIVERSAL + OBJECT_IDENTIFIER;
+		int[] ids = new int[remainder.length + 2];
+		ids[0] = top;
+		ids[1] = l1;
+		System.arraycopy(remainder, 0, ids, 2, remainder.length);
+		payload = ids;
+	}
+
+	public PDU(int tag, PDU... set) {
+		this(tag, (Object) set);
+	}
+
+	public PDU(PDU... set) {
+		this(SEQUENCE + CONSTRUCTED, set);
+	}
+
+	public int getTag() {
+		return identifier & TAGMASK;
+	}
+
+	int getClss() {
+		return identifier & CLASSMASK;
+	}
+
+	public boolean isConstructed() {
+		return (identifier & CONSTRUCTED) != 0;
+	}
+
+	public String getString() {
+		return (String) payload;
+	}
+
+	public Iterator<PDU> iterator() {
+		return Arrays.asList((PDU[]) payload).iterator();
+	}
+
+	public int[] getOID() {
+		assert getTag() == OBJECT_IDENTIFIER;
+		return (int[]) payload;
+	}
+
+	public Boolean getBoolean() {
+		assert getTag() == BOOLEAN;
+		return (Boolean) payload;
+	}
+
+	public BitSet getBits() {
+		assert getTag() == BIT_STRING;
+		return (BitSet) payload;
+	}
+
+	public int getInt() {
+		assert getTag() == INTEGER || getTag() == ENUMERATED;
+		return (Integer) payload;
+	}
+
+	public byte[] getBytes() {
+		return (byte[]) payload;
+	}
+
+	public PDU[] getChildren() {
+		assert isConstructed();
+		return (PDU[]) payload;
+	}
+
+	public Date getDate() {
+		assert getTag() == UTCTIME || getTag() == GENERALIZED_TIME;
+		return (Date) payload;
+	}
 
 }
diff --git a/aQute.libg/src/aQute/libg/asn1/Types.java b/aQute.libg/src/aQute/libg/asn1/Types.java
index 630ed1c..8f189ed 100644
--- a/aQute.libg/src/aQute/libg/asn1/Types.java
+++ b/aQute.libg/src/aQute/libg/asn1/Types.java
@@ -1,65 +1,66 @@
 package aQute.libg.asn1;
 
 public interface Types {
-    int      UNIVERSAL         = 0x00000000;
-    int      APPLICATION       = 0x40000000;
-    int      CONTEXT           = 0x80000000;
-    int      PRIVATE           = 0xC0000000;
-    int      CLASSMASK         = 0xC0000000;
-    int      CONSTRUCTED       = 0x20000000;
-    int      TAGMASK           = 0x1FFFFFFF;
+	int			UNIVERSAL			= 0x00000000;
+	int			APPLICATION			= 0x40000000;
+	int			CONTEXT				= 0x80000000;
+	int			PRIVATE				= 0xC0000000;
+	int			CLASSMASK			= 0xC0000000;
+	int			CONSTRUCTED			= 0x20000000;
+	int			TAGMASK				= 0x1FFFFFFF;
 
-    String [] CLASSES = {"U", "A", "C", "P"};
-    
-    // Payload Primitve
-    int      EOC               = 0;                                // null
-    // x
-    int      BOOLEAN           = 1;                                // Boolean
-    // x
-    int      INTEGER           = 2;                                // Long
-    // x
-    int      BIT_STRING        = 3;                                // byte
-    // [] -
-    int      OCTET_STRING      = 4;                                // byte
-    // [] -
-    int      NULL              = 5;                                // null
-    // x
-    int      OBJECT_IDENTIFIER = 6;                                // int[]
-    // x
-    int      OBJECT_DESCRIPTOR = 7;                                // 
-    int      EXTERNAL          = 8;                                //
-    int      REAL              = 9;                                // double
-    // x
-    int      ENUMERATED        = 10;                               // 
-    int      EMBEDDED_PDV      = 11;                               //
-    int      UTF8_STRING       = 12;                               // String
-    int      RELATIVE_OID      = 13;                               // 
-    int      SEQUENCE          = 16;                               // 
-    int      SET               = 17;
-    int      NUMERIC_STRING    = 18;                               // String
-    int      PRINTABLE_STRING  = 19;                               // String
-    int      T61_STRING        = 20;                               // String
-    int      VIDEOTEX_STRING   = 21;                               // String
-    int      IA5STRING         = 22;                               // String
-    int      UTCTIME           = 23;                               // Date
-    int      GENERALIZED_TIME  = 24;                               // Date
-    int      GRAPHIC_STRING    = 25;                               // String
-    int      VISIBLE_STRING    = 26;                               // String
-    int      GENERAL_STRING    = 27;                               // String
-    int      UNIVERSAL_STRING  = 28;                               // String
-    int      CHARACTER_STRING  = 29;                               // String
-    int      BMP_STRING        = 30;                               // byte[]
+	String[]	CLASSES				= {
+			"U", "A", "C", "P"
+									};
 
-    String[] TAGS              = { "EOC               ",
-            "BOOLEAN           ", "INTEGER           ", "BIT_STRING        ",
-            "OCTET_STRING      ", "NULL              ", "OBJECT_IDENTIFIER ",
-            "OBJECT_DESCRIPTOR ", "EXTERNAL          ", "REAL              ",
-            "ENUMERATED        ", "EMBEDDED_PDV      ", "UTF8_STRING       ",
-            "RELATIVE_OID      ", "?(14)             ", "?(15)             ",
-            "SEQUENCE          ", "SET               ", "NUMERIC_STRING    ",
-            "PRINTABLE_STRING  ", "T61_STRING        ", "VIDEOTEX_STRING   ",
-            "IA5STRING         ", "UTCTIME           ", "GENERALIZED_TIME  ",
-            "GRAPHIC_STRING    ", "VISIBLE_STRING    ", "GENERAL_STRING    ",
-            "UNIVERSAL_STRING  ", "CHARACTER_STRING  ", "BMP_STRING        ", };
+	// Payload Primitve
+	int			EOC					= 0;			// null
+	// x
+	int			BOOLEAN				= 1;			// Boolean
+	// x
+	int			INTEGER				= 2;			// Long
+	// x
+	int			BIT_STRING			= 3;			// byte
+	// [] -
+	int			OCTET_STRING		= 4;			// byte
+	// [] -
+	int			NULL				= 5;			// null
+	// x
+	int			OBJECT_IDENTIFIER	= 6;			// int[]
+	// x
+	int			OBJECT_DESCRIPTOR	= 7;			//
+	int			EXTERNAL			= 8;			//
+	int			REAL				= 9;			// double
+	// x
+	int			ENUMERATED			= 10;			//
+	int			EMBEDDED_PDV		= 11;			//
+	int			UTF8_STRING			= 12;			// String
+	int			RELATIVE_OID		= 13;			//
+	int			SEQUENCE			= 16;			//
+	int			SET					= 17;
+	int			NUMERIC_STRING		= 18;			// String
+	int			PRINTABLE_STRING	= 19;			// String
+	int			T61_STRING			= 20;			// String
+	int			VIDEOTEX_STRING		= 21;			// String
+	int			IA5STRING			= 22;			// String
+	int			UTCTIME				= 23;			// Date
+	int			GENERALIZED_TIME	= 24;			// Date
+	int			GRAPHIC_STRING		= 25;			// String
+	int			VISIBLE_STRING		= 26;			// String
+	int			GENERAL_STRING		= 27;			// String
+	int			UNIVERSAL_STRING	= 28;			// String
+	int			CHARACTER_STRING	= 29;			// String
+	int			BMP_STRING			= 30;			// byte[]
+
+	String[]	TAGS				= {
+			"EOC               ", "BOOLEAN           ", "INTEGER           ", "BIT_STRING        ",
+			"OCTET_STRING      ", "NULL              ", "OBJECT_IDENTIFIER ", "OBJECT_DESCRIPTOR ",
+			"EXTERNAL          ", "REAL              ", "ENUMERATED        ", "EMBEDDED_PDV      ",
+			"UTF8_STRING       ", "RELATIVE_OID      ", "?(14)             ", "?(15)             ",
+			"SEQUENCE          ", "SET               ", "NUMERIC_STRING    ", "PRINTABLE_STRING  ",
+			"T61_STRING        ", "VIDEOTEX_STRING   ", "IA5STRING         ", "UTCTIME           ",
+			"GENERALIZED_TIME  ", "GRAPHIC_STRING    ", "VISIBLE_STRING    ", "GENERAL_STRING    ",
+			"UNIVERSAL_STRING  ", "CHARACTER_STRING  ", "BMP_STRING        ",
+									};
 
 }
diff --git a/aQute.libg/src/aQute/libg/cafs/CAFS.java b/aQute.libg/src/aQute/libg/cafs/CAFS.java
index d747391..c89c5f2 100644
--- a/aQute.libg/src/aQute/libg/cafs/CAFS.java
+++ b/aQute.libg/src/aQute/libg/cafs/CAFS.java
@@ -17,15 +17,14 @@ import aQute.libg.cryptography.*;
  * in the universe has a unique SHA-1. Hard to believe but people smarter than
  * me have come to that conclusion. This class maintains a compressed store of
  * SHA-1 identified files. So if you have the SHA-1, you can get the contents.
- * 
  * This makes it easy to store a SHA-1 instead of the whole file or maintain a
  * naming scheme. An added advantage is that it is always easy to verify you get
  * the right stuff. The SHA-1 Content Addressable File Store is the core
  * underlying idea in Git.
  */
 public class CAFS implements Closeable, Iterable<SHA1> {
-	final static byte[]	CAFS			= "CAFS".getBytes();
-	final static byte[]	CAFE			= "CAFE".getBytes();
+	final static byte[]	CAFS;
+	final static byte[]	CAFE;
 	final static String	INDEXFILE		= "index.idx";
 	final static String	STOREFILE		= "store.cafs";
 	final static String	ALGORITHM		= "SHA-1";
@@ -34,15 +33,24 @@ public class CAFS implements Closeable, Iterable<SHA1> {
 												+ 4 // flags
 												+ 4 // compressed length
 												+ 4 // uncompressed length
-												+ KEYLENGTH	// key
+												+ KEYLENGTH // key
 												+ 2 // header checksum
-												;
+										;
 
 	final File			home;
 	Index				index;
 	RandomAccessFile	store;
 	FileChannel			channel;
 
+	static {
+		try {
+		CAFS = "CAFS".getBytes("UTF-8");
+		CAFE = "CAFE".getBytes("UTF-8");
+		} catch (Throwable e) {
+			throw new ExceptionInInitializerError(e);
+		}
+	}
+
 	/**
 	 * Constructor for a Content Addressable File Store
 	 * 
@@ -54,7 +62,12 @@ public class CAFS implements Closeable, Iterable<SHA1> {
 		this.home = home;
 		if (!home.isDirectory()) {
 			if (create) {
-				home.mkdirs();
+				if (home.exists()) {
+					throw new IOException(home + " is not a directory");
+				}
+				if (!home.mkdirs()) {
+					throw new IOException("Could not create directory " + home);
+				}
 			} else
 				throw new IllegalArgumentException("CAFS requires a directory with create=false");
 		}
@@ -69,9 +82,8 @@ public class CAFS implements Closeable, Iterable<SHA1> {
 					store.writeInt(0);
 				channel.force(true);
 			} else
-				throw new IllegalArgumentException("Invalid store file, length is too short "
-						+ store);
-			System.out.println(store.length());
+				throw new IllegalArgumentException("Invalid store file, length is too short " + store);
+			System.err.println(store.length());
 		}
 		store.seek(0);
 		if (!verifySignature(store, CAFS))
@@ -94,14 +106,14 @@ public class CAFS implements Closeable, Iterable<SHA1> {
 		Deflater deflater = new Deflater();
 		MessageDigest md = MessageDigest.getInstance(ALGORITHM);
 		DigestInputStream din = new DigestInputStream(in, md);
-		DeflaterInputStream dfl = new DeflaterInputStream(din, deflater);
 		ByteArrayOutputStream bout = new ByteArrayOutputStream();
-		copy(dfl, bout);
+		DeflaterOutputStream dout = new DeflaterOutputStream(bout, deflater);
+		copy(din, dout);
 
 		synchronized (store) {
 			// First check if it already exists
 			SHA1 sha1 = new SHA1(md.digest());
-			
+
 			long search = index.search(sha1.digest());
 			if (search > 0)
 				return sha1;
@@ -136,7 +148,8 @@ public class CAFS implements Closeable, Iterable<SHA1> {
 				update(sha1.digest(), compressed, totalLength);
 				index.insert(sha1.digest(), insertPoint);
 				return sha1;
-			} finally {
+			}
+			finally {
 				if (lock != null)
 					lock.release();
 			}
@@ -163,20 +176,20 @@ public class CAFS implements Closeable, Iterable<SHA1> {
 			if (!verifySignature(store, CAFE))
 				throw new IllegalArgumentException("No signature");
 
-			int flags =store.readInt();
+			int flags = store.readInt();
 			int compressedLength = store.readInt();
 			int uncompressedLength = store.readInt();
 			readSha1 = new byte[KEYLENGTH];
 			store.read(readSha1);
 			SHA1 rsha1 = new SHA1(readSha1);
-			
+
 			if (!sha1.equals(rsha1))
 				throw new IOException("SHA1 read and asked mismatch: " + sha1 + " " + rsha1);
 
 			short crc = store.readShort(); // Read CRC
-			if ( crc != checksum(flags,compressedLength, uncompressedLength, readSha1))
+			if (crc != checksum(flags, compressedLength, uncompressedLength, readSha1))
 				throw new IllegalArgumentException("Invalid header checksum: " + sha1);
-			
+
 			buffer = new byte[compressedLength];
 			store.readFully(buffer);
 			return getSha1Stream(sha1, buffer, uncompressedLength);
@@ -192,8 +205,7 @@ public class CAFS implements Closeable, Iterable<SHA1> {
 		synchronized (store) {
 			length = store.length();
 			if (length < 0x100)
-				throw new IllegalArgumentException(
-						"Store file is too small, need to be at least 256 bytes: " + store);
+				throw new IllegalArgumentException("Store file is too small, need to be at least 256 bytes: " + store);
 		}
 
 		RandomAccessFile in = new RandomAccessFile(new File(home, STOREFILE), "r");
@@ -217,9 +229,10 @@ public class CAFS implements Closeable, Iterable<SHA1> {
 				index.close();
 				File indexFile = new File(home, INDEXFILE);
 				ixf.renameTo(indexFile);
-				index = new Index(indexFile, KEYLENGTH);
+				this.index = new Index(indexFile, KEYLENGTH);
 			}
-		} finally {
+		}
+		finally {
 			in.close();
 		}
 	}
@@ -228,7 +241,8 @@ public class CAFS implements Closeable, Iterable<SHA1> {
 		synchronized (store) {
 			try {
 				store.close();
-			} finally {
+			}
+			finally {
 				index.close();
 			}
 		}
@@ -246,7 +260,7 @@ public class CAFS implements Closeable, Iterable<SHA1> {
 		byte[] key = new byte[KEYLENGTH];
 		in.readFully(key);
 		SHA1 sha1 = new SHA1(key);
-		
+
 		byte[] buffer = new byte[compressedSize];
 		in.readFully(buffer);
 
@@ -262,25 +276,26 @@ public class CAFS implements Closeable, Iterable<SHA1> {
 		return Arrays.equals(read, org);
 	}
 
-	private InputStream getSha1Stream(final SHA1 sha1, byte[] buffer, final int total)
-			throws NoSuchAlgorithmException {
+	private InputStream getSha1Stream(final SHA1 sha1, byte[] buffer, final int total) throws NoSuchAlgorithmException {
 		ByteArrayInputStream in = new ByteArrayInputStream(buffer);
 		InflaterInputStream iin = new InflaterInputStream(in) {
-			int count = 0;
-			final MessageDigest digestx = MessageDigest.getInstance(ALGORITHM);
-			final AtomicBoolean calculated = new AtomicBoolean();
-			
-			@Override public int read(byte[] data, int offset, int length) throws IOException {
+			int					count		= 0;
+			final MessageDigest	digestx		= MessageDigest.getInstance(ALGORITHM);
+			final AtomicBoolean	calculated	= new AtomicBoolean();
+
+			@Override
+			public int read(byte[] data, int offset, int length) throws IOException {
 				int size = super.read(data, offset, length);
 				if (size <= 0)
 					eof();
 				else {
-					count+=size;
+					count += size;
 					this.digestx.update(data, offset, size);
 				}
 				return size;
 			}
 
+			@Override
 			public int read() throws IOException {
 				int c = super.read();
 				if (c < 0)
@@ -293,18 +308,20 @@ public class CAFS implements Closeable, Iterable<SHA1> {
 			}
 
 			void eof() throws IOException {
-				if ( calculated.getAndSet(true))
+				if (calculated.getAndSet(true))
 					return;
-				
-				if ( count != total )
-					throw new IOException("Counts do not match. Expected to read: " + total + " Actually read: " + count);
-				
+
+				if (count != total)
+					throw new IOException("Counts do not match. Expected to read: " + total + " Actually read: "
+							+ count);
+
 				SHA1 calculatedSha1 = new SHA1(digestx.digest());
 				if (!sha1.equals(calculatedSha1))
-					throw ( new IOException("SHA1 caclulated and asked mismatch, asked: "
-							+ sha1 + ", \nfound: " +calculatedSha1));
+					throw (new IOException("SHA1 caclulated and asked mismatch, asked: " + sha1 + ", \nfound: "
+							+ calculatedSha1));
 			}
 
+			@Override
 			public void close() throws IOException {
 				eof();
 				super.close();
@@ -327,87 +344,86 @@ public class CAFS implements Closeable, Iterable<SHA1> {
 	 *             The exception
 	 */
 	private void update(byte[] sha1, byte[] compressed, int totalLength) throws IOException {
-		System.out.println("pos: " + store.getFilePointer());
+		// System.err.println("pos: " + store.getFilePointer());
 		store.write(CAFE); // 00-03 Signature
 		store.writeInt(0); // 04-07 Flags for the future
 		store.writeInt(compressed.length); // 08-11 Length deflated data
 		store.writeInt(totalLength); // 12-15 Length
 		store.write(sha1); // 16-35
-		store.writeShort( checksum(0,compressed.length, totalLength, sha1));
+		store.writeShort(checksum(0, compressed.length, totalLength, sha1));
 		store.write(compressed);
 		channel.force(false);
 	}
 
-	
-	
-	private short checksum(int flags, int compressedLength, int totalLength, byte[] sha1) {
+	short checksum(int flags, int compressedLength, int totalLength, byte[] sha1) {
 		CRC32 crc = new CRC32();
 		crc.update(flags);
-		crc.update(flags>>8);
-		crc.update(flags>>16);
-		crc.update(flags>>24);
+		crc.update(flags >> 8);
+		crc.update(flags >> 16);
+		crc.update(flags >> 24);
 		crc.update(compressedLength);
-		crc.update(compressedLength>>8);
-		crc.update(compressedLength>>16);
-		crc.update(compressedLength>>24);
+		crc.update(compressedLength >> 8);
+		crc.update(compressedLength >> 16);
+		crc.update(compressedLength >> 24);
 		crc.update(totalLength);
-		crc.update(totalLength>>8);
-		crc.update(totalLength>>16);
-		crc.update(totalLength>>24);
+		crc.update(totalLength >> 8);
+		crc.update(totalLength >> 16);
+		crc.update(totalLength >> 24);
 		crc.update(sha1);
 		return (short) crc.getValue();
 	}
 
 	public Iterator<SHA1> iterator() {
-		
+
 		return new Iterator<SHA1>() {
-			long position = 0x100;
-			
+			long	position	= 0x100;
+
 			public boolean hasNext() {
-				synchronized(store) {
+				synchronized (store) {
 					try {
 						return position < store.length();
-					} catch (IOException e) {
+					}
+					catch (IOException e) {
 						throw new RuntimeException(e);
 					}
 				}
 			}
 
 			public SHA1 next() {
-				synchronized(store) {
+				synchronized (store) {
 					try {
 						store.seek(position);
-						byte [] signature = new byte[4];
+						byte[] signature = new byte[4];
 						store.readFully(signature);
-						if ( !Arrays.equals(CAFE, signature))
+						if (!Arrays.equals(CAFE, signature))
 							throw new IllegalArgumentException("No signature");
 
 						int flags = store.readInt();
 						int compressedLength = store.readInt();
 						int totalLength = store.readInt();
-						byte []sha1 = new byte[KEYLENGTH];
+						byte[] sha1 = new byte[KEYLENGTH];
 						store.readFully(sha1);
 						short crc = store.readShort();
-						if ( crc != checksum(flags,compressedLength, totalLength, sha1))
+						if (crc != checksum(flags, compressedLength, totalLength, sha1))
 							throw new IllegalArgumentException("Header checksum fails");
-						
+
 						position += HEADERLENGTH + compressedLength;
 						return new SHA1(sha1);
-					} catch (IOException e) {
+					}
+					catch (IOException e) {
 						throw new RuntimeException(e);
-					}				
+					}
 				}
 			}
 
 			public void remove() {
 				throw new UnsupportedOperationException("Remvoe not supported, CAFS is write once");
-			}			
+			}
 		};
 	}
 
-	
 	public boolean isEmpty() throws IOException {
-		synchronized(store) {
+		synchronized (store) {
 			return store.getFilePointer() <= 256;
 		}
 	}
diff --git a/aQute.libg/src/aQute/libg/classdump/ClassDumper.java b/aQute.libg/src/aQute/libg/classdump/ClassDumper.java
index 7423af1..86740ca 100755
--- a/aQute.libg/src/aQute/libg/classdump/ClassDumper.java
+++ b/aQute.libg/src/aQute/libg/classdump/ClassDumper.java
@@ -1,696 +1,648 @@
-/* Copyright 2006 aQute SARL 
- * Licensed under the Apache License, Version 2.0, see http://www.apache.org/licenses/LICENSE-2.0 */
 package aQute.libg.classdump;
 
 import java.io.*;
 import java.lang.reflect.*;
 
 public class ClassDumper {
-    /**
-     * <pre>
-     * ACC_PUBLIC 0x0001 Declared public; may be accessed from outside its
-     * package. 
-     * ACC_FINAL 0x0010 Declared final; no subclasses allowed.
-     * ACC_SUPER 0x0020 Treat superclass methods specially when invoked by the
-     * invokespecial instruction. 
-     * ACC_INTERFACE 0x0200 Is an interface, not a
-     * class. 
-     * ACC_ABSTRACT 0x0400 Declared abstract; may not be instantiated.
-     * </pre>
-     * 
-     * @param mod
-     */
-    final static int ACC_PUBLIC  = 0x0001; // Declared public; may be accessed
-                                            // from outside its package.
-    final static int ACC_FINAL     = 0x0010; // Declared final; no subclasses
-    // allowed.
-    final static int ACC_SUPER     = 0x0020; // Treat superclass methods
-    // specially when invoked by the
-    // invokespecial instruction.
-    final static int ACC_INTERFACE = 0x0200; // Is an interface, not a classs
-    final static int ACC_ABSTRACT  = 0x0400; // Declared abstract; may not be
-                                                // instantiated.
-    
-    final static protected class Assoc {
-        Assoc(byte tag, int a, int b) {
-            this.tag = tag;
-            this.a = a;
-            this.b = b;
-        }
-
-        byte tag;
-        int  a;
-        int  b;
-
-    }
-
-    final String        path;
-    final static String NUM_COLUMN = "%-30s %d\n";
-    final static String HEX_COLUMN = "%-30s %x\n";
-    final static String STR_COLUMN = "%-30s %s\n";
-
-    PrintStream         ps         = System.out;
-    Object[]            pool;
-    InputStream         in;
-
-    public ClassDumper(String path) throws Exception {
-        this(path, new FileInputStream(new File(path)));
-    }
-
-    public ClassDumper(String path, InputStream in) throws IOException {
-        this.path = path;
-        this.in = in;
-    }
-
-    public void dump(PrintStream ps) throws Exception {
-        if (ps != null)
-            this.ps = ps;
-        DataInputStream din = new DataInputStream(in);
-        parseClassFile(din);
-        din.close();
-    }
-
-    void parseClassFile(DataInputStream in) throws IOException {
-        int magic = in.readInt();
-        if (magic != 0xCAFEBABE)
-            throw new IOException("Not a valid class file (no CAFEBABE header)");
-
-        ps.printf(HEX_COLUMN, "magic", magic);
-        int minor = in.readUnsignedShort(); // minor version
-        int major = in.readUnsignedShort(); // major version
-        ps.printf(STR_COLUMN, "version", "" + major + "." + minor);
-        int pool_size = in.readUnsignedShort();
-        ps.printf(NUM_COLUMN, "pool size", pool_size);
-        pool = new Object[pool_size];
-
-        process: for (int poolIndex = 1; poolIndex < pool_size; poolIndex++) {
-            byte tag = in.readByte();
-
-            switch (tag) {
-            case 0:
-                ps.printf("%30d tag (0)\n", poolIndex);
-                break process;
-
-            case 1:
-                String name = in.readUTF();
-                pool[poolIndex] = name;
-                ps.printf("%30d tag(1) utf8 '%s'\n", poolIndex, name);
-                break;
-
-            case 2:
-                throw new IOException("Invalid tag " + tag);
-
-            case 3:
-                int i = in.readInt();
-                pool[poolIndex] = new Integer(i);
-                ps.printf("%30d tag(3) int %s\n", poolIndex, i);
-                break;
-
-            case 4:
-                float f = in.readFloat();
-                pool[poolIndex] = new Float(f);
-                ps.printf("%30d tag(4) float %s\n", poolIndex, f);
-                break;
-
-            // For some insane optimization reason are
-            // the long and the double two entries in the
-            // constant pool. See 4.4.5
-            case 5:
-                long l = in.readLong();
-                pool[poolIndex] = new Long(l);
-                ps.printf("%30d tag(5) long %s\n", poolIndex, l);
-                poolIndex++;
-                break;
-
-            case 6:
-                double d = in.readDouble();
-                pool[poolIndex] = new Double(d);
-                ps.printf("%30d tag(6) double %s\n", poolIndex, d);
-                poolIndex++;
-                break;
-
-            case 7:
-                int class_index = in.readUnsignedShort();
-                pool[poolIndex] = new Integer(class_index);
-                ps.printf("%30d tag(7) constant classs %d\n", poolIndex,
-                        class_index);
-                break;
-
-            case 8:
-                int string_index = in.readUnsignedShort();
-                pool[poolIndex] = new Integer(string_index);
-                ps.printf("%30d tag(8) constant string %d\n", poolIndex,
-                        string_index);
-                break;
-
-            case 9: // Field ref
-                class_index = in.readUnsignedShort();
-                int name_and_type_index = in.readUnsignedShort();
-                pool[poolIndex] = new Assoc((byte) 9, class_index,
-                        name_and_type_index);
-                ps.printf("%30d tag(9) field ref %d/%d\n", poolIndex,
-                        class_index, name_and_type_index);
-                break;
-
-            case 10: // Method ref
-                class_index = in.readUnsignedShort();
-                name_and_type_index = in.readUnsignedShort();
-                pool[poolIndex] = new Assoc((byte) 10, class_index,
-                        name_and_type_index);
-                ps.printf("%30d tag(10) method ref %d/%d\n", poolIndex,
-                        class_index, name_and_type_index);
-                break;
-
-            case 11: // Interface and Method ref
-                class_index = in.readUnsignedShort();
-                name_and_type_index = in.readUnsignedShort();
-                pool[poolIndex] = new Assoc((byte) 11, class_index,
-                        name_and_type_index);
-                ps.printf("%30d tag(11) interface and method ref %d/%d\n",
-                        poolIndex, class_index, name_and_type_index);
-                break;
-
-            // Name and Type
-            case 12:
-                int name_index = in.readUnsignedShort();
-                int descriptor_index = in.readUnsignedShort();
-                pool[poolIndex] = new Assoc(tag, name_index, descriptor_index);
-                ps.printf("%30d tag(12) name and type %d/%d\n", poolIndex,
-                        name_index, descriptor_index);
-                break;
-
-            default:
-                throw new IllegalArgumentException("Unknown tag: " + tag);
-            }
-        }
-
-        int access = in.readUnsignedShort(); // access
-        printAccess(access);
-        int this_class = in.readUnsignedShort();
-        int super_class = in.readUnsignedShort();
-        ps.printf("%-30s %x %s(#%d)\n", "this_class", access, pool[this_class],
-                this_class);
-        ps.printf("%-30s %s(#%d)\n", "super_class", pool[super_class],
-                super_class);
-
-        int interfaces_count = in.readUnsignedShort();
-        ps.printf(NUM_COLUMN, "interface count", interfaces_count);
-        for (int i = 0; i < interfaces_count; i++) {
-            int interface_index = in.readUnsignedShort();
-            ps.printf("%-30s interface %s(#%d)", "interface count",
-                    pool[interface_index], interfaces_count);
-        }
-
-        int field_count = in.readUnsignedShort();
-        ps.printf(NUM_COLUMN, "field count", field_count);
-        for (int i = 0; i < field_count; i++) {
-            access = in.readUnsignedShort(); // access
-            printAccess(access);
-            int name_index = in.readUnsignedShort();
-            int descriptor_index = in.readUnsignedShort();
-            ps.printf("%-30s %x %s(#%d) %s(#%d)\n", "field def", access,
-                    pool[name_index], name_index, pool[descriptor_index],
-                    descriptor_index);
-            doAttributes(in, "  ");
-        }
-
-        int method_count = in.readUnsignedShort();
-        ps.printf(NUM_COLUMN, "method count", method_count);
-        for (int i = 0; i < method_count; i++) {
-            int access_flags = in.readUnsignedShort();
-            printAccess(access_flags);
-            int name_index = in.readUnsignedShort();
-            int descriptor_index = in.readUnsignedShort();
-            ps.printf("%-30s %x %s(#%d) %s(#%d)\n", "method def", access_flags,
-                    pool[name_index], name_index, pool[descriptor_index],
-                    descriptor_index);
-            doAttributes(in, "  ");
-        }
-
-        doAttributes(in, "");
-        if (in.read() >= 0)
-            ps.printf("Extra bytes follow ...");
-    }
-
-    /**
-     * Called for each attribute in the class, field, or method.
-     * 
-     * @param in
-     *            The stream
-     * @throws IOException
-     */
-    private void doAttributes(DataInputStream in, String indent)
-            throws IOException {
-        int attribute_count = in.readUnsignedShort();
-        ps.printf(NUM_COLUMN, indent + "attribute count", attribute_count);
-        for (int j = 0; j < attribute_count; j++) {
-            doAttribute(in, indent + j + ": ");
-        }
-    }
-
-    /**
-     * Process a single attribute, if not recognized, skip it.
-     * 
-     * @param in
-     *            the data stream
-     * @throws IOException
-     */
-    private void doAttribute(DataInputStream in, String indent)
-            throws IOException {
-        int attribute_name_index = in.readUnsignedShort();
-        long attribute_length = in.readInt();
-        attribute_length &= 0xFFFF;
-        String attributeName = (String) pool[attribute_name_index];
-        ps.printf("%-30s %s(#%d)\n", indent + "attribute", attributeName,
-                attribute_name_index);
-        if ("RuntimeVisibleAnnotations".equals(attributeName))
-            doAnnotations(in, indent);
-        else if ("SourceFile".equals(attributeName))
-            doSourceFile(in, indent);
-        else if ("Code".equals(attributeName))
-            doCode(in, indent);
-        else if ("LineNumberTable".equals(attributeName))
-            doLineNumberTable(in, indent);
-        else if ("LocalVariableTable".equals(attributeName))
-            doLocalVariableTable(in, indent);
-        else if ("InnerClasses".equals(attributeName))
-            doInnerClasses(in, indent);
-        else if ("Exceptions".equals(attributeName))
-            doExceptions(in, indent);
-        else if ("EnclosingMethod".equals(attributeName))
-            doEnclosingMethod(in, indent);
-        else if ("Signature".equals(attributeName))
-            doSignature(in, indent);
-        else if ("Synthetic".equals(attributeName))
-            ; // Is empty!
-        else if ("Deprecated".equals(attributeName))
-            ; // Is Empty
-        else {
-            ps.printf("%-30s %d\n", indent + "Unknown attribute, skipping",
-                    attribute_length);
-            if (attribute_length > 0x7FFFFFFF) {
-                throw new IllegalArgumentException("Attribute > 2Gb");
-            }
-            byte buffer[] = new byte[(int) attribute_length];
-            in.readFully(buffer);
-            printHex(buffer);
-        }
-    }
-
-    /**
-     * <pre>
-     * Signature_attribute {
-     * 	u2 attribute_name_index;
-     * 	u4 attribute_length;
-     * 	u2 signature_index;
-     * 	}
-     * </pre>
-     * 
-     * @param in
-     * @param indent
-     */
-    void doSignature(DataInputStream in, String indent) throws IOException {
-        int signature_index = in.readUnsignedShort();
-        ps.printf("%-30s %s(#%d)\n", indent + "signature",
-                pool[signature_index], signature_index);
-    }
-
-    /**
-     * <pre>
-     * EnclosingMethod_attribute {
-     * 	u2 attribute_name_index;
-     * 	u4 attribute_length;
-     * 	u2 class_index
-     * 	u2 method_index;
-     * 	}
-     * 	
-     * </pre>
-     */
-    void doEnclosingMethod(DataInputStream in, String indent)
-            throws IOException {
-        int class_index = in.readUnsignedShort();
-        int method_index = in.readUnsignedShort();
-        ps.printf("%-30s %s(#%d/c) %s(#%d)\n", indent + "enclosing method",
-                pool[((Integer) pool[class_index]).intValue()], class_index,
-                (method_index == 0 ? "<>" : pool[method_index]));
-    }
-
-    /**
-     * <pre>
-     *  Exceptions_attribute {
-     * 		u2 attribute_name_index;
-     * 		u4 attribute_length;
-     * 		u2 number_of_exceptions;
-     * 		u2 exception_index_table[number_of_exceptions];
-     * 	}
-     * </pre>
-     * 
-     * @param in
-     * @param indent
-     */
-    private void doExceptions(DataInputStream in, String indent)
-            throws IOException {
-        int number_of_exceptions = in.readUnsignedShort();
-        ps.printf(NUM_COLUMN, indent + "number of exceptions",
-                number_of_exceptions);
-        StringBuffer sb = new StringBuffer();
-        String del = "";
-        for (int i = 0; i < number_of_exceptions; i++) {
-            int exception_index_table = in.readUnsignedShort();
-            sb.append(del);
-            sb.append(pool[((Integer) pool[exception_index_table])]);
-            sb.append("(#");
-            sb.append(exception_index_table);
-            sb.append("/c)");
-            del = ", ";
-        }
-        ps.printf("%-30s %d: %s\n", indent + "exceptions",
-                number_of_exceptions, sb);
-    }
-
-    /**
-     * <pre>
-     * Code_attribute {
-     * 		u2 attribute_name_index;
-     * 		u4 attribute_length;
-     * 		u2 max_stack;
-     * 		u2 max_locals;
-     * 		u4 code_length;
-     * 		u1 code[code_length];
-     * 		u2 exception_table_length;
-     * 		{    	u2 start_pc;
-     * 		      	u2 end_pc;
-     * 		      	u2  handler_pc;
-     * 		      	u2  catch_type;
-     * 		}	exception_table[exception_table_length];
-     * 		u2 attributes_count;
-     * 		attribute_info attributes[attributes_count];
-     * 	}
-     * </pre>
-     * 
-     * @param in
-     * @param pool
-     * @throws IOException
-     */
-    private void doCode(DataInputStream in, String indent) throws IOException {
-        int max_stack = in.readUnsignedShort();
-        int max_locals = in.readUnsignedShort();
-        int code_length = in.readInt();
-        ps.printf(NUM_COLUMN, indent + "max_stack", max_stack);
-        ps.printf(NUM_COLUMN, indent + "max_locals", max_locals);
-        ps.printf(NUM_COLUMN, indent + "code_length", code_length);
-        byte code[] = new byte[code_length];
-        in.readFully(code);
-        printHex(code);
-        int exception_table_length = in.readUnsignedShort();
-        ps.printf(NUM_COLUMN, indent + "exception_table_length",
-                exception_table_length);
-
-        for (int i = 0; i < exception_table_length; i++) {
-            int start_pc = in.readUnsignedShort();
-            int end_pc = in.readUnsignedShort();
-            int handler_pc = in.readUnsignedShort();
-            int catch_type = in.readUnsignedShort();
-            ps.printf("%-30s %d/%d/%d/%d\n", indent + "exception_table",
-                    start_pc, end_pc, handler_pc, catch_type);
-        }
-        doAttributes(in, indent + "  ");
-    }
-
-    /**
-     * We must find Class.forName references ...
-     * 
-     * @param code
-     */
-    protected void printHex(byte[] code) {
-        int index = 0;
-        while (index < code.length) {
-            StringBuilder sb = new StringBuilder();
-            for (int i = 0; i < 16 && index < code.length; i++) {
-                String s = Integer.toHexString((0xFF & code[index++]))
-                        .toUpperCase();
-                if (s.length() == 1)
-                    sb.append("0");
-                sb.append(s);
-                sb.append(" ");
-            }
-            ps.printf(STR_COLUMN, "", sb.toString());
-        }
-    }
-
-    private void doSourceFile(DataInputStream in, String indent)
-            throws IOException {
-        int sourcefile_index = in.readUnsignedShort();
-        ps.printf("%-30s %s(#%d)\n", indent + "Source file",
-                pool[sourcefile_index], sourcefile_index);
-    }
-
-    private void doAnnotations(DataInputStream in, String indent)
-            throws IOException {
-        int num_annotations = in.readUnsignedShort(); // # of annotations
-        ps
-                .printf(NUM_COLUMN, indent + "Number of annotations",
-                        num_annotations);
-        for (int a = 0; a < num_annotations; a++) {
-            doAnnotation(in, indent);
-        }
-    }
-
-    private void doAnnotation(DataInputStream in, String indent)
-            throws IOException {
-        int type_index = in.readUnsignedShort();
-        ps.printf("%-30s %s(#%d)", indent + "type", pool[type_index],
-                type_index);
-        int num_element_value_pairs = in.readUnsignedShort();
-        ps.printf(NUM_COLUMN, indent + "num_element_value_pairs",
-                num_element_value_pairs);
-        for (int v = 0; v < num_element_value_pairs; v++) {
-            int element_name_index = in.readUnsignedShort();
-            ps.printf(NUM_COLUMN, indent + "element_name_index",
-                    element_name_index);
-            doElementValue(in, indent);
-        }
-    }
-
-    private void doElementValue(DataInputStream in, String indent)
-            throws IOException {
-        int tag = in.readUnsignedByte();
-        switch (tag) {
-        case 'B':
-        case 'C':
-        case 'D':
-        case 'F':
-        case 'I':
-        case 'J':
-        case 'S':
-        case 'Z':
-        case 's':
-            int const_value_index = in.readUnsignedShort();
-            ps.printf("%-30s %c %s(#%d)\n", indent + "element value", tag,
-                    pool[const_value_index], const_value_index);
-            break;
-
-        case 'e':
-            int type_name_index = in.readUnsignedShort();
-            int const_name_index = in.readUnsignedShort();
-            ps.printf("%-30s %c %s(#%d) %s(#%d)\n", indent + "type+const", tag,
-                    pool[type_name_index], type_name_index,
-                    pool[const_name_index], const_name_index);
-            break;
-
-        case 'c':
-            int class_info_index = in.readUnsignedShort();
-            ps.printf("%-30s %c %s(#%d)\n", indent + "element value", tag,
-                    pool[class_info_index], class_info_index);
-            break;
-
-        case '@':
-            ps.printf("%-30s %c\n", indent + "sub annotation", tag);
-            doAnnotation(in, indent);
-            break;
-
-        case '[':
-            int num_values = in.readUnsignedShort();
-            ps.printf("%-30s %c num_values=%d\n", indent + "sub element value",
-                    tag, num_values);
-            for (int i = 0; i < num_values; i++) {
-                doElementValue(in, indent);
-            }
-            break;
-
-        default:
-            throw new IllegalArgumentException(
-                    "Invalid value for Annotation ElementValue tag " + tag);
-        }
-    }
-
-    /**
-     * <pre>
-     *  LineNumberTable_attribute {
-     * 		u2 attribute_name_index;
-     * 		u4 attribute_length;
-     * 		u2 line_number_table_length;
-     * 		{  u2 start_pc;	     
-     * 		   u2 line_number;	     
-     * 		} line_number_table[line_number_table_length];
-     * 	}
-     * 	
-     * </pre>
-     */
-    void doLineNumberTable(DataInputStream in, String indent)
-            throws IOException {
-        int line_number_table_length = in.readUnsignedShort();
-        ps.printf(NUM_COLUMN, indent + "line number table length",
-                line_number_table_length);
-        StringBuffer sb = new StringBuffer();
-        for (int i = 0; i < line_number_table_length; i++) {
-            int start_pc = in.readUnsignedShort();
-            int line_number = in.readUnsignedShort();
-            sb.append(start_pc);
-            sb.append("/");
-            sb.append(line_number);
-            sb.append(" ");
-        }
-        ps.printf("%-30s %d: %s\n", indent + "line number table",
-                line_number_table_length, sb);
-    }
-
-    /**
-     * 
-     * <pre>
-     * 	LocalVariableTable_attribute {
-     * 		u2 attribute_name_index;
-     * 		u4 attribute_length;
-     * 		u2 local_variable_table_length;
-     * 		{  u2 start_pc;
-     * 		    u2 length;
-     * 		    u2 name_index;
-     * 		    u2 descriptor_index;
-     * 		    u2 index;
-     * 		} local_variable_table[local_variable_table_length];
-     * 	}	
-     * </pre>
-     */
-
-    void doLocalVariableTable(DataInputStream in, String indent)
-            throws IOException {
-        int local_variable_table_length = in.readUnsignedShort();
-        ps.printf(NUM_COLUMN, indent + "local variable table length",
-                local_variable_table_length);
-        for (int i = 0; i < local_variable_table_length; i++) {
-            int start_pc = in.readUnsignedShort();
-            int length = in.readUnsignedShort();
-            int name_index = in.readUnsignedShort();
-            int descriptor_index = in.readUnsignedShort();
-            int index = in.readUnsignedShort();
-            ps.printf("%-30s %d: %d/%d %s(#%d) %s(#%d)\n", indent, index,
-                    start_pc, length, pool[name_index], name_index,
-                    pool[descriptor_index], descriptor_index);
-        }
-    }
-
-    /**
-     * <pre>
-     *    InnerClasses_attribute {
-     * 		u2 attribute_name_index;
-     * 		u4 attribute_length;
-     * 		u2 number_of_classes;
-     * 		{  u2 inner_class_info_index;	     
-     * 		   u2 outer_class_info_index;	     
-     * 		   u2 inner_name_index;	     
-     * 		   u2 inner_class_access_flags;	     
-     * 		} classes[number_of_classes];
-     * 	}
-     * </pre>
-     * 
-     */
-    void doInnerClasses(DataInputStream in, String indent) throws IOException {
-        int number_of_classes = in.readUnsignedShort();
-        ps.printf(NUM_COLUMN, indent + "number of classes", number_of_classes);
-        for (int i = 0; i < number_of_classes; i++) {
-            int inner_class_info_index = in.readUnsignedShort();
-            int outer_class_info_index = in.readUnsignedShort();
-            int inner_name_index = in.readUnsignedShort();
-            int inner_class_access_flags = in.readUnsignedShort();
-            printAccess(inner_class_access_flags);
-
-            String iname = "<>";
-            String oname = iname;
-
-            if (inner_class_info_index != 0)
-                iname = (String) pool[((Integer) pool[inner_class_info_index])
-                        .intValue()];
-            if (outer_class_info_index != 0)
-                oname = (String) pool[((Integer) pool[outer_class_info_index])
-                        .intValue()];
-
-            ps.printf("%-30s %d: %x %s(#%d/c) %s(#%d/c) %s(#%d) \n", indent, i,
-                    inner_class_access_flags, iname, inner_class_info_index,
-                    oname, outer_class_info_index, pool[inner_name_index],
-                    inner_name_index);
-        }
-    }
-
-
-    void printClassAccess(int mod) {
-        ps.printf("%-30s", "Class Access");
-        if ((ACC_PUBLIC&mod)!= 0)
-            ps.print(" public");
-        if ((ACC_FINAL&mod)!= 0)
-            ps.print(" final");
-        if ((ACC_SUPER&mod)!= 0)
-            ps.print(" super");
-        if ((ACC_INTERFACE&mod)!= 0)
-            ps.print(" interface");
-        if ((ACC_ABSTRACT&mod)!= 0)
-            ps.print(" abstract");
-
-        ps.println();
-    }
-
-    void printAccess(int mod) {
-        ps.printf("%-30s", "Access");
-        if (Modifier.isStatic(mod))
-            ps.print(" static");
-        if (Modifier.isAbstract(mod))
-            ps.print(" abstract");
-        if (Modifier.isPublic(mod))
-            ps.print(" public");
-        if (Modifier.isFinal(mod))
-            ps.print(" final");
-        if (Modifier.isInterface(mod))
-            ps.print(" interface");
-        if (Modifier.isNative(mod))
-            ps.print(" native");
-        if (Modifier.isPrivate(mod))
-            ps.print(" private");
-        if (Modifier.isProtected(mod))
-            ps.print(" protected");
-        if (Modifier.isStrict(mod))
-            ps.print(" strict");
-        if (Modifier.isSynchronized(mod))
-            ps.print(" synchronized");
-        if (Modifier.isTransient(mod))
-            ps.print(" transient");
-        if (Modifier.isVolatile(mod))
-            ps.print(" volatile");
-
-        ps.println();
-    }
-
-    public static void main(String args[]) throws Exception {
-        if (args.length == 0) {
-            System.err.println("clsd <class file>+");
-        }
-        for (int i = 0; i < args.length; i++) {
-            File f = new File(args[i]);
-            if (!f.isFile())
-                System.err.println("File does not exist or is directory " + f);
-            else {
-                ClassDumper cd = new ClassDumper(args[i]);
-                cd.dump(null);
-            }
-        }
-    }
+	/**
+	 * <pre>
+	 * ACC_PUBLIC 0x0001 Declared public; may be accessed from outside its
+	 * package. 
+	 * ACC_FINAL 0x0010 Declared final; no subclasses allowed.
+	 * ACC_SUPER 0x0020 Treat superclass methods specially when invoked by the
+	 * invokespecial instruction. 
+	 * ACC_INTERFACE 0x0200 Is an interface, not a
+	 * class. 
+	 * ACC_ABSTRACT 0x0400 Declared abstract; may not be instantiated.
+	 * </pre>
+	 * 
+	 * @param mod
+	 */
+	final static int	ACC_PUBLIC		= 0x0001;	// Declared public; may be
+													// accessed
+													// from outside its package.
+	final static int	ACC_FINAL		= 0x0010;	// Declared final; no
+													// subclasses
+	// allowed.
+	final static int	ACC_SUPER		= 0x0020;	// Treat superclass methods
+	// specially when invoked by the
+	// invokespecial instruction.
+	final static int	ACC_INTERFACE	= 0x0200;	// Is an interface, not a
+													// classs
+	final static int	ACC_ABSTRACT	= 0x0400;	// Declared abstract; may
+													// not be
+													// instantiated.
+
+	final static class Assoc {
+		Assoc(byte tag, int a, int b) {
+			this.tag = tag;
+			this.a = a;
+			this.b = b;
+		}
+
+		byte	tag;
+		int		a;
+		int		b;
+
+	}
+
+	final String		path;
+	final static String	NUM_COLUMN	= "%-30s %d%n";
+	final static String	HEX_COLUMN	= "%-30s %x%n";
+	final static String	STR_COLUMN	= "%-30s %s%n";
+
+	PrintStream			ps			= System.err;
+	Object[]			pool;
+	InputStream			in;
+
+	public ClassDumper(String path) throws Exception {
+		this(path, new FileInputStream(new File(path)));
+	}
+
+	public ClassDumper(String path, InputStream in) throws IOException {
+		this.path = path;
+		this.in = in;
+	}
+
+	public void dump(PrintStream ps) throws Exception {
+		if (ps != null)
+			this.ps = ps;
+		DataInputStream din = new DataInputStream(in);
+		parseClassFile(din);
+		din.close();
+	}
+
+	void parseClassFile(DataInputStream in) throws IOException {
+		int magic = in.readInt();
+		if (magic != 0xCAFEBABE)
+			throw new IOException("Not a valid class file (no CAFEBABE header)");
+
+		ps.printf(HEX_COLUMN, "magic", magic);
+		int minor = in.readUnsignedShort(); // minor version
+		int major = in.readUnsignedShort(); // major version
+		ps.printf(STR_COLUMN, "version", "" + major + "." + minor);
+		int pool_size = in.readUnsignedShort();
+		ps.printf(NUM_COLUMN, "pool size", pool_size);
+		pool = new Object[pool_size];
+
+		process: for (int poolIndex = 1; poolIndex < pool_size; poolIndex++) {
+			byte tag = in.readByte();
+
+			switch (tag) {
+				case 0 :
+					ps.printf("%30d tag (0)%n", poolIndex);
+					break process;
+
+				case 1 :
+					String name = in.readUTF();
+					pool[poolIndex] = name;
+					ps.printf("%30d tag(1) utf8 '%s'%n", poolIndex, name);
+					break;
+
+				case 2 :
+					throw new IOException("Invalid tag " + tag);
+
+				case 3 :
+					int i = in.readInt();
+					pool[poolIndex] = Integer.valueOf(i);
+					ps.printf("%30d tag(3) int %s%n", poolIndex, i);
+					break;
+
+				case 4 :
+					float f = in.readFloat();
+					pool[poolIndex] = new Float(f);
+					ps.printf("%30d tag(4) float %s%n", poolIndex, f);
+					break;
+
+				// For some insane optimization reason are
+				// the long and the double two entries in the
+				// constant pool. See 4.4.5
+				case 5 :
+					long l = in.readLong();
+					pool[poolIndex] = Long.valueOf(l);
+					ps.printf("%30d tag(5) long %s%n", poolIndex, l);
+					poolIndex++;
+					break;
+
+				case 6 :
+					double d = in.readDouble();
+					pool[poolIndex] = new Double(d);
+					ps.printf("%30d tag(6) double %s%n", poolIndex, d);
+					poolIndex++;
+					break;
+
+				case 7 :
+					int class_index = in.readUnsignedShort();
+					pool[poolIndex] = Integer.valueOf(class_index);
+					ps.printf("%30d tag(7) constant classs %d%n", poolIndex, class_index);
+					break;
+
+				case 8 :
+					int string_index = in.readUnsignedShort();
+					pool[poolIndex] = Integer.valueOf(string_index);
+					ps.printf("%30d tag(8) constant string %d%n", poolIndex, string_index);
+					break;
+
+				case 9 : // Field ref
+					class_index = in.readUnsignedShort();
+					int name_and_type_index = in.readUnsignedShort();
+					pool[poolIndex] = new Assoc((byte) 9, class_index, name_and_type_index);
+					ps.printf("%30d tag(9) field ref %d/%d%n", poolIndex, class_index, name_and_type_index);
+					break;
+
+				case 10 : // Method ref
+					class_index = in.readUnsignedShort();
+					name_and_type_index = in.readUnsignedShort();
+					pool[poolIndex] = new Assoc((byte) 10, class_index, name_and_type_index);
+					ps.printf("%30d tag(10) method ref %d/%d%n", poolIndex, class_index, name_and_type_index);
+					break;
+
+				case 11 : // Interface and Method ref
+					class_index = in.readUnsignedShort();
+					name_and_type_index = in.readUnsignedShort();
+					pool[poolIndex] = new Assoc((byte) 11, class_index, name_and_type_index);
+					ps.printf("%30d tag(11) interface and method ref %d/%d%n", poolIndex, class_index,
+							name_and_type_index);
+					break;
+
+				// Name and Type
+				case 12 :
+					int name_index = in.readUnsignedShort();
+					int descriptor_index = in.readUnsignedShort();
+					pool[poolIndex] = new Assoc(tag, name_index, descriptor_index);
+					ps.printf("%30d tag(12) name and type %d/%d%n", poolIndex, name_index, descriptor_index);
+					break;
+
+				default :
+					throw new IllegalArgumentException("Unknown tag: " + tag);
+			}
+		}
+
+		int access = in.readUnsignedShort(); // access
+		printAccess(access);
+		int this_class = in.readUnsignedShort();
+		int super_class = in.readUnsignedShort();
+		ps.printf("%-30s %x %s(#%d)%n", "this_class", access, pool[this_class], this_class);
+		ps.printf("%-30s %s(#%d)%n", "super_class", pool[super_class], super_class);
+
+		int interfaces_count = in.readUnsignedShort();
+		ps.printf(NUM_COLUMN, "interface count", interfaces_count);
+		for (int i = 0; i < interfaces_count; i++) {
+			int interface_index = in.readUnsignedShort();
+			ps.printf("%-30s interface %s(#%d)", "interface count", pool[interface_index], interfaces_count);
+		}
+
+		int field_count = in.readUnsignedShort();
+		ps.printf(NUM_COLUMN, "field count", field_count);
+		for (int i = 0; i < field_count; i++) {
+			access = in.readUnsignedShort(); // access
+			printAccess(access);
+			int name_index = in.readUnsignedShort();
+			int descriptor_index = in.readUnsignedShort();
+			ps.printf("%-30s %x %s(#%d) %s(#%d)%n", "field def", access, pool[name_index], name_index,
+					pool[descriptor_index], descriptor_index);
+			doAttributes(in, "  ");
+		}
+
+		int method_count = in.readUnsignedShort();
+		ps.printf(NUM_COLUMN, "method count", method_count);
+		for (int i = 0; i < method_count; i++) {
+			int access_flags = in.readUnsignedShort();
+			printAccess(access_flags);
+			int name_index = in.readUnsignedShort();
+			int descriptor_index = in.readUnsignedShort();
+			ps.printf("%-30s %x %s(#%d) %s(#%d)%n", "method def", access_flags, pool[name_index], name_index,
+					pool[descriptor_index], descriptor_index);
+			doAttributes(in, "  ");
+		}
+
+		doAttributes(in, "");
+		if (in.read() >= 0)
+			ps.printf("Extra bytes follow ...");
+	}
+
+	/**
+	 * Called for each attribute in the class, field, or method.
+	 * 
+	 * @param in
+	 *            The stream
+	 * @throws IOException
+	 */
+	private void doAttributes(DataInputStream in, String indent) throws IOException {
+		int attribute_count = in.readUnsignedShort();
+		ps.printf(NUM_COLUMN, indent + "attribute count", attribute_count);
+		for (int j = 0; j < attribute_count; j++) {
+			doAttribute(in, indent + j + ": ");
+		}
+	}
+
+	/**
+	 * Process a single attribute, if not recognized, skip it.
+	 * 
+	 * @param in
+	 *            the data stream
+	 * @throws IOException
+	 */
+	private void doAttribute(DataInputStream in, String indent) throws IOException {
+		int attribute_name_index = in.readUnsignedShort();
+		long attribute_length = in.readInt();
+		attribute_length &= 0xFFFF;
+		String attributeName = (String) pool[attribute_name_index];
+		ps.printf("%-30s %s(#%d)%n", indent + "attribute", attributeName, attribute_name_index);
+		if ("RuntimeVisibleAnnotations".equals(attributeName))
+			doAnnotations(in, indent);
+		else if ("SourceFile".equals(attributeName))
+			doSourceFile(in, indent);
+		else if ("Code".equals(attributeName))
+			doCode(in, indent);
+		else if ("LineNumberTable".equals(attributeName))
+			doLineNumberTable(in, indent);
+		else if ("LocalVariableTable".equals(attributeName))
+			doLocalVariableTable(in, indent);
+		else if ("InnerClasses".equals(attributeName))
+			doInnerClasses(in, indent);
+		else if ("Exceptions".equals(attributeName))
+			doExceptions(in, indent);
+		else if ("EnclosingMethod".equals(attributeName))
+			doEnclosingMethod(in, indent);
+		else if ("Signature".equals(attributeName))
+			doSignature(in, indent);
+		else if ("Synthetic".equals(attributeName))
+			; // Is empty!
+		else if ("Deprecated".equals(attributeName))
+			; // Is Empty
+		else {
+			ps.printf("%-30s %d%n", indent + "Unknown attribute, skipping", attribute_length);
+			if (attribute_length > 0x7FFFFFFF) {
+				throw new IllegalArgumentException("Attribute > 2Gb");
+			}
+			byte buffer[] = new byte[(int) attribute_length];
+			in.readFully(buffer);
+			printHex(buffer);
+		}
+	}
+
+	/**
+	 * <pre>
+	 * Signature_attribute {
+	 * 	u2 attribute_name_index;
+	 * 	u4 attribute_length;
+	 * 	u2 signature_index;
+	 * 	}
+	 * </pre>
+	 * 
+	 * @param in
+	 * @param indent
+	 */
+	void doSignature(DataInputStream in, String indent) throws IOException {
+		int signature_index = in.readUnsignedShort();
+		ps.printf("%-30s %s(#%d)%n", indent + "signature", pool[signature_index], signature_index);
+	}
+
+	/**
+	 * <pre>
+	 * EnclosingMethod_attribute {
+	 * 	u2 attribute_name_index;
+	 * 	u4 attribute_length;
+	 * 	u2 class_index
+	 * 	u2 method_index;
+	 * 	}
+	 * 
+	 * </pre>
+	 */
+	void doEnclosingMethod(DataInputStream in, String indent) throws IOException {
+		int class_index = in.readUnsignedShort();
+		int method_index = in.readUnsignedShort();
+		ps.printf("%-30s %s(#%d/c) %s%n", //
+				indent + "enclosing method", //
+				pool[((Integer) pool[class_index]).intValue()], //
+				class_index, //
+				(method_index == 0 ? "<>" : pool[method_index]));
+	}
+
+	/**
+	 * <pre>
+	 *  Exceptions_attribute {
+	 * 		u2 attribute_name_index;
+	 * 		u4 attribute_length;
+	 * 		u2 number_of_exceptions;
+	 * 		u2 exception_index_table[number_of_exceptions];
+	 * 	}
+	 * </pre>
+	 * 
+	 * @param in
+	 * @param indent
+	 */
+	private void doExceptions(DataInputStream in, String indent) throws IOException {
+		int number_of_exceptions = in.readUnsignedShort();
+		ps.printf(NUM_COLUMN, indent + "number of exceptions", number_of_exceptions);
+		StringBuilder sb = new StringBuilder();
+		String del = "";
+		for (int i = 0; i < number_of_exceptions; i++) {
+			int exception_index_table = in.readUnsignedShort();
+			sb.append(del);
+			sb.append(pool[((Integer) pool[exception_index_table])]);
+			sb.append("(#");
+			sb.append(exception_index_table);
+			sb.append("/c)");
+			del = ", ";
+		}
+		ps.printf("%-30s %d: %s%n", indent + "exceptions", number_of_exceptions, sb);
+	}
+
+	/**
+	 * <pre>
+	 * Code_attribute {
+	 * 		u2 attribute_name_index;
+	 * 		u4 attribute_length;
+	 * 		u2 max_stack;
+	 * 		u2 max_locals;
+	 * 		u4 code_length;
+	 * 		u1 code[code_length];
+	 * 		u2 exception_table_length;
+	 * 		{    	u2 start_pc;
+	 * 		      	u2 end_pc;
+	 * 		      	u2  handler_pc;
+	 * 		      	u2  catch_type;
+	 * 		}	exception_table[exception_table_length];
+	 * 		u2 attributes_count;
+	 * 		attribute_info attributes[attributes_count];
+	 * 	}
+	 * </pre>
+	 * 
+	 * @param in
+	 * @param pool
+	 * @throws IOException
+	 */
+	private void doCode(DataInputStream in, String indent) throws IOException {
+		int max_stack = in.readUnsignedShort();
+		int max_locals = in.readUnsignedShort();
+		int code_length = in.readInt();
+		ps.printf(NUM_COLUMN, indent + "max_stack", max_stack);
+		ps.printf(NUM_COLUMN, indent + "max_locals", max_locals);
+		ps.printf(NUM_COLUMN, indent + "code_length", code_length);
+		byte code[] = new byte[code_length];
+		in.readFully(code);
+		printHex(code);
+		int exception_table_length = in.readUnsignedShort();
+		ps.printf(NUM_COLUMN, indent + "exception_table_length", exception_table_length);
+
+		for (int i = 0; i < exception_table_length; i++) {
+			int start_pc = in.readUnsignedShort();
+			int end_pc = in.readUnsignedShort();
+			int handler_pc = in.readUnsignedShort();
+			int catch_type = in.readUnsignedShort();
+			ps.printf("%-30s %d/%d/%d/%d%n", indent + "exception_table", start_pc, end_pc, handler_pc, catch_type);
+		}
+		doAttributes(in, indent + "  ");
+	}
+
+	/**
+	 * We must find Class.forName references ...
+	 * 
+	 * @param code
+	 */
+	protected void printHex(byte[] code) {
+		int index = 0;
+		while (index < code.length) {
+			StringBuilder sb = new StringBuilder();
+			for (int i = 0; i < 16 && index < code.length; i++) {
+				String s = Integer.toHexString((0xFF & code[index++])).toUpperCase();
+				if (s.length() == 1)
+					sb.append("0");
+				sb.append(s);
+				sb.append(" ");
+			}
+			ps.printf(STR_COLUMN, "", sb.toString());
+		}
+	}
+
+	private void doSourceFile(DataInputStream in, String indent) throws IOException {
+		int sourcefile_index = in.readUnsignedShort();
+		ps.printf("%-30s %s(#%d)%n", indent + "Source file", pool[sourcefile_index], sourcefile_index);
+	}
+
+	private void doAnnotations(DataInputStream in, String indent) throws IOException {
+		int num_annotations = in.readUnsignedShort(); // # of annotations
+		ps.printf(NUM_COLUMN, indent + "Number of annotations", num_annotations);
+		for (int a = 0; a < num_annotations; a++) {
+			doAnnotation(in, indent);
+		}
+	}
+
+	private void doAnnotation(DataInputStream in, String indent) throws IOException {
+		int type_index = in.readUnsignedShort();
+		ps.printf("%-30s %s(#%d)", indent + "type", pool[type_index], type_index);
+		int num_element_value_pairs = in.readUnsignedShort();
+		ps.printf(NUM_COLUMN, indent + "num_element_value_pairs", num_element_value_pairs);
+		for (int v = 0; v < num_element_value_pairs; v++) {
+			int element_name_index = in.readUnsignedShort();
+			ps.printf(NUM_COLUMN, indent + "element_name_index", element_name_index);
+			doElementValue(in, indent);
+		}
+	}
+
+	private void doElementValue(DataInputStream in, String indent) throws IOException {
+		int tag = in.readUnsignedByte();
+		switch (tag) {
+			case 'B' :
+			case 'C' :
+			case 'D' :
+			case 'F' :
+			case 'I' :
+			case 'J' :
+			case 'S' :
+			case 'Z' :
+			case 's' :
+				int const_value_index = in.readUnsignedShort();
+				ps.printf("%-30s %c %s(#%d)%n", indent + "element value", tag, pool[const_value_index],
+						const_value_index);
+				break;
+
+			case 'e' :
+				int type_name_index = in.readUnsignedShort();
+				int const_name_index = in.readUnsignedShort();
+				ps.printf("%-30s %c %s(#%d) %s(#%d)%n", indent + "type+const", tag, pool[type_name_index],
+						type_name_index, pool[const_name_index], const_name_index);
+				break;
+
+			case 'c' :
+				int class_info_index = in.readUnsignedShort();
+				ps.printf("%-30s %c %s(#%d)%n", indent + "element value", tag, pool[class_info_index], class_info_index);
+				break;
+
+			case '@' :
+				ps.printf("%-30s %c%n", indent + "sub annotation", tag);
+				doAnnotation(in, indent);
+				break;
+
+			case '[' :
+				int num_values = in.readUnsignedShort();
+				ps.printf("%-30s %c num_values=%d%n", indent + "sub element value", tag, num_values);
+				for (int i = 0; i < num_values; i++) {
+					doElementValue(in, indent);
+				}
+				break;
+
+			default :
+				throw new IllegalArgumentException("Invalid value for Annotation ElementValue tag " + tag);
+		}
+	}
+
+	/**
+	 * <pre>
+	 *  LineNumberTable_attribute {
+	 * 		u2 attribute_name_index;
+	 * 		u4 attribute_length;
+	 * 		u2 line_number_table_length;
+	 * 		{  u2 start_pc;	     
+	 * 		   u2 line_number;	     
+	 * 		} line_number_table[line_number_table_length];
+	 * 	}
+	 * 
+	 * </pre>
+	 */
+	void doLineNumberTable(DataInputStream in, String indent) throws IOException {
+		int line_number_table_length = in.readUnsignedShort();
+		ps.printf(NUM_COLUMN, indent + "line number table length", line_number_table_length);
+		StringBuilder sb = new StringBuilder();
+		for (int i = 0; i < line_number_table_length; i++) {
+			int start_pc = in.readUnsignedShort();
+			int line_number = in.readUnsignedShort();
+			sb.append(start_pc);
+			sb.append("/");
+			sb.append(line_number);
+			sb.append(" ");
+		}
+		ps.printf("%-30s %d: %s%n", indent + "line number table", line_number_table_length, sb);
+	}
+
+	/**
+	 * <pre>
+	 * 	LocalVariableTable_attribute {
+	 * 		u2 attribute_name_index;
+	 * 		u4 attribute_length;
+	 * 		u2 local_variable_table_length;
+	 * 		{  u2 start_pc;
+	 * 		    u2 length;
+	 * 		    u2 name_index;
+	 * 		    u2 descriptor_index;
+	 * 		    u2 index;
+	 * 		} local_variable_table[local_variable_table_length];
+	 * 	}
+	 * </pre>
+	 */
+
+	void doLocalVariableTable(DataInputStream in, String indent) throws IOException {
+		int local_variable_table_length = in.readUnsignedShort();
+		ps.printf(NUM_COLUMN, indent + "local variable table length", local_variable_table_length);
+		for (int i = 0; i < local_variable_table_length; i++) {
+			int start_pc = in.readUnsignedShort();
+			int length = in.readUnsignedShort();
+			int name_index = in.readUnsignedShort();
+			int descriptor_index = in.readUnsignedShort();
+			int index = in.readUnsignedShort();
+			ps.printf("%-30s %d: %d/%d %s(#%d) %s(#%d)%n", indent, index, start_pc, length, pool[name_index],
+					name_index, pool[descriptor_index], descriptor_index);
+		}
+	}
+
+	/**
+	 * <pre>
+	 *    InnerClasses_attribute {
+	 * 		u2 attribute_name_index;
+	 * 		u4 attribute_length;
+	 * 		u2 number_of_classes;
+	 * 		{  u2 inner_class_info_index;	     
+	 * 		   u2 outer_class_info_index;	     
+	 * 		   u2 inner_name_index;	     
+	 * 		   u2 inner_class_access_flags;	     
+	 * 		} classes[number_of_classes];
+	 * 	}
+	 * </pre>
+	 */
+	void doInnerClasses(DataInputStream in, String indent) throws IOException {
+		int number_of_classes = in.readUnsignedShort();
+		ps.printf(NUM_COLUMN, indent + "number of classes", number_of_classes);
+		for (int i = 0; i < number_of_classes; i++) {
+			int inner_class_info_index = in.readUnsignedShort();
+			int outer_class_info_index = in.readUnsignedShort();
+			int inner_name_index = in.readUnsignedShort();
+			int inner_class_access_flags = in.readUnsignedShort();
+			printAccess(inner_class_access_flags);
+
+			String iname = "<>";
+			String oname = iname;
+
+			if (inner_class_info_index != 0)
+				iname = (String) pool[((Integer) pool[inner_class_info_index]).intValue()];
+			if (outer_class_info_index != 0)
+				oname = (String) pool[((Integer) pool[outer_class_info_index]).intValue()];
+
+			ps.printf("%-30s %d: %x %s(#%d/c) %s(#%d/c) %s(#%d) %n", indent, i, inner_class_access_flags, iname,
+					inner_class_info_index, oname, outer_class_info_index, pool[inner_name_index], inner_name_index);
+		}
+	}
+
+	void printClassAccess(int mod) {
+		ps.printf("%-30s", "Class Access");
+		if ((ACC_PUBLIC & mod) != 0)
+			ps.print(" public");
+		if ((ACC_FINAL & mod) != 0)
+			ps.print(" final");
+		if ((ACC_SUPER & mod) != 0)
+			ps.print(" super");
+		if ((ACC_INTERFACE & mod) != 0)
+			ps.print(" interface");
+		if ((ACC_ABSTRACT & mod) != 0)
+			ps.print(" abstract");
+
+		ps.println();
+	}
+
+	void printAccess(int mod) {
+		ps.printf("%-30s", "Access");
+		if (Modifier.isStatic(mod))
+			ps.print(" static");
+		if (Modifier.isAbstract(mod))
+			ps.print(" abstract");
+		if (Modifier.isPublic(mod))
+			ps.print(" public");
+		if (Modifier.isFinal(mod))
+			ps.print(" final");
+		if (Modifier.isInterface(mod))
+			ps.print(" interface");
+		if (Modifier.isNative(mod))
+			ps.print(" native");
+		if (Modifier.isPrivate(mod))
+			ps.print(" private");
+		if (Modifier.isProtected(mod))
+			ps.print(" protected");
+		if (Modifier.isStrict(mod))
+			ps.print(" strict");
+		if (Modifier.isSynchronized(mod))
+			ps.print(" synchronized");
+		if (Modifier.isTransient(mod))
+			ps.print(" transient");
+		if (Modifier.isVolatile(mod))
+			ps.print(" volatile");
+
+		ps.println();
+	}
+
+	public static void main(String args[]) throws Exception {
+		if (args.length == 0) {
+			System.err.println("clsd <class file>+");
+		}
+		for (int i = 0; i < args.length; i++) {
+			File f = new File(args[i]);
+			if (!f.isFile())
+				System.err.println("File does not exist or is directory " + f);
+			else {
+				ClassDumper cd = new ClassDumper(args[i]);
+				cd.dump(null);
+			}
+		}
+	}
 
 }
diff --git a/aQute.libg/src/aQute/libg/classloaders/URLClassLoaderWrapper.java b/aQute.libg/src/aQute/libg/classloaders/URLClassLoaderWrapper.java
index 10ddca5..c199a92 100644
--- a/aQute.libg/src/aQute/libg/classloaders/URLClassLoaderWrapper.java
+++ b/aQute.libg/src/aQute/libg/classloaders/URLClassLoaderWrapper.java
@@ -4,24 +4,25 @@ import java.lang.reflect.*;
 import java.net.*;
 
 public class URLClassLoaderWrapper {
-	final URLClassLoader loader;
-	final Method addURL;
-	
+	final URLClassLoader	loader;
+	final Method			addURL;
+
 	public URLClassLoaderWrapper(ClassLoader loader) throws Exception {
 		this.loader = (URLClassLoader) loader;
 		addURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
 		addURL.setAccessible(true);
 	}
-	
-	public void addURL(URL url) throws Exception  {
+
+	public void addURL(URL url) throws Exception {
 		try {
-		addURL.invoke(loader, url);
-		} catch( InvocationTargetException ite) {
+			addURL.invoke(loader, url);
+		}
+		catch (InvocationTargetException ite) {
 			throw (Exception) ite.getTargetException();
 		}
 	}
-	
-	public Class<?> loadClass(String name) throws Exception {
+
+	public Class< ? > loadClass(String name) throws Exception {
 		return loader.loadClass(name);
 	}
 }
diff --git a/aQute.libg/src/aQute/libg/classloaders/packageinfo b/aQute.libg/src/aQute/libg/classloaders/packageinfo
new file mode 100644
index 0000000..9ad81f6
--- /dev/null
+++ b/aQute.libg/src/aQute/libg/classloaders/packageinfo
@@ -0,0 +1 @@
+version 1.0.0
diff --git a/aQute.libg/src/aQute/libg/clauses/Clauses.java b/aQute.libg/src/aQute/libg/clauses/Clauses.java
index 87da1cf..5701bab 100755
--- a/aQute.libg/src/aQute/libg/clauses/Clauses.java
+++ b/aQute.libg/src/aQute/libg/clauses/Clauses.java
@@ -5,15 +5,14 @@ import java.util.*;
 import aQute.libg.log.*;
 import aQute.libg.qtokens.*;
 
-public class Clauses extends LinkedHashMap<String,Map<String,String>>{
+public class Clauses extends LinkedHashMap<String,Map<String,String>> {
 	private static final long	serialVersionUID	= 1L;
-	
+
 	/**
 	 * Standard OSGi header parser. This parser can handle the format clauses
 	 * ::= clause ( ',' clause ) + clause ::= name ( ';' name ) (';' key '='
-	 * value )
-	 * 
-	 * This is mapped to a Map { name => Map { attr|directive => value } }
+	 * value ) This is mapped to a Map { name => Map { attr|directive => value }
+	 * }
 	 * 
 	 * @param value
 	 * @return
@@ -36,9 +35,8 @@ public class Clauses extends LinkedHashMap<String,Map<String,String>>{
 				String adname = qt.nextToken();
 				if ((del = qt.getSeparator()) != '=') {
 					if (hadAttribute)
-						throw new IllegalArgumentException(
-								"Header contains name field after attribute or directive: "
-										+ adname + " from " + value);
+						throw new IllegalArgumentException("Header contains name field after attribute or directive: "
+								+ adname + " from " + value);
 					aliases.add(adname);
 				} else {
 					String advalue = qt.nextToken();
@@ -48,13 +46,11 @@ public class Clauses extends LinkedHashMap<String,Map<String,String>>{
 				}
 			}
 			for (Iterator<String> i = aliases.iterator(); i.hasNext();) {
-				String packageName = (String) i.next();
+				String packageName = i.next();
 				if (result.containsKey(packageName)) {
 					if (logger != null)
-						logger
-								.warning("Duplicate package name in header: "
-										+ packageName
-										+ ". Multiple package names in one clause not supported in Bnd.");
+						logger.warning("Duplicate package name in header: " + packageName
+								+ ". Multiple package names in one clause not supported in Bnd.");
 				} else
 					result.put(packageName, clause);
 			}
diff --git a/aQute.libg/src/aQute/libg/clauses/Selector.java b/aQute.libg/src/aQute/libg/clauses/Selector.java
index 39837c3..50b53fa 100755
--- a/aQute.libg/src/aQute/libg/clauses/Selector.java
+++ b/aQute.libg/src/aQute/libg/clauses/Selector.java
@@ -1,21 +1,3 @@
-/*
- * $Header: /cvsroot/bnd/aQute.libg/src/aQute/libg/clauses/Selector.java,v 1.1 2009/01/19 14:17:42 pkriens Exp $
- * 
- * Copyright (c) OSGi Alliance (2006). All Rights Reserved.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
 package aQute.libg.clauses;
 
 import java.util.*;
@@ -62,21 +44,21 @@ public class Selector {
 			negated = true;
 			string = string.substring(1);
 		}
-		StringBuffer sb = new StringBuffer();
+		StringBuilder sb = new StringBuilder();
 		for (int c = 0; c < string.length(); c++) {
 			switch (string.charAt(c)) {
-			case '.':
-				sb.append("\\.");
-				break;
-			case '*':
-				sb.append(".*");
-				break;
-			case '?':
-				sb.append(".?");
-				break;
-			default:
-				sb.append(string.charAt(c));
-				break;
+				case '.' :
+					sb.append("\\.");
+					break;
+				case '*' :
+					sb.append(".*");
+					break;
+				case '?' :
+					sb.append(".?");
+					break;
+				default :
+					sb.append(string.charAt(c));
+					break;
 			}
 		}
 		string = sb.toString();
@@ -87,6 +69,7 @@ public class Selector {
 		return new Selector(sb.toString(), negated);
 	}
 
+	@Override
 	public String toString() {
 		return getPattern();
 	}
@@ -101,17 +84,16 @@ public class Selector {
 
 	public static List<Selector> getInstructions(Clauses clauses) {
 		List<Selector> result = new ArrayList<Selector>();
-		for (Map.Entry<String, Map<String, String>> entry : clauses.entrySet()) {
+		for (Map.Entry<String,Map<String,String>> entry : clauses.entrySet()) {
 			Selector instruction = getPattern(entry.getKey());
 			result.add(instruction);
 		}
 		return result;
 	}
-	
-	public static <T> List<T> select(Collection<T> domain,
-			List<Selector> instructions) {
+
+	public static <T> List<T> select(Collection<T> domain, List<Selector> instructions) {
 		List<T> result = new ArrayList<T>();
-		Iterator<T> iterator = domain.iterator(); 
+		Iterator<T> iterator = domain.iterator();
 		value: while (iterator.hasNext()) {
 			T value = iterator.next();
 			for (Selector instruction : instructions) {
@@ -124,6 +106,5 @@ public class Selector {
 		}
 		return result;
 	}
-	
 
 }
diff --git a/aQute.libg/src/aQute/libg/command/Command.java b/aQute.libg/src/aQute/libg/command/Command.java
index bae82eb..f48e016 100644
--- a/aQute.libg/src/aQute/libg/command/Command.java
+++ b/aQute.libg/src/aQute/libg/command/Command.java
@@ -2,20 +2,31 @@ package aQute.libg.command;
 
 import java.io.*;
 import java.util.*;
+import java.util.Map.Entry;
 import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
 
-import aQute.libg.reporter.*;
+import aQute.lib.io.*;
+import aQute.service.reporter.*;
 
 public class Command {
 
 	boolean				trace;
 	Reporter			reporter;
 	List<String>		arguments	= new ArrayList<String>();
+	Map<String,String>	variables	= new LinkedHashMap<String,String>();
 	long				timeout		= 0;
 	File				cwd			= new File("").getAbsoluteFile();
-	static Timer		timer		= new Timer();
+	static Timer		timer		= new Timer(Command.class.getName(), true);
 	Process				process;
 	volatile boolean	timedout;
+	String				fullCommand;
+
+	public Command(String fullCommand) {
+		this.fullCommand = fullCommand;
+	}
+
+	public Command() {}
 
 	public int execute(Appendable stdout, Appendable stderr) throws Exception {
 		return execute((InputStream) null, stdout, stderr);
@@ -26,15 +37,60 @@ public class Command {
 		return execute(in, stdout, stderr);
 	}
 
-	public int execute(InputStream in, Appendable stdout, Appendable stderr) throws Exception {
-		int result;
-		if (reporter != null) {
-			reporter.trace("executing cmd: %s", arguments);
+	public static boolean needsWindowsQuoting(String s) {
+		int len = s.length();
+		if (len == 0) // empty string have to be quoted
+			return true;
+		for (int i = 0; i < len; i++) {
+			switch (s.charAt(i)) {
+				case ' ' :
+				case '\t' :
+				case '\\' :
+				case '"' :
+					return true;
+			}
 		}
+		return false;
+	}
 
-		String args[] = arguments.toArray(new String[arguments.size()]);
+	public static String windowsQuote(String s) {
+		if (!needsWindowsQuoting(s))
+			return s;
+		s = s.replaceAll("([\\\\]*)\"", "$1$1\\\\\"");
+		s = s.replaceAll("([\\\\]*)\\z", "$1$1");
+		return "\"" + s + "\"";
+	}
 
-		process = Runtime.getRuntime().exec(args, null, cwd);
+	public int execute(final InputStream in, Appendable stdout, Appendable stderr) throws Exception {
+		if (reporter != null) {
+			reporter.trace("executing cmd: %s", arguments);
+		}
+		
+		ProcessBuilder p;
+		if (fullCommand != null) {
+			p = new ProcessBuilder(fullCommand);
+		} else {
+			//[cs] Arguments on windows aren't processed correctly. Thus the below junk
+			// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6511002
+			
+			if (System.getProperty("os.name").startsWith("Windows")) {
+				List<String> adjustedStrings = new LinkedList<String>();
+				for (String a : arguments) {
+					adjustedStrings.add(windowsQuote(a));
+				}
+				p = new ProcessBuilder(adjustedStrings);
+			} else {
+				p = new ProcessBuilder(arguments);
+			}
+		}
+		
+		Map<String, String> env = p.environment();
+		for (Entry<String,String> s : variables.entrySet()) {
+			env.put(s.getKey(), s.getValue());
+		}
+		
+		p.directory(cwd);
+		process = p.start();
 
 		// Make sure the command will not linger when we go
 		Runnable r = new Runnable() {
@@ -45,49 +101,104 @@ public class Command {
 		Thread hook = new Thread(r, arguments.toString());
 		Runtime.getRuntime().addShutdownHook(hook);
 		TimerTask timer = null;
-		OutputStream stdin = process.getOutputStream();
-		final InputStreamHandler handler = in != null ? new InputStreamHandler(in, stdin) : null;
-		
+		final OutputStream stdin = process.getOutputStream();
+		Thread rdInThread = null;
+
 		if (timeout != 0) {
 			timer = new TimerTask() {
+				//@Override TODO why did this not work? TimerTask implements Runnable
 				public void run() {
 					timedout = true;
 					process.destroy();
-					if (handler != null)
-						handler.interrupt();
 				}
 			};
 			Command.timer.schedule(timer, timeout);
 		}
 
+		final AtomicBoolean finished = new AtomicBoolean(false);
 		InputStream out = process.getInputStream();
 		try {
 			InputStream err = process.getErrorStream();
 			try {
-				new Collector(out, stdout).start();
-				new Collector(err, stdout).start();
-				if (handler != null)
-					handler.start();
+				Collector cout = new Collector(out, stdout);
+				cout.start();
+				Collector cerr = new Collector(err, stderr);
+				cerr.start();
 
-				result = process.waitFor();
-			} finally {
+				if (in != null) {
+					if (in == System.in) {
+						rdInThread = new Thread("Read Input Thread") {
+							@Override
+							public void run() {
+								try {
+									while (!finished.get()) {
+										int n = in.available();
+										if (n == 0) {
+											sleep(100);
+										} else {
+											int c = in.read();
+											if (c < 0) {
+												stdin.close();
+												return;
+											}
+											stdin.write(c);
+											if (c == '\n')
+												stdin.flush();
+										}
+									}
+								}
+								catch (InterruptedIOException e) {
+									// Ignore here
+								}
+								catch (Exception e) {
+									// Who cares?
+								}
+								finally {
+									IO.close(stdin);
+								}
+							}
+						};
+						rdInThread.setDaemon(true);
+						rdInThread.start();
+					} else {
+						IO.copy(in, stdin);
+						stdin.close();
+					}
+				}
+				if (reporter != null)
+					reporter.trace("exited process");
+
+				cerr.join();
+				cout.join();
+				if (reporter != null)
+					reporter.trace("stdout/stderr streams have finished");
+			}
+			finally {
 				err.close();
 			}
-		} finally {
+		}
+		finally {
 			out.close();
 			if (timer != null)
 				timer.cancel();
 			Runtime.getRuntime().removeShutdownHook(hook);
-			if (handler != null)
-				handler.interrupt();
 		}
+
+		byte exitValue = (byte) process.waitFor();
+		finished.set(true);
+		if (rdInThread != null) {
+			if (in != null)
+				IO.close(in);
+			rdInThread.interrupt();
+		}
+
 		if (reporter != null)
-			reporter.trace("cmd %s executed with result=%d, result: %s/%s", arguments, result,
-					stdout, stderr);
+			reporter.trace("cmd %s executed with result=%d, result: %s/%s, timedout=%s", arguments, exitValue, stdout,
+					stderr, timedout);
 
-		if( timedout )
+		if (timedout)
 			return Integer.MIN_VALUE;
-		byte exitValue = (byte) process.exitValue();
+
 		return exitValue;
 	}
 
@@ -127,27 +238,31 @@ public class Command {
 		final InputStream	in;
 		final Appendable	sb;
 
-		public Collector(InputStream inputStream, Appendable sb) {
+		Collector(InputStream inputStream, Appendable sb) {
 			this.in = inputStream;
 			this.sb = sb;
+			setDaemon(true);
 		}
 
+		@Override
 		public void run() {
 			try {
 				int c = in.read();
 				while (c >= 0) {
-					if (trace)
-						System.out.print((char) c);
 					sb.append((char) c);
 					c = in.read();
 				}
-			} catch (Exception e) {
+			}
+			catch (IOException e) {
+				// We assume the socket is closed
+			}
+			catch (Exception e) {
 				try {
 					sb.append("\n**************************************\n");
 					sb.append(e.toString());
 					sb.append("\n**************************************\n");
-				} catch (IOException e1) {
 				}
+				catch (IOException e1) {}
 				if (reporter != null) {
 					reporter.trace("cmd exec: %s", e);
 				}
@@ -155,31 +270,33 @@ public class Command {
 		}
 	}
 
-	class InputStreamHandler extends Thread {
-		final InputStream	in;
-		final OutputStream	stdin;
+	public Command var(String name, String value) {
+		variables.put(name, value);
+		return this;
+	}
 
-		public InputStreamHandler(InputStream in, OutputStream stdin) {
-			this.stdin = stdin;
-			this.in = in;
-		}
+	public Command arg(String... args) {
+		add(args);
+		return this;
+	}
 
-		public void run() {
-			try {
-				int c = in.read();
-				while (c >= 0) {
-					stdin.write(c);
-					stdin.flush();
-					c = in.read();
-				}
-			} catch (InterruptedIOException e) {
-				// Ignore here
-			} catch (Exception e) {
-				// Who cares?
-			}
+	public Command full(String full) {
+		fullCommand = full;
+		return this;
+	}
+
+	public void inherit() {
+		ProcessBuilder pb = new ProcessBuilder();
+		for (Entry<String,String> e : pb.environment().entrySet()) {
+			var(e.getKey(), e.getValue());
 		}
 	}
 
+	public String var(String name) {
+		return variables.get(name);
+	}
+
+	@Override
 	public String toString() {
 		StringBuilder sb = new StringBuilder();
 		String del = "";
diff --git a/aQute.libg/src/aQute/libg/command/packageinfo b/aQute.libg/src/aQute/libg/command/packageinfo
index 7c8de03..63eb236 100644
--- a/aQute.libg/src/aQute/libg/command/packageinfo
+++ b/aQute.libg/src/aQute/libg/command/packageinfo
@@ -1 +1 @@
-version 1.0
+version 3.0.0
diff --git a/aQute.libg/src/aQute/libg/cryptography/Crypto.java b/aQute.libg/src/aQute/libg/cryptography/Crypto.java
index 630597f..3d27188 100644
--- a/aQute.libg/src/aQute/libg/cryptography/Crypto.java
+++ b/aQute.libg/src/aQute/libg/cryptography/Crypto.java
@@ -7,61 +7,56 @@ import java.security.spec.*;
 import java.util.regex.*;
 
 public class Crypto {
-	static final Pattern	RSA_PRIVATE	= Pattern
-												.compile("\\s*RSA.Private\\((\\p{xDigit})+:(\\p{xDigit})+\\)\\s*");
-	static final Pattern	RSA_PUBLIC	= Pattern
-												.compile("\\s*RSA.Public\\((\\p{xDigit})+:(\\p{xDigit})+\\)\\s*");
+	static final Pattern	RSA_PRIVATE	= Pattern.compile("\\s*RSA\\.Private\\((\\p{XDigit})+:(\\p{XDigit})+\\)\\s*");
+	static final Pattern	RSA_PUBLIC	= Pattern.compile("\\s*RSA\\.Public\\((\\p{XDigit})+:(\\p{XDigit})+\\)\\s*");
 
 	/**
-	 * 
 	 * @param <T>
 	 * @param spec
 	 * @return
 	 * @throws Exception
 	 */
-	@SuppressWarnings("unchecked") public static <T> T fromString(String spec, Class<T> c) throws Exception {
-		if ( PrivateKey.class.isAssignableFrom(c)) {
-			Matcher m = RSA_PRIVATE.matcher(spec); 
-			if ( m.matches()) {
-				return (T) RSA.createPrivate(  
-						new BigInteger(m.group(1)), new BigInteger(m.group(2)));
+	public static <T> T fromString(String spec, Class<T> c) throws Exception {
+		if (PrivateKey.class.isAssignableFrom(c)) {
+			Matcher m = RSA_PRIVATE.matcher(spec);
+			if (m.matches()) {
+				return (T) RSA.createPrivate(new BigInteger(m.group(1)), new BigInteger(m.group(2)));
 			}
-			throw new IllegalArgumentException("No such private key " + spec );
+			throw new IllegalArgumentException("No such private key " + spec);
 		}
-		
-		if ( PublicKey.class.isAssignableFrom(c)) {
-			Matcher m = RSA_PUBLIC.matcher(spec); 
-			if ( m.matches()) {
-				return (T) RSA.create( new RSAPublicKeySpec( 
-						new BigInteger(m.group(1)), new BigInteger(m.group(2))));
+
+		if (PublicKey.class.isAssignableFrom(c)) {
+			Matcher m = RSA_PUBLIC.matcher(spec);
+			if (m.matches()) {
+				return (T) RSA.create(new RSAPublicKeySpec(new BigInteger(m.group(1)), new BigInteger(m.group(2))));
 			}
-			throw new IllegalArgumentException("No such public key " + spec );			
+			throw new IllegalArgumentException("No such public key " + spec);
 		}
 		return null;
 	}
 
-	public static String toString( Object key ) {
-		if ( key instanceof RSAPrivateKey ) {
+	public static String toString(Object key) {
+		if (key instanceof RSAPrivateKey) {
 			RSAPrivateKey pk = (RSAPrivateKey) key;
 			return "RSA.Private(" + pk.getModulus() + ":" + pk.getPrivateExponent() + ")";
 		}
-		if ( key instanceof RSAPublicKey ) {
+		if (key instanceof RSAPublicKey) {
 			RSAPublicKey pk = (RSAPublicKey) key;
 			return "RSA.Private(" + pk.getModulus() + ":" + pk.getPublicExponent() + ")";
 		}
 		return null;
 	}
 
-
-	public static <T extends Digest> Signer<T> signer(PrivateKey key, Digester<T> digester) throws NoSuchAlgorithmException {
-		Signature s = Signature.getInstance(key.getAlgorithm() + "with" + digester.getAlgorithm());
-		return new Signer<T>(s,digester);
-	}
+	// public static <T extends Digest> Signer<T> signer(PrivateKey key,
+	// Digester<T> digester) throws NoSuchAlgorithmException {
+	// Signature s = Signature.getInstance(key.getAlgorithm() + "with" +
+	// digester.getAlgorithm());
+	// return new Signer<T>(s,digester);
+	// }
 
 	public static Verifier verifier(PublicKey key, Digest digest) throws NoSuchAlgorithmException {
 		Signature s = Signature.getInstance(key.getAlgorithm() + "with" + digest.getAlgorithm());
-		return new Verifier(s,digest);
+		return new Verifier(s, digest);
 	}
 
-	
 }
diff --git a/aQute.libg/src/aQute/libg/cryptography/Digest.java b/aQute.libg/src/aQute/libg/cryptography/Digest.java
index f70caa0..119a35b 100644
--- a/aQute.libg/src/aQute/libg/cryptography/Digest.java
+++ b/aQute.libg/src/aQute/libg/cryptography/Digest.java
@@ -1,5 +1,7 @@
 package aQute.libg.cryptography;
 
+import java.util.*;
+
 import aQute.lib.hex.*;
 
 public abstract class Digest {
@@ -8,18 +10,39 @@ public abstract class Digest {
 	protected Digest(byte[] checksum, int width) {
 		this.digest = checksum;
 		if (digest.length != width)
-			throw new IllegalArgumentException("Invalid width for digest: " + digest.length
-					+ " expected " + width);
+			throw new IllegalArgumentException("Invalid width for digest: " + digest.length + " expected " + width);
 	}
 
-
 	public byte[] digest() {
 		return digest;
 	}
 
-	@Override public String toString() {
+	public String asHex() {
+		return Hex.toHexString(digest());
+	}
+
+	@Override
+	public String toString() {
 		return String.format("%s(d=%s)", getAlgorithm(), Hex.toHexString(digest));
 	}
 
 	public abstract String getAlgorithm();
+
+	@Override
+	public boolean equals(Object other) {
+		if (!(other instanceof Digest))
+			return false;
+
+		Digest d = (Digest) other;
+		return Arrays.equals(d.digest, digest);
+	}
+
+	@Override
+	public int hashCode() {
+		return Arrays.hashCode(digest);
+	}
+
+	public byte[] toByteArray() {
+		return digest();
+	}
 }
diff --git a/aQute.libg/src/aQute/libg/cryptography/Digester.java b/aQute.libg/src/aQute/libg/cryptography/Digester.java
index 50b9659..2722ab1 100644
--- a/aQute.libg/src/aQute/libg/cryptography/Digester.java
+++ b/aQute.libg/src/aQute/libg/cryptography/Digester.java
@@ -7,29 +7,54 @@ import aQute.lib.io.*;
 
 public abstract class Digester<T extends Digest> extends OutputStream {
 	protected MessageDigest	md;
-	
-	public Digester(MessageDigest instance){
+	OutputStream			out[];
+
+	public Digester(MessageDigest instance, OutputStream... out) {
 		md = instance;
+		this.out = out;
 	}
+
 	@Override
-	public void write( byte[] buffer, int offset, int length) throws IOException{
-		md.update(buffer,offset,length);
+	public void write(byte[] buffer, int offset, int length) throws IOException {
+		md.update(buffer, offset, length);
+		for (OutputStream o : out) {
+			o.write(buffer, offset, length);
+		}
 	}
+
 	@Override
-	public void write( int b) throws IOException{
+	public void write(int b) throws IOException {
 		md.update((byte) b);
+		for (OutputStream o : out) {
+			o.write(b);
+		}
 	}
-	
+
 	public MessageDigest getMessageDigest() throws Exception {
 		return md;
 	}
-	
+
 	public T from(InputStream in) throws Exception {
-		IO.copy(in,this);
+		IO.copy(in, this);
 		return digest();
 	}
-		
+
+	public void setOutputs(OutputStream... out) {
+		this.out = out;
+	}
+
 	public abstract T digest() throws Exception;
-	public abstract T digest( byte [] bytes) throws Exception;
+
+	public abstract T digest(byte[] bytes) throws Exception;
+
 	public abstract String getAlgorithm();
+
+	public T from(File f) throws Exception {
+		IO.copy(f, this);
+		return digest();
+	}
+	public T from(byte[] f) throws Exception {
+		IO.copy(f, this);
+		return digest();
+	}
 }
diff --git a/aQute.libg/src/aQute/libg/cryptography/Key.java b/aQute.libg/src/aQute/libg/cryptography/Key.java
index 160ec05..f4fc217 100644
--- a/aQute.libg/src/aQute/libg/cryptography/Key.java
+++ b/aQute.libg/src/aQute/libg/cryptography/Key.java
@@ -1,8 +1,6 @@
 package aQute.libg.cryptography;
 
-
 public abstract class Key implements java.security.Key {
 	private static final long	serialVersionUID	= 1L;
 
-
 }
diff --git a/aQute.libg/src/aQute/libg/cryptography/MD5.java b/aQute.libg/src/aQute/libg/cryptography/MD5.java
index 3fd7158..c6def1b 100644
--- a/aQute.libg/src/aQute/libg/cryptography/MD5.java
+++ b/aQute.libg/src/aQute/libg/cryptography/MD5.java
@@ -1,33 +1,48 @@
 package aQute.libg.cryptography;
 
+import java.io.*;
 import java.security.*;
 
+public class MD5 extends Digest {
+	public final static String	ALGORITHM	= "MD5";
 
+	public static Digester<MD5> getDigester(OutputStream... out) throws Exception {
+		return new Digester<MD5>(MessageDigest.getInstance(ALGORITHM), out) {
 
-public class MD5 extends Digest {
-	public final static String ALGORITHM = "MD5";
-	
-	public static Digester<MD5> getDigester() throws Exception {
-		return new Digester<MD5>(MessageDigest.getInstance(ALGORITHM)) {
-			
-			@Override public MD5 digest() throws Exception {
+			@Override
+			public MD5 digest() throws Exception {
 				return new MD5(md.digest());
 			}
 
-			@Override public MD5 digest(byte[] bytes) {
+			@Override
+			public MD5 digest(byte[] bytes) {
 				return new MD5(bytes);
 			}
-			@Override public String getAlgorithm() {
+
+			@Override
+			public String getAlgorithm() {
 				return ALGORITHM;
 			}
 		};
 	}
-	
-	
+
 	public MD5(byte[] digest) {
-		super(digest,16);
+		super(digest, 16);
 	}
 
-	@Override public String getAlgorithm() { return ALGORITHM; }
+	@Override
+	public String getAlgorithm() {
+		return ALGORITHM;
+	}
 
+	public static MD5 digest(byte [] data) throws Exception {
+		return getDigester().from(data);
+	}
+
+	public static MD5 digest(File f) throws NoSuchAlgorithmException, Exception {
+		return getDigester().from(f);
+	}
+	public static MD5 digest(InputStream f) throws NoSuchAlgorithmException, Exception {
+		return getDigester().from(f);
+	}
 }
\ No newline at end of file
diff --git a/aQute.libg/src/aQute/libg/cryptography/RSA.java b/aQute.libg/src/aQute/libg/cryptography/RSA.java
index 61bafb5..c1aa2ee 100644
--- a/aQute.libg/src/aQute/libg/cryptography/RSA.java
+++ b/aQute.libg/src/aQute/libg/cryptography/RSA.java
@@ -15,7 +15,8 @@ public class RSA {
 	static private KeyFactory getKeyFactory() {
 		try {
 			return KeyFactory.getInstance(ALGORITHM);
-		} catch (Exception e) {
+		}
+		catch (Exception e) {
 			// built in
 		}
 		return null;
@@ -24,20 +25,23 @@ public class RSA {
 	public static RSAPrivateKey create(RSAPrivateKeySpec keyspec) throws InvalidKeySpecException {
 		return (RSAPrivateKey) factory.generatePrivate(keyspec);
 	}
+
 	public static RSAPublicKey create(RSAPublicKeySpec keyspec) throws InvalidKeySpecException {
 		return (RSAPublicKey) factory.generatePrivate(keyspec);
 	}
-	
+
 	public static RSAPublicKey createPublic(BigInteger m, BigInteger e) throws InvalidKeySpecException {
-		return create( new RSAPublicKeySpec(m,e));
+		return create(new RSAPublicKeySpec(m, e));
 	}
+
 	public static RSAPrivateKey createPrivate(BigInteger m, BigInteger e) throws InvalidKeySpecException {
-		return create( new RSAPrivateKeySpec(m,e));
+		return create(new RSAPrivateKeySpec(m, e));
 	}
-	
-	public static Pair<RSAPrivateKey, RSAPublicKey> generate() throws NoSuchAlgorithmException {
+
+	public static Pair<RSAPrivateKey,RSAPublicKey> generate() throws NoSuchAlgorithmException {
 		KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM);
 		KeyPair keypair = kpg.generateKeyPair();
-		return new Pair<RSAPrivateKey,RSAPublicKey>( (RSAPrivateKey) keypair.getPrivate(), (RSAPublicKey) keypair.getPublic());
+		return new Pair<RSAPrivateKey,RSAPublicKey>((RSAPrivateKey) keypair.getPrivate(),
+				(RSAPublicKey) keypair.getPublic());
 	}
 }
diff --git a/aQute.libg/src/aQute/libg/cryptography/SHA1.java b/aQute.libg/src/aQute/libg/cryptography/SHA1.java
index 22e725b..c2f1e8d 100644
--- a/aQute.libg/src/aQute/libg/cryptography/SHA1.java
+++ b/aQute.libg/src/aQute/libg/cryptography/SHA1.java
@@ -1,33 +1,48 @@
 package aQute.libg.cryptography;
 
+import java.io.*;
 import java.security.*;
 
-
-
 public class SHA1 extends Digest {
-	public final static String ALGORITHM = "SHA1";
-	
-	public static Digester<SHA1> getDigester() throws NoSuchAlgorithmException {
+	public final static String	ALGORITHM	= "SHA1";
+
+	public static Digester<SHA1> getDigester(OutputStream... out) throws NoSuchAlgorithmException {
 		MessageDigest md = MessageDigest.getInstance(ALGORITHM);
-		return new Digester<SHA1>(md) {
-			@Override public SHA1 digest() throws Exception {
+		return new Digester<SHA1>(md, out) {
+			@Override
+			public SHA1 digest() throws Exception {
 				return new SHA1(md.digest());
 			}
 
-			@Override public SHA1 digest(byte[] bytes) {
+			@Override
+			public SHA1 digest(byte[] bytes) {
 				return new SHA1(bytes);
 			}
-			@Override public String getAlgorithm() {
+
+			@Override
+			public String getAlgorithm() {
 				return ALGORITHM;
 			}
 		};
 	}
-	
+
 	public SHA1(byte[] b) {
 		super(b, 20);
 	}
 
+	@Override
+	public String getAlgorithm() {
+		return ALGORITHM;
+	}
 
-	@Override public String getAlgorithm() { return ALGORITHM; }
+	public static SHA1 digest(byte [] data) throws Exception {
+		return getDigester().from(data);
+	}
 
+	public static SHA1 digest(File f) throws NoSuchAlgorithmException, Exception {
+		return getDigester().from(f);
+	}
+	public static SHA1 digest(InputStream f) throws NoSuchAlgorithmException, Exception {
+		return getDigester().from(f);
+	}
 }
\ No newline at end of file
diff --git a/aQute.libg/src/aQute/libg/cryptography/SHA256.java b/aQute.libg/src/aQute/libg/cryptography/SHA256.java
new file mode 100644
index 0000000..42baf4e
--- /dev/null
+++ b/aQute.libg/src/aQute/libg/cryptography/SHA256.java
@@ -0,0 +1,49 @@
+package aQute.libg.cryptography;
+
+import java.io.*;
+import java.security.*;
+
+public class SHA256 extends Digest {
+	public final static String	ALGORITHM	= "SHA256";
+
+	public static Digester<SHA256> getDigester(OutputStream... out) throws NoSuchAlgorithmException {
+		MessageDigest md = MessageDigest.getInstance(ALGORITHM);
+		return new Digester<SHA256>(md, out) {
+			@Override
+			public SHA256 digest() throws Exception {
+				return new SHA256(md.digest());
+			}
+
+			@Override
+			public SHA256 digest(byte[] bytes) {
+				return new SHA256(bytes);
+			}
+
+			@Override
+			public String getAlgorithm() {
+				return ALGORITHM;
+			}
+		};
+	}
+
+	public SHA256(byte[] b) {
+		super(b, 32);
+	}
+
+	@Override
+	public String getAlgorithm() {
+		return ALGORITHM;
+	}
+
+
+	public static SHA256 digest(byte [] data) throws Exception {
+		return getDigester().from(data);
+	}
+
+	public static SHA256 digest(File f) throws NoSuchAlgorithmException, Exception {
+		return getDigester().from(f);
+	}
+	public static SHA256 digest(InputStream f) throws NoSuchAlgorithmException, Exception {
+		return getDigester().from(f);
+	}
+}
\ No newline at end of file
diff --git a/aQute.libg/src/aQute/libg/cryptography/Signer.java b/aQute.libg/src/aQute/libg/cryptography/Signer.java
index a068677..977eda6 100644
--- a/aQute.libg/src/aQute/libg/cryptography/Signer.java
+++ b/aQute.libg/src/aQute/libg/cryptography/Signer.java
@@ -5,31 +5,40 @@ import java.security.*;
 
 public class Signer<D extends Digest> extends OutputStream {
 	Signature	signature;
-	Digester<D> digester;
-	
+	Digester<D>	digester;
+
 	Signer(Signature s, Digester<D> digester) {
 		this.signature = s;
-		this.digester  = digester;
+		this.digester = digester;
 	}
 
-	@Override public void write(byte[] buffer, int offset, int length) throws IOException {
+	@Override
+	public void write(byte[] buffer, int offset, int length) throws IOException {
 		try {
 			signature.update(buffer, offset, length);
-		} catch (SignatureException e) {
-			throw new IOException(e);
+			digester.write(buffer, offset, length);
+		}
+		catch (SignatureException e) {
+			throw new IOException(e.getLocalizedMessage());
 		}
 	}
 
-	@Override public void write(int b) throws IOException {
+	@Override
+	public void write(int b) throws IOException {
 		try {
 			signature.update((byte) b);
-		} catch (SignatureException e) {
-			throw new IOException(e);
+			digester.write(b);
+		}
+		catch (SignatureException e) {
+			throw new IOException(e.getLocalizedMessage());
 		}
 	}
-	
 
-	public D signature() throws Exception {
-		return digester.digest(signature().digest());
+	public Signature signature() throws Exception {
+		return signature;
+	}
+
+	public D digest() throws Exception {
+		return digester.digest();
 	}
 }
diff --git a/aQute.libg/src/aQute/libg/cryptography/Verifier.java b/aQute.libg/src/aQute/libg/cryptography/Verifier.java
index 90d6993..1005e0a 100644
--- a/aQute.libg/src/aQute/libg/cryptography/Verifier.java
+++ b/aQute.libg/src/aQute/libg/cryptography/Verifier.java
@@ -3,36 +3,37 @@ package aQute.libg.cryptography;
 import java.io.*;
 import java.security.*;
 
-
 public class Verifier extends OutputStream {
-	final Signature signature;
-	final Digest d;
-	
+	final Signature	signature;
+	final Digest	d;
+
 	Verifier(Signature s, Digest d) {
 		this.signature = s;
 		this.d = d;
 	}
-	
+
 	@Override
-	public void write( byte[] buffer, int offset, int length) throws IOException {
+	public void write(byte[] buffer, int offset, int length) throws IOException {
 		try {
 			signature.update(buffer, offset, length);
-		} catch (SignatureException e) {
-			throw new IOException(e);
+		}
+		catch (SignatureException e) {
+			throw new IOException(e.getLocalizedMessage());
 		}
 	}
 
 	@Override
-	public void write( int b) throws IOException {
+	public void write(int b) throws IOException {
 		try {
 			signature.update((byte) b);
-		} catch (SignatureException e) {
-			throw new IOException(e);
+		}
+		catch (SignatureException e) {
+			throw new IOException(e.getLocalizedMessage());
 		}
 	}
 
 	public boolean verify() throws Exception {
 		return signature.verify(d.digest());
 	}
-	
+
 }
diff --git a/aQute.libg/src/aQute/libg/cryptography/packageinfo b/aQute.libg/src/aQute/libg/cryptography/packageinfo
index 7c8de03..e39f616 100644
--- a/aQute.libg/src/aQute/libg/cryptography/packageinfo
+++ b/aQute.libg/src/aQute/libg/cryptography/packageinfo
@@ -1 +1 @@
-version 1.0
+version 1.1.0
diff --git a/aQute.libg/src/aQute/libg/dumpzip/DumpZip.java b/aQute.libg/src/aQute/libg/dumpzip/DumpZip.java
deleted file mode 100644
index 89f3e6b..0000000
--- a/aQute.libg/src/aQute/libg/dumpzip/DumpZip.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package aQute.libg.dumpzip;
-
-import java.io.*;
-
-public class DumpZip {
-    PrintStream out;
-    
-    
-}
diff --git a/aQute.libg/src/aQute/libg/filecheck/FileCheck.java b/aQute.libg/src/aQute/libg/filecheck/FileCheck.java
deleted file mode 100644
index 9cca361..0000000
--- a/aQute.libg/src/aQute/libg/filecheck/FileCheck.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package aQute.libg.filecheck;
-
-
-public class FileCheck {
-
-	public static void main(String args[] ) {
-//		File f = new File("/Ws/osgi/build").getAbsoluteFile();
-//		long now = System.currentTimeMillis();
-//		traverse(f);
-//		System.out.printf("")
-	}
-}
diff --git a/aQute.libg/src/aQute/libg/fileiterator/FileIterator.java b/aQute.libg/src/aQute/libg/fileiterator/FileIterator.java
index c60ed6b..2c988e6 100644
--- a/aQute.libg/src/aQute/libg/fileiterator/FileIterator.java
+++ b/aQute.libg/src/aQute/libg/fileiterator/FileIterator.java
@@ -4,42 +4,39 @@ import java.io.*;
 import java.util.*;
 
 public class FileIterator implements Iterator<File> {
-    File         dir;
-    int          n = 0;
-    FileIterator next;
+	File			dir;
+	int				n	= 0;
+	FileIterator	next;
 
-    public FileIterator(File nxt) {
-        assert nxt.isDirectory();
-        this.dir = nxt;
-    }
+	public FileIterator(File nxt) {
+		assert nxt.isDirectory();
+		this.dir = nxt;
+	}
 
-    public boolean hasNext() {
-        if (next != null)
-            return next.hasNext();
-        else
-            return n < dir.list().length;
-    }
+	public boolean hasNext() {
+		if (next != null)
+			return next.hasNext();
+		return n < dir.list().length;
+	}
 
-    public File next() {
-        if (next != null) {
-            File answer = next.next();
-            if (!next.hasNext())
-                next = null;
-            return answer;
-        } else {
-            File nxt = dir.listFiles()[n++];
-            if (nxt.isDirectory()) {
-                next = new FileIterator(nxt);
-                return nxt;
-            } else if (nxt.isFile()) {
-                return nxt;
-            } else
-                throw new IllegalStateException("File disappeared");
-        }
-    }
+	public File next() {
+		if (next != null) {
+			File answer = next.next();
+			if (!next.hasNext())
+				next = null;
+			return answer;
+		}
+		File nxt = dir.listFiles()[n++];
+		if (nxt.isDirectory()) {
+			next = new FileIterator(nxt);
+			return nxt;
+		} else if (nxt.isFile()) {
+			return nxt;
+		} else
+			throw new IllegalStateException("File disappeared");
+	}
 
-    public void remove() {
-        throw new UnsupportedOperationException(
-                "Cannot remove from a file iterator");
-    }
+	public void remove() {
+		throw new UnsupportedOperationException("Cannot remove from a file iterator");
+	}
 }
diff --git a/aQute.libg/src/aQute/libg/filelock/DirectoryLock.java b/aQute.libg/src/aQute/libg/filelock/DirectoryLock.java
index 6e6b11e..9f82899 100644
--- a/aQute.libg/src/aQute/libg/filelock/DirectoryLock.java
+++ b/aQute.libg/src/aQute/libg/filelock/DirectoryLock.java
@@ -3,9 +3,9 @@ package aQute.libg.filelock;
 import java.io.*;
 
 public class DirectoryLock {
-	final File						lock;
-	final long						timeout;
-	final public static String LOCKNAME = ".lock";
+	final File					lock;
+	final long					timeout;
+	final public static String	LOCKNAME	= ".lock";
 
 	public DirectoryLock(File directory, long timeout) {
 		this.lock = new File(directory, LOCKNAME);
@@ -13,7 +13,6 @@ public class DirectoryLock {
 		this.timeout = timeout;
 	}
 
-	
 	public void release() {
 		lock.delete();
 	}
@@ -22,10 +21,10 @@ public class DirectoryLock {
 		if (lock.mkdir())
 			return;
 
-		long deadline = System.currentTimeMillis()+ timeout;
-		while ( System.currentTimeMillis() < deadline) {
+		long deadline = System.currentTimeMillis() + timeout;
+		while (System.currentTimeMillis() < deadline) {
 			if (lock.mkdir())
-				return;	
+				return;
 			Thread.sleep(50);
 		}
 	}
diff --git a/aQute.libg/src/aQute/libg/filelock/packageinfo b/aQute.libg/src/aQute/libg/filelock/packageinfo
new file mode 100644
index 0000000..9ad81f6
--- /dev/null
+++ b/aQute.libg/src/aQute/libg/filelock/packageinfo
@@ -0,0 +1 @@
+version 1.0.0
diff --git a/aQute.libg/src/aQute/libg/filerepo/FileRepo.java b/aQute.libg/src/aQute/libg/filerepo/FileRepo.java
deleted file mode 100644
index db93ec1..0000000
--- a/aQute.libg/src/aQute/libg/filerepo/FileRepo.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package aQute.libg.filerepo;
-
-import java.io.*;
-import java.util.*;
-import java.util.regex.*;
-
-import aQute.libg.version.*;
-
-public class FileRepo {
-	File	root;
-	Pattern	REPO_FILE	= Pattern.compile("([-a-zA-z0-9_\\.]+)-([0-9\\.]+|latest)\\.(jar|lib)");
-
-	public FileRepo(File root) {
-		this.root = root;
-	}
-
-	/**
-	 * Get a list of URLs to bundles that are constrained by the bsn and
-	 * versionRange.
-	 */
-	public File[] get(String bsn, final VersionRange versionRange) throws Exception {
-
-		//
-		// Check if the entry exists
-		//
-		File f = new File(root, bsn);
-		if (!f.isDirectory())
-			return null;
-
-		//
-		// Iterator over all the versions for this BSN.
-		// Create a sorted map over the version as key
-		// and the file as URL as value. Only versions
-		// that match the desired range are included in
-		// this list.
-		//
-		return f.listFiles(new FilenameFilter() {
-			public boolean accept(File dir, String name) {
-				Matcher m = REPO_FILE.matcher(name);
-				if (!m.matches())
-					return false;
-
-				Version v = new Version(m.group(2));
-				return versionRange.includes(v);
-			}
-		});
-	}
-
-	public List<String> list(String regex) throws Exception {
-		if (regex == null)
-			regex = ".*";
-		final Pattern pattern = Pattern.compile(regex);
-
-		String list[] = root.list(new FilenameFilter() {
-
-			public boolean accept(File dir, String name) {
-				Matcher matcher = pattern.matcher(name);
-				return matcher.matches();
-			}
-
-		});
-		return Arrays.asList(list);
-	}
-
-	public List<Version> versions(String bsn) throws Exception {
-		File dir = new File(root, bsn);
-		final List<Version> versions = new ArrayList<Version>();
-		dir.list(new FilenameFilter() {
-
-			public boolean accept(File dir, String name) {
-				Matcher m = REPO_FILE.matcher(name);
-				if (m.matches()) {
-					versions.add(new Version(m.group(2)));
-					return true;
-				}
-				return false;
-			}
-
-		});
-		return versions;
-	}
-
-	public File get(String bsn, VersionRange range, int strategy) throws Exception {
-		File[] files = get(bsn, range);
-		if (files.length == 0)
-			return null;
-
-		if (files.length == 1)
-			return files[0];
-
-		if (strategy < 0) {
-			return files[0];
-		} else
-			return files[files.length - 1];
-	}
-
-	public File put(String bsn, Version version) {
-		File dir = new File(bsn);
-		dir.mkdirs();
-		File file = new File(dir, bsn + "-" + version.getMajor() + "." + version.getMinor() + "." + version.getMicro());
-		return file;
-	}
-	
-	
-	
-}
diff --git a/aQute.libg/src/aQute/libg/filters/AndFilter.java b/aQute.libg/src/aQute/libg/filters/AndFilter.java
new file mode 100644
index 0000000..2561d77
--- /dev/null
+++ b/aQute.libg/src/aQute/libg/filters/AndFilter.java
@@ -0,0 +1,30 @@
+package aQute.libg.filters;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public final class AndFilter extends Filter {
+	
+	private final List<Filter> children = new LinkedList<Filter>();
+	
+	public AndFilter addChild(Filter child) {
+		if (child instanceof AndFilter)
+			children.addAll(((AndFilter) child).children);
+		else
+			children.add(child);
+		return this;
+	}
+
+	@Override
+	public void append(StringBuilder builder) {
+		if (children.isEmpty())
+			return;
+		
+		builder.append("(&");
+		for (Filter child : children) {
+			child.append(builder);
+		}
+		builder.append(")");
+	}
+
+}
diff --git a/aQute.libg/src/aQute/libg/filters/Filter.java b/aQute.libg/src/aQute/libg/filters/Filter.java
new file mode 100644
index 0000000..e0a4555
--- /dev/null
+++ b/aQute.libg/src/aQute/libg/filters/Filter.java
@@ -0,0 +1,14 @@
+package aQute.libg.filters;
+
+public abstract class Filter {
+
+	public abstract void append(StringBuilder builder);
+
+	@Override
+	public String toString() {
+		StringBuilder builder = new StringBuilder();
+		append(builder);
+		return builder.toString();
+	}
+
+}
diff --git a/aQute.libg/src/aQute/libg/filters/LiteralFilter.java b/aQute.libg/src/aQute/libg/filters/LiteralFilter.java
new file mode 100644
index 0000000..ca09228
--- /dev/null
+++ b/aQute.libg/src/aQute/libg/filters/LiteralFilter.java
@@ -0,0 +1,16 @@
+package aQute.libg.filters;
+
+public class LiteralFilter extends Filter {
+	
+	private String	filterString;
+
+	public LiteralFilter(String filterString) {
+		this.filterString = filterString;
+	}
+
+	@Override
+	public void append(StringBuilder builder) {
+		builder.append(filterString);
+	}
+
+}
diff --git a/aQute.libg/src/aQute/libg/filters/NotFilter.java b/aQute.libg/src/aQute/libg/filters/NotFilter.java
new file mode 100644
index 0000000..0f1061c
--- /dev/null
+++ b/aQute.libg/src/aQute/libg/filters/NotFilter.java
@@ -0,0 +1,19 @@
+package aQute.libg.filters;
+
+public final class NotFilter extends Filter {
+
+	private final Filter	child;
+
+	public NotFilter(Filter child) {
+		this.child = child;
+	}
+
+	@Override
+	public void append(StringBuilder builder) {
+		builder.append("(!");
+		child.append(builder);
+		builder.append(")");
+	}
+	
+	
+}
diff --git a/aQute.libg/src/aQute/libg/filters/Operator.java b/aQute.libg/src/aQute/libg/filters/Operator.java
new file mode 100644
index 0000000..b17aaff
--- /dev/null
+++ b/aQute.libg/src/aQute/libg/filters/Operator.java
@@ -0,0 +1,17 @@
+package aQute.libg.filters;
+
+public enum Operator {
+
+	Equals("="), LessThanOrEqual("<="), GreaterThanOrEqual(">="), ApproxEqual("~=");
+
+	private final String	symbol;
+
+	Operator(String symbol) {
+		this.symbol = symbol;
+	}
+
+	public String getSymbol() {
+		return symbol;
+	}
+
+}
diff --git a/aQute.libg/src/aQute/libg/filters/OrFilter.java b/aQute.libg/src/aQute/libg/filters/OrFilter.java
new file mode 100644
index 0000000..b3332bd
--- /dev/null
+++ b/aQute.libg/src/aQute/libg/filters/OrFilter.java
@@ -0,0 +1,30 @@
+package aQute.libg.filters;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public final class OrFilter extends Filter {
+	
+	private final List<Filter> children = new LinkedList<Filter>();
+	
+	public OrFilter addChild(Filter child) {
+		if (child instanceof OrFilter)
+			children.addAll(((OrFilter) child).children);
+		else
+			children.add(child);
+		return this;
+	}
+
+	@Override
+	public void append(StringBuilder builder) {
+		if (children.isEmpty())
+			return;
+		
+		builder.append("(|");
+		for (Filter child : children) {
+			child.append(builder);
+		}
+		builder.append(")");
+	}
+
+}
diff --git a/aQute.libg/src/aQute/libg/filters/SimpleFilter.java b/aQute.libg/src/aQute/libg/filters/SimpleFilter.java
new file mode 100644
index 0000000..f0dea65
--- /dev/null
+++ b/aQute.libg/src/aQute/libg/filters/SimpleFilter.java
@@ -0,0 +1,33 @@
+package aQute.libg.filters;
+
+public final class SimpleFilter extends Filter {
+
+	private final String	name;
+	private final Operator	operator;
+	private final String	value;
+
+	/**
+	 * Construct a simple filter with the default "equals" operator, i.e.
+	 * {@code (name=value)}.
+	 */
+	public SimpleFilter(String name, String value) {
+		this(name, Operator.Equals, value);
+	}
+
+	/**
+	 * Construct a simple filter with any of the comparison operators.
+	 */
+	public SimpleFilter(String name, Operator operator, String value) {
+		this.name = name;
+		this.operator = operator;
+		this.value = value;
+	}
+
+	@Override
+	public void append(StringBuilder builder) {
+		builder.append('(');
+		builder.append(name).append(operator.getSymbol()).append(value);
+		builder.append(')');
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/help/packageinfo b/aQute.libg/src/aQute/libg/filters/packageinfo
similarity index 100%
copy from biz.aQute.bndlib/src/aQute/bnd/help/packageinfo
copy to aQute.libg/src/aQute/libg/filters/packageinfo
diff --git a/aQute.libg/src/aQute/libg/forker/Forker.java b/aQute.libg/src/aQute/libg/forker/Forker.java
index 7eb6f36..14bb0f8 100644
--- a/aQute.libg/src/aQute/libg/forker/Forker.java
+++ b/aQute.libg/src/aQute/libg/forker/Forker.java
@@ -12,12 +12,11 @@ import java.util.concurrent.atomic.*;
  * have ran their associated runnable.
  * 
  * @author aqute
- * 
  * @param <T>
  */
 public class Forker<T> {
 	final Executor		executor;
-	final Map<T, Job>	waiting		= new HashMap<T, Job>();
+	final Map<T,Job>	waiting		= new HashMap<T,Job>();
 	final Set<Job>		executing	= new HashSet<Job>();
 	final AtomicBoolean	canceled	= new AtomicBoolean();
 	private int			count;
@@ -47,13 +46,13 @@ public class Forker<T> {
 
 					t = Thread.currentThread();
 				}
-				System.out.println("Running " + target);
 				runnable.run();
-				System.out.println("Done running " + target);
-			} catch (Exception e) {
+			}
+			catch (Exception e) {
 				exception = e;
 				e.printStackTrace();
-			} finally {
+			}
+			finally {
 				synchronized (this) {
 					t = null;
 				}
@@ -65,7 +64,7 @@ public class Forker<T> {
 		/**
 		 * Cancel this job
 		 */
-		private void cancel() {
+		void cancel() {
 			if (!canceled.getAndSet(true)) {
 				synchronized (this) {
 					if (t != null)
@@ -86,7 +85,6 @@ public class Forker<T> {
 
 	/**
 	 * Constructor
-	 * 
 	 */
 	public Forker() {
 		this.executor = Executors.newFixedThreadPool(4);
@@ -103,12 +101,11 @@ public class Forker<T> {
 	 * @param runnable
 	 *            the runnable to run
 	 */
-	public synchronized void doWhen(Collection<? extends T> dependencies, T target,
-			Runnable runnable) {
+	public synchronized void doWhen(Collection< ? extends T> dependencies, T target, Runnable runnable) {
 		if (waiting.containsKey(target))
 			throw new IllegalArgumentException("You can only add a target once to the forker");
 
-		System.out.println("doWhen " + dependencies + " " + target);
+		System.err.println("doWhen " + dependencies + " " + target);
 		Job job = new Job();
 		job.dependencies = new HashSet<T>(dependencies);
 		job.target = target;
@@ -119,7 +116,7 @@ public class Forker<T> {
 	public void start(long ms) throws InterruptedException {
 		check();
 		count = waiting.size();
-		System.out.println("Count " + count);
+		System.err.println("Count " + count);
 		schedule();
 		if (ms >= 0)
 			sync(ms);
@@ -132,18 +129,17 @@ public class Forker<T> {
 		dependencies.removeAll(waiting.keySet());
 		if (dependencies.size() > 0)
 			throw new IllegalArgumentException(
-					"There are dependencies in the jobs that are not present in the targets: "
-							+ dependencies);
+					"There are dependencies in the jobs that are not present in the targets: " + dependencies);
 
 	}
 
 	public synchronized void sync(long ms) throws InterruptedException {
-		System.out.println("Waiting for sync");
+		System.err.println("Waiting for sync");
 		while (count > 0) {
-			System.out.println("Waiting for sync " + count);
+			System.err.println("Waiting for sync " + count);
 			wait(ms);
 		}
-		System.out.println("Exiting sync " + count);
+		System.err.println("Exiting sync " + count);
 	}
 
 	private void schedule() {
@@ -170,20 +166,22 @@ public class Forker<T> {
 	 * 
 	 * @param done
 	 */
-	private void done(Job done) {
+	void done(Job done) {
 		synchronized (this) {
-			System.out.println("count = " + count);
+			System.err.println("count = " + count);
 			executing.remove(done);
 			count--;
 			if (count == 0) {
-				System.out.println("finished");
+				System.err.println("finished");
 				notifyAll();
 				return;
 			}
 
 			for (Job job : waiting.values()) {
-				boolean x = job.dependencies.remove(done.target);
-				//System.out.println( "Removing " + done.target + " from " + job.target + " ?" + x  + " " + job.dependencies.size());
+				// boolean x =
+				job.dependencies.remove(done.target);
+				// System.err.println( "Removing " + done.target + " from " +
+				// job.target + " ?" + x + " " + job.dependencies.size());
 			}
 		}
 		schedule();
@@ -195,7 +193,7 @@ public class Forker<T> {
 	 * @throws InterruptedException
 	 */
 	public void cancel(long ms) throws InterruptedException {
-		System.out.println("canceled " + count);
+		System.err.println("canceled " + count);
 
 		if (!canceled.getAndSet(true)) {
 			synchronized (this) {
diff --git a/aQute.libg/src/aQute/libg/generics/Create.java b/aQute.libg/src/aQute/libg/generics/Create.java
index 6edc687..3e071b3 100644
--- a/aQute.libg/src/aQute/libg/generics/Create.java
+++ b/aQute.libg/src/aQute/libg/generics/Create.java
@@ -3,40 +3,51 @@ package aQute.libg.generics;
 import java.util.*;
 
 public class Create {
-    
-    public static <K,V>  Map<K, V> map() {
-        return new LinkedHashMap<K,V>();
-    }
-
-    public static <T>  List<T> list() {
-        return new ArrayList<T>();
-    }
-
-    public static <T>  Set<T> set() {
-        return new HashSet<T>();
-    }
-
-    public static <T>  List<T> list(T[] source) {
-        return new ArrayList<T>(Arrays.asList(source));
-    }
-
-    public static <T>  Set<T> set(T[]source) {
-        return new HashSet<T>(Arrays.asList(source));
-    }
-
-    public static <K,V>  Map<K, V> copy(Map<K,V> source) {
-        return new LinkedHashMap<K,V>(source);
-    }
-
-    public static <T>  List<T> copy(List<T> source) {
-        return new ArrayList<T>(source);
-    }
-
-    public static <T>  Set<T> copy(Collection<T> source) {
-        if ( source == null )
-            return set();
-        return new HashSet<T>(source);
-    }
-
-    
+
+	public static <K, V> Map<K,V> map() {
+		return new LinkedHashMap<K,V>();
+	}
+
+	public static <K, V> Map<K,V> map(Class<K> key, Class<V> value) {
+		return Collections.checkedMap(new LinkedHashMap<K,V>(), key, value);
+	}
+
+	public static <T> List<T> list() {
+		return new ArrayList<T>();
+	}
+
+	public static <T> List<T> list(Class<T> c) {
+		return Collections.checkedList(new ArrayList<T>(), c);
+	}
+
+	public static <T> Set<T> set() {
+		return new HashSet<T>();
+	}
+
+	public static <T> Set<T> set(Class<T> c) {
+		return Collections.checkedSet(new HashSet<T>(), c);
+	}
+
+	public static <T> List<T> list(T[] source) {
+		return new ArrayList<T>(Arrays.asList(source));
+	}
+
+	public static <T> Set<T> set(T[] source) {
+		return new HashSet<T>(Arrays.asList(source));
+	}
+
+	public static <K, V> Map<K,V> copy(Map<K,V> source) {
+		return new LinkedHashMap<K,V>(source);
+	}
+
+	public static <T> List<T> copy(List<T> source) {
+		return new ArrayList<T>(source);
+	}
+
+	public static <T> Set<T> copy(Collection<T> source) {
+		if (source == null)
+			return set();
+		return new HashSet<T>(source);
+	}
+
 }
diff --git a/aQute.libg/src/aQute/libg/glob/Glob.java b/aQute.libg/src/aQute/libg/glob/Glob.java
index c4d06a7..6202524 100644
--- a/aQute.libg/src/aQute/libg/glob/Glob.java
+++ b/aQute.libg/src/aQute/libg/glob/Glob.java
@@ -1,22 +1,22 @@
 package aQute.libg.glob;
 
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import java.util.*;
+import java.util.regex.*;
 
 public class Glob {
 
-	private final String glob;
-	private final Pattern pattern;
-	
+	private final String	glob;
+	private final Pattern	pattern;
+
 	public Glob(String globString) {
 		this.glob = globString;
 		this.pattern = Pattern.compile(convertGlobToRegEx(globString));
 	}
-	
+
 	public Matcher matcher(CharSequence input) {
 		return pattern.matcher(input);
 	}
-	
+
 	@Override
 	public String toString() {
 		return glob;
@@ -26,85 +26,93 @@ public class Glob {
 		line = line.trim();
 		int strLen = line.length();
 		StringBuilder sb = new StringBuilder(strLen);
-		// Remove beginning and ending * globs because they're useless
-		if (line.startsWith("*")) {
-			line = line.substring(1);
-			strLen--;
-		}
-		if (line.endsWith("*")) {
-			line = line.substring(0, strLen - 1);
-			strLen--;
-		}
 		boolean escaping = false;
 		int inCurlies = 0;
 		for (char currentChar : line.toCharArray()) {
 			switch (currentChar) {
-			case '*':
-				if (escaping)
-					sb.append("\\*");
-				else
-					sb.append(".*");
-				escaping = false;
-				break;
-			case '?':
-				if (escaping)
-					sb.append("\\?");
-				else
-					sb.append('.');
-				escaping = false;
-				break;
-			case '.':
-			case '(':
-			case ')':
-			case '+':
-			case '|':
-			case '^':
-			case '$':
-			case '@':
-			case '%':
-				sb.append('\\');
-				sb.append(currentChar);
-				escaping = false;
-				break;
-			case '\\':
-				if (escaping) {
-					sb.append("\\\\");
+				case '*' :
+					if (escaping)
+						sb.append("\\*");
+					else
+						sb.append(".*");
+					escaping = false;
+					break;
+				case '?' :
+					if (escaping)
+						sb.append("\\?");
+					else
+						sb.append('.');
+					escaping = false;
+					break;
+				case '.' :
+				case '(' :
+				case ')' :
+				case '+' :
+				case '|' :
+				case '^' :
+				case '$' :
+				case '@' :
+				case '%' :
+					sb.append('\\');
+					sb.append(currentChar);
+					escaping = false;
+					break;
+				case '\\' :
+					if (escaping) {
+						sb.append("\\\\");
+						escaping = false;
+					} else
+						escaping = true;
+					break;
+				case '{' :
+					if (escaping) {
+						sb.append("\\{");
+					} else {
+						sb.append('(');
+						inCurlies++;
+					}
 					escaping = false;
-				} else
-					escaping = true;
-				break;
-			case '{':
-				if (escaping) {
-					sb.append("\\{");
-				} else {
-					sb.append('(');
-					inCurlies++;
-				}
-				escaping = false;
-				break;
-			case '}':
-				if (inCurlies > 0 && !escaping) {
-					sb.append(')');
-					inCurlies--;
-				} else if (escaping)
-					sb.append("\\}");
-				else
-					sb.append("}");
-				escaping = false;
-				break;
-			case ',':
-				if (inCurlies > 0 && !escaping) {
-					sb.append('|');
-				} else if (escaping)
-					sb.append("\\,");
-				else
-					sb.append(",");
-				break;
-			default:
-				escaping = false;
-				sb.append(currentChar);
+					break;
+				case '}' :
+					if (inCurlies > 0 && !escaping) {
+						sb.append(')');
+						inCurlies--;
+					} else if (escaping)
+						sb.append("\\}");
+					else
+						sb.append("}");
+					escaping = false;
+					break;
+				case ',' :
+					if (inCurlies > 0 && !escaping) {
+						sb.append('|');
+					} else if (escaping)
+						sb.append("\\,");
+					else
+						sb.append(",");
+					break;
+				default :
+					escaping = false;
+					sb.append(currentChar);
 			}
 		}
 		return sb.toString();
 	}
+
+	public void select(List<?> objects) {
+		for ( Iterator<?> i =objects.iterator(); i.hasNext(); ) {
+			String s = i.next().toString();
+			if ( !matcher(s).matches())
+				i.remove();
+		}
+	}
+
+	public static Pattern toPattern(String s) {
+		try {
+			return Pattern.compile( convertGlobToRegEx(s));
+		} catch( Exception e) {
+			// ignore
+		}
+		return null;
+	}
 }
diff --git a/aQute.libg/src/aQute/libg/glob/packageinfo b/aQute.libg/src/aQute/libg/glob/packageinfo
new file mode 100644
index 0000000..9ad81f6
--- /dev/null
+++ b/aQute.libg/src/aQute/libg/glob/packageinfo
@@ -0,0 +1 @@
+version 1.0.0
diff --git a/aQute.libg/src/aQute/libg/gzip/GZipUtils.java b/aQute.libg/src/aQute/libg/gzip/GZipUtils.java
new file mode 100644
index 0000000..81c9785
--- /dev/null
+++ b/aQute.libg/src/aQute/libg/gzip/GZipUtils.java
@@ -0,0 +1,57 @@
+package aQute.libg.gzip;
+
+import java.io.*;
+import java.util.zip.*;
+
+public class GZipUtils {
+
+	/**
+	 * Determines whether the specified stream contains gzipped data, by
+	 * checking for the GZIP magic number, and returns a stream capable of
+	 * reading those data.
+	 * 
+	 * @throws IOException
+	 */
+	public static InputStream detectCompression(InputStream stream) throws IOException {
+		InputStream buffered;
+		if (stream.markSupported())
+			buffered = stream;
+		else
+			buffered = new BufferedInputStream(stream);
+
+		buffered.mark(2);
+		int magic = readUShort(buffered);
+		buffered.reset();
+
+		InputStream result;
+		if (magic == GZIPInputStream.GZIP_MAGIC)
+			result = new GZIPInputStream(buffered);
+		else
+			result = buffered;
+		return result;
+	}
+
+	/*
+	 * Reads unsigned short in Intel byte order.
+	 */
+	private static int readUShort(InputStream in) throws IOException {
+		int b = readUByte(in);
+		return (readUByte(in) << 8) | b;
+	}
+
+	/*
+	 * Reads unsigned byte.
+	 */
+	private static int readUByte(InputStream in) throws IOException {
+		int b = in.read();
+		if (b == -1) {
+			throw new EOFException();
+		}
+		if (b < -1 || b > 255) {
+			// Report on this.in, not argument in; see read{Header, Trailer}.
+			throw new IOException(in.getClass().getName() + ".read() returned value out of range -1..255: " + b);
+		}
+		return b;
+	}
+
+}
diff --git a/aQute.libg/src/aQute/libg/gzip/packageinfo b/aQute.libg/src/aQute/libg/gzip/packageinfo
new file mode 100644
index 0000000..9ad81f6
--- /dev/null
+++ b/aQute.libg/src/aQute/libg/gzip/packageinfo
@@ -0,0 +1 @@
+version 1.0.0
diff --git a/aQute.libg/src/aQute/libg/header/OSGiHeader.java b/aQute.libg/src/aQute/libg/header/OSGiHeader.java
deleted file mode 100755
index 5632034..0000000
--- a/aQute.libg/src/aQute/libg/header/OSGiHeader.java
+++ /dev/null
@@ -1,145 +0,0 @@
-package aQute.libg.header;
-
-import java.util.*;
-
-import aQute.libg.generics.*;
-import aQute.libg.qtokens.*;
-import aQute.libg.reporter.*;
-
-public class OSGiHeader {
-
-    static public Map<String, Map<String, String>> parseHeader(String value) {
-        return parseHeader(value, null);
-    }
-
-    /**
-     * Standard OSGi header parser. This parser can handle the format clauses
-     * ::= clause ( ',' clause ) + clause ::= name ( ';' name ) (';' key '='
-     * value )
-     * 
-     * This is mapped to a Map { name => Map { attr|directive => value } }
-     * 
-     * @param value
-     *            A string
-     * @return a Map<String,Map<String,String>>
-     */
-    static public Map<String, Map<String, String>> parseHeader(String value,
-            Reporter logger) {
-        if (value == null || value.trim().length() == 0)
-            return Create.map();
-
-        Map<String, Map<String, String>> result = Create.map();
-        QuotedTokenizer qt = new QuotedTokenizer(value, ";=,");
-        char del = 0;
-        do {
-            boolean hadAttribute = false;
-            Map<String, String> clause = Create.map();
-            List<String> aliases = Create.list();
-            String name = qt.nextToken(",;");
-
-            del = qt.getSeparator();
-            if (name == null || name.length() == 0) {
-                if (logger != null && logger.isPedantic()) {
-                    logger
-                            .warning("Empty clause, usually caused by repeating a comma without any name field or by having spaces after the backslash of a property file: "
-                                    + value);
-                }
-                if (name == null)
-                    break;
-            } else {
-                name = name.trim();
-
-                aliases.add(name);
-                while (del == ';') {
-                    String adname = qt.nextToken();
-                    if ((del = qt.getSeparator()) != '=') {
-                        if (hadAttribute)
-                            if (logger != null) {
-                                logger
-                                        .error("Header contains name field after attribute or directive: "
-                                                + adname
-                                                + " from "
-                                                + value
-                                                + ". Name fields must be consecutive, separated by a ';' like a;b;c;x=3;y=4");
-                            }
-                        if (adname != null && adname.length() > 0)
-                            aliases.add(adname.trim());
-                    } else {
-                        String advalue = qt.nextToken();
-                        if (clause.containsKey(adname)) {
-                            if (logger != null && logger.isPedantic())
-                                logger
-                                        .warning("Duplicate attribute/directive name "
-                                                + adname
-                                                + " in "
-                                                + value
-                                                + ". This attribute/directive will be ignored");
-                        }
-                        if (advalue == null) {
-                            if (logger != null)
-                                logger
-                                        .error("No value after '=' sign for attribute "
-                                                + adname);
-                            advalue = "";
-                        }
-                        clause.put(adname.trim(), advalue.trim());
-                        del = qt.getSeparator();
-                        hadAttribute = true;
-                    }
-                }
-
-                // Check for duplicate names. The aliases list contains
-                // the list of nams, for each check if it exists. If so,
-                // add a number of "~" to make it unique.
-                for (String clauseName : aliases) {
-                    if (result.containsKey(clauseName)) {
-                        if (logger != null && logger.isPedantic())
-                            logger
-                                    .warning("Duplicate name "
-                                            + clauseName
-                                            + " used in header: '"
-                                            + clauseName
-                                            + "'. Duplicate names are specially marked in Bnd with a ~ at the end (which is stripped at printing time).");
-                        while (result.containsKey(clauseName))
-                            clauseName += "~";
-                    }
-                    result.put(clauseName, clause);
-                }
-            }
-        } while (del == ',');
-        return result;
-    }
-
-    public static Map<String, String> parseProperties(String input) {
-        return parseProperties(input, null);
-    }
-
-    public static Map<String, String> parseProperties(String input, Reporter logger) {
-        if (input == null || input.trim().length() == 0)
-            return Create.map();
-
-        Map<String, String> result = Create.map();
-        QuotedTokenizer qt = new QuotedTokenizer(input, "=,");
-        char del = ',';
-
-        while (del == ',') {
-            String key = qt.nextToken(",=");
-            String value = "";
-            del = qt.getSeparator();
-            if (del == '=') {
-                value = qt.nextToken(",=");
-                del = qt.getSeparator();
-            }
-            result.put(key, value);
-        }
-        if (del != 0)
-            if ( logger == null )
-            throw new IllegalArgumentException(
-                    "Invalid syntax for properties: " + input);
-            else
-                logger.error("Invalid syntax for properties: " + input);
-
-        return result;
-    }
-
-}
diff --git a/aQute.libg/src/aQute/libg/log/Logger.java b/aQute.libg/src/aQute/libg/log/Logger.java
index bb87707..05d869f 100755
--- a/aQute.libg/src/aQute/libg/log/Logger.java
+++ b/aQute.libg/src/aQute/libg/log/Logger.java
@@ -2,15 +2,18 @@ package aQute.libg.log;
 
 import java.util.*;
 
-
 public interface Logger {
-	void error(String s, Object ... args);
-	void warning(String s, Object ... args);
-	void progress(String s, Object ... args);
-	
+	void error(String s, Object... args);
+
+	void warning(String s, Object... args);
+
+	void progress(String s, Object... args);
+
 	List<String> getWarnings();
+
 	List<String> getErrors();
+
 	List<String> getProgress();
-	
+
 	boolean isPedantic();
 }
diff --git a/aQute.libg/src/aQute/libg/map/MAP.java b/aQute.libg/src/aQute/libg/map/MAP.java
index bdbbe43..e4776f7 100644
--- a/aQute.libg/src/aQute/libg/map/MAP.java
+++ b/aQute.libg/src/aQute/libg/map/MAP.java
@@ -2,19 +2,42 @@ package aQute.libg.map;
 
 import java.util.*;
 
+/**
+ * Easy way to build a map: Map<String,Integer> s = MAP.$("a",2).$("b",3);
+ */
 public class MAP {
 
-	static public class MAPX<K, V> extends LinkedHashMap<K, V> {
+	static public class MAPX<K, V> extends LinkedHashMap<K,V> {
 		private static final long	serialVersionUID	= 1L;
-		public MAPX<K, V> $(K key, V value) {
+
+		public MAPX<K,V> $(K key, V value) {
 			put(key, value);
 			return this;
 		}
+
+		public MAPX<K,V> $(Map<K,V> all) {
+			putAll(all);
+			return this;
+		}
+
+		public Hashtable<K,V> asHashtable() {
+			return new Hashtable<K,V>(this);
+		}
 	}
 
-	public static <Kx, Vx> MAPX<Kx, Vx> $(Kx key, Vx value) {
-		MAPX<Kx, Vx> map = new MAPX<Kx, Vx>();
+	public static <Kx, Vx> MAPX<Kx,Vx> $(Kx key, Vx value) {
+		MAPX<Kx,Vx> map = new MAPX<Kx,Vx>();
 		map.put(key, value);
 		return map;
 	}
+
+	public <K, V> Map<K,V> dictionary(Dictionary<K,V> dict) {
+		Map<K,V> map = new LinkedHashMap<K,V>();
+		for (Enumeration<K> e = dict.keys(); e.hasMoreElements();) {
+			K k = e.nextElement();
+			V v = dict.get(k);
+			map.put(k, v);
+		}
+		return map;
+	}
 }
\ No newline at end of file
diff --git a/aQute.libg/src/aQute/libg/map/packageinfo b/aQute.libg/src/aQute/libg/map/packageinfo
new file mode 100644
index 0000000..897578f
--- /dev/null
+++ b/aQute.libg/src/aQute/libg/map/packageinfo
@@ -0,0 +1 @@
+version 1.2.0
diff --git a/aQute.libg/src/aQute/libg/qtokens/QuotedTokenizer.java b/aQute.libg/src/aQute/libg/qtokens/QuotedTokenizer.java
index 43ef7c4..30e744b 100755
--- a/aQute.libg/src/aQute/libg/qtokens/QuotedTokenizer.java
+++ b/aQute.libg/src/aQute/libg/qtokens/QuotedTokenizer.java
@@ -13,42 +13,41 @@ public class QuotedTokenizer {
 	String	peek;
 	char	separator;
 
-	public QuotedTokenizer(String string, String separators, boolean returnTokens ) {
-		if ( string == null )
+	public QuotedTokenizer(String string, String separators, boolean returnTokens) {
+		if (string == null)
 			throw new IllegalArgumentException("string argument must be not null");
 		this.string = string;
 		this.separators = separators;
 		this.returnTokens = returnTokens;
 	}
+
 	public QuotedTokenizer(String string, String separators) {
-		this(string,separators,false);
+		this(string, separators, false);
 	}
 
 	public String nextToken(String separators) {
 		separator = 0;
-		if ( peek != null ) {
+		if (peek != null) {
 			String tmp = peek;
 			peek = null;
 			return tmp;
 		}
-		
-		if ( index == string.length())
+
+		if (index == string.length())
 			return null;
-		
-		StringBuffer sb = new StringBuffer();
+
+		StringBuilder sb = new StringBuilder();
 
 		while (index < string.length()) {
 			char c = string.charAt(index++);
 
-			if ( Character.isWhitespace(c)) {
-				if ( index == string.length())
+			if (Character.isWhitespace(c)) {
+				if (index == string.length())
 					break;
-				else {
-				    sb.append(c);
-					continue;
-				}
+				sb.append(c);
+				continue;
 			}
-			
+
 			if (separators.indexOf(c) >= 0) {
 				if (returnTokens)
 					peek = Character.toString(c);
@@ -68,7 +67,7 @@ public class QuotedTokenizer {
 			}
 		}
 		String result = sb.toString().trim();
-		if ( result.length()==0 && index==string.length())
+		if (result.length() == 0 && index == string.length())
 			return null;
 		return result;
 	}
@@ -77,14 +76,13 @@ public class QuotedTokenizer {
 		return nextToken(separators);
 	}
 
-	private void quotedString(StringBuffer sb, char c) {
+	private void quotedString(StringBuilder sb, char c) {
 		char quote = c;
 		while (index < string.length()) {
 			c = string.charAt(index++);
 			if (c == quote)
 				break;
-			if (c == '\\' && index < string.length()
-					&& string.charAt(index + 1) == quote)
+			if (c == '\\' && index < string.length() && string.charAt(index) == quote)
 				c = string.charAt(index++);
 			sb.append(c);
 		}
@@ -94,22 +92,24 @@ public class QuotedTokenizer {
 		return getTokens(0);
 	}
 
-	private String [] getTokens(int cnt){
+	private String[] getTokens(int cnt) {
 		String token = nextToken();
-		if ( token == null ) 
+		if (token == null)
 			return new String[cnt];
-		
-		String result[] = getTokens(cnt+1);
-		result[cnt]=token;
+
+		String result[] = getTokens(cnt + 1);
+		result[cnt] = token;
 		return result;
 	}
 
-	public char getSeparator() { return separator; }
-	
+	public char getSeparator() {
+		return separator;
+	}
+
 	public List<String> getTokenSet() {
 		List<String> list = Create.list();
 		String token = nextToken();
-		while ( token != null ) {
+		while (token != null) {
 			list.add(token);
 			token = nextToken();
 		}
diff --git a/aQute.libg/src/aQute/libg/reporter/Message.java b/aQute.libg/src/aQute/libg/reporter/Message.java
new file mode 100644
index 0000000..afaad88
--- /dev/null
+++ b/aQute.libg/src/aQute/libg/reporter/Message.java
@@ -0,0 +1,5 @@
+package aQute.libg.reporter;
+
+public @interface Message {
+	String value();
+}
diff --git a/aQute.libg/src/aQute/libg/reporter/Reporter.java b/aQute.libg/src/aQute/libg/reporter/Reporter.java
deleted file mode 100755
index c6179af..0000000
--- a/aQute.libg/src/aQute/libg/reporter/Reporter.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package aQute.libg.reporter;
-
-import java.util.*;
-
-
-public interface Reporter {
-	void error(String s, Object ... args);
-	void warning(String s, Object ... args);
-	void progress(String s, Object ... args);
-	void trace(String s, Object ... args);
-	List<String> getWarnings();
-	List<String> getErrors();
-	
-	boolean isPedantic();
-}
diff --git a/aQute.libg/src/aQute/libg/reporter/ReporterAdapter.java b/aQute.libg/src/aQute/libg/reporter/ReporterAdapter.java
new file mode 100644
index 0000000..8c3f68b
--- /dev/null
+++ b/aQute.libg/src/aQute/libg/reporter/ReporterAdapter.java
@@ -0,0 +1,304 @@
+package aQute.libg.reporter;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.regex.*;
+
+import aQute.libg.generics.*;
+import aQute.service.reporter.*;
+
+/**
+ * Mainly used for testing where reporters are needed.
+ */
+public class ReporterAdapter implements Reporter, Report, Runnable {
+	final List<String>	errors		= new ArrayList<String>();
+	final List<String>	warnings	= new ArrayList<String>();
+	final List<LocationImpl> locations = new ArrayList<LocationImpl>();
+	
+	static class LocationImpl extends Location implements SetLocation {
+
+
+
+		public LocationImpl(String e) {
+			// TODO Auto-generated constructor stub
+		}
+
+		public SetLocation file(String file) {
+			this.file = file;
+			return this;
+		}
+
+		public SetLocation header(String header) {
+			this.header = header;
+			return this;
+		}
+
+		public SetLocation context(String context) {
+			this.context = context;
+			return this;
+		}
+
+		public SetLocation method(String methodName) {
+			this.methodName = methodName;
+			return this;
+		}
+
+		public SetLocation line(int line) {
+			this.line = line;
+			return this;
+		}
+
+		public SetLocation reference(String reference) {
+			this.reference = reference;
+			return this;
+		}
+		
+	}
+	
+	final Formatter		out;
+	boolean				trace;
+	boolean				pedantic;
+	boolean				exceptions;
+	
+	/**
+	 * @return the exceptions
+	 */
+	public boolean isExceptions() {
+		return exceptions;
+	}
+
+	/**
+	 * @param exceptions
+	 *            the exceptions to set
+	 */
+	public void setExceptions(boolean exceptions) {
+		this.exceptions = exceptions;
+	}
+
+	/**
+	 * @return the out
+	 */
+	public Formatter getOut() {
+		return out;
+	}
+
+	/**
+	 * @return the trace
+	 */
+	public boolean isTrace() {
+		return trace;
+	}
+
+	/**
+	 * @param pedantic
+	 *            the pedantic to set
+	 */
+	public void setPedantic(boolean pedantic) {
+		this.pedantic = pedantic;
+	}
+
+	public ReporterAdapter() {
+		out = null;
+	}
+
+	public ReporterAdapter(Appendable app) {
+		out = new Formatter(app);
+	}
+
+	public SetLocation error(String s, Object... args) {
+		String e = String.format(s, args);
+		errors.add(e);
+		trace("ERROR: %s", e);
+		return location(e);
+	}
+
+	public SetLocation exception(Throwable t, String s, Object... args) {
+		StackTraceElement[] stackTrace = t.getStackTrace();
+		String method = stackTrace[0].getMethodName();
+		String cname = stackTrace[0].getClassName();
+		String e = String.format("["+shorten(cname) +"."+method+"] " +s, args);
+		errors.add(e);
+		trace("ERROR: %s", e);
+		if (isExceptions() || isTrace())
+			if (t instanceof InvocationTargetException)
+				t.getCause().printStackTrace(System.err);
+			else
+				t.printStackTrace(System.err);
+		return location(e);
+	}
+
+	private String shorten(String cname) {
+		int index = cname.lastIndexOf('$');
+		if ( index < 0)
+			index = cname.lastIndexOf('.');
+		
+		return cname.substring(index+1);
+	}
+
+	public SetLocation warning(String s, Object... args) {
+		String e = String.format(s, args);
+		warnings.add(e);
+		trace("warning: %s", e);
+		return location(e);
+	}
+
+	private SetLocation location(String e) {
+		LocationImpl loc = new LocationImpl(e);
+		locations.add( loc );
+		return loc;
+	}
+
+	public void progress(float progress, String s, Object... args) {
+		if (out != null) {
+			out.format(s, args);
+			if (!s.endsWith(String.format("%n")))
+				out.format("%n");
+		}
+	}
+
+	public void trace(String s, Object... args) {
+		if (trace && out != null) {
+			out.format("# " + s + "%n", args);
+			out.flush();
+		}
+	}
+
+	public List<String> getWarnings() {
+		return warnings;
+	}
+
+	public List<String> getErrors() {
+		return errors;
+	}
+
+	public boolean isPedantic() {
+		return false;
+	}
+
+	public void setTrace(boolean b) {
+		this.trace = b;
+	}
+
+	public boolean isOk() {
+		return errors.isEmpty();
+	}
+
+	public boolean isPerfect() {
+		return isOk() && warnings.isEmpty();
+	}
+
+	public boolean check(String... pattern) {
+		Set<String> missed = Create.set();
+
+		if (pattern != null) {
+			for (String p : pattern) {
+				boolean match = false;
+				Pattern pat = Pattern.compile(p);
+				for (Iterator<String> i = errors.iterator(); i.hasNext();) {
+					if (pat.matcher(i.next()).find()) {
+						i.remove();
+						match = true;
+					}
+				}
+				for (Iterator<String> i = warnings.iterator(); i.hasNext();) {
+					if (pat.matcher(i.next()).find()) {
+						i.remove();
+						match = true;
+					}
+				}
+				if (!match)
+					missed.add(p);
+
+			}
+		}
+		if (missed.isEmpty() && isPerfect())
+			return true;
+
+		if (!missed.isEmpty())
+			System.err.println("Missed the following patterns in the warnings or errors: " + missed);
+
+		report(System.err);
+		return false;
+	}
+
+	/**
+	 * Report the errors and warnings
+	 */
+
+	public void report(Appendable out) {
+		Formatter f = new Formatter(out);
+		report("Error", getErrors(), f);
+		report("Warning", getWarnings(), f);
+		f.flush();
+	}
+
+	void report(String title, Collection<String> list, Formatter f) {
+		if (list.isEmpty())
+			return;
+		f.format(title + (list.size() > 1 ? "s" : "") + "%n");
+		int n = 0;
+		for (String s : list) {
+			f.format("%3s. %s%n", n++, s);
+		}
+	}
+
+	public boolean getInfo(Report other) {
+		return getInfo(other,null);
+	}
+	public boolean getInfo(Report other, String prefix) {
+		addErrors(prefix, other.getErrors());
+		addWarnings(prefix, other.getWarnings());
+		return other.isOk();
+	}
+
+	public Location getLocation(String msg) {
+		for ( LocationImpl loc : locations ) {
+			if ((loc.message != null) && loc.message.equals(msg))
+				return loc;
+		}
+		return null;
+	}
+
+	/**
+	 * Handy routine that can be extended by subclasses
+	 * so they can run inside the context
+	 */
+	public void run() {
+		throw new UnsupportedOperationException("Must be implemented by subclass");
+	}
+
+	/**
+	 * Return a messages object bound to this adapter
+	 */
+	
+	public <T> T getMessages(Class<T> c) {
+		return ReporterMessages.base(this, c);
+	}
+	
+	/**
+	 * Add a number of errors
+	 */
+	
+	public void addErrors( String prefix, Collection<String> errors) {
+		if ( prefix == null)
+			prefix = "";
+		else
+			prefix = prefix + ": ";
+		for ( String s: errors) {
+			this.errors.add( prefix + s);
+		}
+	}
+	/**
+	 * Add a number of warnings
+	 */
+	
+	public void addWarnings( String prefix, Collection<String> warnings) {
+		if ( prefix == null)
+			prefix = "";
+		else
+			prefix = prefix + ": ";
+		for ( String s: warnings) {
+			this.warnings.add( prefix  + s);
+		}
+	}
+}
diff --git a/aQute.libg/src/aQute/libg/reporter/ReporterMessages.java b/aQute.libg/src/aQute/libg/reporter/ReporterMessages.java
new file mode 100644
index 0000000..17191f8
--- /dev/null
+++ b/aQute.libg/src/aQute/libg/reporter/ReporterMessages.java
@@ -0,0 +1,97 @@
+package aQute.libg.reporter;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import aQute.service.reporter.*;
+import aQute.service.reporter.Messages.*;
+import aQute.service.reporter.Reporter.SetLocation;
+
+public class ReporterMessages {
+
+	static class WARNINGImpl implements WARNING {
+		Reporter.SetLocation	loc;
+
+		public SetLocation file(String file) {
+			return loc.file(file);
+		}
+
+		public SetLocation header(String header) {
+			return loc.header(header);
+		}
+
+		public SetLocation context(String context) {
+			return loc.context(context);
+		}
+
+		public SetLocation method(String methodName) {
+			return loc.method(methodName);
+		}
+
+		public SetLocation line(int n) {
+			return loc.line(n);
+		}
+
+		public SetLocation reference(String reference) {
+			return loc.reference(reference);
+		}
+
+		public WARNINGImpl(Reporter.SetLocation loc) {
+			this.loc = loc;
+		}
+	}
+
+	static class ERRORImpl extends WARNINGImpl implements ERROR {
+		public ERRORImpl(SetLocation e) {
+			super(e);
+		}
+	}
+
+	public static <T> T base(final Reporter reporter, Class<T> messages) {
+		return (T) Proxy.newProxyInstance(messages.getClassLoader(), new Class[] {
+			messages
+		}, new InvocationHandler() {
+
+			public Object invoke(Object target, Method method, Object[] args) throws Throwable {
+				String format;
+				Message d = method.getAnnotation(Message.class);
+				if (d == null) {
+					String name = method.getName();
+					StringBuilder sb = new StringBuilder();
+					sb.append(name.charAt(0));
+					for (int i = 1; i < name.length(); i++) {
+						char c = name.charAt(i);
+						switch (c) {
+							case '_' :
+								sb.append(" %s, ");
+								break;
+
+							default :
+								if (Character.isUpperCase(c)) {
+									sb.append(" ");
+									c = Character.toLowerCase(c);
+								}
+								sb.append(c);
+						}
+					}
+					format = sb.toString();
+				} else
+					format = d.value();
+
+				try {
+					if (method.getReturnType() == ERROR.class) {
+						return new ERRORImpl(reporter.error(format, args));
+
+					} else if (method.getReturnType() == WARNING.class) {
+						return new WARNINGImpl(reporter.warning(format, args));
+					} else
+						reporter.trace(format, args);
+				}
+				catch (IllegalFormatException e) {
+					reporter.error("Formatter failed: %s %s %s", method.getName(), format, Arrays.toString(args));
+				}
+				return null;
+			}
+		});
+	}
+}
diff --git a/aQute.libg/src/aQute/libg/reporter/packageinfo b/aQute.libg/src/aQute/libg/reporter/packageinfo
index 7c8de03..0117a56 100644
--- a/aQute.libg/src/aQute/libg/reporter/packageinfo
+++ b/aQute.libg/src/aQute/libg/reporter/packageinfo
@@ -1 +1 @@
-version 1.0
+version 1.3
diff --git a/aQute.libg/src/aQute/libg/sax/ContentFilter.java b/aQute.libg/src/aQute/libg/sax/ContentFilter.java
index 62ca259..e08f4de 100644
--- a/aQute.libg/src/aQute/libg/sax/ContentFilter.java
+++ b/aQute.libg/src/aQute/libg/sax/ContentFilter.java
@@ -1,8 +1,9 @@
 package aQute.libg.sax;
 
-import org.xml.sax.ContentHandler;
+import org.xml.sax.*;
 
 public interface ContentFilter extends ContentHandler {
 	void setParent(ContentHandler parent);
+
 	ContentHandler getParent();
 }
diff --git a/aQute.libg/src/aQute/libg/sax/ContentFilterImpl.java b/aQute.libg/src/aQute/libg/sax/ContentFilterImpl.java
index 7f71568..3bfb6b5 100644
--- a/aQute.libg/src/aQute/libg/sax/ContentFilterImpl.java
+++ b/aQute.libg/src/aQute/libg/sax/ContentFilterImpl.java
@@ -1,17 +1,14 @@
 package aQute.libg.sax;
 
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.Locator;
-import org.xml.sax.SAXException;
+import org.xml.sax.*;
 
 public class ContentFilterImpl implements ContentFilter {
 
-	private ContentHandler parent;
+	private ContentHandler	parent;
 
 	public void setParent(ContentHandler parent) {
 		this.parent = parent;
-		
+
 	}
 
 	public ContentHandler getParent() {
@@ -30,8 +27,7 @@ public class ContentFilterImpl implements ContentFilter {
 		parent.endDocument();
 	}
 
-	public void startPrefixMapping(String prefix, String uri)
-			throws SAXException {
+	public void startPrefixMapping(String prefix, String uri) throws SAXException {
 		parent.startPrefixMapping(prefix, uri);
 	}
 
@@ -39,28 +35,23 @@ public class ContentFilterImpl implements ContentFilter {
 		parent.endPrefixMapping(prefix);
 	}
 
-	public void startElement(String uri, String localName, String qName,
-			Attributes atts) throws SAXException {
+	public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
 		parent.startElement(uri, localName, qName, atts);
 	}
 
-	public void endElement(String uri, String localName, String qName)
-			throws SAXException {
+	public void endElement(String uri, String localName, String qName) throws SAXException {
 		parent.endElement(uri, localName, qName);
 	}
 
-	public void characters(char[] ch, int start, int length)
-			throws SAXException {
+	public void characters(char[] ch, int start, int length) throws SAXException {
 		parent.characters(ch, start, length);
 	}
 
-	public void ignorableWhitespace(char[] ch, int start, int length)
-			throws SAXException {
+	public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
 		parent.ignorableWhitespace(ch, start, length);
 	}
 
-	public void processingInstruction(String target, String data)
-			throws SAXException {
+	public void processingInstruction(String target, String data) throws SAXException {
 		parent.processingInstruction(target, data);
 	}
 
diff --git a/aQute.libg/src/aQute/libg/sax/SAXElement.java b/aQute.libg/src/aQute/libg/sax/SAXElement.java
index b7ce35e..0b7e914 100644
--- a/aQute.libg/src/aQute/libg/sax/SAXElement.java
+++ b/aQute.libg/src/aQute/libg/sax/SAXElement.java
@@ -1,16 +1,15 @@
 package aQute.libg.sax;
 
-import org.xml.sax.Attributes;
+import org.xml.sax.*;
 
 public class SAXElement {
 
-	private final String uri;
-	private final String localName;
-	private final String qName;
-	private final Attributes atts;
+	private final String		uri;
+	private final String		localName;
+	private final String		qName;
+	private final Attributes	atts;
 
-	public SAXElement(String uri, String localName, String qName,
-			Attributes atts) {
+	public SAXElement(String uri, String localName, String qName, Attributes atts) {
 		this.uri = uri;
 		this.localName = localName;
 		this.qName = qName;
diff --git a/aQute.libg/src/aQute/libg/sax/SAXUtil.java b/aQute.libg/src/aQute/libg/sax/SAXUtil.java
index 87b058e..ab7b470 100644
--- a/aQute.libg/src/aQute/libg/sax/SAXUtil.java
+++ b/aQute.libg/src/aQute/libg/sax/SAXUtil.java
@@ -1,29 +1,28 @@
 package aQute.libg.sax;
 
-import javax.xml.parsers.SAXParserFactory;
-import javax.xml.transform.Result;
-import javax.xml.transform.sax.SAXTransformerFactory;
-import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.parsers.*;
+import javax.xml.transform.*;
+import javax.xml.transform.sax.*;
 
-import org.xml.sax.ContentHandler;
-import org.xml.sax.XMLReader;
+import org.xml.sax.*;
 
 public class SAXUtil {
-	
+
 	public static XMLReader buildPipeline(Result output, ContentFilter... filters) throws Exception {
 		SAXTransformerFactory factory = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
 		TransformerHandler handler = factory.newTransformerHandler();
 		handler.setResult(output);
-		
+
 		ContentHandler last = handler;
-		if (filters != null) for (ContentFilter filter : filters) {
-			filter.setParent(last);
-			last = filter;
-		}
+		if (filters != null)
+			for (ContentFilter filter : filters) {
+				filter.setParent(last);
+				last = filter;
+			}
 		XMLReader reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
 		reader.setContentHandler(last);
-		
+
 		return reader;
 	}
-	
+
 }
diff --git a/aQute.libg/src/aQute/libg/sax/filters/ElementSelectionFilter.java b/aQute.libg/src/aQute/libg/sax/filters/ElementSelectionFilter.java
index 4411db9..3ba7f5a 100644
--- a/aQute.libg/src/aQute/libg/sax/filters/ElementSelectionFilter.java
+++ b/aQute.libg/src/aQute/libg/sax/filters/ElementSelectionFilter.java
@@ -1,17 +1,16 @@
 package aQute.libg.sax.filters;
 
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
+import org.xml.sax.*;
 
-import aQute.libg.sax.ContentFilterImpl;
+import aQute.libg.sax.*;
+
+public abstract class ElementSelectionFilter extends ContentFilterImpl {
+
+	int	depth		= 0;
+	int	hiddenDepth	= -1;
 
-public abstract class ElementSelectionFilter extends ContentFilterImpl{
-	
-	int depth = 0;
-	int hiddenDepth = -1;
-	
 	protected abstract boolean select(int depth, String uri, String localName, String qName, Attributes attribs);
-	
+
 	@Override
 	public final void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
 		if (hiddenDepth < 0) {
@@ -21,29 +20,31 @@ public abstract class ElementSelectionFilter extends ContentFilterImpl{
 			else
 				hiddenDepth = 0;
 		} else {
-			hiddenDepth ++;
+			hiddenDepth++;
 		}
 		depth++;
 	}
-	
+
 	@Override
 	public final void endElement(String uri, String localName, String qName) throws SAXException {
 		if (hiddenDepth < 0) {
 			super.endElement(uri, localName, qName);
 		} else {
-			hiddenDepth --;
+			hiddenDepth--;
 		}
-		depth --;
+		depth--;
 	}
-	
+
 	@Override
 	public void characters(char[] ch, int start, int length) throws SAXException {
-		if (hiddenDepth < 0) super.characters(ch, start, length);
+		if (hiddenDepth < 0)
+			super.characters(ch, start, length);
 	}
-	
+
 	@Override
 	public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
-		if (hiddenDepth < 0) super.ignorableWhitespace(ch, start, length);
+		if (hiddenDepth < 0)
+			super.ignorableWhitespace(ch, start, length);
 	}
-	
+
 }
diff --git a/aQute.libg/src/aQute/libg/sax/filters/MergeContentFilter.java b/aQute.libg/src/aQute/libg/sax/filters/MergeContentFilter.java
index acf5d12..b0d4df8 100644
--- a/aQute.libg/src/aQute/libg/sax/filters/MergeContentFilter.java
+++ b/aQute.libg/src/aQute/libg/sax/filters/MergeContentFilter.java
@@ -1,28 +1,26 @@
 package aQute.libg.sax.filters;
 
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
+import java.util.*;
 
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
+import org.xml.sax.*;
 
-import aQute.libg.sax.ContentFilterImpl;
-import aQute.libg.sax.SAXElement;
+import aQute.libg.sax.*;
 
 public class MergeContentFilter extends ContentFilterImpl {
 
-	private int elementDepth = 0;
-	
-	private final List<SAXElement> rootElements = new LinkedList<SAXElement>();
-	
+	private int						elementDepth	= 0;
+
+	private final List<SAXElement>	rootElements	= new LinkedList<SAXElement>();
+
 	@Override
 	public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
 		if (elementDepth++ == 0) {
 			if (rootElements.isEmpty())
 				super.startElement(uri, localName, qName, atts);
 			else if (!rootElements.get(0).getqName().equals(qName))
-				throw new SAXException(String.format("Documents have inconsistent root element names: first was %s, current is %s.", rootElements.get(0).getqName(), qName));
+				throw new SAXException(String.format(
+						"Documents have inconsistent root element names: first was %s, current is %s.", rootElements
+								.get(0).getqName(), qName));
 			rootElements.add(new SAXElement(uri, localName, qName, atts));
 		} else {
 			super.startElement(uri, localName, qName, atts);
@@ -35,13 +33,13 @@ public class MergeContentFilter extends ContentFilterImpl {
 			super.endElement(uri, localName, qName);
 		}
 	}
-	
+
 	@Override
 	public void processingInstruction(String target, String data) throws SAXException {
 		if (rootElements.isEmpty())
 			super.processingInstruction(target, data);
 	}
-	
+
 	public void closeRootAndDocument() throws SAXException {
 		if (!rootElements.isEmpty()) {
 			SAXElement root = rootElements.get(0);
@@ -49,7 +47,7 @@ public class MergeContentFilter extends ContentFilterImpl {
 		}
 		super.endDocument();
 	}
-	
+
 	public List<SAXElement> getRootElements() {
 		return Collections.unmodifiableList(rootElements);
 	}
diff --git a/aQute.libg/src/aQute/libg/sed/Domain.java b/aQute.libg/src/aQute/libg/sed/Domain.java
new file mode 100644
index 0000000..c030c83
--- /dev/null
+++ b/aQute.libg/src/aQute/libg/sed/Domain.java
@@ -0,0 +1,9 @@
+package aQute.libg.sed;
+
+import java.util.*;
+
+public interface Domain {
+	Map<String,String> getMap();
+
+	Domain getParent();
+}
diff --git a/aQute.libg/src/aQute/libg/sed/Replacer.java b/aQute.libg/src/aQute/libg/sed/Replacer.java
index fa181f4..3c02aaf 100644
--- a/aQute.libg/src/aQute/libg/sed/Replacer.java
+++ b/aQute.libg/src/aQute/libg/sed/Replacer.java
@@ -1,5 +1,5 @@
 package aQute.libg.sed;
 
 public interface Replacer {
-    String process(String line);
+	String process(String line);
 }
diff --git a/aQute.libg/src/aQute/libg/sed/ReplacerAdapter.java b/aQute.libg/src/aQute/libg/sed/ReplacerAdapter.java
new file mode 100644
index 0000000..1bd8e07
--- /dev/null
+++ b/aQute.libg/src/aQute/libg/sed/ReplacerAdapter.java
@@ -0,0 +1,935 @@
+package aQute.libg.sed;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.net.*;
+import java.text.*;
+import java.util.*;
+import java.util.regex.*;
+
+import aQute.lib.collections.*;
+import aQute.lib.io.*;
+import aQute.libg.glob.*;
+import aQute.libg.reporter.*;
+import aQute.service.reporter.*;
+
+/**
+ * Provide a macro Domain. This Domain can replace variables in strings based on
+ * a properties and a domain. The domain can implement functions that start with
+ * a "_" and take args[], the names of these functions are available as
+ * functions in the macro Domain (without the _). Macros can nest to any depth
+ * but may not contain loops. Add POSIX macros: ${#parameter} String length.
+ * ${parameter%word} Remove smallest suffix pattern. ${parameter%%word} Remove
+ * largest suffix pattern. ${parameter#word} Remove smallest prefix pattern.
+ * ${parameter##word} Remove largest prefix pattern.
+ */
+public class ReplacerAdapter extends ReporterAdapter implements Replacer {
+	static final Random	random		= new Random();
+	static Pattern		WILDCARD	= Pattern.compile("[*?|[\\\\]\\(\\)]");
+	Domain				domain;
+	List<Object>		targets		= new ArrayList<Object>();
+	boolean				flattening;
+	File				base		= new File(System.getProperty("user.dir"));
+	Reporter			reporter	= this;
+
+	public ReplacerAdapter(Domain domain) {
+		this.domain = domain;
+	}
+
+	public ReplacerAdapter(final Map<String,String> domain) {
+		this(new Domain() {
+
+			public Map<String,String> getMap() {
+				return domain;
+			}
+
+			public Domain getParent() {
+				return null;
+			}
+			
+		});
+	}
+
+	public ReplacerAdapter target(Object target) {
+		assert target != null;
+		targets.add(target);
+		return this;
+	}
+
+	public ReplacerAdapter target(File base) {
+		this.base = base;
+		return this;
+	}
+
+	public String process(String line, Domain source) {
+		return process(line, new Link(source, null, line));
+	}
+
+	String process(String line, Link link) {
+		StringBuilder sb = new StringBuilder();
+		process(line, 0, '\u0000', '\u0000', sb, link);
+		return sb.toString();
+	}
+
+	int process(CharSequence org, int index, char begin, char end, StringBuilder result, Link link) {
+		StringBuilder line = new StringBuilder(org);
+		int nesting = 1;
+
+		StringBuilder variable = new StringBuilder();
+		outer: while (index < line.length()) {
+			char c1 = line.charAt(index++);
+			if (c1 == end) {
+				if (--nesting == 0) {
+					result.append(replace(variable.toString(), link));
+					return index;
+				}
+			} else if (c1 == begin)
+				nesting++;
+			else if (c1 == '\\' && index < line.length() - 1 && line.charAt(index) == '$') {
+				// remove the escape backslash and interpret the dollar
+				// as a
+				// literal
+				index++;
+				variable.append('$');
+				continue outer;
+			} else if (c1 == '$' && index < line.length() - 2) {
+				char c2 = line.charAt(index);
+				char terminator = getTerminator(c2);
+				if (terminator != 0) {
+					index = process(line, index + 1, c2, terminator, variable, link);
+					continue outer;
+				}
+			} else if (c1 == '.' && index < line.length() && line.charAt(index) == '/') {
+				// Found the sequence ./
+				if (index == 1 || Character.isWhitespace(line.charAt(index - 2))) {
+					// make sure it is preceded by whitespace or starts at begin
+					index++;
+					variable.append(base.getAbsolutePath());
+					variable.append('/');
+					continue outer;
+				}
+			}
+			variable.append(c1);
+		}
+		result.append(variable);
+		return index;
+	}
+
+	public static char getTerminator(char c) {
+		switch (c) {
+			case '(' :
+				return ')';
+			case '[' :
+				return ']';
+			case '{' :
+				return '}';
+			case '<' :
+				return '>';
+			case '\u00ab' : // Guillemet double << >>
+				return '\u00bb';
+			case '\u2039' : // Guillemet single
+				return '\u203a';
+		}
+		return 0;
+	}
+
+	public String getProcessed(String key) {
+		return replace(key, null);
+	}
+
+	protected String replace(String key, Link link) {
+		if (link != null && link.contains(key))
+			return "${infinite:" + link.toString() + "}";
+
+		if (key != null) {
+			key = key.trim();
+			if (key.length() > 0) {
+				Domain source = domain;
+				String value = null;
+				if (key.indexOf(';') < 0) {
+					if (WILDCARD.matcher(key).find()) {
+						Glob ins = new Glob(key);
+						StringBuilder sb = new StringBuilder();
+						String del = "";
+						for (String k : getAllKeys()) {
+							if (ins.matcher(k).find()) {
+								String v = replace(k, new Link(source, link, key));
+								if (v != null) {
+									sb.append(del);
+									del = ",";
+									sb.append(v);
+								}
+							}
+						}
+						return sb.toString();
+					}
+
+					while (value == null && source != null) {
+						value = source.getMap().get(key);
+						if (value != null)
+							return process(value, new Link(source, link, key));
+
+						source = source.getParent();
+					}
+				}
+				value = doCommands(key, link);
+				if (value != null)
+					return process(value, new Link(source, link, key));
+
+				if (key != null && key.trim().length() > 0) {
+					value = System.getProperty(key);
+					if (value != null)
+						return value;
+				}
+				if (!flattening && !key.equals("@"))
+					reporter.warning("No translation found for macro: " + key);
+			} else {
+				reporter.warning("Found empty macro key");
+			}
+		} else {
+			reporter.warning("Found null macro key");
+		}
+		return "${" + key + "}";
+	}
+
+	private List<String> getAllKeys() {
+		List<String> l = new ArrayList<String>();
+		Domain source = domain;
+		do {
+			l.addAll(source.getMap().keySet());
+			source = source.getParent();
+		} while (source != null);
+
+		Collections.sort(l);
+		return l;
+	}
+
+	/**
+	 * Parse the key as a command. A command consist of parameters separated by
+	 * ':'.
+	 * 
+	 * @param key
+	 * @return
+	 */
+	static Pattern	commands	= Pattern.compile("(?<!\\\\);");
+
+	private String doCommands(String key, Link source) {
+		String[] args = commands.split(key);
+		if (args == null || args.length == 0)
+			return null;
+
+		for (int i = 0; i < args.length; i++)
+			if (args[i].indexOf('\\') >= 0)
+				args[i] = args[i].replaceAll("\\\\;", ";");
+
+		if (args[0].startsWith("^")) {
+			String varname = args[0].substring(1).trim();
+
+			Domain parent = source.start.getParent();
+			if (parent != null)
+				return parent.getMap().get(varname);
+			return null;
+		}
+
+		Domain rover = domain;
+		while (rover != null) {
+			String result = doCommand(rover, args[0], args);
+			if (result != null)
+				return result;
+
+			rover = rover.getParent();
+		}
+
+		for (Object target : targets) {
+			String result = doCommand(target, args[0], args);
+			if (result != null)
+				return result;
+		}
+
+		return doCommand(this, args[0], args);
+	}
+
+	private String doCommand(Object target, String method, String[] args) {
+		if (target == null)
+			; // System.err.println("Huh? Target should never be null " +
+		// domain);
+		else {
+			String cname = "_" + method.replaceAll("-", "_");
+			try {
+				Method m = target.getClass().getMethod(cname, new Class[] {
+					String[].class
+				});
+				return (String) m.invoke(target, new Object[] {
+					args
+				});
+			}
+			catch (NoSuchMethodException e) {
+				// Ignore
+			}
+			catch (InvocationTargetException e) {
+				if (e.getCause() instanceof IllegalArgumentException) {
+					reporter.error("%s, for cmd: %s, arguments; %s", e.getCause().getMessage(), method, Arrays.toString(args));
+				} else {
+					reporter.warning("Exception in replace: " + e.getCause());
+					e.getCause().printStackTrace();
+				}
+			}
+			catch (Exception e) {
+				reporter.warning("Exception in replace: " + e + " method=" + method);
+				e.printStackTrace();
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Return a unique list where the duplicates are removed.
+	 * 
+	 * @param args
+	 * @return
+	 */
+	static String	_uniqHelp	= "${uniq;<list> ...}";
+
+	public String _uniq(String args[]) {
+		verifyCommand(args, _uniqHelp, null, 1, Integer.MAX_VALUE);
+		Set<String> set = new LinkedHashSet<String>();
+		for (int i = 1; i < args.length; i++) {
+			set.addAll(ExtList.from(args[i].trim()));
+		}
+		ExtList<String> rsult = new ExtList<String>();
+		rsult.addAll(set);
+		return rsult.join(",");
+	}
+
+	public String _pathseparator(String args[]) {
+		return File.pathSeparator;
+	}
+
+	public String _separator(String args[]) {
+		return File.separator;
+	}
+
+	public String _filter(String args[]) {
+		return filter(args, false);
+	}
+
+	public String _filterout(String args[]) {
+		return filter(args, true);
+
+	}
+
+	static String	_filterHelp	= "${%s;<list>;<regex>}";
+
+	String filter(String[] args, boolean include) {
+		verifyCommand(args, String.format(_filterHelp, args[0]), null, 3, 3);
+
+		ExtList<String> list = ExtList.from(args[1]);
+		Pattern pattern = Pattern.compile(args[2]);
+
+		for (Iterator<String> i = list.iterator(); i.hasNext();) {
+			if (pattern.matcher(i.next()).matches() == include)
+				i.remove();
+		}
+		return list.join();
+	}
+
+	static String	_sortHelp	= "${sort;<list>...}";
+
+	public String _sort(String args[]) {
+		verifyCommand(args, _sortHelp, null, 2, Integer.MAX_VALUE);
+
+		ExtList<String> result = new ExtList<String>();
+		for (int i = 1; i < args.length; i++) {
+			result.addAll(ExtList.from(args[i]));
+		}
+		Collections.sort(result);
+		return result.join();
+	}
+
+	static String	_joinHelp	= "${join;<list>...}";
+
+	public String _join(String args[]) {
+
+		verifyCommand(args, _joinHelp, null, 1, Integer.MAX_VALUE);
+
+		ExtList<String> result = new ExtList<String>();
+		for (int i = 1; i < args.length; i++) {
+			result.addAll(ExtList.from(args[i]));
+		}
+		return result.join();
+	}
+
+	static String	_ifHelp	= "${if;<condition>;<iftrue> [;<iffalse>] }";
+
+	public String _if(String args[]) {
+		verifyCommand(args, _ifHelp, null, 3, 4);
+		String condition = args[1].trim();
+		if (!condition.equalsIgnoreCase("false"))
+			if (condition.length() != 0)
+				return args[2];
+
+		if (args.length > 3)
+			return args[3];
+		return "";
+	}
+
+	public String _now(String args[]) {
+		return new Date().toString();
+	}
+
+	public final static String	_fmodifiedHelp	= "${fmodified;<list of filenames>...}, return latest modification date";
+
+	public String _fmodified(String args[]) throws Exception {
+		verifyCommand(args, _fmodifiedHelp, null, 2, Integer.MAX_VALUE);
+
+		long time = 0;
+		Collection<String> names = new ExtList<String>();
+		for (int i = 1; i < args.length; i++) {
+			names.addAll(ExtList.from(args[i]));
+		}
+		for (String name : names) {
+			File f = new File(name);
+			if (f.exists() && f.lastModified() > time)
+				time = f.lastModified();
+		}
+		return "" + time;
+	}
+
+	public String _long2date(String args[]) {
+		try {
+			return new Date(Long.parseLong(args[1])).toString();
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}
+		return "not a valid long";
+	}
+
+	public String _literal(String args[]) {
+		if (args.length != 2)
+			throw new RuntimeException("Need a value for the ${literal;<value>} macro");
+		return "${" + args[1] + "}";
+	}
+
+	public String _def(String args[]) {
+		if (args.length != 2)
+			throw new RuntimeException("Need a value for the ${def;<value>} macro");
+
+		String value = domain.getMap().get(args[1]);
+		if (value == null)
+			return "";
+
+		return value;
+	}
+
+	/**
+	 * replace ; <list> ; regex ; replace
+	 * 
+	 * @param args
+	 * @return
+	 */
+	public String _replace(String args[]) {
+		if (args.length != 4) {
+			reporter.warning("Invalid nr of arguments to replace " + Arrays.asList(args));
+			return null;
+		}
+
+		String list[] = args[1].split("\\s*,\\s*");
+		StringBuilder sb = new StringBuilder();
+		String del = "";
+		for (int i = 0; i < list.length; i++) {
+			String element = list[i].trim();
+			if (!element.equals("")) {
+				sb.append(del);
+				sb.append(element.replaceAll(args[2], args[3]));
+				del = ", ";
+			}
+		}
+
+		return sb.toString();
+	}
+
+	public String _warning(String args[]) {
+		for (int i = 1; i < args.length; i++) {
+			reporter.warning(process(args[i]));
+		}
+		return "";
+	}
+
+	public String _error(String args[]) {
+		for (int i = 1; i < args.length; i++) {
+			reporter.error(process(args[i]));
+		}
+		return "";
+	}
+
+	/**
+	 * toclassname ; <path>.class ( , <path>.class ) *
+	 * 
+	 * @param args
+	 * @return
+	 */
+	static String	_toclassnameHelp	= "${classname;<list of class names>}, convert class paths to FQN class names ";
+
+	public String _toclassname(String args[]) {
+		verifyCommand(args, _toclassnameHelp, null, 2, 2);
+		Collection<String> paths = ExtList.from(args[1]);
+
+		ExtList<String> names = new ExtList<String>(paths.size());
+		for (String path : paths) {
+			if (path.endsWith(".class")) {
+				String name = path.substring(0, path.length() - 6).replace('/', '.');
+				names.add(name);
+			} else if (path.endsWith(".java")) {
+				String name = path.substring(0, path.length() - 5).replace('/', '.');
+				names.add(name);
+			} else {
+				reporter.warning("in toclassname, %s, is not a class path because it does not end in .class", args[1]);
+			}
+		}
+		return names.join(",");
+	}
+
+	/**
+	 * toclassname ; <path>.class ( , <path>.class ) *
+	 * 
+	 * @param args
+	 * @return
+	 */
+
+	static String	_toclasspathHelp	= "${toclasspath;<list>[;boolean]}, convert a list of class names to paths";
+
+	public String _toclasspath(String args[]) {
+		verifyCommand(args, _toclasspathHelp, null, 2, 3);
+		boolean cl = true;
+		if (args.length > 2)
+			cl = Boolean.valueOf(args[2]);
+
+		ExtList<String> names = ExtList.from(args[1]);
+		ExtList<String> paths = new ExtList<String>(names.size());
+		for (String name : names) {
+			String path = name.replace('.', '/') + (cl ? ".class" : "");
+			paths.add(path);
+		}
+		return paths.join(",");
+	}
+
+	public String _dir(String args[]) {
+		if (args.length < 2) {
+			reporter.warning("Need at least one file name for ${dir;...}");
+			return null;
+		}
+		String del = "";
+		StringBuilder sb = new StringBuilder();
+		for (int i = 1; i < args.length; i++) {
+			File f = IO.getFile(base, args[i]);
+			if (f.exists() && f.getParentFile().exists()) {
+				sb.append(del);
+				sb.append(f.getParentFile().getAbsolutePath());
+				del = ",";
+			}
+		}
+		return sb.toString();
+
+	}
+
+	public String _basename(String args[]) {
+		if (args.length < 2) {
+			reporter.warning("Need at least one file name for ${basename;...}");
+			return null;
+		}
+		String del = "";
+		StringBuilder sb = new StringBuilder();
+		for (int i = 1; i < args.length; i++) {
+			File f = IO.getFile(base, args[i]);
+			if (f.exists() && f.getParentFile().exists()) {
+				sb.append(del);
+				sb.append(f.getName());
+				del = ",";
+			}
+		}
+		return sb.toString();
+
+	}
+
+	public String _isfile(String args[]) {
+		if (args.length < 2) {
+			reporter.warning("Need at least one file name for ${isfile;...}");
+			return null;
+		}
+		boolean isfile = true;
+		for (int i = 1; i < args.length; i++) {
+			File f = new File(args[i]).getAbsoluteFile();
+			isfile &= f.isFile();
+		}
+		return isfile ? "true" : "false";
+
+	}
+
+	public String _isdir(String args[]) {
+		if (args.length < 2) {
+			reporter.warning("Need at least one file name for ${isdir;...}");
+			return null;
+		}
+		boolean isdir = true;
+		for (int i = 1; i < args.length; i++) {
+			File f = new File(args[i]).getAbsoluteFile();
+			isdir &= f.isDirectory();
+		}
+		return isdir ? "true" : "false";
+
+	}
+
+	public String _tstamp(String args[]) {
+		String format = "yyyyMMddHHmm";
+		long now = System.currentTimeMillis();
+		TimeZone tz = TimeZone.getTimeZone("UTC");
+
+		if (args.length > 1) {
+			format = args[1];
+		}
+		if (args.length > 2) {
+			tz = TimeZone.getTimeZone(args[2]);
+		}
+		if (args.length > 3) {
+			now = Long.parseLong(args[3]);
+		}
+		if (args.length > 4) {
+			reporter.warning("Too many arguments for tstamp: " + Arrays.toString(args));
+		}
+
+		SimpleDateFormat sdf = new SimpleDateFormat(format);
+		sdf.setTimeZone(tz);
+
+		return sdf.format(new Date(now));
+	}
+
+	/**
+	 * Wildcard a directory. The lists can contain Instruction that are matched
+	 * against the given directory ${lsr;<dir>;<list>(;<list>)*}
+	 * ${lsa;<dir>;<list>(;<list>)*}
+	 * 
+	 * @author aqute
+	 */
+
+	public String _lsr(String args[]) {
+		return ls(args, true);
+	}
+
+	public String _lsa(String args[]) {
+		return ls(args, false);
+	}
+
+	String ls(String args[], boolean relative) {
+		if (args.length < 2)
+			throw new IllegalArgumentException("the ${ls} macro must at least have a directory as parameter");
+
+		File dir = IO.getFile(base, args[1]);
+		if (!dir.isAbsolute())
+			throw new IllegalArgumentException("the ${ls} macro directory parameter is not absolute: " + dir);
+
+		if (!dir.exists())
+			throw new IllegalArgumentException("the ${ls} macro directory parameter does not exist: " + dir);
+
+		if (!dir.isDirectory())
+			throw new IllegalArgumentException(
+					"the ${ls} macro directory parameter points to a file instead of a directory: " + dir);
+
+		List<File> files = new ArrayList<File>(new SortedList<File>(dir.listFiles()));
+
+		for (int i = 2; i < args.length; i++) {
+			Glob filters = new Glob(args[i]);
+			filters.select(files);
+		}
+
+		ExtList<String> result = new ExtList<String>();
+		for (File file : files)
+			result.add(relative ? file.getName() : file.getAbsolutePath());
+
+		return result.join(",");
+	}
+
+	public String _currenttime(String args[]) {
+		return Long.toString(System.currentTimeMillis());
+	}
+
+	/**
+	 * System command. Execute a command and insert the result.
+	 * 
+	 * @param args
+	 * @param help
+	 * @param patterns
+	 * @param low
+	 * @param high
+	 */
+	public String system_internal(boolean allowFail, String args[]) throws Exception {
+		verifyCommand(args, "${" + (allowFail ? "system-allow-fail" : "system")
+				+ ";<command>[;<in>]}, execute a system command", null, 2, 3);
+		String command = args[1];
+		String input = null;
+
+		if (args.length > 2) {
+			input = args[2];
+		}
+
+		Process process = Runtime.getRuntime().exec(command, null, base);
+		if (input != null) {
+			process.getOutputStream().write(input.getBytes("UTF-8"));
+		}
+		process.getOutputStream().close();
+
+		String s = IO.collect(process.getInputStream(), "UTF-8");
+		int exitValue = process.waitFor();
+		if (exitValue != 0)
+			return exitValue + "";
+
+		if (!allowFail && (exitValue != 0)) {
+			reporter.error("System command " + command + " failed with " + exitValue);
+		}
+		return s.trim();
+	}
+
+	public String _system(String args[]) throws Exception {
+		return system_internal(false, args);
+	}
+
+	public String _system_allow_fail(String args[]) throws Exception {
+		String result = "";
+		try {
+			result = system_internal(true, args);
+		}
+		catch (Throwable t) {
+			/* ignore */
+		}
+		return result;
+	}
+
+	public String _env(String args[]) {
+		verifyCommand(args, "${env;<name>}, get the environmet variable", null, 2, 2);
+
+		try {
+			return System.getenv(args[1]);
+		}
+		catch (Throwable t) {
+			return null;
+		}
+	}
+
+	/**
+	 * Get the contents of a file.
+	 * 
+	 * @param in
+	 * @return
+	 * @throws IOException
+	 */
+
+	public String _cat(String args[]) throws IOException {
+		verifyCommand(args, "${cat;<in>}, get the content of a file", null, 2, 2);
+		File f = IO.getFile(base, args[1]);
+		if (f.isFile()) {
+			return IO.collect(f);
+		} else if (f.isDirectory()) {
+			return Arrays.toString(f.list());
+		} else {
+			try {
+				URL url = new URL(args[1]);
+				return IO.collect(url, "UTF-8");
+			}
+			catch (MalformedURLException mfue) {
+				// Ignore here
+			}
+			return null;
+		}
+	}
+
+	public static void verifyCommand(String args[], String help, Pattern[] patterns, int low, int high) {
+		String message = "";
+		if (args.length > high) {
+			message = "too many arguments";
+		} else if (args.length < low) {
+			message = "too few arguments";
+		} else {
+			for (int i = 0; patterns != null && i < patterns.length && i < args.length; i++) {
+				if (patterns[i] != null) {
+					Matcher m = patterns[i].matcher(args[i]);
+					if (!m.matches())
+						message += String.format("Argument %s (%s) does not match %s%n", i, args[i],
+								patterns[i].pattern());
+				}
+			}
+		}
+		if (message.length() != 0) {
+			StringBuilder sb = new StringBuilder();
+			String del = "${";
+			for (String arg : args) {
+				sb.append(del);
+				sb.append(arg);
+				del = ";";
+			}
+			sb.append("}, is not understood. ");
+			sb.append(message);
+			throw new IllegalArgumentException(sb.toString());
+		}
+	}
+
+	// Helper class to track expansion of variables
+	// on the stack.
+	static class Link {
+		Link	previous;
+		String	key;
+		Domain	start;
+
+		public Link(Domain start, Link previous, String key) {
+			this.previous = previous;
+			this.key = key;
+			this.start = start;
+		}
+
+		public boolean contains(String key) {
+			if (this.key.equals(key))
+				return true;
+
+			if (previous == null)
+				return false;
+
+			return previous.contains(key);
+		}
+
+		@Override
+		public String toString() {
+			StringBuilder sb = new StringBuilder("[");
+			append(sb);
+			sb.append("]");
+			return sb.toString();
+		}
+
+		private void append(StringBuilder sb) {
+			if (previous != null) {
+				previous.append(sb);
+				sb.append(",");
+			}
+			sb.append(key);
+		}
+	}
+
+	/**
+	 * Take all the properties and translate them to actual values. This method
+	 * takes the set properties and traverse them over all entries, including
+	 * the default properties for that properties. The values no longer contain
+	 * macros.
+	 * 
+	 * @return A new Properties with the flattened values
+	 */
+	public Map<String,String> getFlattenedProperties() {
+		// Some macros only work in a lower Domain, so we
+		// do not report unknown macros while flattening
+		flattening = true;
+		try {
+			Map<String,String> flattened = new HashMap<String,String>();
+			Map<String,String> source = domain.getMap();
+			for (String key : source.keySet()) {
+				if (!key.startsWith("_"))
+					if (key.startsWith("-"))
+						flattened.put(key, source.get(key));
+					else
+						flattened.put(key, process(source.get(key)));
+			}
+			return flattened;
+		}
+		finally {
+			flattening = false;
+		}
+	}
+
+	public final static String	_fileHelp	= "${file;<base>;<paths>...}, create correct OS dependent path";
+
+	public String _osfile(String args[]) {
+		verifyCommand(args, _fileHelp, null, 3, 3);
+		File base = new File(args[1]);
+		File f = IO.getFile(base, args[2]);
+		return f.getAbsolutePath();
+	}
+
+	public String _path(String args[]) {
+		ExtList<String> list = new ExtList<String>();
+		for (int i = 1; i < args.length; i++) {
+			list.addAll(ExtList.from(args[i]));
+		}
+		return list.join(File.pathSeparator);
+	}
+
+	public static Properties getParent(Properties p) {
+		try {
+			Field f = Properties.class.getDeclaredField("defaults");
+			f.setAccessible(true);
+			return (Properties) f.get(p);
+		}
+		catch (Exception e) {
+			Field[] fields = Properties.class.getFields();
+			System.err.println(Arrays.toString(fields));
+			return null;
+		}
+	}
+
+	public String process(String line) {
+		return process(line, domain);
+	}
+
+	/**
+	 * Generate a random string, which is guaranteed to be a valid Java
+	 * identifier (first character is an ASCII letter, subsequent characters are
+	 * ASCII letters or numbers). Takes an optional parameter for the length of
+	 * string to generate; default is 8 characters.
+	 */
+	public String _random(String[] args) {
+		int numchars = 8;
+		if (args.length > 1) {
+			try {
+				numchars = Integer.parseInt(args[1]);
+			}
+			catch (NumberFormatException e) {
+				throw new IllegalArgumentException("Invalid character count parameter in ${random} macro.");
+			}
+		}
+
+		char[] letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
+		char[] alphanums = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
+
+		char[] array = new char[numchars];
+		for (int i = 0; i < numchars; i++) {
+			char c;
+			if (i == 0)
+				c = letters[random.nextInt(letters.length)];
+			else
+				c = alphanums[random.nextInt(alphanums.length)];
+			array[i] = c;
+		}
+
+		return new String(array);
+	}
+
+	public void setReporter(Reporter reporter) {
+		this.reporter = reporter;
+	}
+
+	
+	public int _processors(String args[]) {
+		float multiplier = 1F;
+		if ( args.length > 1 )
+			multiplier = Float.parseFloat(args[1]);
+		
+		return (int) (Runtime.getRuntime().availableProcessors() * multiplier);
+	}
+	
+	public long _maxMemory(String args[]) {
+		return Runtime.getRuntime().maxMemory();
+	}
+	public long _freeMemory(String args[]) {
+		return Runtime.getRuntime().freeMemory();
+	}
+
+	public long _nanoTime(String args[]) {
+		return System.nanoTime();
+	}
+	
+}
diff --git a/aQute.libg/src/aQute/libg/sed/Sed.java b/aQute.libg/src/aQute/libg/sed/Sed.java
index 86971bb..0542f65 100644
--- a/aQute.libg/src/aQute/libg/sed/Sed.java
+++ b/aQute.libg/src/aQute/libg/sed/Sed.java
@@ -4,79 +4,98 @@ import java.io.*;
 import java.util.*;
 import java.util.regex.*;
 
+import aQute.lib.io.*;
+
 public class Sed {
-    final File                 file;
-    final Replacer             macro;
-    File                       output;
+	final File					file;
+	final Replacer				macro;
+	File						output;
+	boolean						backup			= true;
+
+	final Map<Pattern,String>	replacements	= new LinkedHashMap<Pattern,String>();
 
-    final Map<Pattern, String> replacements = new LinkedHashMap<Pattern, String>();
+	public Sed(Replacer macro, File file) {
+		assert file.isFile();
+		this.file = file;
+		this.macro = macro;
+	}
 
-    public Sed(Replacer macro, File file) {
-        assert file.isFile();
-        this.file = file;
-        this.macro = macro;
-    }
+	public Sed(File file) {
+		assert file.isFile();
+		this.file = file;
+		this.macro = null;
+	}
 
-    public void setOutput(File f) {
-        output = f;
-    }
+	public void setOutput(File f) {
+		output = f;
+	}
 
-    public void replace(String pattern, String replacement) {
-        replacements.put(Pattern.compile(pattern), replacement);
-    }
+	public void replace(String pattern, String replacement) {
+		replacements.put(Pattern.compile(pattern), replacement);
+	}
 
-    public void doIt() throws IOException {
-        BufferedReader brdr = new BufferedReader(new FileReader(file));
-        File out;
-        if (output != null)
-            out = output;
-        else
-            out = new File(file.getAbsolutePath() + ".tmp");
-        File bak = new File(file.getAbsolutePath() + ".bak");
-        PrintWriter pw = new PrintWriter(new FileWriter(out));
-        try {
-            String line;
-            while ((line = brdr.readLine()) != null) {
-                for (Pattern p : replacements.keySet()) {
-                    String replace = replacements.get(p);
-                    Matcher m = p.matcher(line);
+	public int doIt() throws IOException {
+		int actions = 0;
+		BufferedReader brdr = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
+		File out;
+		if (output != null)
+			out = output;
+		else
+			out = new File(file.getAbsolutePath() + ".tmp");
+		PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(out), "UTF-8"));
+		try {
+			String line;
+			while ((line = brdr.readLine()) != null) {
+				for (Pattern p : replacements.keySet()) {
+					String replace = replacements.get(p);
+					Matcher m = p.matcher(line);
 
-                    StringBuffer sb = new StringBuffer();
-                    while (m.find()) {
-                        String tmp = setReferences(m, replace);
-                        tmp = macro.process(tmp);
-                        m.appendReplacement(sb, Matcher.quoteReplacement(tmp));
-                    }
-                    m.appendTail(sb);
+					StringBuffer sb = new StringBuffer();
+					while (m.find()) {
+						String tmp = setReferences(m, replace);
+						if (macro != null)
+							tmp = Matcher.quoteReplacement(macro.process(tmp));
+						m.appendReplacement(sb, tmp);
+						actions++;
+					}
+					m.appendTail(sb);
 
-                    line = sb.toString();
-                }
-                pw.println(line);
-            }
-            pw.close();
-            if (output == null) {
-                file.renameTo(bak);
-                out.renameTo(file);
-            }
+					line = sb.toString();
+				}
+				pw.println(line);
+			}
         } finally {
-            brdr.close();
-            pw.close();
+        	brdr.close();
+			pw.close();
         }
-    }
+        
+		if (output == null) {
+			if (backup) {
+				File bak = new File(file.getAbsolutePath() + ".bak");
+				IO.rename(file, bak);
+			}
+			IO.rename(out, file);
+		}
+        
+		return actions;
+	}
+    
+	private String setReferences(Matcher m, String replace) {
+		StringBuilder sb = new StringBuilder();
+		for (int i = 0; i < replace.length(); i++) {
+			char c = replace.charAt(i);
+			if (c == '$' && i < replace.length() - 1 && Character.isDigit(replace.charAt(i + 1))) {
+				int n = replace.charAt(i + 1) - '0';
+				if (n <= m.groupCount())
+					sb.append(m.group(n));
+				i++;
+			} else
+				sb.append(c);
+		}
+		return sb.toString();
+	}
 
-    private String setReferences(Matcher m, String replace) {
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < replace.length(); i++) {
-            char c = replace.charAt(i);
-            if (c == '$' && i < replace.length() - 1
-                    && Character.isDigit(replace.charAt(i + 1))) {
-                int n = replace.charAt(i + 1) - '0';
-                if ( n <= m.groupCount() )
-                    sb.append(m.group(n));
-                i++;
-            } else
-                sb.append(c);
-        }
-        return sb.toString();
-    }
+	public void setBackup(boolean b) {
+		this.backup = b;
+	}
 }
diff --git a/aQute.libg/src/aQute/libg/sed/packageinfo b/aQute.libg/src/aQute/libg/sed/packageinfo
index 7c8de03..b3d1f97 100644
--- a/aQute.libg/src/aQute/libg/sed/packageinfo
+++ b/aQute.libg/src/aQute/libg/sed/packageinfo
@@ -1 +1 @@
-version 1.0
+version 1.0.1
diff --git a/aQute.libg/src/aQute/libg/tarjan/Tarjan.java b/aQute.libg/src/aQute/libg/tarjan/Tarjan.java
index 063006e..c3e8ee1 100644
--- a/aQute.libg/src/aQute/libg/tarjan/Tarjan.java
+++ b/aQute.libg/src/aQute/libg/tarjan/Tarjan.java
@@ -15,43 +15,43 @@ public class Tarjan<T> {
 		public Node(T name) {
 			this.name = name;
 		}
-		
+
+		@Override
 		public String toString() {
 			return name + "{" + index + "," + low + "}";
 		}
 	}
 
-	private int				index	= 0;
-	private List<Node>		stack	= new ArrayList<Node>();
+	private int			index	= 0;
+	private List<Node>	stack	= new ArrayList<Node>();
 	private Set<Set<T>>	scc		= new HashSet<Set<T>>();
-	private Node			root	= new Node(null);
+	private Node		root	= new Node(null);
 
-	
-//	   public ArrayList<ArrayList<Node>> tarjan(Node v, AdjacencyList list){
-//	       v.index = index;
-//	       v.lowlink = index;
-//	       index++;
-//	       stack.add(0, v);
-//	       for(Edge e : list.getAdjacent(v)){
-//	           Node n = e.to;
-//	           if(n.index == -1){
-//	               tarjan(n, list);
-//	               v.lowlink = Math.min(v.lowlink, n.lowlink);
-//	           }else if(stack.contains(n)){
-//	               v.lowlink = Math.min(v.lowlink, n.index);
-//	           }
-//	       }
-//	       if(v.lowlink == v.index){
-//	           Node n;
-//	           ArrayList<Node> component = new ArrayList<Node>();
-//	           do{
-//	               n = stack.remove(0);
-//	               component.add(n);
-//	           }while(n != v);
-//	           SCC.add(component);
-//	       }
-//	       return SCC;
-//	   }
+	// public ArrayList<ArrayList<Node>> tarjan(Node v, AdjacencyList list){
+	// v.index = index;
+	// v.lowlink = index;
+	// index++;
+	// stack.add(0, v);
+	// for(Edge e : list.getAdjacent(v)){
+	// Node n = e.to;
+	// if(n.index == -1){
+	// tarjan(n, list);
+	// v.lowlink = Math.min(v.lowlink, n.lowlink);
+	// }else if(stack.contains(n)){
+	// v.lowlink = Math.min(v.lowlink, n.index);
+	// }
+	// }
+	// if(v.lowlink == v.index){
+	// Node n;
+	// ArrayList<Node> component = new ArrayList<Node>();
+	// do{
+	// n = stack.remove(0);
+	// component.add(n);
+	// }while(n != v);
+	// SCC.add(component);
+	// }
+	// return SCC;
+	// }
 
 	void tarjan(Node v) {
 		v.index = index;
@@ -68,7 +68,7 @@ public class Tarjan<T> {
 			}
 		}
 
-		if (v!=root && v.low == v.index) {
+		if (v != root && v.low == v.index) {
 			Set<T> component = new HashSet<T>();
 			Node n;
 			do {
@@ -80,7 +80,7 @@ public class Tarjan<T> {
 	}
 
 	Set<Set<T>> getResult(Map<T, ? extends Collection<T>> graph) {
-		Map<T, Node> index = new HashMap<T, Node>();
+		Map<T,Node> index = new HashMap<T,Node>();
 
 		for (Map.Entry<T, ? extends Collection<T>> entry : graph.entrySet()) {
 			Node node = getNode(index, entry.getKey());
@@ -92,7 +92,7 @@ public class Tarjan<T> {
 		return scc;
 	}
 
-	private Node getNode(Map<T, Node> index, T key) {
+	private Node getNode(Map<T,Node> index, T key) {
 		Node node = index.get(key);
 		if (node == null) {
 			node = new Node(key);
@@ -101,7 +101,7 @@ public class Tarjan<T> {
 		return node;
 	}
 
-	public static <T> Set<Set<T>> tarjan(Map<T, Set<T>> graph) {
+	public static <T> Collection< ? extends Collection<T>> tarjan(Map<T, ? extends Collection<T>> graph) {
 		Tarjan<T> tarjan = new Tarjan<T>();
 		return tarjan.getResult(graph);
 	}
diff --git a/aQute.libg/src/aQute/libg/tuple/ComparablePair.java b/aQute.libg/src/aQute/libg/tuple/ComparablePair.java
new file mode 100644
index 0000000..36f0242
--- /dev/null
+++ b/aQute.libg/src/aQute/libg/tuple/ComparablePair.java
@@ -0,0 +1,14 @@
+package aQute.libg.tuple;
+
+public class ComparablePair<A extends Comparable<A>, B> extends Pair<A,B> implements Comparable<Pair<A, ? >> {
+
+	private static final long	serialVersionUID	= 1L;
+
+	public ComparablePair(A first, B second) {
+		super(first, second);
+	}
+
+	public int compareTo(Pair<A, ? > o) {
+		return getFirst().compareTo(o.getFirst());
+	}
+}
\ No newline at end of file
diff --git a/aQute.libg/src/aQute/libg/tuple/Pair.java b/aQute.libg/src/aQute/libg/tuple/Pair.java
index efb2298..d4612ee 100644
--- a/aQute.libg/src/aQute/libg/tuple/Pair.java
+++ b/aQute.libg/src/aQute/libg/tuple/Pair.java
@@ -1,11 +1,71 @@
 package aQute.libg.tuple;
 
-public class Pair<A,B> {
-	final public A a;
-	final public B b;
-	
-	public Pair(A a, B b) {
-		this.a = a;
-		this.b = b;
-	}
-}
+import java.io.Serializable;
+
+public class Pair<A, B> implements Serializable, Cloneable {
+
+	private static final long	serialVersionUID	= 1L;
+
+	private final A				first;
+	private final B				second;
+
+	public Pair(A first, B second) {
+		assert first != null && second != null : "both parameters must be non-null";
+		this.first = first;
+		this.second = second;
+	}
+
+	public static <A, B> Pair<A,B> newInstance(A first, B second) {
+		return new Pair<A,B>(first, second);
+	}
+
+	public A getFirst() {
+		return first;
+	}
+
+	public B getSecond() {
+		return second;
+	}
+
+	@Override
+	public String toString() {
+		return "Pair [" + first + ", " + second + "]";
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((first == null) ? 0 : first.hashCode());
+		result = prime * result + ((second == null) ? 0 : second.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		@SuppressWarnings("unchecked")
+		Pair<A,B> other = (Pair<A,B>) obj;
+		if (first == null) {
+			if (other.first != null)
+				return false;
+		} else if (!first.equals(other.first))
+			return false;
+		if (second == null) {
+			if (other.second != null)
+				return false;
+		} else if (!second.equals(other.second))
+			return false;
+		return true;
+	}
+
+	@Override
+	public Pair<A,B> clone() {
+		return new Pair<A,B>(first, second);
+	}
+}
\ No newline at end of file
diff --git a/aQute.libg/src/aQute/libg/version/Version.java b/aQute.libg/src/aQute/libg/version/Version.java
deleted file mode 100755
index 4e3a450..0000000
--- a/aQute.libg/src/aQute/libg/version/Version.java
+++ /dev/null
@@ -1,164 +0,0 @@
-package aQute.libg.version;
-
-import java.util.regex.*;
-
-public class Version implements Comparable<Version> {
-    final int                   major;
-    final int                   minor;
-    final int                   micro;
-    final String                qualifier;
-    public final static String  VERSION_STRING = "(\\d+)(\\.(\\d+)(\\.(\\d+)(\\.([-_\\da-zA-Z]+))?)?)?";
-    public final static Pattern VERSION        = Pattern
-                                                       .compile(VERSION_STRING);
-    public final static Version LOWEST         = new Version();
-    public final static Version HIGHEST        = new Version(Integer.MAX_VALUE,
-                                                       Integer.MAX_VALUE,
-                                                       Integer.MAX_VALUE,
-                                                       "\uFFFF");
-
-    public static final Version	emptyVersion	= LOWEST;
-
-    public Version() {
-        this(0);
-    }
-
-    public Version(int major, int minor, int micro, String qualifier) {
-        this.major = major;
-        this.minor = minor;
-        this.micro = micro;
-        this.qualifier = qualifier;
-    }
-
-    public Version(int major, int minor, int micro) {
-        this(major, minor, micro, null);
-    }
-
-    public Version(int major, int minor) {
-        this(major, minor, 0, null);
-    }
-
-    public Version(int major) {
-        this(major, 0, 0, null);
-    }
-
-    public Version(String version) {
-        Matcher m = VERSION.matcher(version);
-        if (!m.matches())
-            throw new IllegalArgumentException("Invalid syntax for version: "
-                    + version);
-
-        major = Integer.parseInt(m.group(1));
-        if (m.group(3) != null)
-            minor = Integer.parseInt(m.group(3));
-        else
-            minor = 0;
-
-        if (m.group(5) != null)
-            micro = Integer.parseInt(m.group(5));
-        else
-            micro = 0;
-
-        qualifier = m.group(7);
-    }
-
-    public int getMajor() {
-        return major;
-    }
-
-    public int getMinor() {
-        return minor;
-    }
-
-    public int getMicro() {
-        return micro;
-    }
-
-    public String getQualifier() {
-        return qualifier;
-    }
-
-    public int compareTo(Version other) {
-        if (other == this)
-            return 0;
-
-        if (!(other instanceof Version))
-            throw new IllegalArgumentException(
-                    "Can only compare versions to versions");
-
-        Version o = (Version) other;
-        if (major != o.major)
-            return major - o.major;
-
-        if (minor != o.minor)
-            return minor - o.minor;
-
-        if (micro != o.micro)
-            return micro - o.micro;
-
-        int c = 0;
-        if (qualifier != null)
-            c = 1;
-        if (o.qualifier != null)
-            c += 2;
-
-        switch (c) {
-        case 0:
-            return 0;
-        case 1:
-            return 1;
-        case 2:
-            return -1;
-        }
-        return qualifier.compareTo(o.qualifier);
-    }
-
-    public String toString() {
-        StringBuffer sb = new StringBuffer();
-        sb.append(major);
-        sb.append(".");
-        sb.append(minor);
-        sb.append(".");
-        sb.append(micro);
-        if (qualifier != null) {
-            sb.append(".");
-            sb.append(qualifier);
-        }
-        return sb.toString();
-    }
-
-    public boolean equals(Object ot) {
-        if ( ! (ot instanceof Version))
-            return false;
-        
-        return compareTo((Version)ot) == 0;
-    }
-
-    public int hashCode() {
-        return major * 97 ^ minor * 13 ^ micro
-                + (qualifier == null ? 97 : qualifier.hashCode());
-    }
-
-    public int get(int i) {
-        switch(i) {
-        case 0 : return major;
-        case 1 : return minor;
-        case 2 : return micro;
-        default:
-            throw new IllegalArgumentException("Version can only get 0 (major), 1 (minor), or 2 (micro)");
-        }
-    }
-    
-    public static Version parseVersion(String version) {
-		if (version == null) {
-			return LOWEST;
-		}
-
-		version = version.trim();
-		if (version.length() == 0) {
-			return LOWEST;
-		}
-
-		return new Version(version);
-
-    }
-}
diff --git a/aQute.libg/src/aQute/libg/version/VersionRange.java b/aQute.libg/src/aQute/libg/version/VersionRange.java
deleted file mode 100755
index 47e7447..0000000
--- a/aQute.libg/src/aQute/libg/version/VersionRange.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package aQute.libg.version;
-
-import java.util.regex.*;
-
-public class VersionRange {
-	Version			high;
-	Version			low;
-	char			start	= '[';
-	char			end		= ']';
-
-	static Pattern	RANGE	= Pattern.compile("(\\(|\\[)\\s*(" +
-									Version.VERSION_STRING + ")\\s*,\\s*(" +
-									Version.VERSION_STRING + ")\\s*(\\)|\\])");
-
-	public VersionRange(String string) {
-		string = string.trim();
-		Matcher m = RANGE.matcher(string);
-		if (m.matches()) {
-			start = m.group(1).charAt(0);
-			String v1 = m.group(2);
-			String v2 = m.group(10);
-			low = new Version(v1);
-			high = new Version(v2);
-			end = m.group(18).charAt(0);
-			if (low.compareTo(high) > 0)
-				throw new IllegalArgumentException(
-						"Low Range is higher than High Range: " + low + "-" +
-								high);
-
-		} else
-			high = low = new Version(string);
-	}
-
-	public boolean isRange() {
-		return high != low;
-	}
-
-	public boolean includeLow() {
-		return start == '[';
-	}
-
-	public boolean includeHigh() {
-		return end == ']';
-	}
-
-	public String toString() {
-		if (high == low)
-			return high.toString();
-
-		StringBuffer sb = new StringBuffer();
-		sb.append(start);
-		sb.append(low);
-		sb.append(',');
-		sb.append(high);
-		sb.append(end);
-		return sb.toString();
-	}
-
-	public Version getLow() {
-		return low;
-	}
-
-	public Version getHigh() {
-		return high;
-	}
-
-	public boolean includes(Version v) {
-		if ( !isRange() ) {
-			return low.compareTo(v) <=0;
-		}
-		if (includeLow()) {
-			if (v.compareTo(low) < 0)
-				return false;
-		} else if (v.compareTo(low) <= 0)
-			return false;
-
-		if (includeHigh()) {
-			if (v.compareTo(high) > 0)
-				return false;
-		} else if (v.compareTo(high) >= 0)
-			return false;
-		
-		return true;
-	}
-}
\ No newline at end of file
diff --git a/aQute.libg/src/aQute/libg/version/packageinfo b/aQute.libg/src/aQute/libg/version/packageinfo
deleted file mode 100644
index 7c8de03..0000000
--- a/aQute.libg/src/aQute/libg/version/packageinfo
+++ /dev/null
@@ -1 +0,0 @@
-version 1.0
diff --git a/aQute.libg/src/aQute/libg/xslt/Transform.java b/aQute.libg/src/aQute/libg/xslt/Transform.java
index ea0fcd0..a505c4b 100644
--- a/aQute.libg/src/aQute/libg/xslt/Transform.java
+++ b/aQute.libg/src/aQute/libg/xslt/Transform.java
@@ -9,36 +9,35 @@ import javax.xml.transform.*;
 import javax.xml.transform.stream.*;
 
 public class Transform {
-    static TransformerFactory transformerFactory = TransformerFactory
-                                                         .newInstance();
-
-    static Map<URL, Templates> cache          = new ConcurrentHashMap<URL, Templates>();
-
-    public static void transform(TransformerFactory transformerFactory, URL xslt, InputStream in, OutputStream out)
-            throws Exception {
-        if ( xslt == null ) 
-            throw new IllegalArgumentException("No source template specified");
-        
-        Templates templates = cache.get(xslt);
-        if (templates == null) {
-            InputStream xsltIn = xslt.openStream();
-            try {
-                templates = transformerFactory
-                        .newTemplates(new StreamSource(xsltIn));
-
-                cache.put(xslt, templates);
-            } finally {
-                in.close();
-            }
-        }
-        Result xmlResult = new StreamResult(out);
-        Source xmlSource = new StreamSource(in);
-        Transformer t = templates.newTransformer();
-        t.transform(xmlSource, xmlResult);
-        out.flush();
-    }
-
-    public static void transform(URL xslt, InputStream in, OutputStream out) throws Exception {
-        transform(transformerFactory,xslt, in, out);
-    }
+	static TransformerFactory	transformerFactory	= TransformerFactory.newInstance();
+
+	static Map<URI,Templates>	cache				= new ConcurrentHashMap<URI,Templates>();
+
+	public static void transform(TransformerFactory transformerFactory, URL xslt, InputStream in, OutputStream out)
+			throws Exception {
+		if (xslt == null)
+			throw new IllegalArgumentException("No source template specified");
+
+		Templates templates = cache.get(xslt.toURI());
+		if (templates == null) {
+			InputStream xsltIn = xslt.openStream();
+			try {
+				templates = transformerFactory.newTemplates(new StreamSource(xsltIn));
+
+				cache.put(xslt.toURI(), templates);
+			}
+			finally {
+				in.close();
+			}
+		}
+		Result xmlResult = new StreamResult(out);
+		Source xmlSource = new StreamSource(in);
+		Transformer t = templates.newTransformer();
+		t.transform(xmlSource, xmlResult);
+		out.flush();
+	}
+
+	public static void transform(URL xslt, InputStream in, OutputStream out) throws Exception {
+		transform(transformerFactory, xslt, in, out);
+	}
 }
diff --git a/aQute.libg/src/aQute/service/reporter/Messages.java b/aQute.libg/src/aQute/service/reporter/Messages.java
new file mode 100644
index 0000000..e4b589e
--- /dev/null
+++ b/aQute.libg/src/aQute/service/reporter/Messages.java
@@ -0,0 +1,14 @@
+package aQute.service.reporter;
+
+
+
+public interface Messages {
+	static public interface ERROR extends Reporter.SetLocation {}
+
+	static public interface WARNING extends Reporter.SetLocation {}
+
+	ERROR NoSuchFile_(Object r);
+
+	ERROR Unexpected_Error_(String context, Exception e);
+
+}
diff --git a/aQute.libg/src/aQute/service/reporter/Report.java b/aQute.libg/src/aQute/service/reporter/Report.java
new file mode 100644
index 0000000..a637c8e
--- /dev/null
+++ b/aQute.libg/src/aQute/service/reporter/Report.java
@@ -0,0 +1,53 @@
+package aQute.service.reporter;
+
+import java.util.*;
+
+/**
+ * A base interface to represent the state of a work in progress.
+ */
+public interface Report {
+	/**
+	 * Defines a record for the location of an error/warning
+	 */
+	class Location {
+		public String	message;
+		public int		line;
+		public String	file;
+		public String	header;
+		public String	context;
+		public String	reference;
+		public String	methodName;
+	}
+
+
+	/**
+	 * Return the warnings. This list must not be changed and may be immutable.
+	 * 
+	 * @return the warnings
+	 */
+	List<String> getWarnings();
+
+	/**
+	 * Return the errors. This list must not be changed and may be immutable.
+	 * 
+	 * @return the errors
+	 */
+	List<String> getErrors();
+
+	/**
+	 * Return the errors for the given error or warning. Can return null.
+	 * 
+	 * @param msg
+	 *            The message
+	 * @return null or the location of the message
+	 */
+	Location getLocation(String msg);
+
+	/**
+	 * Check if this report has any errors.
+	 * 
+	 * @return true if errors is empty
+	 */
+	
+	boolean isOk();
+}
diff --git a/aQute.libg/src/aQute/service/reporter/Reporter.java b/aQute.libg/src/aQute/service/reporter/Reporter.java
new file mode 100755
index 0000000..521ec5e
--- /dev/null
+++ b/aQute.libg/src/aQute/service/reporter/Reporter.java
@@ -0,0 +1,130 @@
+package aQute.service.reporter;
+
+/**
+ * A base interface to model a work in progress. Though exceptions work well for
+ * major, well, exceptions, they are lousy for reporting errors/warnings in a
+ * task. Logging also sucks because it is global, hard to relate to a single
+ * piece of work. This small (uncoupled) interface is intended to fill this gap.
+ * The idea is that different tasks can perform parts and the progress can be
+ * integrated. A reporter is not mandated to track locations. Locations should
+ * be seen as best effort.
+ */
+public interface Reporter extends Report {
+	/**
+	 * Fluid interface to set location data
+	 */
+	interface SetLocation {
+		/**
+		 * Set the file location
+		 */
+		SetLocation file(String file);
+
+		/**
+		 * Set the header/section location. This is normally the header in a
+		 * manifest or properties file.
+		 */
+		SetLocation header(String header);
+
+		/**
+		 * Set the context in the header.
+		 * 
+		 * @param context
+		 * @return
+		 */
+		SetLocation context(String context);
+
+		/**
+		 * Set the method where the error is reported.
+		 * 
+		 * @param context
+		 * @return
+		 */
+		SetLocation method(String methodName);
+
+		/**
+		 * Set the line number. Line 0 is the top line.
+		 */
+		SetLocation line(int n);
+
+		/**
+		 * Set a reference for the error (url or so)
+		 */
+
+		SetLocation reference(String reference);
+	}
+
+	/**
+	 * Create an error. Implementations must ensure that the given args are not
+	 * prevented from garbage collecting. The args must have a proper toString
+	 * method.
+	 * 
+	 * @param format
+	 *            The format of the error
+	 * @param args
+	 *            The arguments of the error
+	 * @return a SetLocation to set the location
+	 */
+	SetLocation error(String format, Object... args);
+
+	/**
+	 * Create a warning. Implementations must ensure that the given args are not
+	 * prevented from garbage collecting. The args must have a proper toString
+	 * method.
+	 * 
+	 * @param format
+	 *            The format of the error
+	 * @param args
+	 *            The arguments of the error
+	 * @return a SetLocation to set the location
+	 */
+	SetLocation warning(String format, Object... args);
+
+	/**
+	 * Create a warning. Implementations must ensure that the given args are not
+	 * prevented from garbage collecting. The args must have a proper toString
+	 * method.
+	 * 
+	 * @param format
+	 *            The format of the error
+	 * @param args
+	 *            The arguments of the error
+	 */
+	void trace(String format, Object... args);
+
+	/**
+	 * Create a warning. Implementations must ensure that the given args are not
+	 * prevented from garbage collecting. The args must have a proper toString
+	 * method.
+	 * 
+	 * @param progress
+	 *            A value between 0 and 1 indicating the progress. 0 is starting
+	 *            and >=1 is done.
+	 * @param format
+	 *            The format of the error
+	 * @param args
+	 *            The arguments of the error
+	 * @return a SetLocation to set the location
+	 */
+	void progress(float progress, String format, Object... args);
+
+	/**
+	 * Dedicated message for an exception.
+	 * 
+	 * @param t
+	 *            The exception
+	 * @param s
+	 *            The format of the message
+	 * @param args
+	 *            The arguments
+	 */
+	public SetLocation exception(Throwable t, String format, Object... args);
+
+	/**
+	 * The provider of the reporter wants pedantic reporting, meaning every
+	 * possible warning should be reported.
+	 * 
+	 * @return if this is a pedantic reporter.
+	 */
+	boolean isPedantic();
+
+}
diff --git a/aQute.libg/src/aQute/service/reporter/packageinfo b/aQute.libg/src/aQute/service/reporter/packageinfo
new file mode 100644
index 0000000..9ad81f6
--- /dev/null
+++ b/aQute.libg/src/aQute/service/reporter/packageinfo
@@ -0,0 +1 @@
+version 1.0.0
diff --git a/aQute.libg/src/test/CommandTest.java b/aQute.libg/src/test/CommandTest.java
new file mode 100644
index 0000000..e22d1ff
--- /dev/null
+++ b/aQute.libg/src/test/CommandTest.java
@@ -0,0 +1,95 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+
+import junit.framework.*;
+import aQute.lib.collections.*;
+import aQute.lib.getopt.*;
+import aQute.lib.justif.*;
+import aQute.libg.reporter.*;
+
+public class CommandTest extends TestCase {
+	ReporterAdapter	rp	= new ReporterAdapter(System.err);
+
+	public static void testWrap() {
+		StringBuilder sb = new StringBuilder();
+		sb.append("Abc \t3Def ghi asoudg gd ais gdiasgd asgd auysgd asyudga8sdga8sydga 8sdg\fSame column\nbegin\n"
+				+ "\t3abc\t5def\nabc");
+		Justif justif = new Justif(30);
+		justif.wrap(sb);
+		System.err.println(sb);
+	}
+
+	interface xoptions extends Options {
+		boolean exceptions();
+	}
+
+	static class X {
+		public void _cmda(@SuppressWarnings("unused") xoptions opts) {
+
+		}
+
+		public void _cmdb(@SuppressWarnings("unused") xoptions opts) {
+
+		}
+	}
+
+	public void testCommand() throws Exception {
+		CommandLine getopt = new CommandLine(rp);
+		assertEquals("[cmda, cmdb]", getopt.getCommands(new X()).keySet().toString());
+
+		getopt.execute(new X(), "cmda", Arrays.asList("-e", "help"));
+
+	}
+
+	static interface c1options extends Options {
+		boolean flag();
+
+		boolean notset();
+
+		int a();
+
+		String bb();
+
+		Collection<File> input();
+	}
+
+	interface c2options extends Options {
+
+	}
+
+	public static class C1 extends Assert {
+		public static String _c1(c1options x) {
+
+			assertEquals(true, x.flag());
+			assertEquals(33, x.a());
+			assertEquals("bb", x.bb(), "bb");
+			assertEquals(Arrays.asList(new File("f1.txt"), new File("f2.txt")), x.input());
+			assertEquals(false, x.notset());
+			assertEquals(Arrays.asList("-a", "--a", "a"), x._());
+
+			return "a";
+		}
+
+		public void _c2(@SuppressWarnings("unused") c2options x) {
+
+		}
+	}
+
+	public void testHelp() throws Exception {
+		CommandLine getopt = new CommandLine(rp);
+		C1 c1 = new C1();
+		getopt.execute(c1, "help", new ExtList<String>("c1"));
+
+	}
+
+	public void testSimple() throws Exception {
+		CommandLine getopt = new CommandLine(rp);
+		C1 c1 = new C1();
+		String help = getopt.execute(c1, "c1", new ExtList<String>("-f", "-a", "33", "--bb", "bb", "-i", "f1.txt",
+				"-i", "f2.txt", "--", "-a", "--a", "a"));
+		System.err.println(help);
+	}
+
+}
diff --git a/aQute.libg/src/test/ConverterTest.java b/aQute.libg/src/test/ConverterTest.java
new file mode 100644
index 0000000..107c306
--- /dev/null
+++ b/aQute.libg/src/test/ConverterTest.java
@@ -0,0 +1,395 @@
+package test;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import junit.framework.*;
+import aQute.lib.converter.*;
+import aQute.lib.converter.Converter.Hook;
+import aQute.lib.io.*;
+import aQute.libg.cryptography.*;
+import aQute.libg.map.*;
+
+ at SuppressWarnings({
+		"unchecked", "rawtypes"
+})
+public class ConverterTest extends TestCase {
+	Converter	converter	= new Converter();
+
+	
+	interface M {
+		String a();
+		int b();
+		int c();
+		double d();
+	}
+	public void testMap() throws Exception {
+		Map<String,String> map = MAP.$("a", "A").$("b", "2");
+		M m = converter.convert(M.class, map);
+		assertEquals("A", m.a());
+		assertEquals(2, m.b());
+		assertEquals(0, m.c());
+		assertEquals(0d, m.d());
+	}
+	
+	
+	public void testTypeRef() throws Exception {
+		Map<String,Integer> f;
+		Type type = (new TypeReference<Map<String,Integer>>() {}).getType();
+		assertTrue( type instanceof ParameterizedType);
+		ParameterizedType ptype  = (ParameterizedType) type; 
+		assertEquals( Map.class, ptype.getRawType());
+		assertEquals( String.class, ptype.getActualTypeArguments()[0]);
+		assertEquals( Integer.class, ptype.getActualTypeArguments()[1]);
+		
+		Map<Integer,String> m = MAP.$(1, "1").$(2,"2");
+		f = converter.convert(new TypeReference<Map<String,Integer>>(){}, m);
+		
+		assertEquals( f.get("1"),(Integer) 1);
+		assertEquals( f.get("2"),(Integer) 2);
+	}
+	
+	
+	public static void hookTest() throws Exception {
+		Converter converter = new Converter().hook(File.class, new Hook() {
+
+			public Object convert(Type dest, Object o) {
+				if (o instanceof String) {
+					return IO.getFile(new File(""), o.toString());
+				}
+				return null;
+			}
+
+		});
+		assertEquals(new Integer(6), converter.convert(Integer.class, "6"));
+		assertEquals(new File("src").getAbsoluteFile(), converter.convert(File.class, "src"));
+		
+		converter.hook(null, new Hook() {
+			
+			public Object convert(Type dest, Object o) throws Exception {
+				if ( dest instanceof Class) {
+					if ( Number.class.isAssignableFrom((Class< ? >) dest))
+						return 1;
+				}
+				return null;
+			}
+		});
+		assertEquals(new Integer(1), converter.convert(Integer.class, "6"));
+		assertEquals(new Integer(1), converter.convert(Long.class, "6"));
+		assertEquals("6", converter.convert(String.class, "6"));
+	}
+
+	/**
+	 * Test map to object
+	 */
+
+	public class DD {
+
+	}
+
+	public class D {
+		int		n;
+		String	s;
+
+	}
+
+	public void testMap2Object() throws Exception {
+
+	}
+
+	/**
+	 * Digests as byte[]
+	 * 
+	 * @throws Exception
+	 */
+
+	public void testDigest() throws Exception {
+		Digester<SHA1> digester = SHA1.getDigester();
+		IO.copy("ABC".getBytes(), digester);
+		SHA1 digest = digester.digest();
+		byte[] out = converter.convert(byte[].class, digest);
+		assertTrue(Arrays.equals(digest.digest(), out));
+
+		ByteArrayOutputStream bout = new ByteArrayOutputStream();
+		bout.write("Hello World".getBytes());
+		assertTrue(Arrays.equals("Hello World".getBytes(), converter.convert(byte[].class, bout)));
+
+	}
+
+	/**
+	 * Map a string to a char[], Character[], or Collection<Character>
+	 */
+
+	public void testCharacters() throws Exception {
+		assertTrue(Arrays.equals(new char[] {
+				'A', 'B', 'C'
+		}, converter.convert(char[].class, "ABC")));
+		assertEquals("ABC", converter.convert(String.class, new char[] {
+				'A', 'B', 'C'
+		}));
+
+	}
+
+	/**
+	 * Test string to primitives
+	 * 
+	 * @throws Exception
+	 */
+
+	public void testStringtoPrimitives() throws Exception {
+		assertEquals((Integer) (int) 'A', converter.convert(int.class, 'A'));
+		assertEquals((Integer) (int) 'A', converter.convert(Integer.class, 'A'));
+		assertEquals((Boolean) true, converter.convert(boolean.class, "1"));
+		assertEquals((Boolean) true, converter.convert(Boolean.class, "1"));
+		assertEquals((Boolean) false, converter.convert(boolean.class, "0"));
+		assertEquals((Boolean) false, converter.convert(Boolean.class, "0"));
+		assertEquals((Byte) (byte) 1, converter.convert(byte.class, "1"));
+		assertEquals((Byte) (byte) 1, converter.convert(Byte.class, "1"));
+		assertEquals((Short) (short) 1, converter.convert(short.class, "1"));
+		assertEquals((Short) (short) 1, converter.convert(Short.class, "1"));
+		assertEquals((Integer) 1, converter.convert(int.class, "1"));
+		assertEquals((Integer) 1, converter.convert(Integer.class, "1"));
+		assertEquals((Long) 1L, converter.convert(long.class, "1"));
+		assertEquals((Long) 1L, converter.convert(Long.class, "1"));
+		assertEquals(1f, converter.convert(float.class, "1"));
+		assertEquals(1f, converter.convert(Float.class, "1"));
+		assertEquals(1d, converter.convert(double.class, "1"));
+		assertEquals(1d, converter.convert(double.class, "1"));
+		assertEquals((Character) 'A', converter.convert(char.class, "A"));
+		assertEquals((Character) 'A', converter.convert(Character.class, "A"));
+	}
+
+	/**
+	 * Test the wrappers
+	 * 
+	 * @throws Exception
+	 */
+	public void testWrappers() throws Exception {
+		Object[] types = {
+				Boolean.FALSE, (byte) 0, '\u0000', (short) 0, 0, 0L, 0f, 0d
+		};
+		for (int i = 0; i < types.length; i++) {
+			for (int j = 0; j < types.length; j++) {
+				assertEquals("" + i + " " + j, types[i], converter.convert(types[i].getClass(), types[j]));
+			}
+		}
+	}
+
+	/**
+	 * Create an array and see if we can convert a single number
+	 * 
+	 * @throws Exception
+	 */
+	public void testPrimitives() throws Exception {
+		assertPrimitives1(1);
+		assertPrimitives(0);
+		assertPrimitives(new Object[] {
+				0, 1, 2
+		});
+		assertPrimitives1(new Object[] {
+				1, 2
+		});
+		assertPrimitives(false);
+		assertPrimitives1(true);
+		assertPrimitives('\u0000');
+		assertPrimitives1('\u0001');
+	}
+
+	/**
+	 * Test enums
+	 * 
+	 * @param source
+	 * @throws Exception
+	 */
+	public enum X {
+		A, B, C;
+	}
+
+	public void testEnums() throws Exception {
+		assertEquals(X.A, converter.convert(X.class, "A"));
+		assertEquals(X.B, converter.convert(X.class, 1));
+	}
+
+	/**
+	 * Test collections
+	 * 
+	 * @param source
+	 * @throws Exception
+	 */
+	static class XX {
+		public ArrayList<String>				al;
+		public Collection<String>				col;
+		public Queue<String>					queue;
+		public Stack<String>					stack;
+		public Vector<String>					vector;
+		public Set<String>						set;
+		public TreeSet<String>					treeset;
+		public SortedSet<String>				sorted;
+		public ConcurrentLinkedQueue<String>	concurrent;
+		public CopyOnWriteArrayList<String>		concurrentList;
+		public CopyOnWriteArraySet<String>		concurrentSet;
+	}
+
+	public void testCollections() throws Exception {
+		Class<XX> xx = XX.class;
+		Object xxx = xx.newInstance();
+		int count = 11;
+		for (Field field : xx.getFields()) {
+			Object o = converter.convert(field.getGenericType(), 1);
+			assertTrue(o instanceof Collection);
+			Collection c = (Collection) o;
+			assertEquals("1", c.iterator().next());
+			field.set(xxx, o);
+			count--;
+		}
+		assertEquals(0, count);
+	}
+
+	/**
+	 * Test generic collections
+	 * 
+	 * @param source
+	 * @throws Exception
+	 */
+	static class GC {
+		public Collection<String>				strings;
+		public Collection<Collection<String>>	stringss;
+		public Collection<String>[]				stringsarray;
+		public List<X>							enums;
+		public X[]								enuma;
+		public List								list;
+	}
+
+	public void testGenericCollections() throws Exception {
+		Class<GC> xx = GC.class;
+		GC g = xx.newInstance();
+
+		for (Field field : xx.getFields()) {
+			Object o = converter.convert(field.getGenericType(), 1);
+			field.set(g, o);
+		}
+		assertEquals("[1]", g.strings.toString());
+		assertEquals(String.class, g.strings.iterator().next().getClass());
+		assertEquals("[[1]]", g.stringss.toString());
+		assertEquals("[1]", g.stringsarray[0].toString());
+		assertEquals("[1]", g.list.toString());
+		assertTrue(g.list.get(0) instanceof Integer);
+		assertEquals(X.B, g.enuma[0]);
+		assertEquals(X.B, g.enums.get(0));
+	}
+
+	/**
+	 * Test generic maps
+	 * 
+	 * @param source
+	 * @throws Exception
+	 */
+	public static class GM {
+		public Map<String,Integer>					strings;
+		public SortedMap<String,Integer>			sorted;
+		public TreeMap<String,Integer>				tree;
+		public ConcurrentHashMap<String,Integer>	concurrenthash;
+		public ConcurrentMap<String,Integer>		concurrent;
+		public Map									map;
+	}
+
+	public static class GT {
+		public int		a	= 1;
+		public double	b	= 2;
+	}
+
+	public void testGenericMaps() throws Exception {
+		Class<GM> xx = GM.class;
+		GM gMap = xx.newInstance();
+		GM gSemiMap = xx.newInstance();
+
+		GT semiMap = new GT();
+		Map map = new HashMap<String,Integer>();
+		map.put("a", 1);
+		map.put("b", 2);
+
+		for (Field field : xx.getFields()) {
+			Object o = converter.convert(field.getGenericType(), map);
+			field.set(gMap, o);
+			Object o2 = converter.convert(field.getGenericType(), semiMap);
+			field.set(gSemiMap, o2);
+		}
+		assertEquals("{a=1, b=2}", new TreeMap(gMap.strings).toString());
+		assertEquals("{a=1, b=2}", new TreeMap(gSemiMap.strings).toString());
+	}
+
+	void assertPrimitives(@SuppressWarnings("unused") Object source) throws Exception {
+		Class[] types = {
+				byte.class, boolean.class, char.class, short.class, int.class, long.class, float.class, double.class
+		};
+		for (Class c : types) {
+			Class at = Array.newInstance(c, 1).getClass();
+			Object parray = converter.convert(at, 0);
+			Object o = Array.get(parray, 0);
+			if (o instanceof Number)
+				assertEquals(0, ((Number) o).intValue());
+			else if (o instanceof Character)
+				assertEquals(0, ((Character) o).charValue());
+			else if (o instanceof Boolean)
+				assertEquals(false, ((Boolean) o).booleanValue());
+			else
+				fail(o.getClass() + " unexpected ");
+
+			assertEquals(at, parray.getClass());
+			assertEquals(c, parray.getClass().getComponentType());
+		}
+	}
+
+	/**
+	 * Test constructor
+	 * 
+	 * @param source
+	 * @throws Exception
+	 */
+
+	public void testConstructor() throws Exception {
+		String home = System.getProperty("user.home");
+		assertEquals(new File(home), converter.convert(File.class, home));
+		//assertEquals(new Version(1, 0, 0), converter.convert(Version.class, "1.0.0"));
+	}
+
+	/**
+	 * Test valueOf
+	 * 
+	 * @param source
+	 * @throws Exception
+	 */
+
+	public void testValueOf() throws Exception {
+		assertEquals((Byte) (byte) 12, converter.convert(Byte.class, "12"));
+		assertEquals((Boolean) true, converter.convert(Boolean.class, "TRUE"));
+		assertEquals((Character) '1', converter.convert(char.class, "49"));
+		assertEquals((Boolean) true, converter.convert(Boolean.class, "TRUE"));
+		assertEquals((Boolean) true, converter.convert(Boolean.class, "TRUE"));
+		assertEquals((Boolean) true, converter.convert(Boolean.class, "TRUE"));
+	}
+
+	void assertPrimitives1(Object source) throws Exception {
+		Class[] types = {
+				byte.class, boolean.class, char.class, short.class, int.class, long.class, float.class, double.class
+		};
+		for (Class c : types) {
+			Class at = Array.newInstance(c, 1).getClass();
+			Object parray = converter.convert(at, source);
+			Object o = Array.get(parray, 0);
+			if (o instanceof Number)
+				assertEquals(1, ((Number) o).intValue());
+			else if (o instanceof Character)
+				assertEquals(1, ((Character) o).charValue());
+			else if (o instanceof Boolean)
+				assertEquals(true, ((Boolean) o).booleanValue());
+			else
+				fail(o.getClass() + " unexpected ");
+
+			assertEquals(at, parray.getClass());
+			assertEquals(c, parray.getClass().getComponentType());
+		}
+	}
+}
diff --git a/aQute.libg/src/test/ExecuteTest.java b/aQute.libg/src/test/ExecuteTest.java
new file mode 100644
index 0000000..fb604e9
--- /dev/null
+++ b/aQute.libg/src/test/ExecuteTest.java
@@ -0,0 +1,23 @@
+package test;
+
+import junit.framework.*;
+import aQute.libg.command.*;
+
+public class ExecuteTest extends TestCase {
+
+	public static void testSimple() throws Exception {
+		Command c = new Command();
+		c.add("java");
+		c.add("-version");
+		assertEquals(0, c.execute(System.out, System.err));
+	}
+
+	// public void testCoffee() throws Exception {
+	// Command c = new Command();
+	// c.arg("sh", "-c", "coffee -sc")
+	// //
+	// .var("PATH",
+	// "/opt/local/bin:/opt/local/sbin:/Developer/usr/bin:/opt/local/bin:/opt/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin:/usr/local/git/bin");
+	// assertEquals(0, c.execute("()->1", System.out, System.err));
+	// }
+}
diff --git a/aQute.libg/src/test/GlobTest.java b/aQute.libg/src/test/GlobTest.java
new file mode 100644
index 0000000..3da4ad7
--- /dev/null
+++ b/aQute.libg/src/test/GlobTest.java
@@ -0,0 +1,29 @@
+package test;
+
+import junit.framework.*;
+import aQute.libg.glob.*;
+
+public class GlobTest extends TestCase {
+	public static void testSimple() {
+		Glob glob = new Glob("*foo*");
+		assertTrue(glob.matcher("foo").find());
+		assertTrue(glob.matcher("food").find());
+		assertTrue(glob.matcher("Xfoo").find());
+		assertTrue(glob.matcher("XfooY").find());
+		assertFalse(glob.matcher("ood").find());
+	}
+
+	public static void testUrl() {
+		Glob glob;
+
+		glob = new Glob("http://www.example.com/*");
+		assertTrue(glob.matcher("http://www.example.com/repository.xml").find());
+		assertFalse(glob.matcher("https://www.example.com/repository.xml").find());
+
+		glob = new Glob("http://*.example.com/*");
+		assertTrue(glob.matcher("http://www.example.com/repository.xml").find());
+		assertTrue(glob.matcher("http://foo.example.com/repository.xml").find());
+		assertFalse(glob.matcher("http://example.com/repository.xml").find());
+		assertFalse(glob.matcher("http://foo.exampleXcom/repository.xml").find());
+	}
+}
diff --git a/aQute.libg/src/test/HexTest.java b/aQute.libg/src/test/HexTest.java
new file mode 100644
index 0000000..e53b755
--- /dev/null
+++ b/aQute.libg/src/test/HexTest.java
@@ -0,0 +1,95 @@
+package test;
+
+import java.util.*;
+
+import junit.framework.*;
+import aQute.lib.base64.*;
+import aQute.lib.hex.*;
+
+public class HexTest extends TestCase {
+
+	static final char	ns[]	= {
+			' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'A', 'B', 'C',
+			'D', 'E', 'F', 'G', '_'
+								};
+	static final int	nsr[]	= {
+			-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1, 10, 11, 12, 13, 14, 15, -1, -1
+								};
+
+	public static void testNibble() {
+		for (int i = 0; i<ns.length;i++) {
+			try {
+				assertEquals(nsr[i], Hex.nibble(ns[i]));
+			} catch (IllegalArgumentException e) {
+				assertEquals("Did not get an exception for nibble \"" + ns[i] + "\"", -1, nsr[i]);
+			}
+		}
+	}
+
+	public static void testHexOddCount() {
+		boolean ex = false;
+		byte[] bytes = null;
+		try {
+			Hex.toByteArray("b10a8db164e0754105b7a99be72e3fe");
+		}
+		catch (IllegalArgumentException e) {
+			ex = true;
+		}
+		assertTrue(ex);
+		assertNull(bytes);
+	}
+
+	public static void testHex() {
+		byte[] bytes = Hex.toByteArray("b10a8db164e0754105b7a99be72e3fe5");
+		String s = Hex.toHexString(bytes);
+		assertEquals("b10a8db164e0754105b7a99be72e3fe5", s.toLowerCase());
+	}
+
+	public static void testBase64() {
+		assertEquals("", Base64.encodeBase64(new byte[] {}));
+		assertEquals("MQ==", Base64.encodeBase64(new byte[] {
+			'1'
+		}));
+		assertEquals("MTI=", Base64.encodeBase64(new byte[] {
+				'1', '2'
+		}));
+		assertEquals("MTIz", Base64.encodeBase64(new byte[] {
+				'1', '2', '3'
+		}));
+		assertEquals("MTIzNA==", Base64.encodeBase64(new byte[] {
+				'1', '2', '3', '4'
+		}));
+		assertEquals("MTIzNDU=", Base64.encodeBase64(new byte[] {
+				'1', '2', '3', '4', '5'
+		}));
+		assertEquals("MTIzNDU2", Base64.encodeBase64(new byte[] {
+				'1', '2', '3', '4', '5', '6'
+		}));
+		assertEquals("MTIzNDU2Nw==", Base64.encodeBase64(new byte[] {
+				'1', '2', '3', '4', '5', '6', '7'
+		}));
+		assertEquals("MTIzNDU2Nzg=", Base64.encodeBase64(new byte[] {
+				'1', '2', '3', '4', '5', '6', '7', '8'
+		}));
+		assertEquals("MTIzNDU2Nzg5", Base64.encodeBase64(new byte[] {
+				'1', '2', '3', '4', '5', '6', '7', '8', '9'
+		}));
+		assertEquals("MTIzNDU2Nzg5AA==", Base64.encodeBase64(new byte[] {
+				'1', '2', '3', '4', '5', '6', '7', '8', '9', 0
+		}));
+		assertEquals("MTIzNDU2Nzg59g==", Base64.encodeBase64(new byte[] {
+				'1', '2', '3', '4', '5', '6', '7', '8', '9', -10
+		}));
+
+		assertTrue(Arrays.equals(new byte[0], Base64.decodeBase64("")));
+		assertTrue(Arrays.equals(new byte[] {
+			'1'
+		}, Base64.decodeBase64("MQ==")));
+		assertTrue(Arrays.equals(new byte[] {
+				'1', '2', '3', '4', '5', '6', '7'
+		}, Base64.decodeBase64("MTIzNDU2Nw==")));
+		assertTrue(Arrays.equals(new byte[] {
+				'1', '2', '3', '4', '5', '6', '7', '8', '9', -10
+		}, Base64.decodeBase64("MTIzNDU2Nzg59g==")));
+	}
+}
diff --git a/aQute.libg/src/test/JSONTest.java b/aQute.libg/src/test/JSONTest.java
new file mode 100644
index 0000000..84dbbbe
--- /dev/null
+++ b/aQute.libg/src/test/JSONTest.java
@@ -0,0 +1,707 @@
+package test;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.text.*;
+import java.util.*;
+import java.util.regex.*;
+
+import junit.framework.*;
+import aQute.lib.converter.*;
+import aQute.lib.io.*;
+import aQute.lib.json.*;
+import aQute.libg.map.*;
+
+public class JSONTest extends TestCase {
+	JSONCodec	codec	= new JSONCodec();
+
+	/**
+	 * test the hex/base64 encoding
+	 * 
+	 * @throws Exception
+	 */
+	public void testBase64AndHex() throws Exception {
+		byte[] b = "abc".getBytes("UTF-8");
+
+		assertTrue(Arrays.equals(b, codec.dec().from("\" 616263\"").get(byte[].class)));
+		assertTrue(Arrays.equals(b, codec.dec().from("\"61 62 63\"").get(byte[].class)));
+		assertTrue(Arrays.equals(b, codec.dec().from("\"YWJj\"").get(byte[].class)));
+		assertTrue(Arrays.equals(b, codec.dec().from("\" Y W J j\"").get(byte[].class)));
+	}
+
+	/**
+	 * Test the use of inflate/deflate
+	 */
+
+	static public class X {
+		public String		hello;
+		public int			value;
+		public List<String>	list;
+	}
+
+	public void testZip() throws Exception {
+		X x = new X();
+		x.hello = "hello";
+		x.value = 42;
+		x.list = Arrays.asList("1", "2");
+
+		ByteArrayOutputStream bout = new ByteArrayOutputStream();
+		codec.enc().deflate().to(bout).put(x).close();
+		byte[] data = bout.toByteArray();
+
+		X xx = codec.dec().inflate().from(new ByteArrayInputStream(data)).get(X.class);
+		assertNotNull(xx);
+		assertEquals("hello", xx.hello);
+		assertEquals(42, xx.value);
+		assertEquals(Arrays.asList("1", "2"), xx.list);
+
+	}
+
+	public void testToDictionary() throws Exception {
+		Dictionary<String,String> dictionary = codec.dec().from("{\"x\":3, \"y\":\"\"}")
+				.get(new TypeReference<Dictionary<String,String>>() {});
+		assertEquals("3", dictionary.get("x"));
+		assertEquals("", dictionary.get("y"));
+	}
+
+	/**
+	 * Test conversion of iterable
+	 * 
+	 * @throws Exception
+	 * @throws IOException
+	 */
+
+	public void testIterable() throws IOException, Exception {
+		final List<String> l = Arrays.asList("a", "b", "c");
+		Iterable<String> i = new Iterable<String>() {
+
+			public Iterator<String> iterator() {
+				return l.iterator();
+			}
+		};
+
+		String s = codec.enc().to().put(i).toString();
+		assertEquals("[\"a\",\"b\",\"c\"]", s);
+	}
+
+	/**
+	 * Test missing field
+	 */
+
+	public static class MissingField {
+
+	}
+
+	public void testMissingField() throws Exception {
+		Decoder dec = codec.dec();
+		dec.from("{\"field\":3}").get(MissingField.class);
+		assertEquals(3, dec.getExtra().get(MissingField.class.getName() + ".field"));
+
+		try {
+			dec = codec.dec();
+			dec.from("{\"field\":3}").strict().get(MissingField.class);
+			fail("Should have thrown an exception due to a missing field");
+		}
+		catch (Exception e) {
+			// ok
+		}
+	}
+
+	/**
+	 * Test escaping
+	 * 
+	 * @throws Exception
+	 */
+
+	public void testEscape() throws Exception {
+
+		assertEquals("{\"message\":\"Hello world\"}", codec.dec().from("\"{\\\"message\\\":\\\"Hello world\\\"}\"")
+				.get(String.class));
+		assertEquals("\"{\\\"message\\\":\\\"Hello world\\\"}\"", codec.enc().put("{\"message\":\"Hello world\"}")
+				.toString());
+	}
+
+	/**
+	 * Test maps
+	 * 
+	 * @throws Exception
+	 */
+
+	public void testStream() throws Exception {
+		Encoder enc = codec.enc();
+		ByteArrayOutputStream bout = new ByteArrayOutputStream();
+		enc.to(bout).put("Hello").flush();
+		assertEquals("\"Hello\"", new String(bout.toByteArray()));
+	}
+
+	/**
+	 * Test maps
+	 * 
+	 * @throws Exception
+	 */
+
+	public void testMaps() throws Exception {
+		Encoder enc = codec.enc();
+		Map<String,Object> map = new HashMap<String,Object>();
+		map.put("a", new int[] {
+				1, 2
+		});
+		String string = enc.put(map).toString();
+		assertEquals("{\"a\":[1,2]}", string);
+	}
+
+	/**
+	 * Test primitive arrays
+	 * 
+	 * @throws Exception
+	 */
+	public static void testPrimitiveArrays() throws Exception {
+		Decoder dec = new JSONCodec().dec();
+
+		assertTrue(Arrays.equals(new Boolean[] {
+				true, false
+		}, dec.from(" [ true , false ] ").get(Boolean[].class)));
+		assertTrue(Arrays.equals(new boolean[] {
+				true, false
+		}, dec.from(" [ true , false ] ").get(boolean[].class)));
+
+		assertTrue(Arrays.equals(new Character[] {
+				'A', 'B'
+		}, dec.from(" [ 65,66 ] ").get(Character[].class)));
+		assertTrue(Arrays.equals(new char[] {
+				'A', 'B'
+		}, dec.from(" [ 65,66 ] ").get(char[].class)));
+		assertTrue(Arrays.equals(new Short[] {
+				-1, -2
+		}, dec.from("[ -1 , -2 ]").get(Short[].class)));
+		assertTrue(Arrays.equals(new short[] {
+				-1, -2
+		}, dec.from("[ -1 , -2 ]").get(short[].class)));
+		assertTrue(Arrays.equals(new Integer[] {
+				-1, -2
+		}, dec.from("[ -1 , -2 ]").get(Integer[].class)));
+		assertTrue(Arrays.equals(new int[] {
+				-1, -2
+		}, dec.from("[ -1 , -2 ]").get(int[].class)));
+		assertTrue(Arrays.equals(new Long[] {
+				-1L, -2L
+		}, dec.from("[ -1 , -2 ]").get(Long[].class)));
+		assertTrue(Arrays.equals(new long[] {
+				-1, -2
+		}, dec.from("[ -1 , -2 ]").get(long[].class)));
+		assertTrue(Arrays.equals(new Float[] {
+				-1f, -2f
+		}, dec.from("[ -1 ,-2 ]").get(Float[].class)));
+		assertTrue(Arrays.equals(new float[] {
+				-1f, -2f
+		}, dec.from("[ -1, -2 ]").get(float[].class)));
+		assertTrue(Arrays.equals(new Double[] {
+				-1d, -2d
+		}, dec.from("[-1 , -2 ]").get(Double[].class)));
+		assertTrue(Arrays.equals(new double[] {
+				-1d, -2d
+		}, dec.from("[-1, -2]").get(double[].class)));
+
+		Encoder enc = new JSONCodec().enc();
+		assertEquals("[false,true]", enc.to().put(new Boolean[] {
+				false, true
+		}).toString());
+		assertEquals("[false,true]", enc.to().put(new boolean[] {
+				false, true
+		}).toString());
+		assertEquals("[65,66]", enc.to().put(new Character[] {
+				'A', 'B'
+		}).toString());
+		assertEquals("[65,66]", enc.to().put(new char[] {
+				'A', 'B'
+		}).toString());
+		assertEquals("[1,2]", enc.to().put(new short[] {
+				1, 2
+		}).toString());
+		assertEquals("[1,2]", enc.to().put(new Short[] {
+				1, 2
+		}).toString());
+		assertEquals("[1,2]", enc.to().put(new int[] {
+				1, 2
+		}).toString());
+		assertEquals("[1,2]", enc.to().put(new Integer[] {
+				1, 2
+		}).toString());
+		assertEquals("[1,2]", enc.to().put(new long[] {
+				1, 2
+		}).toString());
+		assertEquals("[1,2]", enc.to().put(new Long[] {
+				1L, 2L
+		}).toString());
+		assertEquals("[-1,-2]", enc.to().put(new float[] {
+				-1, -2
+		}).toString());
+		assertEquals("[1,-2]", enc.to().put(new Float[] {
+				1f, -2f
+		}).toString());
+		assertEquals("[-1,2]", enc.to().put(new double[] {
+				-1d, 2d
+		}).toString());
+		assertEquals("[1,2]", enc.to().put(new Double[] {
+				1d, 2d
+		}).toString());
+
+	}
+
+	/**
+	 * Test byte arrays
+	 * 
+	 * @throws Exception
+	 */
+	public static void testByteArrays() throws Exception {
+		Encoder enc = new JSONCodec().enc();
+		assertEquals("[43,41]", enc.to().put(new Byte[] {
+				43, 41
+		}).toString());
+		assertEquals("\"2B29\"", enc.to().put(new byte[] {
+				43, 41
+		}).toString());
+
+		Decoder dec = new JSONCodec().dec();
+		assertTrue(Arrays.equals(new byte[] {
+				43, 41
+		}, dec.faq("'2B29'").get(byte[].class)));
+		assertTrue(Arrays.equals(new Byte[] {
+				43, 41
+		}, dec.from("[43,41]").get(Byte[].class)));
+		assertTrue(Arrays.equals(new byte[] {
+				43, 41
+		}, dec.from("[43,41]").get(byte[].class)));
+	}
+
+	/**
+	 * Basic tests to see if the default types returns something useful
+	 * 
+	 * @throws Exception
+	 */
+	public static void testEncodeBasic() throws Exception {
+		Encoder enc = new JSONCodec().enc();
+		assertEquals("49", enc.to().put((byte) 49).toString());
+		assertEquals("49", enc.to().put('1').toString());
+		assertEquals("\"abc\"", enc.to().put("abc").toString());
+		assertEquals("123", enc.to().put(123).toString());
+		assertEquals("-123", enc.to().put(-123).toString());
+		assertEquals("-123", enc.to().put(-123.0).toString());
+		assertEquals("true", enc.to().put(true).toString());
+		assertEquals("false", enc.to().put(false).toString());
+		assertEquals("null", enc.to().put(null).toString());
+		assertEquals("[1,2,3]", enc.to().put(Arrays.asList(1, 2, 3)).toString());
+		assertEquals("{\"1\":1,\"2\":2,\"3\":3}", enc.to().put(MAP.$(1, 1).$(2, 2).$(3, 3)).toString());
+		assertEquals("{\"1\":1,\"2\":2,\"3\":3}", enc.to().put(MAP.$("1", 1).$("2", 2).$("3", 3)).toString());
+	}
+
+	enum E {
+		A, B;
+	}
+
+	public static void testDecodeBasic() throws Exception {
+		Decoder dec = new JSONCodec().dec();
+
+		// Dates
+		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+		Date d = sdf.parse("2012-03-01T10:23:00");
+		System.out.println(d.getTime());
+		assertEquals(d, dec.from("\"2012-03-01T10:23:00\"").get(Date.class));
+
+		// Numbers
+		assertEquals(49, dec.from("49").get());
+		assertEquals((Integer) 49, dec.from("49").get(Integer.class));
+		assertEquals((Long) 49L, dec.from("49").get(Long.class));
+		assertEquals(49d, dec.from("49").get(Double.class));
+		assertEquals(49.3d, dec.from("49.3").get(Double.class));
+		assertEquals((Byte) (byte) 49, dec.from("49.3").get(Byte.class));
+		assertEquals((Byte) (byte) 49, dec.from("49.9999").get(Byte.class));
+		assertEquals((Short) (short) 49, dec.from("49.9999").get(Short.class));
+		assertEquals(49.9999f, dec.from("49.9999").get(Float.class));
+		assertEquals((Character) '0', dec.from("48").get(Character.class));
+		assertEquals((Boolean) true, dec.from("48").get(Boolean.class));
+		assertEquals((Boolean) false, dec.from("0").get(Boolean.class));
+		assertEquals((Boolean) true, dec.from("48").get(boolean.class));
+		assertEquals((Boolean) false, dec.from("0").get(boolean.class));
+
+		// String based
+		assertEquals("abc", dec.from("\"abc\"").get());
+
+		// Patterns
+		assertTrue(Pattern.class == dec.from("\"abc\"").get(Pattern.class).getClass());
+		assertEquals(Pattern.compile("abc") + "", dec.from("\"abc\"").get(Pattern.class) + "");
+
+		// Check the file system
+		File f = File.createTempFile("tmp", ".tmp");
+		IO.store("Hello", f);
+		String encoded = new JSONCodec().enc().put(f).toString();
+		File otherTempFile = dec.from(encoded).get(File.class);
+		String hello = IO.collect(otherTempFile);
+		assertEquals("Hello", hello);
+		assertNotSame(f, otherTempFile);
+
+		// Enums
+		assertEquals(E.A, dec.from("\"A\"").get(E.class));
+
+		// Arrays as strings
+		assertEquals("[1,2,3]", dec.from("[1,2,3]").get(String.class));
+
+		// Objects as strings
+		assertEquals("{\"a\":1, \"b\":\"abc\"}", dec.from("{\"a\":1, \"b\":\"abc\"}").get(String.class));
+		assertEquals("{\"a\":1, \"b\":\"}{}\"}", dec.from("{\"a\":1, \"b\":\"}{}\"}").get(String.class));
+
+	}
+
+	/**
+	 * Test arrays
+	 */
+	public List<Integer>	integers	= Arrays.asList(1, 2, 3);	// Provides
+																	// generic
+																	// types
+	public int[]			array		= {
+			1, 2, 3
+										};							// Provides
+																	// generic
+																	// types
+
+	public void testArrays() throws Exception {
+		Decoder dec = new JSONCodec().dec();
+
+		// Default is double
+		assertEquals(Arrays.asList(1, 2, 3), dec.from(" [ 1 , 2 , 3 ] ").get());
+
+		// Now use the integers list for the generic type
+
+		Field field = getClass().getField("integers");
+		assertEquals(integers, dec.from(" [ 1 , 2 , 3 ] ").get(field.getGenericType()));
+
+		// And now use the array of primitives
+		field = getClass().getField("array");
+		assertTrue(Arrays.equals(array, (int[]) dec.from(" [ 1 , 2 , 3 ] ").get(field.getGenericType())));
+	}
+
+	/**
+	 * Test the map functionality
+	 */
+	public Map<String,Integer>	map;
+	public Map<Integer,Integer>	mapIntegerKeys;
+
+	public void testObject() throws Exception {
+		Decoder dec = new JSONCodec().dec();
+
+		assertEquals(MAP.$("1", 1).$("2", 2).$("3", 3), dec.from("{\"1\":1,\"2\":2,\"3\":3}").get());
+		assertEquals(MAP.$("1", 1).$("2", 2).$("3", 3), dec.from("\t\n\r {    \"1\"  :  1,  \"2\" :2 ,\"3\" : 3 \n}")
+				.get());
+
+		Field field = getClass().getField("map");
+		assertEquals(MAP.$("1", 1).$("2", 2).$("3", 3), dec.from("\t\n\r {    \"1\"  :  1,  \"2\" :2 ,\"3\" : 3 \n}")
+				.get(field.getGenericType()));
+
+		field = getClass().getField("mapIntegerKeys");
+		assertEquals(MAP.$(1, 1).$(2, 2).$(3, 3), dec.from("{\"1\":1,\"2\":2,\"3\":3}").get(field.getGenericType()));
+	}
+
+	/**
+	 * Test the object support
+	 */
+	public static class Data1 {
+		public boolean				b;
+		public byte					by;
+		public char					ch;
+		public double				d;
+		public float				f;
+		public int					i;
+		public long					l;
+		public String				s;
+		public short				sh;
+		public Map<String,Object>	map;
+	}
+
+	public static class Data1A {
+		public Boolean		b;
+		public Byte			by;
+		public Character	ch;
+		public Double		d;
+		public Float		f;
+		public Integer		i;
+		public Long			l;
+		public String		s;
+		public Short		sh;
+	}
+
+	public static void testEncodeTypeA() throws Exception {
+		Encoder enc = new JSONCodec().enc();
+		Data1A data1 = new Data1A();
+		data1.b = false;
+		data1.by = -1;
+		data1.ch = '1';
+		data1.d = 3.0d;
+		data1.f = 3.0f;
+		data1.i = 1;
+		data1.l = 2l;
+		data1.s = "abc";
+		data1.sh = -10;
+
+		assertEquals("{\"b\":false,\"by\":-1,\"ch\":49,\"d\":3,\"f\":3,\"i\":1,\"l\":2,\"s\":\"abc\",\"sh\":-10}", enc
+				.to().put(data1).toString());
+	}
+
+	public static void testEncodeType() throws Exception {
+		Encoder enc = new JSONCodec().enc();
+		Data1 data1 = new Data1();
+		data1.b = true;
+		data1.by = -1;
+		data1.ch = '1';
+		data1.d = 3.0d;
+		data1.f = 3.0f;
+		data1.i = 1;
+		data1.l = 2l;
+		data1.s = "abc";
+		data1.sh = -10;
+		data1.map = new HashMap<String,Object>();
+		data1.map.put("a", Arrays.asList(1, 2, 3));
+		String s = enc.to().put(data1).toString();
+		assertEquals(
+				"{\"b\":true,\"by\":-1,\"ch\":49,\"d\":3,\"f\":3,\"i\":1,\"l\":2,\"map\":{\"a\":[1,2,3]},\"s\":\"abc\",\"sh\":-10}",
+				s);
+	}
+
+	public static void testDecodeType() throws Exception {
+		Decoder dec = new JSONCodec().dec();
+		Data1 d = dec.from(
+				"{\"b\":false,\"by\":-1,\"ch\":49,\"d\":3.0,\"f\":3.0,\"i\":1,\"l\":2,\"s\":\"abc\",\"sh\":-10}").get(
+				Data1.class);
+		assertEquals(false, d.b);
+		assertEquals(-1, d.by);
+		assertEquals('1', d.ch);
+		assertEquals(3.0d, d.d);
+		assertEquals(3.0f, d.f);
+		assertEquals(1, d.i);
+		assertEquals(2l, d.l);
+		assertEquals("abc", d.s);
+		assertEquals(-10, d.sh);
+	}
+
+	public static void testDecodeTypeA() throws Exception {
+		Decoder dec = new JSONCodec().dec();
+		Data1A d = dec.from(
+				"{\"b\":false,\"by\":-1,\"ch\":49,\"d\":3.0,\"f\":3.0,\"i\":1,\"l\":2,\"s\":\"abc\",\"sh\":-10}").get(
+				Data1A.class);
+		assertEquals((Boolean) false, d.b);
+		assertEquals((Byte) (byte) (-1), d.by);
+		assertEquals((Character) '1', d.ch);
+		assertEquals(3.0d, d.d);
+		assertEquals(3.0f, d.f);
+		assertEquals((Integer) 1, d.i);
+		assertEquals((Long) 2l, d.l);
+		assertEquals("abc", d.s);
+		assertEquals((Short) (short) -10, d.sh);
+
+	}
+
+	/**
+	 * Test complex generic types
+	 */
+
+	public static class Data2 {
+		public Map<String,Integer>						integers;
+		public Map<String,List<Map<Integer,String>>>	map;
+	}
+
+	public static void testComplexMaps() throws Exception {
+		Decoder dec = new JSONCodec().dec();
+		Data2 d = dec.from("{\"map\": {\"a\":[ {\"1\":1}, {\"2\":2} ]},\"integers\":{\"c\":1}}").get(Data2.class);
+
+		// Check integers
+		assertEquals(1, d.integers.size());
+		assertEquals((Integer) 1, d.integers.get("c"));
+
+		// Check map
+		assertEquals(1, d.map.size());
+		List<Map<Integer,String>> sub = d.map.get("a");
+		Map<Integer,String> subsub1 = sub.get(0);
+		String subsubsub1 = subsub1.get(1);
+
+		Map<Integer,String> subsub2 = sub.get(1);
+		String subsubsub2 = subsub2.get(2);
+
+		assertEquals("1", subsubsub1);
+		assertEquals("2", subsubsub2);
+	}
+
+	/**
+	 * Test extra field
+	 */
+	public static class Data3 {
+		public Map<String,Object>	__extra;
+	}
+
+	public static void testExtra() throws Exception {
+		Decoder dec = new JSONCodec().dec();
+		Data3 d = dec.from("{\"a\": 1, \"b\": [1], \"c\": {}}").get(Data3.class);
+
+		assertEquals(1, d.__extra.get("a"));
+		assertEquals(Arrays.asList(1), d.__extra.get("b"));
+		assertEquals(new HashMap<String,Object>(), d.__extra.get("c"));
+	}
+
+	/**
+	 * Test calling the encoder repeatedly
+	 */
+
+	public static void testRepeat() throws Exception {
+		Decoder dec = new JSONCodec().dec().keepOpen();
+		try {
+			StringReader r = new StringReader("1\t2\r3\n 4      5   \n\r");
+			assertEquals((Integer) 1, dec.from(r).get(Integer.class));
+			assertEquals((Integer) 2, dec.get(Integer.class));
+			assertEquals((Integer) 3, dec.get(Integer.class));
+			assertEquals((Integer) 4, dec.get(Integer.class));
+			assertFalse(dec.isEof());
+			assertEquals((Integer) 5, dec.get(Integer.class));
+			assertTrue(dec.isEof());
+		}
+		finally {
+			dec.close();
+		}
+
+	}
+
+	/**
+	 * Test arrays
+	 */
+
+	public static class Data4 {
+		public boolean[]	booleans;
+		public byte[]		bytes;
+		public short[]		shorts;
+		public char[]		chars;
+		public int[]		ints;
+		public long[]		longs;
+		public float[]		floats;
+		public double[]		doubles;
+	}
+
+	public static void testEncodeTypePrimitiveArrays() throws Exception {
+		Encoder enc = new JSONCodec().enc();
+		Data4 d = new Data4();
+		d.booleans = new boolean[] {
+				false, false
+		};
+		d.bytes = new byte[] {
+				1, 2
+		};
+		d.shorts = new short[] {
+				3, 4
+		};
+		d.chars = new char[] {
+				'A', 'B'
+		};
+		d.ints = new int[] {
+				5, 6
+		};
+		d.longs = new long[] {
+				7, 8
+		};
+		d.floats = new float[] {
+				7, 8
+		};
+		d.doubles = new double[] {
+				7, 8
+		};
+
+		assertEquals(
+				"{\"booleans\":[false,false],\"bytes\":\"0102\",\"chars\":[65,66],\"doubles\":[7,8],\"floats\":[7,8],\"ints\":[5,6],\"longs\":[7,8],\"shorts\":[3,4]}",
+				enc.put(d).toString());
+		Decoder dec = new JSONCodec().dec();
+		Data4 dd = dec
+				.from("{\"booleans\":[false,false],\"bytes\":\"0102\",\"chars\":[65,66],\"doubles\":[7,8],\"floats\":[7,8],\"ints\":[5,6],\"longs\":[7,8],\"shorts\":[3,4]}")
+				.get(Data4.class);
+		assertTrue(Arrays.equals(d.booleans, dd.booleans));
+		assertTrue(Arrays.equals(d.bytes, dd.bytes));
+		assertTrue(Arrays.equals(d.shorts, dd.shorts));
+		assertTrue(Arrays.equals(d.chars, dd.chars));
+		assertTrue(Arrays.equals(d.ints, dd.ints));
+		assertTrue(Arrays.equals(d.longs, dd.longs));
+		assertTrue(Arrays.equals(d.floats, dd.floats));
+		assertTrue(Arrays.equals(d.doubles, dd.doubles));
+	}
+
+	/**
+	 * Test defaults
+	 */
+
+	public static class DataDefaults {
+		public int	a	= 3;
+	}
+
+	public static void testDefaults() throws Exception {
+		Encoder enc = new JSONCodec().enc();
+		DataDefaults d = new DataDefaults();
+		// We're not writing out fields with defaults.
+		assertEquals("{}", enc.to().put(d).toString());
+		assertEquals("{\"a\":3}", enc.to().writeDefaults().put(d).toString());
+
+		Decoder dec = new JSONCodec().dec();
+		DataDefaults dd = dec.from("{}").get(DataDefaults.class);
+		assertEquals(d.a, dd.a);
+		DataDefaults ddd = dec.from("{\"a\":4}").get(DataDefaults.class);
+		assertEquals(4, ddd.a);
+	}
+
+	/**
+	 * Test the checksum support
+	 */
+	public static void testDigest() throws Exception {
+		Encoder enc = new JSONCodec().enc();
+		enc.mark().put("Hello World");
+		byte[] original = enc.digest();
+		String string = enc.put(original).append("\n").toString();
+
+		Decoder dec = new JSONCodec().dec().keepOpen();
+		try {
+			String x = dec.mark().from(string).get(String.class);
+			assertEquals("Hello World", x);
+			byte read[] = dec.digest();
+			byte read2[] = dec.get(byte[].class);
+			assertTrue(Arrays.equals(original, read));
+			assertTrue(Arrays.equals(read, read2));
+		}
+		finally {
+			dec.close();
+		}
+	}
+
+	/**
+	 * Test for the blog
+	 */
+	public enum Sex {
+		MALE, FEMALE;
+	}
+
+	public static class Person {
+		public String		name;
+		public Sex			sex;
+		public Date			birthday;
+		public List<Person>	offspring	= new ArrayList<Person>();
+	}
+
+	public void testBlog() throws Exception {
+		Person u1 = new Person();
+		u1.name = "Peter";
+		u1.sex = Sex.MALE;
+		Person u2 = new Person();
+		u2.name = "Mischa";
+		u2.sex = Sex.FEMALE;
+		u1.offspring.add(u2);
+		Person u3 = new Person();
+		u3.name = "Thomas";
+		u3.sex = Sex.MALE;
+		u1.offspring.add(u3);
+
+		String s = codec.enc().indent("  ").put(u1).toString();
+		System.out.println(s);
+		// Person u4 = codec.dec().from(s).get( Person.class );
+
+	}
+}
diff --git a/aQute.libg/src/test/JustifTest.java b/aQute.libg/src/test/JustifTest.java
new file mode 100644
index 0000000..42f479d
--- /dev/null
+++ b/aQute.libg/src/test/JustifTest.java
@@ -0,0 +1,25 @@
+package test;
+
+import java.util.*;
+
+import junit.framework.*;
+import aQute.lib.justif.*;
+
+public class JustifTest extends TestCase {
+
+	public void testSimple() throws Exception {
+		StringBuilder sb = new StringBuilder();
+		Formatter f = new Formatter(sb);
+		Justif j = new Justif(40, 4,8);
+		
+		f.format("0123456789012345\nxx\t0-\t1can\n"
+                                       + "           use instead of including individual modules in your project. Note:\n"
+                                       + "           It does not include the Jiffle scripting language or Jiffle image\n" 
+                                       + "           operator.");
+		f.flush();
+		
+		j.wrap(sb);
+		
+		System.out.println(sb);
+	}
+}
diff --git a/aQute.libg/src/test/ReplacerTest.java b/aQute.libg/src/test/ReplacerTest.java
new file mode 100755
index 0000000..dabd4ac
--- /dev/null
+++ b/aQute.libg/src/test/ReplacerTest.java
@@ -0,0 +1,520 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+
+import junit.framework.*;
+import aQute.libg.reporter.*;
+import aQute.libg.sed.*;
+
+public class ReplacerTest extends TestCase {
+
+	static class Processor extends ReporterAdapter implements Domain {
+		final Map<String,String>	map	= new HashMap<String,String>();
+		final Domain				parent;
+		final ReplacerAdapter		replacer;
+		
+		public Processor(Processor parent) {
+			this.parent = parent;
+			this.replacer= new ReplacerAdapter(this);
+			this.replacer.setReporter(this);
+		}
+
+		public Processor() {
+			this(null);
+		}
+
+		public Map<String,String> getMap() {
+			return map;
+		}
+
+		public Domain getParent() {
+			return parent;
+		}
+
+		
+		String getProcessed(String key) {
+			return replacer.getProcessed(key);
+		}
+
+		public ReplacerAdapter getReplacer() {
+			return replacer;
+		}
+
+		public String process(String string) {
+			return getReplacer().process(string);
+		}
+		
+		@Override
+		public String toString() {
+			return map.toString();
+		}
+	}
+
+	/**
+	 * Test replacement of ./ with cwd
+	 */
+
+	public static void testCurrentWorkingDirectory() {
+		Processor top = new Processor();
+		top.getMap().put("cwd.1", "./"); // empty
+		top.getMap().put("cwd.2", " ./"); // empty
+		top.getMap().put("cwd.3", "./ "); // empty
+		top.getMap().put("cwd.4", " ./ "); // empty
+		top.getMap().put("cwd.5", "|./|"); // empty
+		top.getMap().put("cwd.6", "/.//"); // empty
+		top.getMap().put("cwd.7", "."); // empty
+		top.getMap().put("cwd.8", " . "); // empty
+		top.getMap().put("cwd.9", " . /"); // empty
+		top.getMap().put("cwd.10", " ."); // empty
+		top.getMap().put("cwd.11", "| ./|"); // empty
+		top.getMap().put("cwd.12", "|\t./|"); // empty
+		top.getMap().put("cwd.13", "|\r./|"); // empty
+		top.getMap().put("cwd.14", "|\n./|"); // empty
+
+		String cwd = new File("").getAbsolutePath() + "/";
+
+		assertEquals(" . ", top.getProcessed("cwd.8"));
+		assertEquals(cwd, top.getProcessed("cwd.1"));
+		assertEquals(" " + cwd, top.getProcessed("cwd.2"));
+		assertEquals(cwd + " ", top.getProcessed("cwd.3"));
+		assertEquals(" " + cwd + " ", top.getProcessed("cwd.4"));
+		assertEquals("|./|", top.getProcessed("cwd.5"));
+		assertEquals("/.//", top.getProcessed("cwd.6"));
+		assertEquals(".", top.getProcessed("cwd.7"));
+		assertEquals(" . /", top.getProcessed("cwd.9"));
+		assertEquals(" .", top.getProcessed("cwd.10"));
+		assertEquals("| " + cwd + "|", top.getProcessed("cwd.11"));
+		assertEquals("|\t" + cwd + "|", top.getProcessed("cwd.12"));
+		assertEquals("|\r" + cwd + "|", top.getProcessed("cwd.13"));
+		assertEquals("|\n" + cwd + "|", top.getProcessed("cwd.14"));
+		
+		top.check();
+	}
+
+	/**
+	 * Test if $if accepts isdir
+	 */
+
+	public static void testifDir() {
+		Processor top = new Processor();
+		top.getMap().put("presentd", "${if;${isdir;src};YES;NO}");
+		top.getMap().put("absentd", "${if;${isdir;xxx};YES;NO}");
+		top.getMap().put("wrongd", "${if;${isdir;bnd.bnd};YES;NO}");
+		assertEquals("YES", top.getProcessed("presentd"));
+		assertEquals("NO", top.getProcessed("wrongd"));
+		assertEquals("NO", top.getProcessed("absentd"));
+		top.getMap().put("presentf", "${if;${isfile;bnd.bnd};YES;NO}");
+		top.getMap().put("absentf", "${if;${isfile;xxx};YES;NO}");
+		top.getMap().put("wrongf", "${if;${isfile;jar};YES;NO}");
+		assertEquals("YES", top.getProcessed("presentf"));
+		assertEquals("NO", top.getProcessed("absentf"));
+		assertEquals("NO", top.getProcessed("wrongf"));
+		top.check();
+	}
+
+	/**
+	 * Test the combine macro that groups properties
+	 */
+
+	public static void testWildcardKeys() {
+		Processor top = new Processor();
+		top.getMap().put("a.3", "a.3");
+		top.getMap().put("a.1", "a.1");
+		top.getMap().put("a.2", "a.2");
+		top.getMap().put("a.4", "a.4");
+		top.getMap().put("aa", "${a.*}");
+		assertEquals("a.1,a.2,a.3,a.4", top.getProcessed("a.*"));
+		assertEquals("a.1,a.2,a.3,a.4", top.getProcessed("aa"));
+		top.check();
+	}
+
+	public static void testEnv() {
+		Processor top = new Processor();
+		String s = top.getReplacer().process("${env;USER}");
+		assertNotNull(s);
+		top.check();
+	}
+
+	/**
+	 * Test the random macro
+	 */
+	public static void testRandom() {
+		Processor top = new Processor();
+		top.getMap().put("a", "${random}");
+		top.getMap().put("a12", "${random;12}");
+		String a = top.getProcessed("a");
+		System.err.println(a);
+		assertEquals(8, a.length());
+		String a12 = top.getProcessed("a12");
+		System.err.println(a12);
+		assertEquals(12, a12.length());
+		assertNotSame(a, a12);
+		top.check();
+	}
+
+	/**
+	 * Testing an example with nesting that was supposd not to work
+	 */
+
+	public static void testSuper() {
+		Processor top = new Processor();
+		Processor middle = new Processor(top);
+		Processor bottom = new Processor(middle);
+
+		top.getMap().put("a", "top.a");
+		top.getMap().put("b", "top.b");
+		top.getMap().put("c", "top.c");
+		top.getMap().put("Bundle-Version", "0.0.0");
+		middle.getMap().put("a", "middle.a");
+		middle.getMap().put("b", "${^a}");
+		middle.getMap().put("c", "-${^c}-");
+		middle.getMap().put("Bundle-Version", "${^Bundle-Version}");
+		assertEquals("middle.a", bottom.getProcessed("a"));
+		assertEquals("top.a", bottom.getProcessed("b"));
+		assertEquals("-top.c-", bottom.getProcessed("c"));
+		assertEquals("0.0.0", bottom.getProcessed("Bundle-Version"));
+		top.check();
+		middle.check();
+		bottom.check();
+	}
+
+	/**
+	 * Testing an example with nesting that was supposd not to work
+	 */
+
+	public static void testNesting2() {
+		Processor p = new Processor();
+		p.getMap().put("groupId", "com.trivadis.tomas");
+		p.getMap().put("artifactId", "common");
+		p.getMap().put("bsn", "${if;${symbolicName};${symbolicName};${groupId}.${artifactId}}");
+		p.getMap().put("Bundle-SymbolicName", "${bsn}");
+		p.getMap().put("symbolicName", "");
+
+		// Not set, so get the maven name
+		assertEquals("com.trivadis.tomas.common", p.getProcessed("Bundle-SymbolicName"));
+
+		// Set it
+		p.getMap().put("symbolicName", "testing");
+		assertEquals("testing", p.getProcessed("Bundle-SymbolicName"));
+
+		// And remove it
+		p.getMap().put("symbolicName", "");
+		assertEquals("com.trivadis.tomas.common", p.getProcessed("Bundle-SymbolicName"));
+		p.check();
+	}
+
+	/**
+	 * Verify system command
+	 */
+
+	public static void testSystem() throws Exception {
+		// disable this test on windows
+		if (!"/".equals(File.separator))
+			return;
+
+		Processor p = new Processor();
+		assertEquals("Hello World", p.process("${system;echo Hello World}"));
+		assertTrue(p.process("${system;wc;Hello World}").matches("\\s*[0-9]+\\s+[0-9]+\\s+[0-9]+\\s*"));
+		p.check();
+	}
+
+	public static void testSystemFail() throws Exception {
+		Processor p = new Processor();
+		String cmd = "${system;mostidioticcommandthatwillsurelyfail}";
+		assertTrue(p.process(cmd).startsWith("${system;"));
+		p.check();
+	}
+
+	/**
+	 * Verify system-allow-fail command
+	 */
+
+	public static void testSystemAllowFail() throws Exception {
+		Processor p = new Processor();
+		assertEquals("", p.process("${system-allow-fail;mostidioticcommandthatwillsurelyfail}"));
+		p.check();
+	}
+
+	/**
+	 * Check that variables override macros.
+	 */
+	public static void testPriority() {
+		Processor p = new Processor();
+		p.getMap().put("now", "not set");
+		assertEquals("not set", p.process("${now}"));
+		p.check();
+	}
+
+	public static void testNames() {
+		Processor p = new Processor();
+		p.getMap().put("a", "a");
+		p.getMap().put("aa", "aa");
+
+		assertEquals("aa", p.process("${${a}${a}}"));
+		p.check();
+	}
+
+	/**
+	 * Test the wc function
+	 */
+
+	public static void testWc() {
+		Processor p = new Processor();
+		String a = p.process("${lsr;" + new File("src" + File.separator + "test").getAbsolutePath() + ";*.java}");
+		assertTrue(a.contains("ReplacerTest.java"));
+		assertFalse(a.contains("src" + File.separator + "test" + File.separator + "ReplacerTest.java"));
+
+		String b = p.process("${lsa;" + new File("src" + File.separator + "test").getAbsolutePath() + ";*.java}");
+		assertTrue(b.contains("src" + File.separator + "test" + File.separator + "ReplacerTest.java"));
+		p.check();
+	}
+
+	/**
+	 * Check the uniq command
+	 */
+
+	public static void testUniq() {
+		Processor p = new Processor();
+		p.getMap().put("a", "${uniq;1}");
+		p.getMap().put("b", "${uniq;1,2}");
+		p.getMap().put("c", "${uniq;1;2}");
+		p.getMap().put("d", "${uniq;1; 1,  2 , 3}");
+		p.getMap().put("e", "${uniq;1; 1 , 2 ;      3;3,4,5,6}");
+		assertEquals("1,2,3", p.getProcessed("d"));
+		assertEquals("1,2", p.getProcessed("b"));
+		assertEquals("1", p.getProcessed("a"));
+		assertEquals("1,2", p.getProcessed("c"));
+		assertEquals("1,2,3", p.getProcessed("d"));
+		assertEquals("1,2,3,4,5,6", p.getProcessed("e"));
+		p.check();
+	}
+
+	/**
+	 * Test arguments with difficult characters like ;
+	 */
+
+	public static void testEscapedArgs() {
+		Processor p = new Processor();
+		p.getMap().put("x", "${replace;1,2,3;.+;$0\\;version=1}");
+		assertEquals("1;version=1, 2;version=1, 3;version=1", p.getProcessed("x"));
+		p.check();
+	}
+
+	/**
+	 * Check if variables that contain variables, ad nauseum, really wrk
+	 */
+	public static void testNested() {
+		Processor p = new Processor();
+		p.getMap().put("a", ".");
+		p.getMap().put("b", "${a}");
+		p.getMap().put("c", "${b}");
+
+		p.getMap().put("d", "${tstamp;${format};UTC;${aug152008}}");
+		p.getMap().put("format", "yyyy");
+		p.getMap().put("aug152008", "1218810097322");
+
+		p.getMap().put("f", "${d}");
+		p.getMap().put("aug152008", "1218810097322");
+
+		assertEquals(".", p.getProcessed("c"));
+		assertEquals("2008", p.getProcessed("d"));
+		assertEquals(p.getProcessed("f"), p.getProcessed("d"));
+		p.check();
+	}
+
+	public static void testLoop() {
+		Processor p = new Processor();
+		p.getMap().put("a", "${b}");
+		p.getMap().put("b", "${a}");
+
+		p.getMap().put("d", "${e}");
+		p.getMap().put("e", "${f}");
+		p.getMap().put("f", "${g}");
+		p.getMap().put("g", "${h}");
+		p.getMap().put("h", "${d}");
+
+		assertEquals("${infinite:[a,b]}", p.getProcessed("a"));
+		assertEquals("${infinite:[d,e,f,g,h]}", p.getProcessed("d"));
+		p.check();
+	}
+
+	public static void testTstamp() {
+		String aug152008 = "1218810097322";
+		Processor p = new Processor();
+		assertEquals("200808151421", p.process("${tstamp;yyyyMMddHHmm;UTC;" + aug152008 + "}"));
+		assertEquals("200808151521", p.process("${tstamp;yyyyMMddHHmm;GMT+01;" + aug152008 + "}"));
+		assertEquals("2008", p.process("${tstamp;yyyy;UTC;" + aug152008 + "}"));
+
+		// Why Tokyo? Japan doesn't use daylight savings, so the test shouldn't
+		// break when clocks change.
+		assertEquals("200808152321", p.process("${tstamp;yyyyMMddHHmm;Asia/Tokyo;" + aug152008 + "}"));
+		p.check();
+	}
+
+	public static void testIsfile() {
+		Processor p = new Processor();
+		assertEquals("true", p.process("${isfile;.project}"));
+		assertEquals("false", p.process("${isfile;thisfiledoesnotexist}"));
+		p.check();
+	}
+
+	public static void testParentFile() {
+		Processor p = new Processor();
+		assertTrue(p.process("${dir;.project}").endsWith("aQute.libg"));
+		p.check();
+	}
+
+	public static void testBasename() {
+		Processor p = new Processor();
+		assertEquals("aQute.libg", p.process("${basename;${dir;.project}}"));
+		p.check();
+	}
+
+
+	/**
+	 * Check if we can check for the defintion of a variable
+	 */
+
+	public static void testDef() {
+		Processor p = new Processor();
+		p.getMap().put("set.1", "1");
+		p.getMap().put("set.2", "2");
+		assertEquals("NO", p.process("${if;${def;set.3};YES;NO}"));
+		assertEquals("YES", p.process("${if;${def;set.1};YES;NO}"));
+		assertEquals("YES", p.process("${if;${def;set.2};YES;NO}"));
+		p.check();
+	}
+
+	/**
+	 * NEW
+	 */
+	public static void testReplace() {
+		Processor p = new Processor();
+		p.getMap().put("specs", "a,b, c,    d");
+		assertEquals("xay, xby, xcy, xdy", p.process("${replace;${specs};([^\\s]+);x$1y}"));
+		p.check();
+	}
+
+	public static void testToClassName() {
+		Processor p = new Processor();
+		assertEquals("com.acme.test.Test", p.process("${toclassname;com/acme/test/Test.class}"));
+		assertEquals("Test", p.process("$<toclassname;Test.class>"));
+		assertEquals("Test,com.acme.test.Test", p.process("${toclassname;Test.class, com/acme/test/Test.class}"));
+		assertEquals("", p.process("$(toclassname;Test)"));
+		assertEquals("com/acme/test/Test.class", p.process("$[toclasspath;com.acme.test.Test]"));
+		assertEquals("Test.class", p.process("${toclasspath;Test}"));
+		assertEquals("Test.class,com/acme/test/Test.class", p.process("${toclasspath;Test,com.acme.test.Test}"));
+		p.check();
+	}
+
+
+	public static void testWarning() {
+		Processor p = new Processor();
+		p.getMap().put("three", "333");
+		p.getMap().put("empty", "");
+		p.getMap().put("real", "true");
+
+		p.process("    ${warning;xw;1;2;3 ${three}}");
+		p.process("    ${error;xe;1;2;3 ${three}}");
+		p.process("    ${if;1;$<a>}");
+		assertEquals("xw", p.getWarnings().get(0));
+		assertEquals("1", p.getWarnings().get(1));
+		assertEquals("2", p.getWarnings().get(2));
+		assertEquals("3 333", p.getWarnings().get(3));
+
+		assertEquals("xe", p.getErrors().get(0));
+		assertEquals("1", p.getErrors().get(1));
+		assertEquals("2", p.getErrors().get(2));
+		assertEquals("3 333", p.getErrors().get(3));
+	}
+
+	public static void testNestedReplace() {
+		Processor p = new Processor();
+		String value = p.process("xx$(replace;1.2.3-SNAPSHOT;(\\d(\\.\\d)+).*;$1)xx");
+		System.err.println(p.getWarnings());
+		assertEquals("xx1.2.3xx", value);
+
+		assertEquals("xx1.222.3xx", p.process("xx$(replace;1.222.3-SNAPSHOT;(\\d+(\\.\\d+)+).*;$1)xx"));
+
+		p.getMap().put("a", "aaaa");
+		assertEquals("[cac]", p.process("$[replace;acaca;a(.*)a;[$1]]"));
+		assertEquals("xxx", p.process("$(replace;yxxxy;[^x]*(x+)[^x]*;$1)"));
+		assertEquals("xxx", p.process("$(replace;yxxxy;([^x]*(x+)[^x]*);$2)"));
+		p.check();
+	}
+
+	public static void testParentheses() {
+		Processor p = new Processor();
+		String value = p.process("$(replace;();(\\(\\));$1)");
+		assertEquals("()", value);
+		p.check();
+	}
+
+	public static void testSimple() {
+		Processor p = new Processor();
+		p.getMap().put("a", "aaaa");
+		assertEquals("aaaa", p.process("${a}"));
+		assertEquals("aaaa", p.process("$<a>"));
+		assertEquals("aaaa", p.process("$(a)"));
+		assertEquals("aaaa", p.process("$[a]"));
+
+		assertEquals("xaaaax", p.process("x${a}x"));
+		assertEquals("xaaaaxaaaax", p.process("x${a}x${a}x"));
+		p.check();
+	}
+
+	public static void testFilter() {
+		Processor p = new Processor();
+		p.getMap().put("a", "aaaa");
+		assertEquals("aa,cc,ee", p.process("${filter;aa,bb,cc,dd,ee,ff;[ace]+}"));
+		assertEquals("aaaa,cc,ee", p.process("${filter;${a},bb,cc,dd,ee,ff;[ace]+}"));
+		assertEquals("bb,dd,ff", p.process("${filter;${a},bb,cc,dd,ee,ff;[^ace]+}"));
+		p.check();
+	}
+
+	public static void testFilterOut() {
+		Processor p = new Processor();
+		p.getMap().put("a", "aaaa");
+		assertEquals("bb,dd,ff", p.process("${filterout;aa,bb,cc,dd,ee,ff;[ace]+}"));
+		assertEquals("bb,dd,ff", p.process("${filterout;${a},bb,cc,dd,ee,ff;[ace]+}"));
+		assertEquals("aaaa,cc,ee", p.process("${filterout;${a},bb,cc,dd,ee,ff;[^ace]+}"));
+		p.check();
+	}
+
+	public static void testSort() {
+		Processor p = new Processor();
+		p.getMap().put("a", "aaaa");
+		assertEquals("aa,bb,cc,dd,ee,ff", p.process("${sort;aa,bb,cc,dd,ee,ff}"));
+		assertEquals("aa,bb,cc,dd,ee,ff", p.process("${sort;ff,ee,cc,bb,dd,aa}"));
+		assertEquals("aaaa,bb,cc,dd,ee,ff", p.process("${sort;ff,ee,cc,bb,dd,$<a>}"));
+		p.check();
+	}
+
+	public static void testJoin() {
+		Processor p = new Processor();
+		p.getMap().put("a", "aaaa");
+		assertEquals("aa,bb,cc,dd,ee,ff", p.process("${join;aa,bb,cc,dd,ee,ff}"));
+		assertEquals("aa,bb,cc,dd,ee,ff", p.process("${join;aa,bb,cc;dd,ee,ff}"));
+		assertEquals("aa,bb,cc,dd,ee,ff", p.process("${join;aa;bb;cc;dd;ee,ff}"));
+		p.check();
+	}
+
+	public static void testIf() {
+		Processor p = new Processor();
+		p.getMap().put("a", "aaaa");
+		assertEquals("aaaa", p.process("${if;1;$<a>}"));
+		assertEquals("", p.process("${if;;$<a>}"));
+		assertEquals("yes", p.process("${if;;$<a>;yes}"));
+		assertEquals("yes", p.process("${if;false;$<a>;yes}"));
+		p.check();
+	}
+
+	public static void testLiteral() {
+		Processor p = new Processor();
+		p.getMap().put("a", "aaaa");
+		assertEquals("${aaaa}", p.process("${literal;$<a>}"));
+		p.check();
+	}
+
+}
diff --git a/aQute.libg/src/test/SettingsTest.java b/aQute.libg/src/test/SettingsTest.java
new file mode 100644
index 0000000..e122826
--- /dev/null
+++ b/aQute.libg/src/test/SettingsTest.java
@@ -0,0 +1,36 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+
+import junit.framework.*;
+import aQute.lib.io.*;
+import aQute.lib.settings.*;
+
+public class SettingsTest extends TestCase {
+
+	public void testSimple() throws Exception {
+		File tmp = IO.getFile("tmp");
+		IO.delete(tmp);
+		Settings s = new Settings("tmp");
+		try {
+			s.put("a", "b");
+			assertEquals("b", s.get("a"));
+			assertNotNull(s.getPublicKey());
+			byte[] publicKey = s.getPublicKey();
+			s.save();
+			
+			Settings ss = new Settings("tmp");
+			assertEquals("b", ss.get("a"));
+			assertNotNull(ss.getPublicKey());
+			assertTrue( Arrays.equals(publicKey, ss.getPublicKey()));
+			
+			ss.clear();
+			assertNull(ss.get("a"));
+			
+		}
+		finally {
+			IO.delete(tmp);
+		}
+	}
+}
diff --git a/aQute.libg/src/test/TestCAFS.java b/aQute.libg/src/test/TestCAFS.java
index c0904cd..b15badd 100644
--- a/aQute.libg/src/test/TestCAFS.java
+++ b/aQute.libg/src/test/TestCAFS.java
@@ -1,72 +1,73 @@
 package test;
 
 import java.io.*;
-import java.security.*;
 
 import junit.framework.*;
-import aQute.lib.io.*;
-import aQute.libg.cafs.*;
-import aQute.libg.cryptography.*;
 
 public class TestCAFS extends TestCase {
 	File	tmp;
 
+	@Override
 	public void setUp() throws Exception {
 		tmp = new File(System.getProperty("java.io.tmpdir"));
 		assertTrue(tmp.isDirectory());
 	}
-	
+
 	public void testX() {}
 
-//	public void testSimple() throws Exception {
-//		File dir = new File(tmp, getClass().getName() + System.currentTimeMillis());
-//		CAFS cafs = new CAFS(dir, true);
-//		MessageDigest digester = MessageDigest.getInstance("SHA-1");
-//
-//		DigestInputStream dis = new DigestInputStream(getClass().getResourceAsStream(
-//				"cafs/file1.txt"), digester);
-//		SHA1 sha1 = cafs.write(dis);
-//
-//		assertEquals(new SHA1(digester.digest()), sha1);
-//
-//		digester.reset();
-//		dis = new DigestInputStream(getClass().getResourceAsStream("cafs/file1-1.txt"), digester);
-//
-//		SHA1 sha1_1 = cafs.write(dis);
-//		assertEquals(sha1, sha1_1);
-//		assertEquals( new SHA1(digester.digest()), sha1_1);
-//
-//		SHA1 sha2 = cafs.write(getClass().getResourceAsStream("cafs/file2.txt"));
-//
-//		assertFalse( sha1.equals(sha2));
-//
-//		int n = 0;
-//		for (SHA1 key : cafs) {
-//			assertTrue(sha1.equals(key) || sha2.equals(key));
-//			System.out.println(n++ + ": " + key);
-//			InputStream in = cafs.read(key);
-//			assertNotNull(in);
-//			String s = IO.collect(in, "UTF-8");
-//			byte[] b = s.getBytes("UTF-8");
-//			MessageDigest md = MessageDigest.getInstance("SHA1");
-//			md.update(b);
-//			assertEquals(key, new SHA1(md.digest()));
-//		}
-//
-//		// Close out db and reopen it again.
-//		cafs.close();
-//		cafs = new CAFS(dir, false);
-//
-//		for (SHA1 key : cafs) {
-//			assertTrue(sha1.equals(key) || sha2.equals(key));
-//		}
-//
-//		InputStream in = cafs.read(sha2);
-//		assertNotNull(in);
-//		SHA1 rsha2 = SHA1.getDigester().from(in);
-//		
-//		assertEquals(sha2, rsha2);
-//
-//		cafs.close();
-//	}
+	// public void testSimple() throws Exception {
+	// File dir = new File(tmp, getClass().getName() +
+	// System.currentTimeMillis());
+	// CAFS cafs = new CAFS(dir, true);
+	// MessageDigest digester = MessageDigest.getInstance("SHA-1");
+	//
+	// DigestInputStream dis = new
+	// DigestInputStream(getClass().getResourceAsStream(
+	// "cafs/file1.txt"), digester);
+	// SHA1 sha1 = cafs.write(dis);
+	//
+	// assertEquals(new SHA1(digester.digest()), sha1);
+	//
+	// digester.reset();
+	// dis = new
+	// DigestInputStream(getClass().getResourceAsStream("cafs/file1-1.txt"),
+	// digester);
+	//
+	// SHA1 sha1_1 = cafs.write(dis);
+	// assertEquals(sha1, sha1_1);
+	// assertEquals( new SHA1(digester.digest()), sha1_1);
+	//
+	// SHA1 sha2 = cafs.write(getClass().getResourceAsStream("cafs/file2.txt"));
+	//
+	// assertFalse( sha1.equals(sha2));
+	//
+	// int n = 0;
+	// for (SHA1 key : cafs) {
+	// assertTrue(sha1.equals(key) || sha2.equals(key));
+	// System.err.println(n++ + ": " + key);
+	// InputStream in = cafs.read(key);
+	// assertNotNull(in);
+	// String s = IO.collect(in, "UTF-8");
+	// byte[] b = s.getBytes("UTF-8");
+	// MessageDigest md = MessageDigest.getInstance("SHA1");
+	// md.update(b);
+	// assertEquals(key, new SHA1(md.digest()));
+	// }
+	//
+	// // Close out db and reopen it again.
+	// cafs.close();
+	// cafs = new CAFS(dir, false);
+	//
+	// for (SHA1 key : cafs) {
+	// assertTrue(sha1.equals(key) || sha2.equals(key));
+	// }
+	//
+	// InputStream in = cafs.read(sha2);
+	// assertNotNull(in);
+	// SHA1 rsha2 = SHA1.getDigester().from(in);
+	//
+	// assertEquals(sha2, rsha2);
+	//
+	// cafs.close();
+	// }
 }
diff --git a/aQute.libg/src/test/TestDirectoryInputStream.java b/aQute.libg/src/test/TestDirectoryInputStream.java
index 78049bb..e7426d6 100644
--- a/aQute.libg/src/test/TestDirectoryInputStream.java
+++ b/aQute.libg/src/test/TestDirectoryInputStream.java
@@ -6,16 +6,17 @@ import junit.framework.*;
 
 public class TestDirectoryInputStream extends TestCase {
 
-    public void testComplete() throws IOException {
-//        DirectoryInputStream din2 = new DirectoryInputStream(new File("dir"));
-//        JarInputStream in = new JarInputStream(din2);
-//        assertNotNull(in.getManifest());
-//        JarEntry entry = in.getNextJarEntry();
-//        while (entry != null) {
-//            System.out.println(entry.getName());
-//            entry = in.getNextJarEntry();
-//        }
-//
-//        in.close();
-    }
+	public void testComplete() throws IOException {
+		// DirectoryInputStream din2 = new DirectoryInputStream(new
+		// File("dir"));
+		// JarInputStream in = new JarInputStream(din2);
+		// assertNotNull(in.getManifest());
+		// JarEntry entry = in.getNextJarEntry();
+		// while (entry != null) {
+		// System.err.println(entry.getName());
+		// entry = in.getNextJarEntry();
+		// }
+		//
+		// in.close();
+	}
 }
diff --git a/aQute.libg/src/test/TestForker.java b/aQute.libg/src/test/TestForker.java
index 85c3c26..91e81e9 100644
--- a/aQute.libg/src/test/TestForker.java
+++ b/aQute.libg/src/test/TestForker.java
@@ -8,6 +8,7 @@ import aQute.libg.forker.*;
 public class TestForker extends TestCase {
 
 	final Collection<Integer>	EMPTY	= Collections.emptyList();
+	final int					TIMEOUT	= 1000000;
 
 	static class R implements Runnable {
 		final Collection<Integer>	result;
@@ -43,7 +44,10 @@ public class TestForker extends TestCase {
 		forker.doWhen(EMPTY, 2, new R(result, 2));
 		forker.doWhen(EMPTY, 3, new R(result, 3));
 		forker.start(1000);
-		assertEquals(Arrays.asList(1, 2, 3, 4), result);
+
+		assertTrue(result.containsAll(Arrays.asList(1, 2, 3, 4)));
+		Object[] q = result.toArray();
+		assertEquals(Integer.valueOf(4), q[q.length - 1]);
 	}
 
 	public void testInvalid() {
@@ -53,9 +57,10 @@ public class TestForker extends TestCase {
 		try {
 			forker.start(100);
 			fail();
-		} catch (Exception e) {
-			System.out.println(e.getMessage());
-			assertEquals( IllegalArgumentException.class, e.getClass());
+		}
+		catch (Exception e) {
+			System.err.println(e.getMessage());
+			assertEquals(IllegalArgumentException.class, e.getClass());
 		}
 
 	}
@@ -69,14 +74,16 @@ public class TestForker extends TestCase {
 			public void run() {
 				synchronized (result) {
 					try {
-						System.out.println("starting to wait");
-						result.wait();
-						System.out.println("finished wait");
-					} catch (Exception e) {
-						System.out.println("exception");
+						System.err.println("starting to wait");
+						result.wait(TIMEOUT);
+						System.err.println("finished wait");
+					}
+					catch (Exception e) {
+						System.err.println("exception");
 						e.printStackTrace();
-					} finally {
-						System.out.println("leaving task");
+					}
+					finally {
+						System.err.println("leaving task");
 					}
 				}
 			}
diff --git a/aQute.libg/src/test/TestGzipUtils.java b/aQute.libg/src/test/TestGzipUtils.java
new file mode 100644
index 0000000..6903761
--- /dev/null
+++ b/aQute.libg/src/test/TestGzipUtils.java
@@ -0,0 +1,21 @@
+package test;
+
+import java.io.*;
+
+import junit.framework.*;
+import aQute.lib.io.*;
+import aQute.libg.gzip.*;
+
+public class TestGzipUtils extends TestCase {
+
+	public void testUnzipped() throws Exception {
+		InputStream stream = GZipUtils.detectCompression(TestGzipUtils.class.getResourceAsStream("unzipped.dat"));
+		assertEquals("A plan, a plan, a canal, Panama.", IO.collect(stream));
+	}
+
+	public void testZipped() throws Exception {
+		InputStream stream = GZipUtils.detectCompression(TestGzipUtils.class.getResourceAsStream("zipped.dat"));
+		assertEquals("A plan, a plan, a canal, Panama.", IO.collect(stream));
+	}
+
+}
diff --git a/aQute.libg/src/test/TestIndex.java b/aQute.libg/src/test/TestIndex.java
index 1ced66e..73145c1 100644
--- a/aQute.libg/src/test/TestIndex.java
+++ b/aQute.libg/src/test/TestIndex.java
@@ -7,59 +7,92 @@ import aQute.lib.index.*;
 
 public class TestIndex extends TestCase {
 
-	
 	public void testPersistence() throws Exception {
-		File test = new File("test.tmp");
+		File test = new File("tmp/test.tmp");
 		test.delete();
+		test.getParentFile().mkdirs();
 		Index index = new Index(test, 2000);
-		index.insert( new byte[]{1}, 2);
-		index.insert( new byte[]{2}, 4);
-		index.insert( new byte[]{3}, 6);
-		assertEquals( 2, index.search(new byte[] {1}));
-		assertEquals( 4, index.search(new byte[] {2}));
-		assertEquals( 6, index.search(new byte[] {3}));
-		System.out.println(index.toString());
+		index.insert(new byte[] {
+			1
+		}, 2);
+		index.insert(new byte[] {
+			2
+		}, 4);
+		index.insert(new byte[] {
+			3
+		}, 6);
+		assertEquals(2, index.search(new byte[] {
+			1
+		}));
+		assertEquals(4, index.search(new byte[] {
+			2
+		}));
+		assertEquals(6, index.search(new byte[] {
+			3
+		}));
+		System.err.println(index.toString());
 		index.close();
-		
+
 		index = new Index(test, 2000);
-		System.out.println(index.toString());
-		assertEquals( 2, index.search(new byte[] {1}));
-		assertEquals( 4, index.search(new byte[] {2}));
-		assertEquals( 6, index.search(new byte[] {3}));
-		
+		System.err.println(index.toString());
+		assertEquals(2, index.search(new byte[] {
+			1
+		}));
+		assertEquals(4, index.search(new byte[] {
+			2
+		}));
+		assertEquals(6, index.search(new byte[] {
+			3
+		}));
+
 		index.close();
 	}
-	
-	
-	
+
 	public void testBasic() throws Exception {
-		File test = new File("test.tmp");
+		File test = new File("tmp/test.tmp");
 		test.delete();
+		test.getParentFile().mkdirs();
 		Index index = new Index(test, 2000);
-		
-		index.insert( new byte[] {12}, 24);
-		index.insert( new byte[] {13}, 26);
-		index.insert( new byte[] {6}, 12);
-		index.insert( new byte[] {16}, 32);
-		index.insert( new byte[] {1}, 2);
 
-		assertEquals( 24, index.search(new byte[] {12}));
-		assertEquals( 26, index.search(new byte[] {13}), 26);
-		assertEquals( 12, index.search(new byte[] {6}), 12);
+		index.insert(new byte[] {
+			12
+		}, 24);
+		index.insert(new byte[] {
+			13
+		}, 26);
+		index.insert(new byte[] {
+			6
+		}, 12);
+		index.insert(new byte[] {
+			16
+		}, 32);
+		index.insert(new byte[] {
+			1
+		}, 2);
+
+		assertEquals(24, index.search(new byte[] {
+			12
+		}));
+		assertEquals(26, index.search(new byte[] {
+			13
+		}), 26);
+		assertEquals(12, index.search(new byte[] {
+			6
+		}), 12);
 	}
 
-//	public void testMany() throws Exception {
-//		File test = new File("test.tmp");
-//		test.delete();
-//		Index index = new Index(test, 1000);
-//		for ( int i = 1; i<127; i++)
-//			index.insert( new byte[]{(byte)i}, i*2);
-//		
-//		index.close();
-//		Index index2 = new Index(test, 1000);
-//		for ( int i = 1; i<127; i++)
-//			assertEquals(i*2, index2.search( new byte[(byte)i]));
-//		
-//	}
+	// public void testMany() throws Exception {
+	// File test = new File("tmp/test.tmp");
+	// test.delete();
+	// Index index = new Index(test, 1000);
+	// for ( int i = 1; i<127; i++)
+	// index.insert( new byte[]{(byte)i}, i*2);
+	//
+	// index.close();
+	// Index index2 = new Index(test, 1000);
+	// for ( int i = 1; i<127; i++)
+	// assertEquals(i*2, index2.search( new byte[(byte)i]));
+	//
+	// }
 
 }
diff --git a/aQute.libg/src/test/TestSAXFilters.java b/aQute.libg/src/test/TestSAXFilters.java
index 577d84e..dd1b39a 100644
--- a/aQute.libg/src/test/TestSAXFilters.java
+++ b/aQute.libg/src/test/TestSAXFilters.java
@@ -1,79 +1,75 @@
 package test;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
+import java.io.*;
 
-import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.*;
 
-import junit.framework.TestCase;
+import junit.framework.*;
 
-import org.xml.sax.Attributes;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
+import org.xml.sax.*;
 
-import aQute.libg.sax.SAXUtil;
-import aQute.libg.sax.filters.ElementSelectionFilter;
-import aQute.libg.sax.filters.MergeContentFilter;
+import aQute.libg.sax.*;
+import aQute.libg.sax.filters.*;
 
 public class TestSAXFilters extends TestCase {
-	
-	private static final String SAMPLE1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
-			"<root a=\"1\"><a><b><c></c></b></a></root>";
-	private static final String SAMPLE2 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
-			"<root b=\"2\"><x><y><z></z></y></x></root>";
-	
-	private static final String MERGED1_2 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
-			"<root a=\"1\"><a><b><c/></b></a><x><y><z/></y></x></root>";
-	
-	private static final String SAMPLE3 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
-			"<anotherRoot b=\"2\"><x><y><z></z></y></x></anotherRoot>";
-	private static final String SAMPLE4 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
-			"<root c=\"3\"><a><b><c><d><e><f><g><h></h></g></f></e></d></c></b></a></root>";
-	
-	private static final String SAMPLE5 = "<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet type='text/xsl' href='http://www2.osgi.org/www/obr2html.xsl'?><root><a/></root>";
-	
+
+	private static final String	SAMPLE1		= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+													+ "<root a=\"1\"><a><b><c></c></b></a></root>";
+	private static final String	SAMPLE2		= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+													+ "<root b=\"2\"><x><y><z></z></y></x></root>";
+
+	private static final String	MERGED1_2	= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+													+ "<root a=\"1\"><a><b><c/></b></a><x><y><z/></y></x></root>";
+
+	private static final String	SAMPLE3		= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+													+ "<anotherRoot b=\"2\"><x><y><z></z></y></x></anotherRoot>";
+	private static final String	SAMPLE4		= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+													+ "<root c=\"3\"><a><b><c><d><e><f><g><h></h></g></f></e></d></c></b></a></root>";
+
+	private static final String	SAMPLE5		= "<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet type='text/xsl' href='http://www2.osgi.org/www/obr2html.xsl'?><root><a/></root>";
+
 	public void testMerge() throws Exception {
 		ByteArrayOutputStream output = new ByteArrayOutputStream();
-		
+
 		MergeContentFilter merger = new MergeContentFilter();
 		XMLReader reader = SAXUtil.buildPipeline(new StreamResult(output), merger);
-		
+
 		reader.parse(new InputSource(new ByteArrayInputStream(SAMPLE1.getBytes())));
 		reader.parse(new InputSource(new ByteArrayInputStream(SAMPLE2.getBytes())));
 		merger.closeRootAndDocument();
-		
+
 		assertEquals(MERGED1_2, output.toString());
 		assertEquals(2, merger.getRootElements().size());
 	}
-	
+
 	public void testMergeInconsistentRoots() throws Exception {
 		ByteArrayOutputStream output = new ByteArrayOutputStream();
-		
+
 		MergeContentFilter merger = new MergeContentFilter();
 		XMLReader reader = SAXUtil.buildPipeline(new StreamResult(output), merger);
-		
+
 		try {
 			reader.parse(new InputSource(new ByteArrayInputStream(SAMPLE1.getBytes())));
 			reader.parse(new InputSource(new ByteArrayInputStream(SAMPLE3.getBytes())));
-			fail ("Should throw exception for inconsistent roots");
-		} catch (SAXException e) {
+			fail("Should throw exception for inconsistent roots");
 		}
+		catch (SAXException e) {}
 	}
-	
+
 	public void testDontRepeatProcessingInstruction() throws Exception {
 		ByteArrayOutputStream output = new ByteArrayOutputStream();
-		
+
 		MergeContentFilter merger = new MergeContentFilter();
 		XMLReader reader = SAXUtil.buildPipeline(new StreamResult(output), merger);
-		
+
 		reader.parse(new InputSource(new ByteArrayInputStream(SAMPLE5.getBytes())));
 		reader.parse(new InputSource(new ByteArrayInputStream(SAMPLE5.getBytes())));
 		merger.closeRootAndDocument();
 
-		assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?><?xml-stylesheet type='text/xsl' href='http://www2.osgi.org/www/obr2html.xsl'?>\n<root><a/><a/></root>", output.toString());
+		String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><?xml-stylesheet type='text/xsl' href='http://www2.osgi.org/www/obr2html.xsl'?><root><a/><a/></root>";
+		assertEquals(expected, stripLineBreaks(output.toString()));
 	}
-	
+
 	public void testSelectionFilter() throws Exception {
 		ByteArrayOutputStream output = new ByteArrayOutputStream();
 
@@ -85,7 +81,14 @@ public class TestSAXFilters extends TestCase {
 		};
 		XMLReader reader = SAXUtil.buildPipeline(new StreamResult(output), filter);
 		reader.parse(new InputSource(new ByteArrayInputStream(SAMPLE4.getBytes())));
-		assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?><root c=\"3\"><a><b><c><d/></c></b></a></root>", output.toString());
+		assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?><root c=\"3\"><a><b><c><d/></c></b></a></root>",
+				output.toString());
 	}
 	
+	// Line breaks in the XML (e.g. after a PI node) seem to vary across platforms and even Java versions
+	// on the same platform. Use this utility method to strip all LFs and CRs from an input string.
+	private String stripLineBreaks(String input) {
+		return input == null ? null : input.replaceAll("\\r?\\n", "");
+	}
+
 }
diff --git a/aQute.libg/src/test/TestTarjan.java b/aQute.libg/src/test/TestTarjan.java
index 3dba018..086c3dd 100644
--- a/aQute.libg/src/test/TestTarjan.java
+++ b/aQute.libg/src/test/TestTarjan.java
@@ -9,42 +9,41 @@ import aQute.libg.tarjan.*;
 public class TestTarjan extends TestCase {
 
 	public void testTarjan() throws Exception {
-		MultiMap<String, String> g = mkGraph("A{BC}B{A}C{DE}D{C}E{D}");
-		System.out.println(g);
-		
-		Set<Set<String>> scc = Tarjan.tarjan(g);
-		
+		MultiMap<String,String> g = mkGraph("A{BC}B{A}C{DE}D{C}E{D}");
+		System.err.println(g);
+
+		Collection< ? extends Collection<String>> scc = Tarjan.tarjan(g);
+
 		assertEquals(2, scc.size());
-		for ( Set<String> set : scc) {
-			if ( set.size()==3)
-				assertEquals( new HashSet<String>(Arrays.asList("E","C", "D")), set);
-			else if ( set.size()==2)
-				assertEquals( new HashSet<String>(Arrays.asList("B","A")), set);
+		for (Collection<String> set : scc) {
+			if (set.size() == 3)
+				assertEquals(new HashSet<String>(Arrays.asList("E", "C", "D")), set);
+			else if (set.size() == 2)
+				assertEquals(new HashSet<String>(Arrays.asList("B", "A")), set);
 			else
 				fail();
 		}
 	}
 
-	private MultiMap<String, String> mkGraph(String string) {
-		MultiMap<String, String> map = new MultiMap<String, String>();
+	private MultiMap<String,String> mkGraph(String string) {
+		MultiMap<String,String> map = new MultiMap<String,String>();
 
 		String key = null;
 
 		for (int i = 0; i < string.length(); i++) {
 			char c = string.charAt(i);
 			switch (c) {
-			case '{':
-				break;
-			case '}':
-				key = null;
-				break;
-			default:
-				if (key == null) {
-					key = c + "";
-					map.put(key, new HashSet<String>());
-				}
-				else
-					map.add(key, c + "");
+				case '{' :
+					break;
+				case '}' :
+					key = null;
+					break;
+				default :
+					if (key == null) {
+						key = c + "";
+						map.put(key, new ArrayList<String>());
+					} else
+						map.add(key, c + "");
 			}
 		}
 		return map;
diff --git a/aQute.libg/src/test/unzipped.dat b/aQute.libg/src/test/unzipped.dat
new file mode 100644
index 0000000..43c708c
--- /dev/null
+++ b/aQute.libg/src/test/unzipped.dat
@@ -0,0 +1 @@
+A plan, a plan, a canal, Panama.
\ No newline at end of file
diff --git a/aQute.libg/src/test/zipped.dat b/aQute.libg/src/test/zipped.dat
new file mode 100644
index 0000000..9432b48
Binary files /dev/null and b/aQute.libg/src/test/zipped.dat differ
diff --git a/biz.aQute.bnd/.classpath b/biz.aQute.bnd/.classpath
index 2e77bcc..6d3c62a 100644
--- a/biz.aQute.bnd/.classpath
+++ b/biz.aQute.bnd/.classpath
@@ -1,9 +1,6 @@
 <?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="aQute.bnd.classpath.container"/>
-	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-	<classpathentry combineaccessrules="false" kind="src" path="/biz.aQute.bndlib"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/biz.aQute.bnd/.project b/biz.aQute.bnd/.project
index 4d52498..d10147b 100644
--- a/biz.aQute.bnd/.project
+++ b/biz.aQute.bnd/.project
@@ -11,18 +11,13 @@
 			</arguments>
 		</buildCommand>
 		<buildCommand>
-			<name>org.eclipse.pde.ManifestBuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-		<buildCommand>
-			<name>org.eclipse.pde.SchemaBuilder</name>
+			<name>bndtools.core.bndbuilder</name>
 			<arguments>
 			</arguments>
 		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.eclipse.jdt.core.javanature</nature>
-		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>bndtools.core.bndnature</nature>
 	</natures>
 </projectDescription>
diff --git a/biz.aQute.bnd/.settings/org.eclipse.jdt.core.prefs b/biz.aQute.bnd/.settings/org.eclipse.jdt.core.prefs
index e156e15..3590ca7 100644
--- a/biz.aQute.bnd/.settings/org.eclipse.jdt.core.prefs
+++ b/biz.aQute.bnd/.settings/org.eclipse.jdt.core.prefs
@@ -1,4 +1,4 @@
-#Wed Apr 14 09:17:00 CEST 2010
+#Fri Aug 10 13:46:22 CEST 2012
 eclipse.preferences.version=1
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
@@ -7,6 +7,355 @@ org.eclipse.jdt.core.compiler.compliance=1.5
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
 org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=ignore
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
 org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=true
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/biz.aQute.bnd/.settings/org.eclipse.jdt.ui.prefs b/biz.aQute.bnd/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..f5e8897
--- /dev/null
+++ b/biz.aQute.bnd/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,61 @@
+#Fri Aug 10 13:48:46 CEST 2012
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=false
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=false
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=false
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
+cleanup_settings_version=2
+eclipse.preferences.version=1
+formatter_profile=_bnd(tools)
+formatter_settings_version=12
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=1
+org.eclipse.jdt.ui.staticondemandthreshold=1
diff --git a/biz.aQute.bnd/META-INF/MANIFEST.MF b/biz.aQute.bnd/META-INF/MANIFEST.MF
deleted file mode 100644
index cbc5ed8..0000000
--- a/biz.aQute.bnd/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,38 +0,0 @@
-Manifest-Version: 1
-Bundle-ManifestVersion: 2
-Bundle-Version: 0.0.0
-Bundle-Name: bnd
-Bundle-SymbolicName: biz.aQute.bnd; singleton:=true
-Bundle-ClassPath: .,tmp/biz.aQute.bnd.jar
-Bundle-Activator: aQute.bnd.plugin.Activator
-Require-Bundle: org.eclipse.ui.ide;bundle-version="[3.3.0,
- 4.0.0)",
- org.eclipse.jface.text;bundle-version="[3.3.0,
- 4.0.0)",
- org.eclipse.ui.workbench.texteditor;bundle-version="[3.3.0,
- 4.0.0)",
- org.eclipse.ui.editors;bundle-version="[3.3.0,
- 4.0.0)",
- org.eclipse.ui;bundle-version="[3.3.0,
- 4.0.0)",
- org.eclipse.debug.ui;bundle-version="[3.3.0,
- 4.0.0)",
- org.eclipse.jdt.core;bundle-version="[3.3.0,
- 4.0.0)",
- org.eclipse.jdt.ui;bundle-version="[3.3.0,
- 4.0.0)",
- org.eclipse.core.runtime;bundle-version="[3.2.0,
- 4.0.0)",
- org.eclipse.jdt.launching;bundle-version="[3.2.0,
- 4.0.0)",
- org.eclipse.jdt.debug.ui;bundle-version="[3.2.0,
- 4.0.0)",
- org.eclipse.jdt.junit;bundle-version="[3.2.0,
- 4.0.0)",
- org.junit,
- org.eclipse.osgi.services,
- org.apache.ant,
- org.eclipse.ui.console
-Bundle-RequiredExecutionEnvironment: J2SE-1.5
-Bundle-Description: A utility and plugin to wrap, build, print, or otherwise manipulate bundles
-Bundle-ActivationPolicy: lazy
diff --git a/biz.aQute.bnd/annotation.bnd b/biz.aQute.bnd/annotation.bnd
index bb964f2..85547df 100755
--- a/biz.aQute.bnd/annotation.bnd
+++ b/biz.aQute.bnd/annotation.bnd
@@ -1,4 +1,4 @@
 Bundle-Name:            bnd Annotations Library
 Bundle-Description:     Contains only the annotations for bnd.
 Bundle-DocURL:          http://www.aQute.biz/Code/Bnd
-Export-Package:         aQute.bnd.annotation.*, aQute.bnd.test
+Export-Package:         aQute.bnd.annotation.*
diff --git a/biz.aQute.bnd/biz.aQute.bnd.bnd b/biz.aQute.bnd/biz.aQute.bnd.bnd
index 49358d7..0c10922 100644
--- a/biz.aQute.bnd/biz.aQute.bnd.bnd
+++ b/biz.aQute.bnd/biz.aQute.bnd.bnd
@@ -1,17 +1,32 @@
--sources: 						true
--include: 						~META-INF/MANIFEST.MF
+Include-Resource: 				LICENSE, embedded-repo.jar
 
-Include-Resource: 				plugin.xml, icons=icons, LICENSE, embedded-repo.jar
+Private-Package: aQute.bnd.*,\
+	aQute.configurable.*,\
+	org.osgi.service.component.annotations.*,\
+	aQute.lib.deployer.*;-split-package:=first,\
+	org.osgi.service.coordinator
 
-Private-Package: 				aQute.bnd.*, aQute.lib.*
+Export-Package: aQute.bnd.service.*,\
+        aQute.bnd.header, \
+        aQute.bnd.osgi, \
+        aQute.bnd.build, \
+        aQute.bnd.version, \
+        aQute.bnd.maven.support, \
+	org.osgi.service.bindex,\
+	aQute.service.reporter,\
+	aQute.bnd.osgi.resource,\
+	org.osgi.service.repository,\
+	org.osgi.resource
+
+Import-Package: org.apache.tools.ant.*;resolution:=optional,\
+	junit.framework;resolution:=optional;version='[3.8,4)',\
+	*
 
-#, org.osgi.service.component.annotations
-Conditional-Package: 			aQute.libg.*
-Export-Package: 				aQute.bnd.service.*, org.osgi.service.bindex
-Import-Package: 				!org.eclipse.*,org.apache.tools.ant;resolution:=optional,org.osgi.service.bindex,*
-Bundle-ClassPath:				.
 Main-Class: 					aQute.bnd.main.bnd
+JPM-Command:					bnd
 Bundle-Version:					${^Bundle-Version}
 
+-digests: MD5, SHA1
 
-
+Bundle-Description: This command line utility is the Swiss army knife of OSGi. It provides you with a breadth
+ of tools to understand and manage OSGi based systems. This project basically uses bndlib 
\ No newline at end of file
diff --git a/biz.aQute.bnd/bnd.bnd b/biz.aQute.bnd/bnd.bnd
index b15cd90..b546ae4 100644
--- a/biz.aQute.bnd/bnd.bnd
+++ b/biz.aQute.bnd/bnd.bnd
@@ -1,40 +1,21 @@
--dependson: biz.aQute.junit, biz.aQute.launcher, demo
+Bundle-Version: 				2.1.0.${tstamp;yyyyMMdd-HHmmss}
+Conditional-Package: 			aQute.libg.*,aQute.lib.*,aQute.configurable
 
-Bundle-Version: 				1.48.0
-Bundle-License: 				http://www.opensource.org/licenses/apache2.0.php; \
-									description="${Bundle-Copyright}"; \
-									link=LICENSE
-						
 -sub: *.bnd
 
--buildpath: biz.aQute.bndlib;version=project,\
-	aQute.libg;version=project,\
-	com.springsource.junit,\
-	org.eclipse.core.runtime,\
-	org.eclipse.core.resources,\
-	org.eclipse.core.commands,\
-	org.eclipse.debug.ui,\
-	org.eclipse.debug.core,\
-	org.eclipse.jdt.core,\
-	org.eclipse.jdt.debug.ui,\
-	org.eclipse.jdt.junit,\
-	org.eclipse.jdt.launching,\
-	org.eclipse.jdt.ui,\
-	org.eclipse.jface,\
-	org.eclipse.jface.text,\
-	org.eclipse.text,\
-	org.eclipse.ui,\
-	org.eclipse.ui.workbench,\
-	org.eclipse.ui.editors,\
-	org.eclipse.ui.ide,\
-	org.eclipse.ui.workbench.texteditor,\
-	org.eclipse.swt.carbon.macosx,\
-	org.eclipse.core.jobs,\
-	org.eclipse.equinox.common,\
-	org.eclipse.equinox.registry,\
+-buildpath: aQute.libg;version=latest,\
+	ee.j2se;version=${javac.ee},\
+	biz.aQute.bndlib;version=project,\
+	biz.aQute.junit;version=project,\
+	biz.aQute.launcher;version=project,\
 	org.apache.tools.ant,\
-	osgi.cmpn,\
+	osgi.cmpn;version=4.3,\
 	osgi.core;version=4.1,\
 	junit.osgi,\
-	org.osgi.impl.bundle.bindex
-
+	org.osgi.impl.bundle.bindex,\
+	osgi.r5;version=1.0.1
+	
+# About the aQute.library.bndrepo dep. Needed to add them here
+# by hand even though they are in bndlib. However, they are added
+# and we can unfortunately not see those packages ...
+	
\ No newline at end of file
diff --git a/biz.aQute.bnd/bnd/embedded-repo.bnd b/biz.aQute.bnd/bnd/embedded-repo.bnd
index f45b735..61279c8 100644
--- a/biz.aQute.bnd/bnd/embedded-repo.bnd
+++ b/biz.aQute.bnd/bnd/embedded-repo.bnd
@@ -2,3 +2,5 @@
 Include-Resource: \
 	biz.aQute.launcher/biz.aQute.launcher-latest.jar=${repo;biz.aQute.launcher;snapshot}, \
 	biz.aQute.junit/biz.aQute.junit-latest.jar=${repo;biz.aQute.junit;snapshot}
+	aQute.library.bndrepo/aQute.library.bndrepo-latest.jar=${repo;aQute.library.bndrepo;snapshot}
+	
\ No newline at end of file
diff --git a/biz.aQute.bnd/build.properties b/biz.aQute.bnd/build.properties
deleted file mode 100644
index d87c40f..0000000
--- a/biz.aQute.bnd/build.properties
+++ /dev/null
@@ -1,4 +0,0 @@
-source.. = src/
-bin.includes = plugin.xml,\
-               META-INF/,\
-               .
diff --git a/biz.aQute.bnd/icons/active.gif b/biz.aQute.bnd/icons/active.gif
deleted file mode 100644
index f4151fb..0000000
Binary files a/biz.aQute.bnd/icons/active.gif and /dev/null differ
diff --git a/biz.aQute.bnd/icons/bundle.gif b/biz.aQute.bnd/icons/bundle.gif
deleted file mode 100644
index f4151fb..0000000
Binary files a/biz.aQute.bnd/icons/bundle.gif and /dev/null differ
diff --git a/biz.aQute.bnd/icons/export-package.gif b/biz.aQute.bnd/icons/export-package.gif
deleted file mode 100644
index 1dd79bf..0000000
Binary files a/biz.aQute.bnd/icons/export-package.gif and /dev/null differ
diff --git a/biz.aQute.bnd/icons/fragment.gif b/biz.aQute.bnd/icons/fragment.gif
deleted file mode 100644
index 88edb7b..0000000
Binary files a/biz.aQute.bnd/icons/fragment.gif and /dev/null differ
diff --git a/biz.aQute.bnd/icons/host.gif b/biz.aQute.bnd/icons/host.gif
deleted file mode 100644
index 3b8a5b1..0000000
Binary files a/biz.aQute.bnd/icons/host.gif and /dev/null differ
diff --git a/biz.aQute.bnd/icons/import-package.gif b/biz.aQute.bnd/icons/import-package.gif
deleted file mode 100644
index b9c7bfa..0000000
Binary files a/biz.aQute.bnd/icons/import-package.gif and /dev/null differ
diff --git a/biz.aQute.bnd/icons/importing-bundle.gif b/biz.aQute.bnd/icons/importing-bundle.gif
deleted file mode 100644
index 2572b79..0000000
Binary files a/biz.aQute.bnd/icons/importing-bundle.gif and /dev/null differ
diff --git a/biz.aQute.bnd/icons/installed.gif b/biz.aQute.bnd/icons/installed.gif
deleted file mode 100644
index 5e43705..0000000
Binary files a/biz.aQute.bnd/icons/installed.gif and /dev/null differ
diff --git a/biz.aQute.bnd/icons/inuse.gif b/biz.aQute.bnd/icons/inuse.gif
deleted file mode 100644
index 4cbdf38..0000000
Binary files a/biz.aQute.bnd/icons/inuse.gif and /dev/null differ
diff --git a/biz.aQute.bnd/icons/logo16x16.gif b/biz.aQute.bnd/icons/logo16x16.gif
deleted file mode 100644
index 9bf6a5b..0000000
Binary files a/biz.aQute.bnd/icons/logo16x16.gif and /dev/null differ
diff --git a/biz.aQute.bnd/icons/mini-logo.gif b/biz.aQute.bnd/icons/mini-logo.gif
deleted file mode 100644
index f4151fb..0000000
Binary files a/biz.aQute.bnd/icons/mini-logo.gif and /dev/null differ
diff --git a/biz.aQute.bnd/icons/module.gif b/biz.aQute.bnd/icons/module.gif
deleted file mode 100644
index 88edb7b..0000000
Binary files a/biz.aQute.bnd/icons/module.gif and /dev/null differ
diff --git a/biz.aQute.bnd/icons/property.gif b/biz.aQute.bnd/icons/property.gif
deleted file mode 100644
index 270bdac..0000000
Binary files a/biz.aQute.bnd/icons/property.gif and /dev/null differ
diff --git a/biz.aQute.bnd/icons/registered.gif b/biz.aQute.bnd/icons/registered.gif
deleted file mode 100644
index e41f6ce..0000000
Binary files a/biz.aQute.bnd/icons/registered.gif and /dev/null differ
diff --git a/biz.aQute.bnd/icons/resolved.gif b/biz.aQute.bnd/icons/resolved.gif
deleted file mode 100644
index d3ace48..0000000
Binary files a/biz.aQute.bnd/icons/resolved.gif and /dev/null differ
diff --git a/biz.aQute.bnd/icons/run.gif b/biz.aQute.bnd/icons/run.gif
deleted file mode 100644
index 442c299..0000000
Binary files a/biz.aQute.bnd/icons/run.gif and /dev/null differ
diff --git a/biz.aQute.bnd/icons/test.gif b/biz.aQute.bnd/icons/test.gif
deleted file mode 100644
index d91cc67..0000000
Binary files a/biz.aQute.bnd/icons/test.gif and /dev/null differ
diff --git a/biz.aQute.bnd/icons/unknown.gif b/biz.aQute.bnd/icons/unknown.gif
deleted file mode 100644
index 62903bf..0000000
Binary files a/biz.aQute.bnd/icons/unknown.gif and /dev/null differ
diff --git a/biz.aQute.bnd/installers/MacOs/bnd b/biz.aQute.bnd/installers/MacOs/bnd
new file mode 100755
index 0000000..73fa153
--- /dev/null
+++ b/biz.aQute.bnd/installers/MacOs/bnd
@@ -0,0 +1,3 @@
+#!/bin/sh
+java -jar /usr/local/jar/biz.aQute.bnd.jar $*
+
diff --git a/biz.aQute.bnd/installers/MacOs/bnd.pmdoc/01biz-contents.xml b/biz.aQute.bnd/installers/MacOs/bnd.pmdoc/01biz-contents.xml
new file mode 100644
index 0000000..316ac77
--- /dev/null
+++ b/biz.aQute.bnd/installers/MacOs/bnd.pmdoc/01biz-contents.xml
@@ -0,0 +1 @@
+<pkg-contents spec="1.12"><f n="biz.aQute.bnd.jar" o="root" g="admin" p="33188" pt="/Ws/bnd/biz.aQute.bnd/tmp/biz.aQute.bnd.jar" m="false" t="file"><mod>group</mod><mod>owner</mod></f></pkg-contents>
\ No newline at end of file
diff --git a/biz.aQute.bnd/installers/MacOs/bnd.pmdoc/01biz.xml b/biz.aQute.bnd/installers/MacOs/bnd.pmdoc/01biz.xml
new file mode 100644
index 0000000..e7663fe
--- /dev/null
+++ b/biz.aQute.bnd/installers/MacOs/bnd.pmdoc/01biz.xml
@@ -0,0 +1 @@
+<pkgref spec="1.12" uuid="1EF98095-E9B8-4B9C-95A7-5B0FFB1E59AC"><config><identifier>biz.aQute.bnd.biz.aQute.bnd.pkg</identifier><version>1.0</version><description></description><post-install type="none"/><requireAuthorization/><installFrom relative="true">../tmp/biz.aQute.bnd.jar</installFrom><installTo mod="true">/usr/local/jar</installTo><flags><followSymbolicLinks/></flags><packageStore type="internal"></packageStore><mod>installTo.path</mod><mod>locationType</mod><mod>parent</mod><mo [...]
\ No newline at end of file
diff --git a/biz.aQute.bnd/installers/MacOs/bnd.pmdoc/02bnd-contents.xml b/biz.aQute.bnd/installers/MacOs/bnd.pmdoc/02bnd-contents.xml
new file mode 100644
index 0000000..289c8f0
--- /dev/null
+++ b/biz.aQute.bnd/installers/MacOs/bnd.pmdoc/02bnd-contents.xml
@@ -0,0 +1 @@
+<pkg-contents spec="1.12"><f n="bnd" o="root" g="admin" p="33261" pt="/Ws/bnd/biz.aQute.bnd/MacOs/bnd" m="false" t="file"><mod>group</mod><mod>owner</mod></f></pkg-contents>
\ No newline at end of file
diff --git a/biz.aQute.bnd/installers/MacOs/bnd.pmdoc/02bnd.xml b/biz.aQute.bnd/installers/MacOs/bnd.pmdoc/02bnd.xml
new file mode 100644
index 0000000..e3315c7
--- /dev/null
+++ b/biz.aQute.bnd/installers/MacOs/bnd.pmdoc/02bnd.xml
@@ -0,0 +1 @@
+<pkgref spec="1.12" uuid="67D28F0B-2C50-4043-BD7A-51367F3018FB"><config><identifier>biz.aQute.bnd.bnd.pkg</identifier><version>1.0</version><description></description><post-install type="none"/><requireAuthorization/><installFrom relative="true" mod="true">bnd</installFrom><installTo mod="true" relocatable="true">/usr/local/bin</installTo><flags><followSymbolicLinks/></flags><packageStore type="internal"></packageStore><mod>installTo.path</mod><mod>installFrom.path</mod><mod>parent</mod> [...]
\ No newline at end of file
diff --git a/biz.aQute.bnd/installers/MacOs/bnd.pmdoc/index.xml b/biz.aQute.bnd/installers/MacOs/bnd.pmdoc/index.xml
new file mode 100644
index 0000000..f48adee
--- /dev/null
+++ b/biz.aQute.bnd/installers/MacOs/bnd.pmdoc/index.xml
@@ -0,0 +1 @@
+<pkmkdoc spec="1.12"><properties><title>bnd</title><build>/Users/aqute/Desktop/bnd.mpkg</build><organization>biz.aQute</organization><userSees ui="easy"/><min-target os="2"/><domain anywhere="true"/></properties><distribution><versions min-spec="1.000000"/><scripts></scripts></distribution><description>bnd is the Swiss army knife of OSGi bundles.</description><contents><choice title="biz.aQute.bnd" id="choice0" starts_selected="true" starts_enabled="true" starts_hidden="false"><pkgref id [...]
\ No newline at end of file
diff --git a/biz.aQute.bnd/installers/MacOs/build b/biz.aQute.bnd/installers/MacOs/build
new file mode 100755
index 0000000..563fd9b
--- /dev/null
+++ b/biz.aQute.bnd/installers/MacOs/build
@@ -0,0 +1,4 @@
+#!/bin/sh
+packagemaker --doc bnd.pmdoc
+
+
diff --git a/biz.aQute.bnd/plugin.xml b/biz.aQute.bnd/plugin.xml
deleted file mode 100755
index 161a008..0000000
--- a/biz.aQute.bnd/plugin.xml
+++ /dev/null
@@ -1,243 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?eclipse version="3.2"?>
-<plugin>
-	<extension point="org.eclipse.ui.popupMenus">
-		
-		<objectContribution objectClass="org.eclipse.core.resources.IFile"
-			nameFilter="*.bnd" id="aQute.bnd.plugin.contribution1">
-			<action class="aQute.bnd.plugin.popup.actions.MakeBundle"
-				enablesFor="+" id="aQute.bnd.plugin.Make" label="Make Bundle"
-				menubarPath="additions"
-				tooltip="Create a bundle from this definition file">
-			</action>
-		</objectContribution>
-		<objectContribution objectClass="org.eclipse.core.resources.IFile"
-			nameFilter="*.jar" id="aQute.bnd.plugin.contribution2">
-			<action class="aQute.bnd.plugin.popup.actions.VerifyBundle"
-				enablesFor="+" id="aQute.bnd.plugin.Verify" label="Verify Bundle"
-				menubarPath="additions"
-				tooltip="Verify the consistency of this bundle">
-			</action>
-			<action class="aQute.bnd.plugin.popup.actions.WrapBundle"
-				enablesFor="+" id="aQute.bnd.plugin.Wrap" label="Wrap Bundle"
-				menubarPath="additions" tooltip="Wrap this JAR file as a bundle">
-			</action>
-			<action class="aQute.bnd.plugin.popup.actions.InstallBundle"
-				enablesFor="+" id="aQute.bnd.plugin.Install" label="Install/Update Bundle"
-				menubarPath="additions" tooltip="Install/Updated the JAR in the THIS framework">
-			</action>
-   <action
-         class="aQute.bnd.plugin.popup.actions.AddToRepo"
-         enablesFor="+"
-         id="aQute.bnd.plugin.addtorepo"
-         label="Add to Repository"
-         menubarPath="additions"
-         tooltip="Add this JAR to a repository">
-   </action>
-		</objectContribution>
-	</extension>
-
-
-
-
-	
-	<extension point="org.eclipse.debug.core.launchConfigurationTypes">
-	    <launchConfigurationType
-           delegate="aQute.bnd.launch.LaunchDelegate"
-           id="aQute.bnd.launch"
-           modes="run, debug"
-           name="OSGi Run"
-           sourceLocatorId="org.eclipse.jdt.launching.sourceLocator.JavaSourceLookupDirector"
-           sourcePathComputerId="org.eclipse.jdt.launching.sourceLookup.javaSourcePathComputer">
-	    </launchConfigurationType>	
-      <launchConfigurationType
-            delegate="aQute.bnd.junit.OSGiJUnitLauncherConfigurationDelegate"
-            delegateDescription="Launches the JUnit Tests in an OSGi Framework and injects a BundleContext"
-            delegateName="OSGi JUnit Tests"
-            id="aQute.bnd.junit.launchconfig"
-            migrationDelegate="org.eclipse.jdt.internal.junit.launcher.JUnitMigrationDelegate"
-            modes="run, debug"
-            name="OSGi JUnit Tests"
-            sourceLocatorId="org.eclipse.jdt.launching.sourceLocator.JavaSourceLookupDirector"
-            sourcePathComputerId="org.eclipse.jdt.launching.sourceLookup.javaSourcePathComputer">
-      </launchConfigurationType>
-   </extension>
-	
-	
-	
-	
-	
-	
-	   <extension
-         point="org.eclipse.debug.ui.launchShortcuts">
-      <shortcut
-            label="OSGi JUnit"
-            icon="icons/test.gif"
-            class="aQute.bnd.junit.OSGiJUnitLaunchShortcut"
-            modes="run, debug"
-            id="org.eclipse.jdt.junit.junitShortcut">
-         <contextualLaunch>
-            <enablement>
-               <with variable="selection">
-                  <count value="1"/>
-               	  <iterate>
-                     <adapt type="org.eclipse.jdt.core.IJavaElement">
-		                <test property="org.eclipse.jdt.core.isInJavaProject"/>
-		                <test property="org.eclipse.jdt.core.hasTypeOnClasspath" value="junit.framework.Test"/>
-		                <test property="org.eclipse.jdt.junit.canLaunchAsJUnit" forcePluginActivation="true"/>
-		             </adapt>
-		          </iterate>
-               </with>
-            </enablement>
-         </contextualLaunch>
-         <perspective
-               id="org.eclipse.jdt.ui.JavaPerspective">
-         </perspective>
-         <perspective
-               id="org.eclipse.jdt.ui.JavaHierarchyPerspective">
-         </perspective>
-         <perspective
-               id="org.eclipse.jdt.ui.JavaBrowsingPerspective">
-         </perspective>
-         <perspective
-               id="org.eclipse.debug.ui.DebugPerspective">
-         </perspective>
-         <configurationType
-               id="org.eclipse.jdt.junit.launchconfig">
-         </configurationType>
-         <description
-               description="Debug a JUnit Test in an OSGi Framework"
-               mode="debug">
-         </description>
-         <description
-               description="Run an OSGi JUnit Test in an OSGi framework"
-               mode="run">
-         </description>
-      </shortcut>
-      <shortcut
-            class="aQute.bnd.launch.Shortcut"
-            icon="icons/run.gif"
-            id="aQute.bnd.launch.shortcut"
-            label="OSGi Run"
-            modes="run, debug">
-         <perspective
-               id="org.eclipse.jdt.ui.JavaPerspective">
-         </perspective>
-         <perspective
-               id="org.eclipse.jdt.ui.JavaHierarchyPerspective">
-         </perspective>
-         <perspective
-               id="org.eclipse.jdt.ui.JavaBrowsingPerspective">
-         </perspective>
-         <perspective
-               id="org.eclipse.debug.ui.DebugPerspective">
-         </perspective>
-         <contextualLaunch>
-            <enablement>
-               <with
-                     variable="selection">
-                  <count
-                        value="1">
-                  </count>
-                  <iterate>
-                     <adapt
-                           type="org.eclipse.jdt.core.IJavaElement">
-                        <test
-                              property="org.eclipse.jdt.core.isInJavaProject">
-                        </test>
-                        <test
-                              property="org.eclipse.jdt.core.hasTypeOnClasspath"
-                              value="junit.framework.Test">
-                        </test>
-                        <test
-                              forcePluginActivation="true"
-                              property="org.eclipse.jdt.junit.canLaunchAsJUnit">
-                        </test>
-                     </adapt>
-                  </iterate>
-               </with>
-            </enablement>
-         </contextualLaunch>
-      </shortcut>
-   </extension>
-	
-	
-	
-	
-	
-	   <extension
-         point="org.eclipse.debug.ui.launchConfigurationTabGroups">
-      <launchConfigurationTabGroup
-            class="aQute.bnd.junit.OSGiJUnitTabGroup"
-            description="Help!"
-            id="aQute.bnd.junit.OSGiJUnitTabGroup"
-            type="aQute.bnd.junit.launchconfig">
-         <launchMode
-               description="%jUnitTabGroup.description.debug"
-               mode="debug"
-               perspective="org.eclipse.debug.ui.DebugPerspective">
-         </launchMode>
-         <launchMode
-               description="%jUnitTabGroup.description.run"
-               mode="run">
-         </launchMode>
-      </launchConfigurationTabGroup>
-      <launchConfigurationTabGroup
-            class="aQute.bnd.launch.LaunchTabGroup"
-            id="aQute.bnd.launch.tabgroup"
-            type="aQute.bnd.launch">
-      </launchConfigurationTabGroup>
-   </extension>
-	
-	
-	
- <extension
-       point="org.eclipse.ui.editors">
-    <editor
-          class="aQute.bnd.jareditor.JarEditor"
-          default="true"
-          extensions="jar,zip"
-          icon="icons/bundle.gif"
-          id="aQute.bnd.jareditor.JarEditor"
-          name="Jar Viewer">
-    </editor>
- </extension>
-	   <extension
-       point="org.eclipse.jdt.core.classpathContainerInitializer">
-      <classpathContainerInitializer
-          id="aQute.bnd.classpath.container"
-          class="aQute.bnd.classpath.BndContainerInitializer"/>
-   </extension>
-   <extension 
-       point="org.eclipse.jdt.ui.classpathContainerPage">
-      <classpathContainerPage
-          id="aQute.bnd.classpath.container"
-          name="bnd classpath"
-          class="aQute.bnd.classpath.BndContainerPage"/>
-   </extension>
-	
-	
- <extension
-       point="org.eclipse.ui.menus">
-    <menuContribution
-          locationURI="popup:org.eclipse.ui.popup.any?after=additions">
-          <dynamic
-                class="aQute.bnd.plugin.popup.Scripts"
-                id="aQute.bnd.scripts">
-          </dynamic>
-    </menuContribution>
- </extension>
-	
- <extension
-       point="org.eclipse.ui.editors">
-    <editor
-          class="aQute.bnd.plugin.editors.BndMultiPageEditor"
-          contributorClass="aQute.bnd.plugin.editors.BndMultiPageEditorContributor"
-          extensions="bnd"
-          icon="icons/sample.gif"
-          id="aQute.bndpro.editors.BndMultiPageEditor"
-          name="Bnd Editor">
-    </editor>
- </extension>
- 
- </plugin>
diff --git a/biz.aQute.bnd/schema.xml b/biz.aQute.bnd/schema.xml
new file mode 100644
index 0000000..9fae794
--- /dev/null
+++ b/biz.aQute.bnd/schema.xml
@@ -0,0 +1,34 @@
+<?xml version='1.0'?>
+
+<jschema>
+  <specification jar="generated/biz.aQute.bnd.annotation.jar" id="1000"/>
+  <specification jar="generated/biz.aQute.bnd.jar" id="1001"/>
+  <specification jar="generated/biz.aQute.bnd.test.jar" id="1002">
+    Contains only the test functions for bnd.
+  </specification>
+  <packages>
+    <package name="aQute.bnd.service" version="1.44.0" spec="1001">
+      <import name="aQute.libg.reporter"/>
+      <import name="aQute.libg.version"/>
+      <import name="aQute.bnd.osgi"/>
+      <import name="aQute.bnd.build"/>
+    </package>
+    <package name="aQute.bnd.service.action" version="1.43.1" spec="1001">
+      <import name="aQute.bnd.build"/>
+    </package>
+    <package name="aQute.bnd.service.diff" version="1.52.3" spec="1001">
+      <import name="aQute.bnd.osgi"/>
+    </package>
+    <package name="aQute.bnd.service.url" version="1.52.3" spec="1001"/>
+    <package name="aQute.bnd.test" version="1.52.3" spec="1002">
+      <import name="javax.xml.xpath"/>
+      <import name="aQute.libg.reporter"/>
+      <import name="junit.framework" version="[3.8,4)"/>
+      <import name="javax.xml.parsers"/>
+      <import name="org.w3c.dom"/>
+      <import name="javax.xml.namespace"/>
+    </package>
+    <package name="org.osgi.service.bindex" version="1.0.0" spec="1001"/>
+  </packages>
+  <baseline/>
+</jschema>
\ No newline at end of file
diff --git a/biz.aQute.bnd/src/aQute/bnd/ant/AntMessages.java b/biz.aQute.bnd/src/aQute/bnd/ant/AntMessages.java
new file mode 100644
index 0000000..f90f887
--- /dev/null
+++ b/biz.aQute.bnd/src/aQute/bnd/ant/AntMessages.java
@@ -0,0 +1,17 @@
+package aQute.bnd.ant;
+
+import java.io.*;
+
+import aQute.libg.reporter.*;
+import aQute.service.reporter.*;
+
+ at Message("bnd messages for Ant")
+public interface AntMessages extends Messages {
+
+	ERROR NotAJarFile_(File file);
+
+	ERROR FailedToDeploy_Exception_(File file, Exception e);
+
+	ERROR GotFileNeedDir_(File absoluteFile);
+
+}
diff --git a/biz.aQute.bnd/src/aQute/bnd/ant/BaseTask.java b/biz.aQute.bnd/src/aQute/bnd/ant/BaseTask.java
index 9cb5b10..81d9399 100755
--- a/biz.aQute.bnd/src/aQute/bnd/ant/BaseTask.java
+++ b/biz.aQute.bnd/src/aQute/bnd/ant/BaseTask.java
@@ -4,116 +4,154 @@ import java.io.*;
 import java.util.*;
 
 import org.apache.tools.ant.*;
+import org.apache.tools.ant.taskdefs.*;
 
 import aQute.libg.reporter.*;
+import aQute.service.reporter.*;
 
 public class BaseTask extends Task implements Reporter {
-    List<String>    errors   = new ArrayList<String>();
-    List<String>    warnings = new ArrayList<String>();
-    List<String>    progress = new ArrayList<String>();
-    boolean pedantic;
-    boolean trace;
-
-    public void error(String s, Object... args ) {
-        errors.add(String.format(s, args));
-    }
-
-    public List<String> getErrors() {
-        return errors;
-    }
-
-    public List<String> getProgress() {
-        return progress;
-    }
-
-    public List<String> getWarnings() {
-        // TODO Auto-generated method stub
-        return warnings;
-    }
-
-    public void progress(String s, Object ... args) {
-        progress.add(String.format(s,args));
-    }
-
-    public void warning(String s, Object ... args) {
-        warnings.add(String.format(s, args));
-    }
-
-    protected boolean report() {
-        return report(this);
-    }
-
-    protected boolean report(Reporter reporter) {
-        if (reporter.getWarnings().size() > 0) {
-            System.err.println("Warnings");
-            for (Iterator<String> e = reporter.getWarnings().iterator(); e.hasNext();) {
-                System.err.println(" " + e.next());
-            }
-        }
-        if (reporter.getErrors().size() > 0) {
-            System.err.println( reporter.getErrors().size() + " Errors");
-            for (Iterator<String> e = reporter.getErrors().iterator(); e.hasNext();) {
-                System.err.println(" " + e.next());
-            }
-            return true;
-        }
-        return false;
-    }
-
-    public static File getFile(File base, String file)  {
-        File f = new File(file);
-        if (!f.isAbsolute()) {
-            int n;
-
-            f = base.getAbsoluteFile();
-            while ((n = file.indexOf('/')) > 0) {
-                String first = file.substring(0, n);
-                file = file.substring(n + 1);
-                if (first.equals(".."))
-                    f = f.getParentFile();
-                else
-                    f = new File(f, first);
-            }
-            f = new File(f, file);
-        }
-        try {
-            return f.getCanonicalFile();
-        } catch(IOException e ) {
-            return f.getAbsoluteFile();
-        }
-    }
-
-    protected List<String> split(String dependsOn, String string) {
-        if (dependsOn == null)
-            return new ArrayList<String>();
-
-        return Arrays.asList(string.split("\\s*" + string + "\\s*"));
-    }
-
-    protected String join(Collection<?> classpath, String string) {
-        StringBuffer sb = new StringBuffer();
-        String del = "";
-        for (Object name : classpath) {
-            sb.append(del);
-            sb.append(name);
-            del = string;
-        }
-        return sb.toString();
-    }
-
-    public boolean isPedantic() {
-        return pedantic;
-    }
-
-    public void setPedantic(boolean pedantic) {
-        this.pedantic = pedantic;
-    }
-    public void setTrace(boolean trace) {
-        this.trace = trace;
-    }
-
-    public void trace(String s, Object... args) {
-        System.out.printf("# "+s+"\n", args);
-    }
-
+	ReporterAdapter			reporter= new ReporterAdapter();
+	
+	List<String>			errors			= new ArrayList<String>();
+	List<String>			warnings		= new ArrayList<String>();
+	List<String>			progress		= new ArrayList<String>();
+	boolean					pedantic;
+	boolean					trace;
+	String					onfail;
+	final List<Property>	properties		= new LinkedList<Property>();
+	final List<Property>	workspaceProps	= new LinkedList<Property>();
+	final AntMessages		messages		= ReporterMessages.base(this, AntMessages.class);
+	boolean					exceptions;
+
+
+	protected boolean report() {
+		return report(this);
+	}
+
+	protected boolean report(Reporter reporter) {
+		if (reporter.getWarnings().size() > 0) {
+			System.err.println("Warnings");
+			for (Iterator<String> e = reporter.getWarnings().iterator(); e.hasNext();) {
+				System.err.println(" " + e.next());
+			}
+		}
+		if (reporter.getErrors().size() > 0) {
+			System.err.println(reporter.getErrors().size() + " Errors");
+			for (Iterator<String> e = reporter.getErrors().iterator(); e.hasNext();) {
+				System.err.println(" " + e.next());
+			}
+			return true;
+		}
+		return false;
+	}
+
+	public static File getFile(File base, String file) {
+		File f = new File(file);
+		if (!f.isAbsolute()) {
+			int n;
+
+			f = base.getAbsoluteFile();
+			while ((n = file.indexOf('/')) > 0) {
+				String first = file.substring(0, n);
+				file = file.substring(n + 1);
+				if (first.equals(".."))
+					f = f.getParentFile();
+				else
+					f = new File(f, first);
+			}
+			f = new File(f, file);
+		}
+		try {
+			return f.getCanonicalFile();
+		}
+		catch (IOException e) {
+			return f.getAbsoluteFile();
+		}
+	}
+
+	protected List<String> split(String dependsOn, String string) {
+		if (dependsOn == null)
+			return new ArrayList<String>();
+
+		return Arrays.asList(string.split("\\s*" + string + "\\s*"));
+	}
+
+	protected String join(Collection< ? > classpath, String string) {
+		StringBuilder sb = new StringBuilder();
+		String del = "";
+		for (Object name : classpath) {
+			sb.append(del);
+			sb.append(name);
+			del = string;
+		}
+		return sb.toString();
+	}
+
+	public boolean isPedantic() {
+		return pedantic;
+	}
+
+	public void setPedantic(boolean pedantic) {
+		this.pedantic = pedantic;
+	}
+
+	public void setTrace(boolean trace) {
+		this.trace = trace;
+	}
+
+	public boolean isTrace() {
+		return trace;
+	}
+
+	public void trace(String s, Object... args) {
+		System.err.printf("# " + s + "%n", args);
+	}
+
+	public void addProperty(Property property) {
+		properties.add(property);
+	}
+
+	public void addWsproperty(Property property) {
+		workspaceProps.add(property);
+	}
+
+	public boolean isExceptions() {
+		return exceptions;
+	}
+
+	public void setExceptions(boolean exceptions) {
+		this.exceptions = exceptions;
+	}
+
+	public Location getLocation(String msg) {
+		return reporter.getLocation(msg);
+	}
+
+	public boolean isOk() {
+		return reporter.isOk();
+	}
+
+	public SetLocation exception(Throwable t, String format, Object... args) {
+		return reporter.exception(t, format, args);
+	}
+
+	public SetLocation error(String s, Object... args) {
+		return reporter.error(s, args);
+	}
+
+	public List<String> getErrors() {
+		return reporter.getErrors();
+	}
+
+	public List<String> getWarnings() {
+		return reporter.getWarnings();
+	}
+
+	public void progress(float progress, String s, Object... args) {
+		reporter.progress(progress, s, args);
+	}
+
+	public SetLocation warning(String s, Object... args) {
+		return reporter.warning(s, args);
+	}
 }
diff --git a/biz.aQute.bnd/src/aQute/bnd/ant/BndTask.java b/biz.aQute.bnd/src/aQute/bnd/ant/BndTask.java
index cfc485e..da9fa36 100755
--- a/biz.aQute.bnd/src/aQute/bnd/ant/BndTask.java
+++ b/biz.aQute.bnd/src/aQute/bnd/ant/BndTask.java
@@ -4,63 +4,90 @@ import java.io.*;
 import java.util.*;
 
 import org.apache.tools.ant.*;
+import org.apache.tools.ant.taskdefs.*;
 import org.apache.tools.ant.types.*;
 
 import aQute.bnd.build.*;
 import aQute.bnd.build.Project;
-import aQute.lib.osgi.*;
-import aQute.lib.osgi.eclipse.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Jar;
+import aQute.bnd.osgi.eclipse.*;
 import aQute.libg.qtokens.*;
 
 /**
- * This file is the bnd main task for ant. 
+ * <p>
+ * This file is the bnd main task for ant.
+ * </p>
+ * <p>
+ * To define the task library, load property from <code>build.bnd</code> and
+ * prepare the workspace:
+ * </p>
  * 
- * Example usage
+ * <pre>
+ * <target name="init" unless="initialized">
+ *    <taskdef classpath="${path.to.bnd.jar}" resource="aQute/bnd/ant/taskdef.properties">
+ *    <bndprepare basedir="${projectdir}" print="false" top="${release.dir}"/>
+ *    <property name="initialized" value="set"/>
+ * </target>
+ * </pre>
+ * <p>
+ * To recursively build dependency projects, before building this project:
+ * </p>
  * 
  * <pre>
- * <project name="test path with bnd" default="run-test" basedir=".">
- *    <property file="run-demo.properties"/>
- *    <target name="run-test" description="show bnd usage with classpathref">
- *      <path id="run.demo.id" >
- *        <pathelement location="demo/classes"/>
- *        <fileset dir="${libs.demo.dir}">
- *          <include name="*.jar"/>
- *        </fileset>
- *      </path>
- *      <path id="bnd.path.id" >
- *        <fileset dir="dist">
- *          <include name="*.jar"/>
- *        </fileset>
- *      </path>
- *      <path id="descriptors.id" >
- *        <fileset dir="demo/bnd">
- *          <include name="*.bnd"/>
- *        </fileset>
- *      </path>
+ * <target name="dependencies" depends="init" if="project.dependson" unless="donotrecurse">
+ *    <subant target="build" inheritAll="false" buildpath="${project.dependson}">
+ *       <property name="donotrecurse" value="true"/>
+ *    </subant>
+ * </target>
+ * </pre>
+ * <p>
+ * To build a bundle:
+ * </p>
  * 
- *      <taskdef classpathref="bnd.path.id" classname="aQute.bnd.ant.BndTask" name="bnd"/>
- *      <bnd classpathref="run.demo.id"  eclipse="false" failok="false" exceptions="true" 
- *               output="demo/generated"  bndFiles="descriptors.id"/>
+ * <pre>
+ * <target name="build" depends="compile">
+ *    <mkdir dir="${target}"/>
+ *    <bnd command="build" exceptions="true" basedir="${project}"/>
+ * </target>
+ * </pre>
+ * <p>
+ * To pass properties into bnd from ANT:
+ * </p>
  * 
- * <!-- sample usage with nested paths -->
+ * <pre>
+ * <target name="build" depends="compile">
+ *    <mkdir dir="${target}"/>
+ *    <bnd command="build" exceptions="true" basedir="${project}">
+ *        <!-- Property will be set on the bnd Project: -->
+ *        <property name="foo" value="bar"/>
  * 
- * 	    <bnd eclipse="false" failok="false" exceptions="true" output="demo/generated">
- * 		  <classpath>
- * 		    <pathelement location="demo/classes"/>
- * 		      <fileset dir="${libs.demo.dir}">
- * 			    <include name="*.jar"/>
- *      	  </fileset>	 	
- * 		  </classpath>
- * 		  <bndfiles>
- * 		    <fileset dir="demo/bnd">
- * 		      <include name="*.bnd"/>
- * 		    </fileset>				
- * 		  <bndfiles>
- *      </bnd> 
- *    </target>
- *  </project>
+ *        <!-- Property will be set on the bnd Workspace: -->
+ *        <wsproperty name="foo" value="bar"/>
+ *    </bnd>
+ * </target>
  * </pre>
  * 
+ * @see {@link DeployTask} {@link ReleaseTask}
+ */
+
+/*
+ * OLD JAVADOCS: <pre> <project name="test path with bnd" default="run-test"
+ * basedir="."> <property file="run-demo.properties"/> <target name="run-test"
+ * description="show bnd usage with classpathref"> <path id="run.demo.id" >
+ * <pathelement location="demo/classes"/> <fileset dir="${libs.demo.dir}">
+ * <include name="*.jar"/> </fileset> </path> <path id="bnd.path.id" > <fileset
+ * dir="dist"> <include name="*.jar"/> </fileset> </path> <path
+ * id="descriptors.id" > <fileset dir="demo/bnd"> <include name="*.bnd"/>
+ * </fileset> </path> <taskdef classpathref="bnd.path.id"
+ * classname="aQute.bnd.ant.BndTask" name="bnd"/> <bnd
+ * classpathref="run.demo.id" eclipse="false" failok="false" exceptions="true"
+ * output="demo/generated" bndFiles="descriptors.id"/> <!-- sample usage with
+ * nested paths --> <bnd eclipse="false" failok="false" exceptions="true"
+ * output="demo/generated"> <classpath> <pathelement location="demo/classes"/>
+ * <fileset dir="${libs.demo.dir}"> <include name="*.jar"/> </fileset>
+ * </classpath> <bndfiles> <fileset dir="demo/bnd"> <include name="*.bnd"/>
+ * </fileset> <bndfiles> </bnd> </target> </project> </pre>
  */
 public class BndTask extends BaseTask {
 	String			command;
@@ -75,6 +102,7 @@ public class BndTask extends BaseTask {
 	private Path	classpathReference;
 	private Path	bndfilePath;
 
+	@Override
 	public void execute() throws BuildException {
 		// JME add - ensure every required parameter is present
 		// handle cases where mutual exclusion live..
@@ -94,17 +122,31 @@ public class BndTask extends BaseTask {
 
 		try {
 			Project project = Workspace.getProject(basedir);
+
+			Workspace ws = project.getWorkspace();
+			for (Property prop : workspaceProps) {
+				ws.setProperty(prop.getName(), prop.getValue());
+			}
+
 			project.setProperty("in.ant", "true");
 			project.setProperty("environment", "ant");
 			project.setExceptions(true);
 			project.setTrace(trace);
 			project.setPedantic(pedantic);
 
+			for (Property prop : properties) {
+				project.setProperty(prop.getName(), prop.getValue());
+			}
+
 			project.action(command);
 
-			if (report(project))
+			for (Project p : ws.getCurrentProjects())
+				ws.getInfo(p, p + ":");
+
+			if (report(ws))
 				throw new BuildException("Command " + command + " failed");
-		} catch (Throwable e) {
+		}
+		catch (Throwable e) {
 			if (exceptions)
 				e.printStackTrace();
 			throw new BuildException(e);
@@ -135,6 +177,7 @@ public class BndTask extends BaseTask {
 	boolean		eclipse;
 	boolean		inherit		= true;
 
+	@SuppressWarnings("cast")
 	private void executeBackwardCompatible() throws BuildException {
 		try {
 			if (files == null)
@@ -156,7 +199,7 @@ public class BndTask extends BaseTask {
 				output = getProject().getBaseDir();
 
 			for (Iterator<File> f = files.iterator(); f.hasNext();) {
-				File file = (File) f.next();
+				File file = f.next();
 				Builder builder = new Builder();
 
 				builder.setPedantic(isPedantic());
@@ -170,17 +213,22 @@ public class BndTask extends BaseTask {
 				// properties, if the inherit flag is specified
 				if (inherit) {
 					Properties projectProperties = new Properties();
-					projectProperties.putAll((Map<?, ?>) getProject().getProperties());
+					projectProperties.putAll((Map< ? , ? >) getProject().getProperties());
 					projectProperties.putAll(builder.getProperties());
 					builder.setProperties(projectProperties);
 				}
-				
+
 				builder.setClasspath(toFiles(classpath, "classpath"));
 				builder.setSourcepath(toFiles(sourcepath, "sourcepath"));
 				Jar jars[] = builder.builds();
 
-				if (!failok && report() && report(builder)) {
-					throw new BuildException("bnd failed", new Location(file.getAbsolutePath()));
+				// Report both task failures and bnd build failures.
+				boolean taskFailed = report();
+				boolean bndFailed = report(builder);
+
+				// Fail this build if failure is not ok and either the task failed or the bnd build failed.
+				if (!failok && (taskFailed || bndFailed)) {
+					throw new BuildException("bnd failed", new org.apache.tools.ant.Location(file.getAbsolutePath()));
 				}
 
 				for (int i = 0; i < jars.length; i++) {
@@ -205,8 +253,7 @@ public class BndTask extends BaseTask {
 							output = getFile(this.output, path);
 					} else if (output.isFile()) {
 						if (files.size() > 1)
-							error("Output is a file but there are multiple input files, these files will overwrite the output file: "
-									+ output.getAbsolutePath());
+							messages.GotFileNeedDir_(output.getAbsoluteFile());
 					}
 
 					String msg = "";
@@ -215,14 +262,14 @@ public class BndTask extends BaseTask {
 					} else {
 						msg = "(not modified)";
 					}
-					trace(jar.getName() + " (" + output.getName() + ") "
-							+ jar.getResources().size() + " " + msg);
+					trace(jar.getName() + " (" + output.getName() + ") " + jar.getResources().size() + " " + msg);
 					report();
 					jar.close();
 				}
 				builder.close();
 			}
-		} catch (Exception e) {
+		}
+		catch (Exception e) {
 			// if (exceptions)
 			e.printStackTrace();
 			if (!failok)
@@ -245,7 +292,7 @@ public class BndTask extends BaseTask {
 			if (f.exists())
 				list.add(f);
 			else
-				error("Can not find bnd file to process: " + f.getAbsolutePath());
+				messages.NoSuchFile_(f.getAbsoluteFile());
 		}
 	}
 
@@ -273,14 +320,6 @@ public class BndTask extends BaseTask {
 		this.failok = failok;
 	}
 
-	boolean isExceptions() {
-		return exceptions;
-	}
-
-	public void setExceptions(boolean exceptions) {
-		this.exceptions = exceptions;
-	}
-
 	boolean isPrint() {
 		return print;
 	}
@@ -295,7 +334,7 @@ public class BndTask extends BaseTask {
 
 	static File[]	EMPTY_FILES	= new File[0];
 
-	File[] toFiles(List<File> files, String what) throws IOException {
+	File[] toFiles(List<File> files, @SuppressWarnings("unused") String what) {
 		return files.toArray(EMPTY_FILES);
 	}
 
@@ -368,7 +407,6 @@ public class BndTask extends BaseTask {
 	// updates classpath for classpathref and nested classpath
 
 	private void updateClasspath() {
-		log("Updating classpath after classpathref setting");
 		if (classpathReference == null) {
 			return;
 		}
diff --git a/biz.aQute.bnd/src/aQute/bnd/ant/DeployTask.java b/biz.aQute.bnd/src/aQute/bnd/ant/DeployTask.java
index 742e64c..5432269 100644
--- a/biz.aQute.bnd/src/aQute/bnd/ant/DeployTask.java
+++ b/biz.aQute.bnd/src/aQute/bnd/ant/DeployTask.java
@@ -10,42 +10,53 @@ import aQute.bnd.build.*;
 import aQute.bnd.build.Project;
 
 public class DeployTask extends BaseTask {
-    List<FileSet> filesets = new ArrayList<FileSet>();
-
-    public void execute() throws BuildException {
-        try {
-            Project project = Workspace.getProject(getProject().getBaseDir());
-
-            // Deploy the files that need to be released
-            for (FileSet fileset : filesets) {
-                DirectoryScanner ds = fileset.getDirectoryScanner(getProject());
-                String[] files = ds.getIncludedFiles();
-                if (files.length == 0)
-                    trace("No files included");
-
-                for (int i = 0; i < files.length; i++) {
-                    File file = new File(ds.getBasedir(), files[i]);
-                    try {
-                        if (file.isFile() && file.getName().endsWith(".jar")) {
-                            project.deploy(file);
-                        } else
-                            error("Not a jar file: " + file);
-                    } catch (Exception e) {
-                        error("Failed to deploy " + file + " : " + e);
-                    }
-                }
-            }
-            report(project);
-            if (project.getErrors().size() > 0)
-                throw new BuildException("Deploy failed");
-        } catch (Throwable t) {
-            t.printStackTrace();
-            throw new BuildException(t);
-        }
-    }
-
-    public void addFileset(FileSet files) {
-        this.filesets.add(files);
-    }
+	private String	deployRepo	= null;
+	List<FileSet>	filesets	= new ArrayList<FileSet>();
+
+	@Override
+	public void execute() throws BuildException {
+		try {
+			Project project = Workspace.getProject(getProject().getBaseDir());
+
+			// Deploy the files that need to be released
+			for (FileSet fileset : filesets) {
+				DirectoryScanner ds = fileset.getDirectoryScanner(getProject());
+				String[] files = ds.getIncludedFiles();
+				if (files.length == 0)
+					trace("No files included");
+
+				for (int i = 0; i < files.length; i++) {
+					File file = new File(ds.getBasedir(), files[i]);
+					try {
+						if (file.isFile() && file.getName().endsWith(".jar")) {
+							if (deployRepo != null)
+								project.deploy(deployRepo, file);
+							else
+								project.deploy(file);
+						} else
+							messages.NotAJarFile_(file);
+					}
+					catch (Exception e) {
+						messages.FailedToDeploy_Exception_(file, e);
+					}
+				}
+			}
+			report(project);
+			if (project.getErrors().size() > 0)
+				throw new BuildException("Deploy failed");
+		}
+		catch (Throwable t) {
+			t.printStackTrace();
+			throw new BuildException(t);
+		}
+	}
+
+	public void setDeployrepo(String name) {
+		this.deployRepo = name;
+	}
+
+	public void addFileset(FileSet files) {
+		this.filesets.add(files);
+	}
 
 }
diff --git a/biz.aQute.bnd/src/aQute/bnd/ant/EclipseTask.java b/biz.aQute.bnd/src/aQute/bnd/ant/EclipseTask.java
index 67e8ef7..36cd1a2 100755
--- a/biz.aQute.bnd/src/aQute/bnd/ant/EclipseTask.java
+++ b/biz.aQute.bnd/src/aQute/bnd/ant/EclipseTask.java
@@ -5,95 +5,88 @@ import java.util.*;
 
 import org.apache.tools.ant.*;
 
-import aQute.lib.osgi.eclipse.*;
+import aQute.bnd.osgi.eclipse.*;
 
 public class EclipseTask extends BaseTask {
-    private String     prefix    = "project.";
-    private List<File> prebuild  = new ArrayList<File>();
-    private File       workspaceLocation;
-    private String     separator = ",";
-    private File       projectLocation;
-
-    public void execute() throws BuildException {
-        try {
-            if (projectLocation == null)
-                projectLocation = getProject().getBaseDir();
-
-            if (workspaceLocation == null)
-                workspaceLocation = projectLocation.getParentFile();
-
-            EclipseClasspath eclipse = new EclipseClasspath(this, workspaceLocation,
-                    projectLocation);
-
-            if (report())
-                throw new BuildException(
-                        "Errors during Eclipse Path inspection");
-
-            addProperty(prefix + "classpath", join(eclipse.getClasspath(),
-                    separator));
-
-            addProperty(prefix + "bootclasspath", join(eclipse
-                    .getBootclasspath(), separator));
-
-            if (!eclipse.getSourcepath().isEmpty())
-                addProperty(prefix + "sourcepath", join(
-                        eclipse.getSourcepath(), separator));
-
-            addProperty(prefix + "output", eclipse.getOutput()
-                    .getAbsolutePath());
-
-            /**
-             * The prebuild is an attribute that is prepended to the dependency
-             * path derived from the Eclipse project
-             */
-
-            List<File> dependents = new ArrayList<File>();
-            addCareful(dependents, prebuild);
-            addCareful(dependents, eclipse.getDependents());
-            if (dependents.size() > 0) {
-                addProperty(prefix + "buildpath", join(dependents, separator));
-            }
-        } catch (Exception e) {
-            throw new BuildException(
-                    "Error during parsing Eclipse .classpath files", e);
-        }
-    }
-
-    private void addCareful(List<File> result, Collection<File> projects) {
-        for (Iterator<File> i = projects.iterator(); i.hasNext();) {
-            File d = i.next();
-            if (!result.contains(d))
-                result.add(d);
-        }
-    }
-
-    protected void addProperty(String n, String v) {
-        // System.out.println(" Adding property: " + n + " = " + v);
-        if (v != null)
-            getProject().setProperty(n, v);
-    }
-
-    public void setPrefix(String prefix) {
-        this.prefix = prefix;
-    }
-
-    public void setPrebuild(String prebuild) {
-        StringTokenizer st = new StringTokenizer(prebuild, " ,");
-        while (st.hasMoreTokens()) {
-            this.prebuild.add(getFile(
-                    getProject().getBaseDir().getParentFile(), st.nextToken()));
-        }
-    }
-
-    public void setSeparator(String separator) {
-        this.separator = separator;
-    }
-
-    public void setProjectLocation(File projectLocation) {
-        this.projectLocation = projectLocation;
-    }
-
-    public void setWorkspaceLocation(File workspaceLocation) {
-        this.workspaceLocation = workspaceLocation;
-    }
+	private String		prefix		= "project.";
+	private List<File>	prebuild	= new ArrayList<File>();
+	private File		workspaceLocation;
+	private String		separator	= ",";
+	private File		projectLocation;
+
+	@Override
+	public void execute() throws BuildException {
+		try {
+			if (projectLocation == null)
+				projectLocation = getProject().getBaseDir();
+
+			if (workspaceLocation == null)
+				workspaceLocation = projectLocation.getParentFile();
+
+			EclipseClasspath eclipse = new EclipseClasspath(this, workspaceLocation, projectLocation);
+
+			if (report())
+				throw new BuildException("Errors during Eclipse Path inspection");
+
+			addProperty(prefix + "classpath", join(eclipse.getClasspath(), separator));
+
+			addProperty(prefix + "bootclasspath", join(eclipse.getBootclasspath(), separator));
+
+			if (!eclipse.getSourcepath().isEmpty())
+				addProperty(prefix + "sourcepath", join(eclipse.getSourcepath(), separator));
+
+			addProperty(prefix + "output", eclipse.getOutput().getAbsolutePath());
+
+			/**
+			 * The prebuild is an attribute that is prepended to the dependency
+			 * path derived from the Eclipse project
+			 */
+
+			List<File> dependents = new ArrayList<File>();
+			addCareful(dependents, prebuild);
+			addCareful(dependents, eclipse.getDependents());
+			if (dependents.size() > 0) {
+				addProperty(prefix + "buildpath", join(dependents, separator));
+			}
+		}
+		catch (Exception e) {
+			throw new BuildException("Error during parsing Eclipse .classpath files", e);
+		}
+	}
+
+	private void addCareful(List<File> result, Collection<File> projects) {
+		for (Iterator<File> i = projects.iterator(); i.hasNext();) {
+			File d = i.next();
+			if (!result.contains(d))
+				result.add(d);
+		}
+	}
+
+	protected void addProperty(String n, String v) {
+		if (v != null)
+			getProject().setProperty(n, v);
+	}
+
+	public void setPrefix(String prefix) {
+		this.prefix = prefix;
+	}
+
+	public void setPrebuild(String prebuild) {
+		StringTokenizer st = new StringTokenizer(prebuild, " ,");
+		while (st.hasMoreTokens()) {
+			this.prebuild.add(getFile(getProject().getBaseDir().getParentFile(), st.nextToken()));
+		}
+	}
+
+	public void setSeparator(String separator) {
+		this.separator = separator;
+	}
+
+	public void setProjectLocation(File projectLocation) {
+		this.projectLocation = projectLocation;
+	}
+
+	public void setWorkspaceLocation(File workspaceLocation) {
+		this.workspaceLocation = workspaceLocation;
+	}
 }
diff --git a/biz.aQute.bnd/src/aQute/bnd/ant/ExpandPropertiesTask.java b/biz.aQute.bnd/src/aQute/bnd/ant/ExpandPropertiesTask.java
index 178b36e..51480c6 100755
--- a/biz.aQute.bnd/src/aQute/bnd/ant/ExpandPropertiesTask.java
+++ b/biz.aQute.bnd/src/aQute/bnd/ant/ExpandPropertiesTask.java
@@ -5,18 +5,20 @@ import java.util.*;
 
 import org.apache.tools.ant.*;
 
-import aQute.lib.osgi.*;
+import aQute.bnd.osgi.*;
 
 public class ExpandPropertiesTask extends BaseTask {
 	File	propertyFile;
 
+	@Override
+	@SuppressWarnings("cast")
 	public void execute() throws BuildException {
 		try {
 			if (propertyFile.exists()) {
 				Properties properties = new Properties();
-				properties.putAll((Map<?,?>)getProject().getProperties());
-				
-				Processor   processor = new Processor(properties);
+				properties.putAll((Map< ? , ? >) getProject().getProperties());
+
+				Processor processor = new Processor(properties);
 				processor.setProperties(propertyFile);
 
 				Project project = getProject();
@@ -29,7 +31,8 @@ public class ExpandPropertiesTask extends BaseTask {
 				}
 			}
 			report();
-		} catch (IOException e) {
+		}
+		catch (IOException e) {
 			e.printStackTrace();
 			throw new BuildException(e);
 		}
diff --git a/biz.aQute.bnd/src/aQute/bnd/ant/PackageTask.java b/biz.aQute.bnd/src/aQute/bnd/ant/PackageTask.java
new file mode 100644
index 0000000..bd51cae
--- /dev/null
+++ b/biz.aQute.bnd/src/aQute/bnd/ant/PackageTask.java
@@ -0,0 +1,67 @@
+package aQute.bnd.ant;
+
+import java.io.*;
+import java.util.*;
+
+import org.apache.tools.ant.*;
+
+import aQute.bnd.build.*;
+import aQute.bnd.build.Project;
+import aQute.bnd.osgi.*;
+import aQute.lib.io.*;
+
+public class PackageTask extends BaseTask {
+
+	String	runFilePath	= null;
+	File	output		= null;
+
+	@Override
+	public void execute() throws BuildException {
+		if (output == null)
+			throw new BuildException("Output file must be specified");
+
+		OutputStream outStream = null;
+		try {
+			// Prepare the project to be packaged
+			List<Project> projects;
+			File baseDir = getProject().getBaseDir();
+			Project baseProject = Workspace.getProject(baseDir);
+
+			Project packageProject;
+			if (runFilePath == null || runFilePath.length() == 0 || ".".equals(runFilePath)) {
+				packageProject = baseProject;
+			} else {
+				File runFile = new File(baseDir, runFilePath);
+				if (!runFile.isFile())
+					throw new BuildException(String.format("Run file %s does not exist (or is not a file).", runFile.getAbsolutePath()));
+				packageProject = new Project(baseProject.getWorkspace(), baseDir, runFile);
+				packageProject.setParent(baseProject);
+			}
+
+			// Package it
+			packageProject.clear();
+			ProjectLauncher launcher = packageProject.getProjectLauncher();
+			Jar jar = launcher.executable();
+
+			outStream = new FileOutputStream(output);
+			jar.write(outStream);
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+			throw new BuildException(e);
+		}
+		finally {
+			IO.close(outStream);
+		}
+	}
+
+	public void setRunfile(String runFile) {
+		this.runFilePath = runFile != null ? runFile.trim() : null;
+	}
+
+	public void setOutput(File output) {
+		this.output = output;
+	}
+
+
+}
diff --git a/biz.aQute.bnd/src/aQute/bnd/ant/PrepareTask.java b/biz.aQute.bnd/src/aQute/bnd/ant/PrepareTask.java
index 3042e01..c3781de 100644
--- a/biz.aQute.bnd/src/aQute/bnd/ant/PrepareTask.java
+++ b/biz.aQute.bnd/src/aQute/bnd/ant/PrepareTask.java
@@ -14,79 +14,82 @@ import aQute.bnd.build.*;
 import aQute.bnd.build.Project;
 
 public class PrepareTask extends BaseTask {
-    File    basedir;
-    boolean print = false;
-    String    top;
-
-    public void execute() throws BuildException {
-        try {
-            if (basedir == null || !basedir.isDirectory())
-                throw new BuildException("The given base dir does not exist "
-                        + basedir);
-
-            Project project = Workspace.getProject(basedir);
-            project.setProperty("in.ant", "true");
-            project.setProperty("environment", "ant");
-            
-            // Check if we are in a sub build, in that case
-            // top will be set to the target directory at the
-            // top project.
-            if ( top!=null && top.length()>0 && !top.startsWith("$"))
-                project.setProperty("top", top);
-            
-            project.setExceptions(true);
-            Properties properties = project.getFlattenedProperties();
-            if (report() || report(project))
-                throw new BuildException(
-                        "Errors during Eclipse Path inspection");
-
-            copyProperties(properties);
-        } catch (Exception e) {
-            e.printStackTrace();
-            throw new BuildException(e);
-        }
-    }
-
-    private void copyProperties(Properties flattened) {
-        for (Enumeration<?> k = flattened.propertyNames(); k.hasMoreElements();) {
-            String key = (String) k.nextElement();
-            String value = flattened.getProperty(key);
-            if (isPrint())
-                System.out.printf("%-20s = %s\n", key, value);
-
-            // We override existing values.
-            getProject().setProperty(key, value.trim());
-        }
-    }
-
-    public boolean isPrint() {
-        return print;
-    }
-
-    /**
-     * Print out the properties when they are set in sorted order
-     * 
-     * @param print
-     */
-    public void setPrint(boolean print) {
-        this.print = print;
-    }
-
-    /**
-     * Set the base directory of the project. This property MUST be set.
-     * 
-     * @param basedir
-     */
-    public void setBasedir(File basedir) {
-        this.basedir = basedir;
-    }
-    
-    /**
-     * Set the base directory of the project. This property MUST be set.
-     * 
-     * @param basedir
-     */
-    public void setTop(String top) {
-        this.top = top;
-    }
+	File	basedir;
+	boolean	print	= false;
+	String	top;
+
+	@Override
+	public void execute() throws BuildException {
+		try {
+			if (basedir == null || !basedir.isDirectory())
+				throw new BuildException("The given base dir does not exist " + basedir);
+
+			Project project = Workspace.getProject(basedir);
+			if (project == null)
+				throw new BuildException("Unable to find bnd project in directory: " + basedir);
+
+			project.setProperty("in.ant", "true");
+			project.setProperty("environment", "ant");
+
+			// Check if we are in a sub build, in that case
+			// top will be set to the target directory at the
+			// top project.
+			if (top != null && top.length() > 0 && !top.startsWith("$"))
+				project.setProperty("top", top);
+
+			project.setExceptions(true);
+			Properties properties = project.getFlattenedProperties();
+			if (report() || report(project))
+				throw new BuildException("Errors during Eclipse Path inspection");
+
+			copyProperties(properties);
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+			throw new BuildException(e);
+		}
+	}
+
+	private void copyProperties(Properties flattened) {
+		for (Enumeration< ? > k = flattened.propertyNames(); k.hasMoreElements();) {
+			String key = (String) k.nextElement();
+			String value = flattened.getProperty(key);
+			if (isPrint())
+				System.err.printf("%-20s = %s%n", key, value);
+
+			// We override existing values.
+			getProject().setProperty(key, value.trim());
+		}
+	}
+
+	public boolean isPrint() {
+		return print;
+	}
+
+	/**
+	 * Print out the properties when they are set in sorted order
+	 * 
+	 * @param print
+	 */
+	public void setPrint(boolean print) {
+		this.print = print;
+	}
+
+	/**
+	 * Set the base directory of the project. This property MUST be set.
+	 * 
+	 * @param basedir
+	 */
+	public void setBasedir(File basedir) {
+		this.basedir = basedir;
+	}
+
+	/**
+	 * Set the base directory of the project. This property MUST be set.
+	 * 
+	 * @param basedir
+	 */
+	public void setTop(String top) {
+		this.top = top;
+	}
 }
diff --git a/biz.aQute.bnd/src/aQute/bnd/ant/ProjectBuildOrderTask.java b/biz.aQute.bnd/src/aQute/bnd/ant/ProjectBuildOrderTask.java
new file mode 100644
index 0000000..6a0ce2e
--- /dev/null
+++ b/biz.aQute.bnd/src/aQute/bnd/ant/ProjectBuildOrderTask.java
@@ -0,0 +1,62 @@
+package aQute.bnd.ant;
+
+import java.io.*;
+import java.util.*;
+
+import org.apache.tools.ant.*;
+
+import aQute.bnd.build.*;
+import aQute.bnd.build.Project;
+
+public class ProjectBuildOrderTask extends BaseTask {
+
+	private static final String	PROP_BUILD_ORDER	= "buildorder";
+
+	private String				separator			= ",";
+	private File				workspaceLocation;
+
+	@Override
+	public void execute() throws BuildException {
+		try {
+
+			if (workspaceLocation == null) {
+				throw new BuildException("The given workspace dir is not set");
+			}
+
+			if (!workspaceLocation.isDirectory()) {
+				throw new BuildException("The given workspace dir  not exist " + workspaceLocation);
+			}
+
+			Collection<Project> projects;
+			try {
+				workspaceLocation = workspaceLocation.getCanonicalFile();
+				Workspace workspace = Workspace.getWorkspace(workspaceLocation);
+				projects = workspace.getBuildOrder();
+			}
+			catch (Exception e) {
+				throw new BuildException(e);
+			}
+
+			StringBuilder sb = new StringBuilder();
+			String sep = "";
+			for (Project project : projects) {
+				sb.append(sep);
+				sb.append(project.getName());
+				sep = separator;
+			}
+
+			getProject().setProperty(PROP_BUILD_ORDER, sb.toString());
+		}
+		catch (Exception e) {
+			throw new BuildException(e);
+		}
+	}
+
+	public void setSeparator(String separator) {
+		this.separator = separator;
+	}
+
+	public void setWorkspaceLocation(File workspaceLocation) {
+		this.workspaceLocation = workspaceLocation;
+	}
+}
diff --git a/biz.aQute.bnd/src/aQute/bnd/ant/ProjectTask.java b/biz.aQute.bnd/src/aQute/bnd/ant/ProjectTask.java
index 65c31cc..b42531f 100644
--- a/biz.aQute.bnd/src/aQute/bnd/ant/ProjectTask.java
+++ b/biz.aQute.bnd/src/aQute/bnd/ant/ProjectTask.java
@@ -13,35 +13,35 @@ import aQute.bnd.build.*;
 import aQute.bnd.build.Project;
 
 public class ProjectTask extends BaseTask {
-    File basedir;
-    boolean underTest;
-    
-    public void execute() throws BuildException {
-        try {
-            if (basedir == null || !basedir.isDirectory())
-                throw new BuildException("The given base dir does not exist "
-                        + basedir);
-
-            Project project = Workspace.getProject(basedir);
-            project.build(underTest);
-            report(project);
-        } catch (Exception e) {
-            e.printStackTrace();
-            throw new BuildException(e);
-        }
-    }
-
-    /**
-     * Set the base directory of the project. This property MUST be set.
-     * 
-     * @param basedir
-     */
-    public void setBasedir(File basedir) {
-        this.basedir = basedir;
-    }
-    
-    
-    public void setUnderTest(boolean underTest) {
-        this.underTest = underTest;
-    }
+	File	basedir;
+	boolean	underTest;
+
+	@Override
+	public void execute() throws BuildException {
+		try {
+			if (basedir == null || !basedir.isDirectory())
+				throw new BuildException("The given base dir does not exist " + basedir);
+
+			Project project = Workspace.getProject(basedir);
+			project.build(underTest);
+			report(project);
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+			throw new BuildException(e);
+		}
+	}
+
+	/**
+	 * Set the base directory of the project. This property MUST be set.
+	 * 
+	 * @param basedir
+	 */
+	public void setBasedir(File basedir) {
+		this.basedir = basedir;
+	}
+
+	public void setUnderTest(boolean underTest) {
+		this.underTest = underTest;
+	}
 }
diff --git a/biz.aQute.bnd/src/aQute/bnd/ant/ReleaseTask.java b/biz.aQute.bnd/src/aQute/bnd/ant/ReleaseTask.java
new file mode 100644
index 0000000..3b9145b
--- /dev/null
+++ b/biz.aQute.bnd/src/aQute/bnd/ant/ReleaseTask.java
@@ -0,0 +1,58 @@
+package aQute.bnd.ant;
+
+import org.apache.tools.ant.*;
+
+import aQute.bnd.build.*;
+import aQute.bnd.build.Project;
+
+/**
+ * <p>
+ * ANT task to release into a repository, equivalent to:
+ * <code><bnd command="release"/></code>
+ * </p>
+ * <p>
+ * To release into the <em>default</em> repository (defined by
+ * <code>-releaserepo</code> in <code>build.bnd</code>):
+ * </p>
+ * 
+ * <pre>
+ *    <bndrelease/>
+ * </pre>
+ * <p>
+ * To release into a specific named repository:
+ * 
+ * <pre>
+ *    <bndrelease releaserepo="My Repository"/>
+ * </pre>
+ * 
+ * @author Neil Bartlett
+ * @see {@link BndTask} for setup instructions.
+ */
+public class ReleaseTask extends BaseTask {
+
+	String	releaseRepo	= null;
+
+	@Override
+	public void execute() throws BuildException {
+		try {
+			Project project = Workspace.getProject(getProject().getBaseDir());
+			if (releaseRepo == null) {
+				project.release(false);
+			} else {
+				project.release(releaseRepo);
+			}
+
+			if (report(project))
+				throw new BuildException("Release failed");
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+			throw new BuildException(e);
+		}
+	}
+
+	public void setReleaserepo(String releaseRepo) {
+		this.releaseRepo = releaseRepo;
+	}
+
+}
diff --git a/biz.aQute.bnd/src/aQute/bnd/ant/TestTask.java b/biz.aQute.bnd/src/aQute/bnd/ant/TestTask.java
new file mode 100644
index 0000000..4c9a9e8
--- /dev/null
+++ b/biz.aQute.bnd/src/aQute/bnd/ant/TestTask.java
@@ -0,0 +1,93 @@
+package aQute.bnd.ant;
+
+import java.io.*;
+import java.util.*;
+
+import org.apache.tools.ant.*;
+
+import aQute.bnd.build.*;
+import aQute.bnd.build.Project;
+
+public class TestTask extends BaseTask {
+
+	private boolean	continuous	= false;
+	private String	runFiles	= null;
+	private File dir = null;
+
+	@Override
+	public void execute() throws BuildException {
+
+		try {
+			// Prepare list of projects...
+			List<Project> projects;
+			File baseDir = getProject().getBaseDir();
+			Project baseProject = Workspace.getProject(baseDir);
+			if (runFiles == null) {
+				projects = Collections.singletonList(baseProject);
+			} else {
+				StringTokenizer tokenizer = new StringTokenizer(runFiles, ",");
+				projects = new LinkedList<Project>();
+				while (tokenizer.hasMoreTokens()) {
+					String runFilePath = tokenizer.nextToken().trim();
+					Project runProject;
+					if (".".equals(runFilePath)) {
+						runProject = baseProject;
+					} else {
+						File runFile = new File(baseDir, runFilePath);
+						if (!runFile.isFile())
+							throw new BuildException(String.format("Run file %s does not exist (or is not a file).",
+									runFile.getAbsolutePath()));
+						runProject = new Project(baseProject.getWorkspace(), baseDir, runFile);
+						runProject.setParent(baseProject);
+					}
+					projects.add(runProject);
+				}
+			}
+
+			// Test them
+			for (Project project : projects) {
+				executeProject(project);
+			}
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+			throw new BuildException(e);
+		}
+	}
+
+	private void executeProject(Project project) throws Exception {
+		System.out.println("Testing " + project.getPropertiesFile());
+		project.clear();
+
+		ProjectTester tester = project.getProjectTester();
+		tester.setContinuous(continuous);
+		if (dir != null) tester.setCwd(dir);
+		tester.prepare();
+
+		if (report(project))
+			throw new BuildException("Failed to initialise for testing.");
+
+		int errors = tester.test();
+		if (errors == 0) {
+			System.err.println("All tests passed");
+		} else {
+			if (errors > 0) {
+				System.err.println(errors + " Error(s)");
+			} else
+				System.err.println("Error " + errors);
+			throw new BuildException("Tests failed");
+		}
+
+		if (report(project))
+			throw new BuildException("Tests failed");
+	}
+
+	public void setRunfiles(String runFiles) {
+		this.runFiles = runFiles;
+	}
+	
+	public void setDir(File dir) {
+		this.dir = dir;
+	}
+
+}
diff --git a/biz.aQute.bnd/src/aQute/bnd/ant/WrapTask.java b/biz.aQute.bnd/src/aQute/bnd/ant/WrapTask.java
index 657417a..a13d33b 100755
--- a/biz.aQute.bnd/src/aQute/bnd/ant/WrapTask.java
+++ b/biz.aQute.bnd/src/aQute/bnd/ant/WrapTask.java
@@ -1,4 +1,3 @@
-
 package aQute.bnd.ant;
 
 import java.io.*;
@@ -7,52 +6,114 @@ import java.util.*;
 import org.apache.tools.ant.*;
 import org.apache.tools.ant.types.*;
 
-import aQute.bnd.main.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.version.*;
 import aQute.libg.qtokens.*;
-import aQute.libg.reporter.*;
 
-public class WrapTask extends BaseTask implements Reporter {
+/**
+ * Task to wrap a JAR as an OSGi bundle. You can specify the following
+ * properties:
+ * <ul>
+ * <li>bsn and version = Will set the appropriate properties</li>
+ * <li>a classpath</li>
+ * <li>an output directory or an output file if only one JAR is specified</li>
+ * <li>A search directory (definitions) for bnd files named the same as the
+ * source which are used for info</li>
+ * </ul>
+ */
+public class WrapTask extends BaseTask {
+	/**
+	 * List of jars to wrap
+	 */
 	List<File>	jars		= new ArrayList<File>();
-	File	output		= null;
-	File	definitions = null;
-	List<File>	classpath	= new ArrayList<File>();
-	
-	boolean	failok;
-	boolean	exceptions;
-	boolean	print;
 
-	@SuppressWarnings("unchecked")
-    public void execute() throws BuildException {
+	/**
+	 * Output directory or file (directory must be used
+	 */
+	File		output		= null;
+	File		definitions	= null;
+	List<File>	classpath	= new ArrayList<File>();
+	String		bsn;
+	Version		version;
+	boolean		force;
+	boolean		failok;
+	boolean		exceptions;
+
+	@Override
+	public void execute() throws BuildException {
 		boolean failed = false;
-		
+
 		try {
 			if (jars == null)
-				throw new BuildException("No files set");
-
-			if (output == null)
-				output = getProject().getBaseDir();
-
-			if (definitions == null)
-				definitions = getProject().getBaseDir();
-			
-			for (Iterator<File> f = jars.iterator(); f.hasNext();) {
-				bnd bnd = new bnd();
-				bnd.setPedantic(isPedantic());
-				File file = f.next();
-				String name = file.getName();
-				name = name.replaceFirst("(\\.jar)?$", ".bnd");
-				File bndFile = new File(definitions, name );
-				bnd.doWrap(bndFile.exists()?bndFile:null, file, output,  classpath.toArray(new File[0]), 0, getProject().getProperties());
-				failed |= report(bnd);
+				throw new BuildException("No files set", getLocation());
+
+			if (output != null && jars.size() > 1 && !output.isDirectory()) {
+				throw new BuildException("Multiple jars must be wrapped but the output given is not a directory "
+						+ output, getLocation());
 			}
-		} catch (Exception e) {
+
+			if (definitions != null && jars.size() > 1 && !definitions.isDirectory()) {
+				throw new BuildException(
+						"Multiple jars must be wrapped but the definitions parameters is not a directory "
+								+ definitions, getLocation());
+			}
+
+			for (File file : jars) {
+
+				if (!file.isFile()) {
+					failed = true;
+					System.err.println("Non existent file to wrap " + file);
+					continue;
+				}
+
+				Analyzer wrapper = new Analyzer();
+				wrapper.setPedantic(isPedantic());
+				wrapper.setTrace(isTrace());
+				wrapper.setExceptions(exceptions);
+				wrapper.setBase(getProject().getBaseDir());
+				wrapper.addClasspath(classpath);
+
+				if (failok)
+					wrapper.setFailOk(true);
+
+				wrapper.setJar(file);
+				wrapper.addProperties(getProject().getProperties());
+				wrapper.setDefaults(bsn, version);
+
+				File outputFile = wrapper.getOutputFile(output == null ? null : output.getAbsolutePath());
+
+				if (definitions != null) {
+					File properties = definitions;
+					if (properties.isDirectory()) {
+						String pfile = wrapper.replaceExtension(outputFile.getName(), Constants.DEFAULT_JAR_EXTENSION,
+								Constants.DEFAULT_BND_EXTENSION);
+						properties = new File(definitions, pfile);
+					}
+					if (properties.isFile()) {
+						wrapper.setProperties(properties);
+					}
+				}
+
+				wrapper.calcManifest();
+				if (wrapper.isOk()) {
+					boolean saved = wrapper.save(outputFile, force);
+					log(String.format("%30s %6d %s%n", wrapper.getJar().getBsn() + "-" + wrapper.getJar().getVersion(),
+							outputFile.length(), saved ? "" : "(not modified)"));
+				}
+
+				failed |= report(wrapper);
+			}
+		}
+		catch (Exception e) {
+
 			if (exceptions)
 				e.printStackTrace();
+
 			if (!failok)
-				throw new BuildException("Failed to build jar file: " + e, e);
+				throw new BuildException("Failed to build jar file: " + e, getLocation());
 		}
-		if ( failed && !failok)
-			throw new BuildException("Failed to wrap jar file");
+		if (failed && !failok)
+			throw new BuildException("Failed to wrap jar file", getLocation());
 	}
 
 	public void setJars(String files) {
@@ -68,13 +129,12 @@ public class WrapTask extends BaseTask implements Reporter {
 			if (f.exists())
 				list.add(f);
 			else
-				error("Can not find bnd file to process: "
-						+ f.getAbsolutePath());
+				messages.NoSuchFile_(f.getAbsoluteFile());
 		}
 	}
 
 	public void setClasspath(String files) {
-		addAll(classpath, files, File.pathSeparator+",");
+		addAll(classpath, files, File.pathSeparator + ",");
 	}
 
 	boolean isFailok() {
@@ -85,25 +145,37 @@ public class WrapTask extends BaseTask implements Reporter {
 		this.failok = failok;
 	}
 
+	public void setForce(boolean force) {
+		this.force = force;
+	}
+
+	@Override
 	public void setExceptions(boolean exceptions) {
 		this.exceptions = exceptions;
 	}
 
-
 	public void setOutput(File output) {
 		this.output = output;
 	}
-	
+
 	public void setDefinitions(File out) {
 		definitions = out;
 	}
-	
+
 	public void addConfiguredFileSet(FileSet list) {
 		DirectoryScanner scanner = list.getDirectoryScanner(getProject());
 		String files[] = scanner.getIncludedFiles();
 		for (int i = 0; i < files.length; i++) {
-			File f= getFile(scanner.getBasedir(), files[i]);
+			File f = getFile(scanner.getBasedir(), files[i]);
 			this.jars.add(f);
 		}
-	}	
+	}
+
+	public void setVersion(String version) {
+		this.version = new Version(version);
+	}
+
+	public void setBsn(String bsn) {
+		this.bsn = bsn;
+	}
 }
diff --git a/biz.aQute.bnd/src/aQute/bnd/ant/taskdef.properties b/biz.aQute.bnd/src/aQute/bnd/ant/taskdef.properties
index 30c49e7..98ed414 100755
--- a/biz.aQute.bnd/src/aQute/bnd/ant/taskdef.properties
+++ b/biz.aQute.bnd/src/aQute/bnd/ant/taskdef.properties
@@ -5,3 +5,7 @@ bndexpand=aQute.bnd.ant.ExpandPropertiesTask
 bndwrap=aQute.bnd.ant.WrapTask
 bnddeploy=aQute.bnd.ant.DeployTask
 bndprepare=aQute.bnd.ant.PrepareTask
+bndrelease=aQute.bnd.ant.ReleaseTask
+bndtest=aQute.bnd.ant.TestTask
+bndpackage=aQute.bnd.ant.PackageTask
+bndbuildorder=aQute.bnd.ant.ProjectBuildOrderTask
\ No newline at end of file
diff --git a/biz.aQute.bnd/src/aQute/bnd/classpath/BndContainer.java b/biz.aQute.bnd/src/aQute/bnd/classpath/BndContainer.java
deleted file mode 100644
index 323067e..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/classpath/BndContainer.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package aQute.bnd.classpath;
-
-import java.io.*;
-import java.util.*;
-
-import org.eclipse.core.runtime.*;
-import org.eclipse.jdt.core.*;
-
-import aQute.bnd.build.*;
-import aQute.bnd.plugin.*;
-
-public class BndContainer implements IClasspathContainer {
-
-	final static IClasspathEntry	ICLASSPATHENTRY_EMPTY[]	= new IClasspathEntry[0];
-
-	final Project					project;
-	volatile int					count;
-	volatile IClasspathEntry[]		cachedEntries;
-
-	BndContainer(Project project) {
-		this.project = project;
-	}
-
-	/**
-	 * Get the classpath entries ... seems to be called VERY often
-	 */
-
-	public IClasspathEntry[] getClasspathEntries() {
-		boolean cached = cachedEntries != null && count == project.getChanged();
-		if (!cached) {
-			try {
-				if (project.lock("get class path " + project) )
-				try {
-					project.clear();
-					count = project.getChanged();
-					ArrayList<IClasspathEntry> result = new ArrayList<IClasspathEntry>();
-					// fetch the names of all files that match our filter
-					List<Container> entries = new ArrayList<Container>();
-					entries.addAll(project.getBuildpath());
-
-					// The first file is always the project directory, Eclipse
-					// already includes that for us.
-					if (entries.size() > 0)
-						entries.remove(0);
-					else
-						; //System.err.println("Huh? Should have the bin dir! " + entries);
-					// Eclipse does not know a boot classpath, but it compiles
-					// against
-					// a jre. We add anything on the bootpath
-					entries.addAll(project.getBootclasspath());
-
-					for (Container c : entries) {
-						IClasspathEntry cpe;
-						IPath sourceAttachment = null;
-
-						if (c.getError() == null) {
-							File file = c.getFile();
-							assert file.isAbsolute();
-
-							IPath p = Central.toPath(project, file);
-							// JDT seems to ignore files when they
-							// are outside the workspace
-							if (p == null)
-								p = Path.fromOSString(file.getAbsolutePath());
-							try {
-								Central.refresh(p);
-							} catch (Throwable e) {
-
-							}
-							if (c.getType() == Container.TYPE.PROJECT) {
-								File sourceDir = c.getProject().getSrc();
-								if (sourceDir.isDirectory())
-									sourceAttachment = Central.toPath(c.getProject(), sourceDir);
-							}
-
-							cpe = JavaCore.newLibraryEntry(p, sourceAttachment, null);
-							result.add(cpe);
-						}
-					}
-					cachedEntries = result.toArray(ICLASSPATHENTRY_EMPTY);
-				} finally {
-					project.unlock();
-				}
-			} catch (Exception e) {
-				// TODO Auto-generated catch block
-				e.printStackTrace();
-			}
-		}
-		return cachedEntries;
-	}
-
-	public String getDescription() {
-		return "bnd";
-	}
-
-	public int getKind() {
-		return IClasspathContainer.K_APPLICATION;
-	}
-
-	public IPath getPath() {
-		return BndContainerInitializer.ID;
-	}
-
-	public Project getModel() {
-		return project;
-	}
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/classpath/BndContainerInitializer.java b/biz.aQute.bnd/src/aQute/bnd/classpath/BndContainerInitializer.java
deleted file mode 100644
index 60875ff..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/classpath/BndContainerInitializer.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package aQute.bnd.classpath;
-
-import org.eclipse.core.runtime.*;
-import org.eclipse.jdt.core.*;
-
-import aQute.bnd.build.*;
-import aQute.bnd.plugin.*;
-
-/**
- * A bnd container reads the bnd.bnd file in the project directory and use the
- * information in there to establish the classpath. The classpath is defined by
- * the -build-env instruction. This instruction contains a list of bsn's that
- * are searched in the available repositories and returned as File objects.
- * 
- * This initializer establishes the link between the container object and the
- * BndModel. The container object is just a delegator because for some unknown
- * reasons, you can only update the container (refresh the contents) when you
- * give it a new object ;-(
- * 
- * Because this plugin uses the Bnd Builder in different places, the Bnd Model
- * is centralized and available from the Activator.
- */
-public class BndContainerInitializer extends ClasspathContainerInitializer
-        implements ModelListener {
-
-    public final static Path ID      = new Path("aQute.bnd.classpath.container");
-
-    final Central            central = Activator.getDefault().getCentral();
-
-    public BndContainerInitializer() {
-        central.addModelListener(this);
-    }
-
-    /**
-     * Called when a new project is found. This class is instantiated once and
-     * then used for any project that has a bnd container associated. We create
-     * a link between the project and the Bnd Model. A delegating container
-     * object is created to link the project to the container so it can get its
-     * classpath entries. Note that the container object is not stored or
-     * remembered because we create a new one for every update (otherwise the
-     * update is not visible for some reason)
-     */
-    public void initialize(IPath containerPath, IJavaProject project)
-            throws CoreException {
-
-        // We maintain the models in the actitvator because other
-        // parts also use the model. Unfortunately, one can only
-        // do this with a static method :-(
-
-        Project model = central.getModel(project);
-        if (model == null)
-            throw new CoreException(
-                    new Status(IStatus.ERROR, ID.toString(),
-                            "Can not create model, likely the project does not contain a bnd.bnd file"));
-
-        // Update the Java Model so the changes become visible.
-        // Notice the unreferenced object.
-        requestClasspathContainerUpdate(containerPath, project,
-                new BndContainer(model));
-
-    }
-
-    /**
-     * We can always update.
-     */
-    public boolean canUpdateClasspathContainer(IPath containerPath,
-            IJavaProject project) {
-        return true;
-    }
-
-    /**
-     * Update the container. The containerSuggestion should always be a new
-     * BndContainer ...
-     */
-    public void requestClasspathContainerUpdate(IPath containerPath,
-            IJavaProject project, IClasspathContainer containerSuggestion)
-            throws CoreException {
-
-        JavaCore.setClasspathContainer(containerPath,
-                new IJavaProject[] { project },
-                new IClasspathContainer[] { containerSuggestion }, null);
-    }
-
-    public void modelChanged(Project model) throws Exception {
-        IJavaProject project = central.getJavaProject(model);
-        if (model == null || project == null) {
-            //System.out.println("Help! No IJavaProject for " + model);
-        } else
-            requestClasspathContainerUpdate(ID, project,
-                    new BndContainer(model));
-    }
-
-    public void workspaceChanged(Workspace ws) throws Exception {
-        //System.out.println("Workspace changed");
-    }
-
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/classpath/BndContainerPage.java b/biz.aQute.bnd/src/aQute/bnd/classpath/BndContainerPage.java
deleted file mode 100644
index 3a85785..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/classpath/BndContainerPage.java
+++ /dev/null
@@ -1,252 +0,0 @@
-package aQute.bnd.classpath;
-
-import java.io.*;
-
-import org.eclipse.core.resources.*;
-import org.eclipse.core.runtime.*;
-import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.ui.wizards.*;
-import org.eclipse.jface.viewers.*;
-import org.eclipse.jface.wizard.*;
-import org.eclipse.swt.*;
-import org.eclipse.swt.events.*;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.layout.*;
-import org.eclipse.swt.widgets.*;
-
-import aQute.bnd.build.*;
-import aQute.bnd.plugin.*;
-
-public class BndContainerPage extends WizardPage implements
-        IClasspathContainerPage, IClasspathContainerPageExtension {
-
-    // private Activator activator = Activator.getActivator();
-
-    private Table        table;
-    private Project      model;
-    private File         basedir;
-    private IJavaProject javaProject;
-
-    /**
-     * Default Constructor - sets title, page name, description
-     */
-    public BndContainerPage() {
-        super("bnd", "bnd - classpath", null);
-        setDescription("Ensures that bnd sees the same classpath as eclipse. The table will show the current contents. If there is no bnd file, you can create it with the button");
-        setPageComplete(true);
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.eclipse.jdt.ui.wizards.IClasspathContainerPageExtension#initialize(org.eclipse.jdt.core.IJavaProject,
-     *      org.eclipse.jdt.core.IClasspathEntry[])
-     */
-    public void initialize(IJavaProject project,
-            IClasspathEntry[] currentEntries) {
-        javaProject = project;
-        model = Activator.getDefault().getCentral().getModel(project);
-        basedir = project.getProject().getLocation().makeAbsolute().toFile();
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
-     */
-    public void createControl(Composite parent) {
-        Composite composite = new Composite(parent, SWT.NULL);
-        composite.setLayout(new FormLayout());
-        composite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL
-                | GridData.HORIZONTAL_ALIGN_FILL));
-        composite.setFont(parent.getFont());
-
-        setControl(composite);
-
-        final Button wCreate = new Button(composite, SWT.NONE);
-        wCreate.setEnabled(model == null);
-        final FormData fd_wCreate = new FormData();
-        fd_wCreate.bottom = new FormAttachment(100, -5);
-        fd_wCreate.right = new FormAttachment(100, -4);
-        wCreate.setLayoutData(fd_wCreate);
-        wCreate.setText("Create bnd.bnd");
-
-        final TableViewer tableViewer = new TableViewer(composite, SWT.BORDER);
-        table = tableViewer.getTable();
-        final FormData fd_table = new FormData();
-        fd_table.top = new FormAttachment(0, 3);
-        fd_table.left = new FormAttachment(0, 3);
-        fd_table.right = new FormAttachment(100, -4);
-        fd_table.bottom = new FormAttachment(100, -37);
-        table.setLayoutData(fd_table);
-        table.setLinesVisible(true);
-        table.setHeaderVisible(true);
-
-        final TableColumn wBsn = new TableColumn(table, SWT.NONE);
-        wBsn.setWidth(200);
-        wBsn.setText("Bundle Symbolic Name");
-
-        final TableColumn wVersion = new TableColumn(table, SWT.NONE);
-        wVersion.setWidth(100);
-        wVersion.setText("Version");
-
-        final TableColumn wOptions = new TableColumn(table, SWT.NONE);
-        wOptions.setWidth(200);
-        wOptions.setText("Options");
-
-        final TableColumn wFile = new TableColumn(table, SWT.NONE);
-        wFile.setWidth(100);
-        wFile.setText("File");
-
-        tableViewer.setContentProvider(new IStructuredContentProvider() {
-
-            public Object[] getElements(Object inputElement) {
-                if (model != null)
-                    try {
-                        
-                        return model.getBuildpath().toArray();
-                    } catch (Exception e) {
-                        // TODO Auto-generated catch block
-                        e.printStackTrace();
-                    }
-                return new Object[0];
-
-            }
-
-            public void dispose() {
-                // TODO Auto-generated method stub
-
-            }
-
-            public void inputChanged(Viewer viewer, Object oldInput,
-                    Object newInput) {
-
-            }
-
-        });
-        tableViewer.setLabelProvider(new ITableLabelProvider() {
-
-            public Image getColumnImage(Object element, int columnIndex) {
-                // TODO Auto-generated method stub
-                return null;
-            }
-
-            public String getColumnText(Object element, int columnIndex) {
-                Container c = (Container) element;
-                switch (columnIndex) {
-                case 0:
-                    return c.getBundleSymbolicName();
-                case 1:
-                    return c.getVersion();
-                case 2:
-                    return c.getError();
-                case 3:
-                    return c.getFile() + " (" + (c.getFile()!=null && c.getFile().exists() ? "exists" : "?") + ")";
-                }
-                return null;
-            }
-
-            public void addListener(ILabelProviderListener listener) {
-                // TODO Auto-generated method stub
-
-            }
-
-            public void dispose() {
-                // TODO Auto-generated method stub
-
-            }
-
-            public boolean isLabelProperty(Object element, String property) {
-                // TODO Auto-generated method stub
-                return false;
-            }
-
-            public void removeListener(ILabelProviderListener listener) {
-                // TODO Auto-generated method stub
-
-            }
-
-        });
-        tableViewer.setInput(model);
-        wCreate.addSelectionListener(new SelectionListener() {
-
-            public void widgetDefaultSelected(SelectionEvent e) {
-                //System.out.println("defw selected");
-            }
-
-            public void widgetSelected(SelectionEvent e) {
-                wCreate.setEnabled(!createBnd());
-                tableViewer.setInput(model);
-            }
-
-        });
-    }
-
-    protected boolean createBnd() {
-        if (basedir != null && basedir.isDirectory()) {
-            File bnd = new File(basedir, "bnd.bnd");
-            try {
-                FileOutputStream out = new FileOutputStream(bnd);
-                PrintStream ps = new PrintStream(out);
-                try {
-                    ps.println("# Auto generated by bnd, please adapt");
-                    ps.println();
-                    ps.println("Export-Package:                    ");
-                    ps.println("Private-Package:                   ");
-                    ps
-                            .println("Bundle-Name:                       ${Bundle-SymbolicName}");
-                    ps.println("Bundle-Version:                    1.0");
-                    ps.println();
-                    ps.println("#Example buildpath");
-                    ps
-                            .println("-buildpath:                        osgi;                                        version=4.0, \\");
-                    ps
-                            .println("                                   com.springsource.junit;                      version=\"[3.8,4)\"");
-                } finally {
-                    out.close();
-                    ps.close();
-                }
-                javaProject.getResource().refreshLocal(IResource.DEPTH_ONE, null);
-                model = Activator.getDefault().getCentral().getModel(javaProject);
-                return model != null;
-            } catch (IOException e) {
-                e.printStackTrace();
-            } catch (CoreException e) {
-                // TODO Auto-generated catch block
-                e.printStackTrace();
-            }
-        }
-        return false;
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.eclipse.jdt.ui.wizards.IClasspathContainerPage#finish()
-     */
-    public boolean finish() {
-        return true;
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.eclipse.jdt.ui.wizards.IClasspathContainerPage#getSelection()
-     */
-    public IClasspathEntry getSelection() {
-        IPath containerPath = BndContainerInitializer.ID;
-        IClasspathEntry cpe = JavaCore.newContainerEntry(containerPath);
-        return cpe;
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.eclipse.jdt.ui.wizards.IClasspathContainerPage#setSelection(org.eclipse.jdt.core.IClasspathEntry)
-     */
-    public void setSelection(IClasspathEntry containerEntry) {
-        if (containerEntry != null) {
-            // initPath = containerEntry.getPath();
-        }
-    }
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/classpath/ModelListener.java b/biz.aQute.bnd/src/aQute/bnd/classpath/ModelListener.java
deleted file mode 100644
index d364e73..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/classpath/ModelListener.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package aQute.bnd.classpath;
-
-import aQute.bnd.build.*;
-
-
-public interface ModelListener {
-    void modelChanged(Project model) throws Exception;
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/classpath/messages.properties b/biz.aQute.bnd/src/aQute/bnd/classpath/messages.properties
deleted file mode 100644
index 11e122a..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/classpath/messages.properties
+++ /dev/null
@@ -1,11 +0,0 @@
-Browse=Browse...
-DirErr=The directory must be a subdirectory of the project {0}
-DirLabel=Directory:
-DirSelect=Select the directory for the Simple Dir Container
-ExtErr=Extensions are not valid.  Verify that the extensions are comma separated and do not include the preceding '.'
-ExtLabel=Extensions (comma separated, not including .): 
-InvalidContainer=Invalid container:
-PageDesc=A classpath container that collects files with configured extensions from a configured directory
-PageName=Simple Directory Container Wizard
-PageTitle=Simple Directory Container
-
diff --git a/biz.aQute.bnd/src/aQute/bnd/jareditor/JarConfiguration.java b/biz.aQute.bnd/src/aQute/bnd/jareditor/JarConfiguration.java
deleted file mode 100644
index 28a05b5..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/jareditor/JarConfiguration.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package aQute.bnd.jareditor;
-
-import org.eclipse.jface.text.source.*;
-
-public class JarConfiguration extends SourceViewerConfiguration {
-
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/jareditor/JarDocumentProvider.java b/biz.aQute.bnd/src/aQute/bnd/jareditor/JarDocumentProvider.java
deleted file mode 100644
index 7f064b2..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/jareditor/JarDocumentProvider.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package aQute.bnd.jareditor;
-
-import java.io.*;
-
-import org.eclipse.core.runtime.*;
-import org.eclipse.jface.text.*;
-import org.eclipse.jface.text.source.*;
-import org.eclipse.ui.part.*;
-import org.eclipse.ui.texteditor.*;
-
-public class JarDocumentProvider implements IDocumentProvider {
-	Document	doc;
-	PrintWriter out;
-	
-	public void aboutToChange(Object arg0) {
-		// TODO Auto-generated method stub
-
-	}
-
-	public void addElementStateListener(IElementStateListener arg0) {
-		// TODO Auto-generated method stub
-
-	}
-
-	public boolean canSaveDocument(Object arg0) {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	public void changed(Object arg0) {
-		// TODO Auto-generated method stub
-
-	}
-
-	public void connect(Object source) throws CoreException {
-		try {
-			if (source instanceof FileEditorInput) {
-				FileEditorInput input = (FileEditorInput) source;
-				File file = input.getPath().toFile();
-				doc = new Document(print(file));
-			}
-		} catch (Exception e) {
-			throw new RuntimeException(e);
-		}
-	}
-
-	public void disconnect(Object arg0) {
-		// TODO Auto-generated method stub
-
-	}
-
-	public IAnnotationModel getAnnotationModel(Object arg0) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	public IDocument getDocument(Object arg0) {
-		return doc;
-	}
-
-	public long getModificationStamp(Object arg0) {
-		// TODO Auto-generated method stub
-		return 0;
-	}
-
-	public long getSynchronizationStamp(Object arg0) {
-		// TODO Auto-generated method stub
-		return 0;
-	}
-
-	public boolean isDeleted(Object arg0) {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	public boolean mustSaveDocument(Object arg0) {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	public void removeElementStateListener(IElementStateListener arg0) {
-		// TODO Auto-generated method stub
-
-	}
-
-	public void resetDocument(Object arg0) throws CoreException {
-		// TODO Auto-generated method stub
-
-	}
-
-	public void saveDocument(IProgressMonitor arg0, Object arg1,
-			IDocument arg2, boolean arg3) throws CoreException {
-		// TODO Auto-generated method stub
-
-	}
-	
-	
-	String print(File file) throws Exception {
-		ByteArrayOutputStream bos = new ByteArrayOutputStream();
-		PrintStream ps = new PrintStream(bos);
-		aQute.bnd.main.bnd x = new aQute.bnd.main.bnd();
-		x.setOut(ps);
-		x.doPrint(file.getAbsolutePath(), -1);
-		ps.close();
-		return new String( bos.toByteArray());
-	}
-
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/jareditor/JarEditor.java b/biz.aQute.bnd/src/aQute/bnd/jareditor/JarEditor.java
deleted file mode 100644
index 940b2e8..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/jareditor/JarEditor.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package aQute.bnd.jareditor;
-
-import org.eclipse.ui.texteditor.*;
-
-public class JarEditor extends AbstractTextEditor {
-	public JarEditor() {
-	      //install the source configuration
-	      setSourceViewerConfiguration(new JarConfiguration());
-	      //install the document provider
-	      setDocumentProvider(new JarDocumentProvider());
-	   }
-	   protected void createActions() {
-	      super.createActions();
-	      //... add other editor actions here
-	   }
-
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/junit/OSGiArgumentsTab.java b/biz.aQute.bnd/src/aQute/bnd/junit/OSGiArgumentsTab.java
deleted file mode 100644
index c30b2e0..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/junit/OSGiArgumentsTab.java
+++ /dev/null
@@ -1,129 +0,0 @@
-package aQute.bnd.junit;
-
-
-import org.eclipse.core.resources.*;
-import org.eclipse.core.runtime.*;
-import org.eclipse.debug.core.*;
-import org.eclipse.debug.ui.*;
-import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.launching.*;
-import org.eclipse.swt.*;
-import org.eclipse.swt.layout.*;
-import org.eclipse.swt.widgets.*;
-
-import aQute.bnd.plugin.*;
-
-public class OSGiArgumentsTab extends AbstractLaunchConfigurationTab {
-    public static final String ATTR_KEEP = Activator.PLUGIN_ID
-                                                        + ".CLEARCACHE"; //$NON-NLS-1$
-    public static final String ATTR_REPORT   = Activator.PLUGIN_ID
-                                                        + ".REPORT"; //$NON-NLS-1$
-
-    Button                     wReport;
-    private Button             wKeep;
-
-    public void createControl(Composite parent) {
-        Composite comp = new Composite(parent, SWT.NONE);
-        comp.setLayout(new FormLayout());
-        setControl(comp);
-
-        wKeep = new Button(comp, SWT.CHECK);
-        final FormData fd_wClearCache = new FormData();
-        fd_wClearCache.bottom = new FormAttachment(wKeep, 25, SWT.BOTTOM);
-        fd_wClearCache.top = new FormAttachment(wKeep, 5, SWT.BOTTOM);
-        fd_wClearCache.right = new FormAttachment(wKeep, 189, SWT.LEFT);
-        fd_wClearCache.left = new FormAttachment(wKeep, 0, SWT.LEFT);
-        wKeep.setLayoutData(fd_wClearCache);
-        wKeep.setText("Keep");
-
-        wReport = new Button(comp, SWT.CHECK);
-        final FormData fd_verboseButton = new FormData();
-        fd_verboseButton.top = new FormAttachment(wReport, 5, SWT.BOTTOM);
-        fd_verboseButton.left = new FormAttachment(wReport, 0, SWT.LEFT);
-        wReport.setLayoutData(fd_verboseButton);
-        wReport.setText("Report");
-
-        validatePage();
-
-    }
-
-    private void validatePage() {
-        setErrorMessage(null);
-        setMessage(null);
-    }
-
-    public String getName() {
-        return "OSGi";
-    }
-
-    public void initializeFrom(ILaunchConfiguration configuration) {
-        try {
-            boolean keep = configuration.getAttribute(ATTR_KEEP,
-                    false);
-            wKeep.setSelection(keep);
-            boolean report = configuration.getAttribute(ATTR_REPORT,
-                    false);
-            wReport.setSelection(report);
-        } catch (Exception ce) {
-            ce.printStackTrace();
-        }
-    }
-
-    public void performApply(ILaunchConfigurationWorkingCopy configuration) {
-        configuration.setAttribute(ATTR_REPORT, wReport.getSelection());
-        configuration
-                .setAttribute(ATTR_KEEP, wKeep.getSelection());
-    }
-
-    public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
-        // TODO Auto-generated method stub
-
-    }
-
-    /**
-     * Returns the Java project specified by the given launch configuration, or
-     * <code>null</code> if none.
-     * 
-     * @param configuration
-     *            launch configuration
-     * @return the Java project specified by the given launch configuration, or
-     *         <code>null</code> if none
-     * @exception CoreException
-     *                if unable to retrieve the attribute
-     */
-    public IJavaProject getJavaProject(ILaunchConfiguration configuration)
-            throws CoreException {
-        String projectName = getJavaProjectName(configuration);
-        if (projectName != null) {
-            projectName = projectName.trim();
-            if (projectName.length() > 0) {
-                IProject project = ResourcesPlugin.getWorkspace().getRoot()
-                        .getProject(projectName);
-                IJavaProject javaProject = JavaCore.create(project);
-                if (javaProject != null && javaProject.exists()) {
-                    return javaProject;
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Returns the Java project name specified by the given launch
-     * configuration, or <code>null</code> if none.
-     * 
-     * @param configuration
-     *            launch configuration
-     * @return the Java project name specified by the given launch
-     *         configuration, or <code>null</code> if none
-     * @exception CoreException
-     *                if unable to retrieve the attribute
-     */
-    public String getJavaProjectName(ILaunchConfiguration configuration)
-            throws CoreException {
-        return configuration.getAttribute(
-                IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME,
-                (String) null);
-    }
-
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/junit/OSGiJUnitLaunchShortcut.java b/biz.aQute.bnd/src/aQute/bnd/junit/OSGiJUnitLaunchShortcut.java
deleted file mode 100644
index aabe2d3..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/junit/OSGiJUnitLaunchShortcut.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package aQute.bnd.junit;
-
-
-
-public class OSGiJUnitLaunchShortcut extends
-		org.eclipse.jdt.junit.launcher.JUnitLaunchShortcut {
-	public OSGiJUnitLaunchShortcut() {
-		//System.out.println("Constructore Launch Shortcut");
-	}
-	
-	protected String getLaunchConfigurationTypeId() {
-		return "aQute.bnd.junit.launchconfig";
-	}
-
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/junit/OSGiJUnitLauncherConfigurationDelegate.java b/biz.aQute.bnd/src/aQute/bnd/junit/OSGiJUnitLauncherConfigurationDelegate.java
deleted file mode 100644
index eb93e3c..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/junit/OSGiJUnitLauncherConfigurationDelegate.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package aQute.bnd.junit;
-
-import java.io.*;
-import java.util.*;
-
-import org.eclipse.core.runtime.*;
-import org.eclipse.debug.core.*;
-import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.junit.launcher.*;
-
-import aQute.bnd.build.*;
-import aQute.bnd.plugin.*;
-import aQute.bnd.service.*;
-import aQute.lib.osgi.*;
-
- at SuppressWarnings("unchecked") public class OSGiJUnitLauncherConfigurationDelegate extends
-		JUnitLaunchConfigurationDelegate {
-
-	private ProjectTester	tester;
-
-	private ProjectTester getTester(ILaunchConfiguration configuration) throws CoreException {
-		try {
-			if (tester == null) {
-
-				IJavaProject javaProject = getJavaProject(configuration);
-				Project project = Activator.getDefault().getCentral().getModel(javaProject);
-				project.clear();
-
-				tester = project.getProjectTester();
-				if (tester == null) {
-
-					throw new IllegalArgumentException("Launching " + project
-							+ ". Cannot determine launcher configuration from -runpath: "
-							+ project.getProperty(Constants.RUNPATH));
-				}
-
-			}
-			return tester;
-		} catch (Exception e) {
-			throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
-					"Failed to obtain launcher", e));
-		}
-	}
-
-	public String verifyMainTypeName(ILaunchConfiguration configuration) throws CoreException {
-		return getTester(configuration).getProjectLauncher().getMainTypeName();
-	}
-
-	// protected IMember[] evaluateTests(ILaunchConfiguration configuration,
-	// IProgressMonitor monitor) throws CoreException {
-	// System.out.println("Evaluate Tests");
-	// return super.evaluateTests(configuration, monitor);
-	// }
-
-	protected void collectExecutionArguments(ILaunchConfiguration configuration,
-			List/* String */vmArguments, List/* String */programArguments) throws CoreException {
-
-		try {
-			super.collectExecutionArguments(configuration, vmArguments, programArguments);
-
-			ProjectTester tester = getTester(configuration);
-			ProjectLauncher launcher = tester.getProjectLauncher();
-
-			int port = -1;
-			// Pretty ugly :-(
-			for (int i = 0; i < programArguments.size(); i++) {
-				if (programArguments.get(i).equals("-port")) {
-					port = Integer.parseInt((String) programArguments.get(++i));
-				} else if (programArguments.get(i).equals("-testNameFile")) {
-					File testNameFile = tester.getProject().getFile(
-							(String) programArguments.get(++i));
-					processFile(tester, testNameFile);
-				} else if (programArguments.get(i).equals("-test")) {
-					tester.addTest((String)programArguments.get(++i));
-				}else if (programArguments.get(i).equals("-classNames")) {
-					tester.addTest((String)programArguments.get(++i));
-				}
-			}
-
-			if (tester instanceof EclipseJUnitTester) {
-				EclipseJUnitTester etester = (EclipseJUnitTester) tester;
-				etester.setPort(port);
-			}
-
-			programArguments.addAll(launcher.getArguments());
-			vmArguments.addAll(launcher.getRunVM());
-
-			if (configuration.getAttribute(OSGiArgumentsTab.ATTR_KEEP, false))
-				programArguments.add("-keep");
-
-			if (tester.getProject().isOk()) {
-				tester.prepare();
-				return;
-			}
-
-			String args = vmArguments + " " + programArguments + " "
-					+ Arrays.toString(getClasspath(configuration));
-			Activator.getDefault().report(true, false, tester.getProject(),
-					"Launching " + tester.getProject(), args);
-		} catch (Exception e) {
-			throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
-					"Building arguments for remote VM", e));
-		}
-		throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
-				"Building arguments for remote VM"));
-	}
-
-	private void processFile(ProjectTester tester, File file) throws IOException {
-		FileReader rdr = new FileReader(file);
-		BufferedReader brdr = new BufferedReader(rdr);
-		String line = brdr.readLine();
-		while (line != null) {
-			tester.addTest(line.trim());
-			line = brdr.readLine();
-		}
-		rdr.close();
-	}
-
-	/**
-	 * Calculate the classpath. We include our own runtime.jar which includes
-	 * the test framework and we include the first of the test frameworks
-	 * specified.
-	 */
-	public String[] getClasspath(ILaunchConfiguration configuration) throws CoreException {
-		return getTester(configuration).getProjectLauncher().getClasspath().toArray(new String[0]);
-	}
-
-	public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException {
-		try {
-			super.launch(configuration, mode, launch, monitor);
-		} finally {
-			tester = null;
-		}
-	}
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/junit/OSGiJUnitTabGroup.java b/biz.aQute.bnd/src/aQute/bnd/junit/OSGiJUnitTabGroup.java
deleted file mode 100644
index 421d13b..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/junit/OSGiJUnitTabGroup.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package aQute.bnd.junit;
-
-
-import org.eclipse.debug.ui.*;
-import org.eclipse.debug.ui.sourcelookup.*;
-import org.eclipse.jdt.debug.ui.launchConfigurations.*;
-import org.eclipse.jdt.junit.launcher.*;
-
-
-public class OSGiJUnitTabGroup extends org.eclipse.jdt.internal.junit.launcher.JUnitTabGroup {
-    public void createTabs(ILaunchConfigurationDialog dialog, String mode) {        
-        ILaunchConfigurationTab[] tabs= new ILaunchConfigurationTab[] {
-            new JUnitLaunchConfigurationTab(),
-            new OSGiArgumentsTab(),
-            new JavaArgumentsTab(),
-            new JavaClasspathTab(),
-            new JavaJRETab(),
-            new SourceLookupTab(),
-            new EnvironmentTab(),
-            new CommonTab()
-        };
-        setTabs(tabs);
-    }
-
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/launch/LaunchDelegate.java b/biz.aQute.bnd/src/aQute/bnd/launch/LaunchDelegate.java
deleted file mode 100644
index 93b7a44..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/launch/LaunchDelegate.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package aQute.bnd.launch;
-
-import org.eclipse.core.runtime.*;
-import org.eclipse.debug.core.*;
-import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.launching.*;
-
-import aQute.bnd.build.*;
-import aQute.bnd.plugin.*;
-import aQute.lib.osgi.*;
-
-public class LaunchDelegate extends JavaLaunchDelegate {
-    ProjectLauncher launcher;
-    
-    public void launch(ILaunchConfiguration configuration, String mode,
-            ILaunch launch, IProgressMonitor monitor) throws CoreException {
-        IJavaProject javaProject = getJavaProject(configuration);
-        Project project = Activator.getDefault().getCentral().getModel(javaProject);
-        try {
-            launcher = project.getProjectLauncher();
-            super.launch(configuration, mode, launch, monitor);
-        } catch (Exception e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-    }
-
-    public String verifyMainTypeName(ILaunchConfiguration configuration)
-            throws CoreException {
-        return launcher.getMainTypeName();
-    }
-
-    public String getVMArguments(ILaunchConfiguration c) {
-        return Processor.join(launcher.getRunVM(), " ");
-    }
-
-    public String getProgramArguments(ILaunchConfiguration c) {
-        return Processor.join(launcher.getArguments(), " ");
-    }
-
-    public String[] getClasspath(ILaunchConfiguration configuration) {
-        return launcher.getClasspath().toArray(new String[0]);
-    }
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/launch/LaunchTabGroup.java b/biz.aQute.bnd/src/aQute/bnd/launch/LaunchTabGroup.java
deleted file mode 100644
index 916981b..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/launch/LaunchTabGroup.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package aQute.bnd.launch;
-
-import org.eclipse.debug.ui.*;
-import org.eclipse.debug.ui.sourcelookup.*;
-import org.eclipse.jdt.debug.ui.launchConfigurations.*;
-
-public class LaunchTabGroup extends AbstractLaunchConfigurationTabGroup {
-
-    public void createTabs(ILaunchConfigurationDialog dialog, String mode) {
-        ILaunchConfigurationTab[] tabs = new ILaunchConfigurationTab[] {
-                new JavaArgumentsTab(),
-                new JavaClasspathTab(),
-                new JavaJRETab(),
-                new SourceLookupTab(),
-                new EnvironmentTab(),
-                new CommonTab(),
-        };
-        setTabs(tabs);
-    }
-
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/launch/Shortcut.java b/biz.aQute.bnd/src/aQute/bnd/launch/Shortcut.java
deleted file mode 100644
index 1d34578..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/launch/Shortcut.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package aQute.bnd.launch;
-
-import java.util.*;
-
-import org.eclipse.core.runtime.*;
-import org.eclipse.debug.core.*;
-import org.eclipse.debug.ui.*;
-import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.launching.*;
-import org.eclipse.jface.viewers.*;
-import org.eclipse.ui.*;
-
-public class Shortcut implements ILaunchShortcut {
-
-    public Shortcut() {
-       // System.out.println("Constructor Launch Shortcut");
-    }
-
-    protected String getLaunchConfigurationTypeId() {
-        return "aQute.bnd.launch";
-    }
-
-    public void launch(ISelection selection, String mode) {
-        IStructuredSelection is = (IStructuredSelection) selection;
-        if ( is.getFirstElement() != null ) {
-            Object selected = is.getFirstElement();
-            IJavaElement element = null;
-            if (selected instanceof IJavaElement )
-                element = (IJavaElement) selected;
-            else if ( selected instanceof IAdaptable ) {
-                element = (IJavaElement) ((IAdaptable)selected).getAdapter(IJavaElement.class);
-            }
-            
-            if ( element != null )
-                launch(element.getJavaProject(), mode);
-        }
-        // TODO figure out which project we are in???
-    }
-
-    public void launch(IEditorPart editor, String mode) {
-        IEditorInput input = editor.getEditorInput();
-        IJavaElement je = (IJavaElement) input.getAdapter(IJavaElement.class);
-        if (je != null) {
-            IJavaProject jproject = je.getJavaProject();
-            if (jproject != null) {
-                launch(jproject, mode);
-            }
-        }
-    }
-
-    void launch(IJavaProject project, String mode) {
-        try {
-            ILaunchConfiguration config = find(project);
-            if (config == null)
-                config = createConfiguration(project);
-            
-            DebugUITools.launch(config, mode);
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-
-    ILaunchConfigurationType getConfigurationType() {
-        return getLaunchManager()
-                .getLaunchConfigurationType("aQute.bnd.launch");
-    }
-
-    ILaunchConfiguration find(IJavaProject project) throws CoreException {
-        List<ILaunchConfiguration> candidateConfigs = new ArrayList<ILaunchConfiguration>();
-        ILaunchConfiguration[] configs = DebugPlugin.getDefault()
-                .getLaunchManager().getLaunchConfigurations(
-                        getConfigurationType());
-
-        for (int i = 0; i < configs.length; i++) {
-            ILaunchConfiguration config = configs[i];
-            if (config
-                    .getAttribute(
-                            IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME,
-                            "").equals(project.getElementName())) { //$NON-NLS-1$
-                candidateConfigs.add(config);
-            }
-        }
-        
-        if (candidateConfigs.size() == 0) {
-        	return null;
-        }
-        // return the latest
-        return candidateConfigs.get(candidateConfigs.size() - 1);
-    }
-
-    protected ILaunchManager getLaunchManager() {
-        return DebugPlugin.getDefault().getLaunchManager();
-    }
-
-    protected ILaunchConfiguration createConfiguration(IJavaProject type)
-            throws Exception {
-        ILaunchConfiguration config = null;
-        ILaunchConfigurationWorkingCopy wc = null;
-        ILaunchConfigurationType configType = getConfigurationType();
-        wc = configType.newInstance(null, getLaunchManager()
-                .generateUniqueLaunchConfigurationNameFrom(
-                        type.getElementName()));
-        wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME,
-                type.getElementName());
-        config = wc.doSave();
-        return config;
-    }
-
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/libsync/LibSync.java b/biz.aQute.bnd/src/aQute/bnd/libsync/LibSync.java
deleted file mode 100644
index 17e144b..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/libsync/LibSync.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package aQute.bnd.libsync;
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-
-import aQute.lib.osgi.*;
-
-public class LibSync extends Processor {
-	URL url; 
-	
-	
-	public LibSync() {
-		
-	}
-	
-	public LibSync(Processor parent) {
-		super(parent);
-	}
-	
-	
-	public void submit(Jar jar) throws Exception {
-
-		String host = getProperty("libsync.repo", "http://libsync.com/repo");
-
-		try {
-			URL url = new URL(host);
-			Verifier v = new Verifier(jar);
-			v.setPedantic(true);
-			v.verify();
-			getInfo(v);
-			if (isOk() && v.getWarnings().isEmpty()) {
-				send0(jar, url);
-			}
-		} catch (MalformedURLException e) {
-			error("The libsync.repo property does not contain a proper URL %s, exception: %s",
-					host, e);
-		} catch (Exception e) {
-			error("Submission of %s to %s failed even after retrying", host, jar.getName());
-		}
-	}
-
-	Jar send0(Jar jar, URL url) throws Exception {
-		int retries = Integer.parseInt(getProperty("libsync.retries", "3"));
-
-		for (int i = 0; i < retries - 1; i++) {
-			try {
-				return send1(jar, url);
-			} catch (Exception e) {
-				warning("Submission failed %s, will retry (%d times defined in libsync.retries)",
-						e, retries);
-				Thread.sleep(i * 1000);
-			}
-		}
-		return send1(jar, url);
-	}
-
-	Jar send1(Jar jar, URL url) throws Exception {
-		HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
-		urlc.setDoOutput(true);
-		urlc.setDoInput(true);
-		trace("Connecting to: %s", url);
-		urlc.setRequestMethod("POST");
-		urlc.setRequestProperty("Content-Type", "application/binary");
-
-		urlc.connect();
-
-		OutputStream out = urlc.getOutputStream();
-		try {
-			jar.write(out);
-		} finally {
-			out.close();
-		}
-		trace("Submitted: %s to %s", jar.getName(), url);
-
-		InputStream in = urlc.getInputStream();
-		try {
-			Jar result = new Jar(url.toExternalForm(), in);
-			addClose(result);
-			trace("Received: %s", result.getName());
-			Resource errors = result.getResource("META-INF/errors");
-			Resource warnings = result.getResource("META-INF/warnings");
-			if (errors != null)
-				parse(errors.openInputStream(), url.getFile(), getErrors());
-			if (warnings != null)
-				parse(warnings.openInputStream(), url.getFile(), getWarnings());
-			return result;
-		} finally {
-			in.close();
-		}
-	}
-
-	private void parse(InputStream in, String prefix, List<String> to) throws Exception {
-		try {
-			InputStreamReader r = new InputStreamReader(in, Constants.DEFAULT_CHARSET);
-			BufferedReader br = new BufferedReader(r);
-			String line = br.readLine();
-			while (line != null) {
-				to.add(prefix + line);
-				line = br.readLine();
-			}
-		} finally {
-			in.close();
-		}
-	}
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/main/BaselineCommands.java b/biz.aQute.bnd/src/aQute/bnd/main/BaselineCommands.java
new file mode 100644
index 0000000..ea9a188
--- /dev/null
+++ b/biz.aQute.bnd/src/aQute/bnd/main/BaselineCommands.java
@@ -0,0 +1,430 @@
+package aQute.bnd.main;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.jar.*;
+
+import javax.xml.transform.*;
+import javax.xml.transform.stream.*;
+
+import aQute.bnd.differ.*;
+import aQute.bnd.differ.Baseline.Info;
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Descriptors.PackageRef;
+import aQute.bnd.service.diff.*;
+import aQute.bnd.version.*;
+import aQute.lib.collections.*;
+import aQute.lib.getopt.*;
+import aQute.lib.tag.*;
+
+/**
+ * Implements commands to maintain the Package versions db.
+ */
+public class BaselineCommands {
+	static TransformerFactory	transformerFactory	= TransformerFactory.newInstance();
+	final bnd					bnd;
+	final Baseline				baseline;
+	final DiffPluginImpl		differ				= new DiffPluginImpl();
+	final Collection<String>	SKIP_HEADERS		= Arrays.asList("Created-By", Constants.BND_LASTMODIFIED,
+															Constants.BUNDLE_MANIFESTVERSION, "Manifest-Version",
+															"Tool");
+
+	BaselineCommands(bnd bnd) throws IOException {
+		this.bnd = bnd;
+		this.baseline = new Baseline(bnd, differ);
+	}
+
+	@Description("Compare a newer bundle to a baselined bundle and provide versioning advice")
+	@Arguments(arg = {
+			"newer jar", "older jar"
+	})
+	interface baseLineOptions extends Options {
+		@Description("Output file with fixup info")
+		String fixup();
+	}
+
+	/**
+	 * Compare
+	 */
+
+	@Description("Compare a newer bundle to a baselined bundle and provide versioning advice")
+	public void _baseline(baseLineOptions opts) throws Exception {
+
+		List<String> args = opts._();
+		if (args.size() != 2) {
+			throw new IllegalArgumentException("Accepts only two argument (<jar>)");
+		}
+		PrintStream out = null;
+
+		if (opts.fixup() != null) {
+			out = new PrintStream(bnd.getFile(opts.fixup()), "UTF-8");
+		}
+
+		File newer = bnd.getFile(args.get(0));
+		if (!newer.isFile())
+			throw new IllegalArgumentException("Not a valid newer input file: " + newer);
+
+		File older = bnd.getFile(args.get(1));
+		if (!older.isFile())
+			throw new IllegalArgumentException("Not a valid older input file: " + older);
+
+		Jar nj = new Jar(newer);
+		Jar oj = new Jar(older);
+		Set<Info> infos = baseline.baseline(nj, oj, null);
+		Info[] sorted = infos.toArray(new Info[infos.size()]);
+		Arrays.sort(sorted, new Comparator<Info>() {
+			public int compare(Info o1, Info o2) {
+				return o1.packageName.compareTo(o2.packageName);
+			}
+		});
+
+		bnd.out.printf("  %-50s %-10s %-10s %-10s %-10s %-10s%n", "Package", "Delta", "New", "Old", "Suggest",
+				"If Prov.");
+		for (Info info : sorted) {
+			bnd.out.printf("%s %-50s %-10s %-10s %-10s %-10s %-10s%n", info.mismatch ? '*' : ' ', info.packageName,
+					info.packageDiff.getDelta(), info.newerVersion, info.olderVersion, info.suggestedVersion,
+					info.suggestedIfProviders == null ? "-" : info.suggestedIfProviders);
+		}
+
+		if (out != null) {
+			// Create a fixup file
+
+			Manifest manifest = nj.getManifest();
+			if (manifest == null)
+				manifest = new Manifest();
+
+			for (Map.Entry<Object,Object> e : manifest.getMainAttributes().entrySet()) {
+				String key = e.getKey().toString();
+
+				if (!SKIP_HEADERS.contains(key)) {
+					if (!Constants.EXPORT_PACKAGE.equals(key)) {
+						out.printf("%-40s = ", key);
+						String value = (String) e.getValue();
+						out.append(value);
+					}
+					out.println();
+				}
+			}
+			doExportPackage(sorted, out);
+			out.close();
+		}
+	}
+
+	/**
+	 * Print out the packages from spec jars and check in which ees they appear.
+	 * Example
+	 * 
+	 * <pre>
+	 * package overview -ee j2se-1.6.0 -ee j2se-1.5.0 -ee j2ee-1.4.0 javax.activation-1.1.jar
+	 * </pre>
+	 */
+	@Description("Print out the packages from spec jars and check in which ees they appear. Very specific. For example, schema -ee j2se-1.6.0 -ee j2se-1.5.0 -ee j2ee-1.4.0 javax.activation-1.1.jar")
+	interface schemaOptions extends Options {
+		@Description("Output file")
+		String output(String deflt);
+
+		@Description("Specify an XSL file for pretty printing")
+		String xsl();
+	}
+
+	class PSpec implements Comparable<PSpec> {
+		String			packageName;
+		Version			version;
+		int				id;
+		public Attrs	attrs;
+		public Tree		tree;
+		public Attrs	uses	= new Attrs();
+
+		public int compareTo(PSpec o) {
+			return version.compareTo(o.version);
+		}
+
+	}
+
+	/**
+	 * Create a schema of a set of jars outling the packages and their versions.
+	 * This will create a list of packages with multiple versions, link to their
+	 * specifications, and the deltas between versions.
+	 * 
+	 * <pre>
+	 *    bnd package schema <file.jar>*
+	 * </pre>
+	 * 
+	 * @param opts
+	 * @throws Exception
+	 */
+	public void _schema(schemaOptions opts) throws Exception {
+		MultiMap<String,PSpec> map = new MultiMap<String,PSpec>();
+
+		Tag top = new Tag("jschema");
+		int n = 1000;
+		for (String spec : opts._()) {
+			File f = bnd.getFile(spec);
+			if (!f.isFile()) {
+				bnd.messages.NoSuchFile_(f);
+			} else {
+
+				// For each specification jar we found
+
+				bnd.trace("spec %s", f);
+				Jar jar = new Jar(f); // spec
+				Manifest m = jar.getManifest();
+				Attributes main = m.getMainAttributes();
+				Tag specTag = new Tag(top, "specification");
+				specTag.addAttribute("jar", spec);
+				specTag.addAttribute("name", main.getValue("Specification-Name"));
+				specTag.addAttribute("title", main.getValue("Specification-Title"));
+				specTag.addAttribute("jsr", main.getValue("Specification-JSR"));
+				specTag.addAttribute("url", main.getValue("Specification-URL"));
+				specTag.addAttribute("version", main.getValue("Specification-Version"));
+				specTag.addAttribute("vendor", main.getValue("Specification-Vendor"));
+				specTag.addAttribute("id", n);
+				specTag.addContent(main.getValue(Constants.BUNDLE_DESCRIPTION));
+
+				Parameters exports = OSGiHeader.parseHeader(m.getMainAttributes().getValue(Constants.EXPORT_PACKAGE));
+
+				// Create a map with versions. Ensure import ranges overwrite
+				// the
+				// exported versions
+				Parameters versions = new Parameters();
+				versions.putAll(exports);
+				versions.putAll(OSGiHeader.parseHeader(m.getMainAttributes().getValue(Constants.IMPORT_PACKAGE)));
+
+				Analyzer analyzer = new Analyzer();
+				analyzer.setJar(jar);
+				analyzer.analyze();
+
+				Tree tree = differ.tree(analyzer);
+
+				for (Entry<String,Attrs> entry : exports.entrySet()) {
+
+					// For each exported package in the specification JAR
+
+					Attrs attrs = entry.getValue();
+					String packageName = entry.getKey();
+					PackageRef packageRef = analyzer.getPackageRef(packageName);
+
+					String version = attrs.get(Constants.VERSION_ATTRIBUTE);
+
+					PSpec pspec = new PSpec();
+					pspec.packageName = packageName;
+					pspec.version = new Version(version);
+					pspec.id = n;
+					pspec.attrs = attrs;
+					pspec.tree = tree;
+
+					Collection<PackageRef> uses = analyzer.getUses().get(packageRef);
+					if (uses != null) {
+						for (PackageRef x : uses) {
+							if (x.isJava())
+								continue;
+
+							String imp = x.getFQN();
+
+							if (imp.equals(packageName))
+								continue;
+							String v = null;
+							if (versions.containsKey(imp))
+								v = versions.get(imp).get(Constants.VERSION_ATTRIBUTE);
+							pspec.uses.put(imp, v);
+						}
+					}
+					map.add(packageName, pspec);
+				}
+				jar.close();
+				n++;
+			}
+		}
+
+		// We now gather all the information about all packages in the map.
+		// Next phase is generating the XML. Sorting the packages is
+		// important because XSLT is brain dead.
+
+		SortedList<String> names = new SortedList<String>(map.keySet());
+
+		Tag packagesTag = new Tag(top, "packages");
+		Tag baselineTag = new Tag(top, "baseline");
+
+		for (String pname : names) {
+
+			// For each distinct package name
+
+			SortedList<PSpec> specs = new SortedList<PSpec>(map.get(pname));
+
+			PSpec older = null;
+			Parameters olderExport = null;
+
+			for (PSpec newer : specs) {
+
+				// For each package in the total set
+
+				Tag pack = new Tag(packagesTag, "package");
+				pack.addAttribute("name", newer.packageName);
+				pack.addAttribute("version", newer.version);
+				pack.addAttribute("spec", newer.id);
+
+				Parameters newerExport = new Parameters();
+				newerExport.put(pname, newer.attrs);
+
+				if (older != null) {
+					String compareId = newer.packageName + "-" + newer.id + "-" + older.id;
+					pack.addAttribute("delta", compareId);
+
+					bnd.trace(" newer=%s older=%s", newerExport, olderExport);
+
+					Set<Info> infos = baseline.baseline(newer.tree, newerExport, older.tree, olderExport,
+							new Instructions(pname));
+
+					for (Info info : infos) {
+						Tag tag = getTag(info);
+						tag.addAttribute("id", compareId);
+						tag.addAttribute("newerSpec", newer.id);
+						tag.addAttribute("olderSpec", older.id);
+						baselineTag.addContent(tag);
+					}
+					older.tree = null;
+					older.attrs = null;
+					older = newer;
+				}
+
+				//
+				// XRef, show the used packages for this package
+				//
+
+				for (Entry<String,String> uses : newer.uses.entrySet()) {
+					Tag reference = new Tag(pack, "import");
+					reference.addAttribute("name", uses.getKey());
+					reference.addAttribute("version", uses.getValue());
+				}
+
+				older = newer;
+				olderExport = newerExport;
+			}
+		}
+
+		String o = opts.output("schema.xml");
+		File of = bnd.getFile(o);
+		File pof = of.getParentFile();
+		if (!pof.exists() && !pof.mkdirs()) {
+			throw new IOException("Could not create directory " + pof);
+		}
+		OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(of), "UTF-8");
+		try {
+			PrintWriter pw = new PrintWriter(fw);
+			try {
+				pw.println("<?xml version='1.0'?>");
+				top.print(0, pw);
+			}
+			finally {
+				pw.close();
+			}
+		}
+		finally {
+			fw.close();
+		}
+
+		if (opts.xsl() != null) {
+			URL home = bnd.getBase().toURI().toURL();
+			URL xslt = new URL(home, opts.xsl());
+			String path = of.getAbsolutePath();
+			if (path.endsWith(".xml"))
+				path = path.substring(0, path.length() - 4);
+
+			path = path + ".html";
+			File html = new File(path);
+			bnd.trace("xslt %s %s %s %s", xslt, of, html, html.exists());
+			FileOutputStream out = new FileOutputStream(html);
+			try {
+				Transformer transformer = transformerFactory.newTransformer(new StreamSource(xslt.openStream()));
+				transformer.transform(new StreamSource(of), new StreamResult(out));
+			}
+			finally {
+				out.close();
+			}
+		}
+	}
+
+	private Tag getTag(Info info) {
+		Tag tag = new Tag("info");
+		tag.addAttribute("name", info.packageName);
+		tag.addAttribute("newerVersion", info.newerVersion);
+		tag.addAttribute("olderVersion", info.olderVersion);
+		tag.addAttribute("suggestedVersion", info.suggestedVersion);
+		tag.addAttribute("suggestedIfProviders", info.suggestedIfProviders);
+		tag.addAttribute("mismatch", info.mismatch);
+		tag.addAttribute("warning", info.warning);
+		StringBuilder sb = new StringBuilder();
+		if (info.packageDiff.getDelta() == Delta.UNCHANGED)
+			tag.addAttribute("equals", "true");
+		else {
+			traverseTag(sb, info.packageDiff, "");
+			String s = sb.toString().trim();
+			if (s.length() != 0) {
+				Tag d = new Tag(tag, "diff", s);
+				d.setCDATA();
+			}
+		}
+		if (info.providers != null)
+			for (String provider : info.providers) {
+				Tag p = new Tag(tag, "provider");
+				p.addAttribute("provider", provider);
+			}
+		return tag;
+	}
+
+	private void traverseTag(StringBuilder sb, Diff diff, String indent) {
+		sb.append(indent);
+		sb.append(diff.toString().trim().replace('\n', ' '));
+		sb.append("\n");
+		if (diff.getDelta() == Delta.ADDED || diff.getDelta() == Delta.REMOVED)
+			return;
+
+		for (Diff child : diff.getChildren()) {
+			if (child.getDelta() != Delta.UNCHANGED && child.getDelta() != Delta.IGNORED)
+				traverseTag(sb, child, indent + " ");
+		}
+	}
+
+	/**
+	 * @param exports
+	 * @param out
+	 * @throws IOException
+	 */
+	public void doExportPackage(Info[] infos, PrintStream out) throws IOException {
+
+		out.printf("# Suggested versions\n%-40s = ", Constants.EXPORT_PACKAGE);
+		String del = "";
+		for (Info info : infos) {
+			out.append(del);
+			out.printf("\\\n  ");
+			out.append(info.packageName);
+			info.attributes.put(Constants.VERSION_ATTRIBUTE, info.suggestedVersion.toString());
+			for (Map.Entry<String,String> clause : info.attributes.entrySet()) {
+				if (clause.getKey().equals(Constants.USES_DIRECTIVE))
+					continue;
+
+				out.append(";\\\n    ");
+				out.append(clause.getKey());
+				out.append("=");
+				Processor.quote(out, clause.getValue());
+			}
+
+			if (info.providers != null && !info.providers.isEmpty()) {
+				out.append(";\\\n    " + Constants.PROVIDER_TYPE_DIRECTIVE + "=\"");
+				String del2 = "";
+				for (String part : info.providers) {
+					out.append(del2);
+					out.append("\\\n        ");
+					out.append(part);
+					del2 = ",";
+				}
+				out.append("\"");
+			}
+			del = ",";
+		}
+	}
+
+}
diff --git a/biz.aQute.bnd/src/aQute/bnd/main/BndMessages.java b/biz.aQute.bnd/src/aQute/bnd/main/BndMessages.java
new file mode 100644
index 0000000..dd2f8c0
--- /dev/null
+++ b/biz.aQute.bnd/src/aQute/bnd/main/BndMessages.java
@@ -0,0 +1,28 @@
+package aQute.bnd.main;
+
+import aQute.bnd.build.*;
+import aQute.service.reporter.*;
+
+public interface BndMessages extends Messages {
+
+	ERROR Failed__(Throwable t, String string);
+
+	ERROR UnrecognizedFileType_(String path);
+
+	ERROR MoreArgumentsThanNeeded_(Iterable<String> args);
+
+	ERROR NoCommandForProject(Project p);
+
+	ERROR NoProject();
+
+	ERROR InvalidBumpMask_(String mask);
+
+	ERROR Project_RunFailed_(Project project, Exception e);
+
+	ERROR ForProject_File_FailedToCreateExecutableException_(Project project, String path, Exception e);
+
+	ERROR NoSuchRepository_(String newer);
+
+	ERROR InvalidGlobPattern_(String pattern);
+
+}
diff --git a/biz.aQute.bnd/src/aQute/bnd/main/DiffCommand.java b/biz.aQute.bnd/src/aQute/bnd/main/DiffCommand.java
new file mode 100644
index 0000000..af6c15a
--- /dev/null
+++ b/biz.aQute.bnd/src/aQute/bnd/main/DiffCommand.java
@@ -0,0 +1,221 @@
+package aQute.bnd.main;
+
+import java.io.*;
+import java.util.*;
+
+import aQute.bnd.differ.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.diff.*;
+import aQute.configurable.*;
+import aQute.lib.getopt.*;
+import aQute.lib.tag.*;
+
+public class DiffCommand {
+	bnd	bnd;
+
+	DiffCommand(bnd bnd) {
+		this.bnd = bnd;
+	}
+
+	@Arguments(arg = {
+			"newer file", "[older file]"
+	})
+	interface diffOptions extends Options {
+		@Config(description = "Print the API")
+		boolean api();
+
+		@Config(description = "Print the Resources")
+		boolean resources();
+
+		@Config(description = "Print the Manifest")
+		boolean manifest();
+
+		@Config(description = "Show full tree")
+		boolean full();
+
+		@Config(description = "Print difference as valid XML")
+		boolean xml();
+
+		@Config(description = "Where to send the output")
+		File output();
+
+		@Config(description = "Limit to these packages")
+		Collection<String> pack();
+	}
+
+	public void diff(diffOptions options) throws Exception {
+
+		if (options._().size() == 1) {
+			bnd.trace("Show tree");
+			showTree(bnd, options);
+			return;
+		}
+		if (options._().size() != 2) {
+			throw new IllegalArgumentException("Requires 2 jar files input");
+		}
+		File fout = options.output();
+		PrintWriter pw = null;
+		Jar newer = null;
+		Jar older = null;
+		try {
+			if (fout == null)
+				pw = new PrintWriter(bnd.out);
+			else
+				pw = new PrintWriter(fout, "UTF-8");
+
+			Instructions packageFilters = new Instructions(options.pack());
+
+			Iterator<String> it = options._().iterator();
+			newer = bnd.getJar(it.next());
+			if (newer == null)
+				return;
+
+			older = bnd.getJar(it.next());
+			if (older == null)
+				return;
+
+			Differ di = new DiffPluginImpl();
+			Tree n = di.tree(newer);
+			Tree o = di.tree(older);
+			Diff diff = n.diff(o);
+
+			boolean all = options.api() == false && options.resources() == false && options.manifest() == false;
+			if (!options.xml()) {
+				if (all || options.api())
+					for (Diff packageDiff : diff.get("<api>").getChildren()) {
+						if (packageFilters.matches(packageDiff.getName()))
+							show(pw, packageDiff, 0, !options.full());
+					}
+				if (all || options.manifest())
+					show(pw, diff.get("<manifest>"), 0, !options.full());
+				if (all || options.resources())
+					show(pw, diff.get("<resources>"), 0, !options.full());
+			} else {
+				Tag tag = new Tag("diff");
+				tag.addAttribute("date", new Date());
+				tag.addContent(getTagFrom("newer", newer));
+				tag.addContent(getTagFrom("older", older));
+				if (all || options.api())
+					tag.addContent(getTagFrom(diff.get("<api>"), !options.full()));
+				if (all || options.manifest())
+					tag.addContent(getTagFrom(diff.get("<manifest>"), !options.full()));
+				if (all || options.resources())
+					tag.addContent(getTagFrom(diff.get("<resources>"), !options.full()));
+
+				pw.println("<?xml version='1.0'?>");
+				tag.print(0, pw);
+			}
+		}
+		finally {
+			if (older != null) {
+				older.close();
+			}
+			if (newer != null) {
+				newer.close();
+			}
+			if (pw != null) {
+				pw.close();
+			}
+		}
+	}
+
+	/**
+	 * Just show the single tree
+	 * 
+	 * @param bnd
+	 * @param options
+	 * @throws Exception
+	 */
+
+	private static void showTree(bnd bnd, diffOptions options) throws Exception {
+		File fout = options.output();
+		PrintWriter pw;
+		if (fout == null)
+			pw = new PrintWriter(bnd.out);
+		else
+			pw = new PrintWriter(fout, "UTF-8");
+
+		Instructions packageFilters = new Instructions(options.pack());
+
+		Jar newer = new Jar(bnd.getFile(options._().get(0)));
+		try {
+			Differ di = new DiffPluginImpl();
+			Tree n = di.tree(newer);
+
+			boolean all = options.api() == false && options.resources() == false && options.manifest() == false;
+
+			if (all || options.api())
+				for (Tree packageDiff : n.get("<api>").getChildren()) {
+					if (packageFilters.matches(packageDiff.getName()))
+						show(pw, packageDiff, 0);
+				}
+			if (all || options.manifest())
+				show(pw, n.get("<manifest>"), 0);
+			if (all || options.resources())
+				show(pw, n.get("<resources>"), 0);
+			pw.close();
+		}
+		finally {
+			newer.close();
+		}
+
+	}
+
+	private static Tag getTagFrom(Diff diff, boolean limited) {
+		if (limited && (diff.getDelta() == Delta.UNCHANGED || diff.getDelta() == Delta.IGNORED))
+			return null;
+
+		Tag tag = new Tag("diff");
+		tag.addAttribute("name", diff.getName());
+		tag.addAttribute("delta", diff.getDelta());
+		tag.addAttribute("type", diff.getType());
+
+		if (limited && (diff.getDelta() == Delta.ADDED || diff.getDelta() == Delta.REMOVED))
+			return tag;
+
+		for (Diff c : diff.getChildren()) {
+			Tag child = getTagFrom(c, limited);
+			if (child != null)
+				tag.addContent(child);
+		}
+		return tag;
+	}
+
+	private static Tag getTagFrom(String name, Jar jar) throws Exception {
+		Tag tag = new Tag(name);
+		tag.addAttribute("bsn", jar.getBsn());
+		tag.addAttribute("name", jar.getName());
+		tag.addAttribute("version", jar.getVersion());
+		tag.addAttribute("lastmodified", jar.lastModified());
+		return tag;
+	}
+
+	public static void show(PrintWriter out, Diff diff, int indent, boolean limited) {
+		if (limited && (diff.getDelta() == Delta.UNCHANGED || diff.getDelta() == Delta.IGNORED))
+			return;
+
+		for (int i = 0; i < indent; i++)
+			out.print(" ");
+
+		out.println(diff.toString());
+
+		if (limited && (diff.getDelta() == Delta.ADDED || diff.getDelta() == Delta.REMOVED))
+			return;
+
+		for (Diff c : diff.getChildren()) {
+			show(out, c, indent + 1, limited);
+		}
+	}
+
+	public static void show(PrintWriter out, Tree tree, int indent) {
+		for (int i = 0; i < indent; i++)
+			out.print(" ");
+
+		out.println(tree.toString());
+
+		for (Tree c : tree.getChildren()) {
+			show(out, c, indent + 1);
+		}
+	}
+
+}
diff --git a/biz.aQute.bnd/src/aQute/bnd/main/PatchCommand.java b/biz.aQute.bnd/src/aQute/bnd/main/PatchCommand.java
new file mode 100644
index 0000000..1fa9c8f
--- /dev/null
+++ b/biz.aQute.bnd/src/aQute/bnd/main/PatchCommand.java
@@ -0,0 +1,137 @@
+package aQute.bnd.main;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+
+import aQute.bnd.osgi.*;
+import aQute.lib.getopt.*;
+import aQute.libg.generics.*;
+
+public class PatchCommand {
+	bnd	bnd;
+
+	public PatchCommand(bnd bnd) {
+		this.bnd = bnd;
+	}
+
+	@Description("WIP")
+	@Arguments(arg = {
+			"<older>", "<newer>", "<patch>"
+	})
+	interface createOptions extends Options {
+
+	}
+
+	public void _create(createOptions opts) throws Exception {
+		List<String> arguments = opts._();
+
+		Jar a = new Jar(bnd.getFile(arguments.remove(0)));
+		Manifest am = a.getManifest();
+
+		Jar b = new Jar(bnd.getFile(arguments.remove(0)));
+		Manifest bm = b.getManifest();
+
+		File patch = bnd.getFile(arguments.remove(0));
+
+		// TODO check arguments
+
+		Set<String> delete = Create.set();
+
+		for (String path : a.getResources().keySet()) {
+			Resource br = b.getResource(path);
+			if (br == null) {
+				bnd.trace("DELETE    %s", path);
+				delete.add(path);
+			} else {
+				Resource ar = a.getResource(path);
+				if (isEqual(ar, br)) {
+					bnd.trace("UNCHANGED %s", path);
+					b.remove(path);
+				} else
+					bnd.trace("UPDATE    %s", path);
+			}
+		}
+
+		bm.getMainAttributes().putValue("Patch-Delete", Processor.join(delete, ", "));
+		bm.getMainAttributes().putValue("Patch-Version", am.getMainAttributes().getValue("Bundle-Version"));
+
+		b.write(patch);
+		a.close();
+		a.close();
+
+		// TODO proper close
+	}
+
+	private boolean isEqual(Resource ar, Resource br) throws Exception {
+		InputStream ain = ar.openInputStream();
+		try {
+			InputStream bin = br.openInputStream();
+			try {
+				while (true) {
+					int an = ain.read();
+					int bn = bin.read();
+					if (an == bn) {
+						if (an == -1)
+							return true;
+					} else
+						return false;
+				}
+			}
+			finally {
+				bin.close();
+			}
+		}
+		finally {
+			ain.close();
+		}
+	}
+
+	@Description("WIP")
+	@Arguments(arg = {
+			"<older>", "<newer>", "<patch>"
+	})
+	interface applyOptions {
+
+	}
+
+	public void _apply(@SuppressWarnings("unused") applyOptions opts) throws Exception {
+		// List<String> arguments = opts._();
+		// Jar a = new Jar(bnd.getFile(arguments.remove(0)));
+		// Manifest am = a.getManifest();
+		//
+		// Jar b = new Jar(bnd.getFile(arguments.remove(0)));
+		// Manifest bm = b.getManifest();
+		//
+		// File patch = bnd.getFile(arguments.remove(0));
+		// Jar a = new Jar(new File(old));
+		// Jar b = new Jar(new File(patch));
+		// Manifest bm = b.getManifest();
+		//
+		// String patchDelete = bm.getMainAttributes().getValue("Patch-Delete");
+		// String patchVersion =
+		// bm.getMainAttributes().getValue("Patch-Version");
+		// if (patchVersion == null) {
+		// error("To patch, you must provide a patch bundle.\nThe given " +
+		// patch
+		// + " bundle does not contain the Patch-Version header");
+		// return;
+		// }
+		//
+		// Collection<String> delete = split(patchDelete);
+		// Set<String> paths = new HashSet<String>(a.getResources().keySet());
+		// paths.removeAll(delete);
+		//
+		// for (String path : paths) {
+		// Resource br = b.getResource(path);
+		// if (br == null)
+		// b.putResource(path, a.getResource(path));
+		// }
+		//
+		// bm.getMainAttributes().putValue("Bundle-Version", patchVersion);
+		// b.write(new File(newer));
+		// a.close();
+		// b.close();
+	}
+
+}
diff --git a/biz.aQute.bnd/src/aQute/bnd/main/RepoCommand.java b/biz.aQute.bnd/src/aQute/bnd/main/RepoCommand.java
new file mode 100644
index 0000000..bdbcd3d
--- /dev/null
+++ b/biz.aQute.bnd/src/aQute/bnd/main/RepoCommand.java
@@ -0,0 +1,473 @@
+package aQute.bnd.main;
+
+import java.io.*;
+import java.util.*;
+
+import aQute.bnd.build.*;
+import aQute.bnd.differ.*;
+import aQute.bnd.header.*;
+import aQute.bnd.maven.support.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.*;
+import aQute.bnd.service.RepositoryPlugin.PutResult;
+import aQute.bnd.service.diff.*;
+import aQute.bnd.version.*;
+import aQute.lib.collections.*;
+import aQute.lib.deployer.*;
+import aQute.lib.getopt.*;
+import aQute.lib.io.*;
+import aQute.lib.json.*;
+
+public class RepoCommand {
+	final static JSONCodec	codec	= new JSONCodec();
+
+	@Description("Access to the repositories. Provides a number of sub commands to manipulate the repository "
+			+ "(see repo help) that provide access to the installed repos for the current project.")
+	@Arguments(arg = {
+			"sub-cmd", "..."
+	})
+	interface repoOptions extends Options {
+		@Description("Add a File Repository")
+		Collection<String> repo();
+
+		@Description("Include the maven repository")
+		boolean maven();
+
+		@Description("Specify a project")
+		@OptionArgument("<path>")
+		String project();
+
+		@Description("Include the cache repository")
+		boolean cache();
+	}
+
+	final bnd						bnd;
+	final repoOptions				opts;
+	final RepositoryPlugin			writable;
+	final List<RepositoryPlugin>	repos	= new ArrayList<RepositoryPlugin>();
+
+	/**
+	 * Called from the command line
+	 * 
+	 * @param bnd
+	 * @param opts
+	 * @throws Exception
+	 */
+	public RepoCommand(bnd bnd, repoOptions opts) throws Exception {
+		this.opts = opts;
+		this.bnd = bnd;
+
+		// We can include the maven repository
+
+		if (opts.maven()) {
+			bnd.trace("maven");
+			MavenRemoteRepository maven = new MavenRemoteRepository();
+			maven.setProperties(new Attrs());
+			maven.setReporter(bnd);
+			repos.add(maven);
+		}
+
+		// Repos given by the --repo option
+
+		if (opts.repo() != null) {
+			for (String r : opts.repo()) {
+				bnd.trace("file repo " + r);
+				FileRepo repo = new FileRepo();
+				repo.setReporter(bnd);
+				File location = bnd.getFile(r);
+				repo.setLocation(location.getAbsolutePath());
+				repos.add(repo);
+			}
+		}
+
+		// If no repos are set
+		if (repos.isEmpty()) {
+			bnd.trace("getting project repos");
+			Project p = bnd.getProject(opts.project());
+			if (p != null) {
+				repos.addAll(p.getWorkspace().getRepositories());
+			}
+		}
+		bnd.trace("repos " + repos);
+
+		// Clean up and find first writable
+		RepositoryPlugin w = null;
+		for (Iterator<RepositoryPlugin> rp = repos.iterator(); rp.hasNext();) {
+			RepositoryPlugin rpp = rp.next();
+
+			// Check for the cache
+			if (!opts.cache() && rpp.getName().equals("cache")) {
+				rp.remove();
+			}
+			if (w == null && rpp.canWrite()) {
+				w = rpp;
+			}
+		}
+		this.writable = w;
+		bnd.trace("writable " + w);
+
+		List<String> args = opts._();
+		if (args.size() == 0) {
+			// Default command
+			_repos(null);
+		} else {
+			// Other commands
+			String cmd = args.remove(0);
+			String help = opts._command().execute(this, cmd, args);
+			if (help != null) {
+				bnd.out.print(help);
+			}
+		}
+	}
+
+	/**
+	 * List the repos
+	 */
+	@Arguments(arg = {})
+	@Description("List the current repositories")
+	interface reposOptions extends Options {}
+
+	@Description("List the current repositories")
+	public void _repos(@SuppressWarnings("unused")
+	reposOptions opts) {
+		int n = 1;
+		for (RepositoryPlugin repo : repos) {
+			String location = "";
+			try {
+				location = repo.getLocation();
+			}
+			catch (Throwable e) {
+				// Ignore
+			}
+			bnd.out.printf("%03d: %-20s %4s %-20s %s%n", n++, repo.getName(), repo.canWrite() ? "r/w" : "r/o",
+					Descriptors.getShortName(repo.getClass().getName()), location);
+		}
+	}
+
+	/**
+	 * List the content of the repos
+	 */
+	@Description("List all artifacts from the current repositories with their versions")
+	@Arguments(arg = {})
+	interface listOptions extends Options {
+
+		@Description("Do not list the versions, just the bsns")
+		boolean noversions();
+
+		@Description("Optional search term for the list of bsns (given to the repo)")
+		String query();
+
+		@Description("A glob expression on the source repo, default is all repos")
+		Instruction from();
+	}
+
+	@Description("List all artifacts from the current repositories with their versions")
+	public void _list(listOptions opts) throws Exception {
+		bnd.trace("list");
+		Set<String> bsns = new HashSet<String>();
+		Instruction from = opts.from();
+		if (from == null)
+			from = new Instruction("*");
+
+		for (RepositoryPlugin repo : repos) {
+			if (from.matches(repo.getName()))
+				bsns.addAll(repo.list(opts.query()));
+		}
+		bnd.trace("list " + bsns);
+
+		for (String bsn : new SortedList<String>(bsns)) {
+			if (!opts.noversions()) {
+				Set<Version> versions = new TreeSet<Version>();
+				for (RepositoryPlugin repo : repos) {
+					bnd.trace("get " + bsn + " from " + repo);
+					if (from.matches(repo.getName())) {
+						SortedSet<Version> result = repo.versions(bsn);
+						if (result != null)
+							versions.addAll(result);
+					}
+				}
+				bnd.out.printf("%-40s %s%n", bsn, versions);
+			} else {
+				bnd.out.printf("%s%n", bsn);
+			}
+		}
+	}
+
+	/**
+	 * get a file from the repo
+	 * 
+	 * @param opts
+	 */
+
+	@Description("Get an artifact from a repository.")
+	@Arguments(arg = {
+			"bsn", "[range]"
+	})
+	interface getOptions extends Options {
+		@Description("Where to store the artifact")
+		String output();
+
+		@Description("")
+		boolean lowest();
+
+		Instruction from();
+	}
+
+	@Description("Get an artifact from a repository.")
+	public void _get(getOptions opts) throws Exception {
+		Instruction from = opts.from();
+		if (from == null)
+			from = new Instruction("*");
+
+		List<String> args = opts._();
+		if (args.isEmpty()) {
+			bnd.error("Get needs at least a bsn");
+			return;
+		}
+
+		String bsn = args.remove(0);
+		String range = null;
+
+		if (!args.isEmpty()) {
+			range = args.remove(0);
+			if (!args.isEmpty()) {
+				bnd.error("Extra args %s", args);
+			}
+		}
+
+		VersionRange r = new VersionRange(range == null ? "0" : range);
+		Map<Version,RepositoryPlugin> index = new HashMap<Version,RepositoryPlugin>();
+
+		for (RepositoryPlugin repo : repos) {
+			if (from.matches(repo.getName())) {
+				SortedSet<Version> versions = repo.versions(bsn);
+				if (versions != null)
+					for (Version v : versions) {
+						if (r.includes(v))
+							index.put(v, repo);
+					}
+			}
+		}
+
+		SortedList<Version> l = new SortedList<Version>(index.keySet());
+		if (l.isEmpty()) {
+			bnd.out.printf("No versions found for %s%n", bsn);
+			return;
+		}
+
+		Version v;
+		if (opts.lowest())
+			v = l.first();
+		else
+			v = l.last();
+
+		RepositoryPlugin repo = index.get(v);
+		File file = repo.get(bsn, v, null);
+
+		File dir = bnd.getBase();
+		String name = file.getName();
+
+		if (opts.output() != null) {
+			File f = bnd.getFile(opts.output());
+			if (f.isDirectory())
+				dir = f;
+			else {
+				dir = f.getParentFile();
+				name = f.getName();
+			}
+		}
+
+		if (!dir.exists() && !dir.mkdirs()) {
+			throw new IOException("Could not create directory " + dir);
+		}
+		IO.copy(file, new File(dir, name));
+	}
+
+	/**
+	 * put
+	 */
+
+	@Description("Put an artifact into the repository after it has been verified.")
+	@Arguments(arg = {
+		"<jar>..."
+	})
+	interface putOptions extends Options {
+		@Description("Put in repository even if verification fails (actually, no verification is done).")
+		boolean force();
+	}
+
+	@Description("Put an artifact into the repository after it has been verified.")
+	public void _put(putOptions opts) throws Exception {
+		if (writable == null) {
+			bnd.error("No writable repository in %s", repos);
+			return;
+		}
+
+		List<String> args = opts._();
+		if (args.isEmpty()) {
+			bnd.out.println("Writable repo is " + writable.getName() + " (" + writable.getLocation() + ")");
+			return;
+		}
+
+		while (args.size() > 0) {
+			File file = bnd.getFile(args.remove(0));
+			if (!file.isFile()) {
+				bnd.error("No such file %s", file);
+			} else {
+
+				bnd.trace("put %s", file);
+
+				Jar jar = new Jar(file);
+				try {
+					String bsn = jar.getBsn();
+					if (bsn == null) {
+						bnd.error("File %s is not a bundle (it has no bsn) ", file);
+						return;
+					}
+
+					bnd.trace("bsn %s version %s", bsn, jar.getVersion());
+
+					if (!opts.force()) {
+						Verifier v = new Verifier(jar);
+						v.setTrace(true);
+						v.setExceptions(true);
+						v.verify();
+						bnd.getInfo(v);
+					}
+
+					if (bnd.isOk()) {
+						PutResult r = writable.put(new BufferedInputStream(new FileInputStream(file)),
+								new RepositoryPlugin.PutOptions());
+						bnd.trace("put %s in %s (%s) into %s", file, writable.getName(), writable.getLocation(),
+								r.artifact);
+					}
+				}
+				finally {
+					jar.close();
+				}
+			}
+		}
+	}
+
+	@Arguments(arg = {
+			"newer repo", "[older repo]"
+	})
+	@Description("Show the diff tree of a single repo or compare 2  repos. A diff tree is a "
+			+ "detailed tree of all aspects of a bundle, including its packages, types, methods, "
+			+ "fields, and modifiers.")
+	interface diffOptions extends Options {
+		@Description("Serialize to JSON")
+		boolean json();
+
+		@Description("Show full diff tree (also wen entries are equal)")
+		boolean full();
+
+		@Description("Formatted like diff")
+		boolean diff();
+
+		@Description("Both add and removes")
+		boolean all();
+
+		@Description("Just removes (no additions)")
+		boolean remove();
+
+		@Description("Just additions (no removes)")
+		boolean added();
+	}
+
+	@Description("Diff jars (or show tree)")
+	public void _diff(diffOptions options) throws UnsupportedEncodingException, IOException, Exception {
+
+		List<String> _ = options._();
+		String newer = _.remove(0);
+		String older = _.size() > 0 ? _.remove(0) : null;
+
+		RepositoryPlugin rnewer = findRepo(newer);
+		RepositoryPlugin rolder = older == null ? null : findRepo(older);
+
+		if (rnewer == null) {
+			bnd.messages.NoSuchRepository_(newer);
+			return;
+		}
+		if (older != null && rolder == null) {
+			bnd.messages.NoSuchRepository_(newer);
+			return;
+		}
+
+		PrintWriter pw = new PrintWriter(new OutputStreamWriter(bnd.out, "UTF-8"));
+		Tree tNewer = RepositoryElement.getTree(rnewer);
+		if (rolder == null) {
+			if (options.json())
+				codec.enc().to(new OutputStreamWriter(bnd.out, "UTF-8")).put(tNewer.serialize()).flush();
+			else
+				DiffCommand.show(pw, tNewer, 0);
+		} else {
+			Tree tOlder = RepositoryElement.getTree(rolder);
+			Diff diff = new DiffImpl(tNewer, tOlder);
+			MultiMap<String,String> map = new MultiMap<String,String>();
+			for (Diff bsn : diff.getChildren()) {
+
+				for (Diff version : bsn.getChildren()) {
+					if (version.getDelta() == Delta.UNCHANGED)
+						continue;
+
+					if (options.remove() == false && options.added() == false
+							|| (options.remove() //
+							&& version.getDelta() == Delta.REMOVED)
+							|| (options.added() && version.getDelta() == Delta.ADDED)) {
+
+						map.add(bsn.getName(), version.getName());
+					}
+				}
+			}
+
+			if (options.json())
+				codec.enc().to(new OutputStreamWriter(bnd.out, "UTF-8")).put(map).flush();
+			else if (!options.diff())
+				bnd.printMultiMap(map);
+			else
+				DiffCommand.show(pw, diff, 0, !options.full());
+		}
+		pw.flush();
+	}
+
+	private RepositoryPlugin findRepo(String name) {
+		for (RepositoryPlugin repo : repos) {
+			if (repo.getName().equals(name))
+				return repo;
+		}
+		return null;
+	}
+
+	@Description("Refresh refreshable repositories")
+	@Arguments(arg = {})
+	interface RefreshOptions extends Options {
+
+	}
+
+	@Description("Refresh refreshable repositories")
+	public void _refresh(RefreshOptions opts) throws Exception {
+		for (Object o : repos) {
+			if (o instanceof Refreshable) {
+				bnd.trace("refresh %s", o);
+				((Refreshable) o).refresh();
+			}
+		}
+	}
+
+	@Description("Displays a sorted set of versions for a given bsn that can be found in the current repositories.")
+	@Arguments(arg = "bsn")
+	interface VersionsOptions extends Options {
+
+	}
+
+	@Description("Displays a list of versions for a given bsn that can be found in the current repositories.")
+	public void _versions(VersionsOptions opts) throws Exception {
+		TreeSet<Version> versions = new TreeSet<Version>();
+		String bsn = opts._().remove(0);
+		for (RepositoryPlugin repo : repos) {
+			versions.addAll(repo.versions(bsn));
+		}
+		bnd.out.println(versions);
+	}
+}
diff --git a/biz.aQute.bnd/src/aQute/bnd/main/bnd.java b/biz.aQute.bnd/src/aQute/bnd/main/bnd.java
index 62c7d1e..1138188 100755
--- a/biz.aQute.bnd/src/aQute/bnd/main/bnd.java
+++ b/biz.aQute.bnd/src/aQute/bnd/main/bnd.java
@@ -1,10 +1,13 @@
 package aQute.bnd.main;
 
 import java.io.*;
+import java.lang.reflect.*;
 import java.net.*;
+import java.security.*;
 import java.util.*;
+import java.util.Map.Entry;
 import java.util.jar.*;
-import java.util.prefs.*;
+import java.util.jar.Attributes.Name;
 import java.util.regex.*;
 import java.util.zip.*;
 
@@ -17,882 +20,1670 @@ import javax.xml.xpath.*;
 import org.w3c.dom.*;
 
 import aQute.bnd.build.*;
-import aQute.bnd.concurrent.*;
-import aQute.bnd.libsync.*;
+import aQute.bnd.header.*;
+import aQute.bnd.help.*;
+import aQute.bnd.main.BaselineCommands.baseLineOptions;
+import aQute.bnd.main.BaselineCommands.schemaOptions;
+import aQute.bnd.main.DiffCommand.diffOptions;
+import aQute.bnd.main.RepoCommand.repoOptions;
 import aQute.bnd.maven.*;
-import aQute.bnd.service.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Clazz.Def;
+import aQute.bnd.osgi.Descriptors.PackageRef;
+import aQute.bnd.osgi.Descriptors.TypeRef;
+import aQute.bnd.osgi.Verifier;
+import aQute.bnd.osgi.eclipse.*;
 import aQute.bnd.service.action.*;
-import aQute.bnd.settings.*;
-import aQute.lib.deployer.*;
+import aQute.bnd.version.*;
+import aQute.configurable.*;
+import aQute.lib.base64.*;
+import aQute.lib.codec.*;
+import aQute.lib.collections.*;
+import aQute.lib.filter.*;
+import aQute.lib.getopt.*;
+import aQute.lib.hex.*;
 import aQute.lib.io.*;
-import aQute.lib.jardiff.*;
-import aQute.lib.osgi.*;
-import aQute.lib.osgi.eclipse.*;
+import aQute.lib.json.*;
+import aQute.lib.justif.*;
+import aQute.lib.settings.*;
 import aQute.lib.tag.*;
+import aQute.libg.classdump.*;
+import aQute.libg.cryptography.*;
 import aQute.libg.generics.*;
-import aQute.libg.version.*;
+import aQute.libg.glob.*;
+import aQute.libg.qtokens.*;
+import aQute.libg.reporter.*;
 
 /**
- * Utility to make bundles.
- * 
- * TODO Add Javadoc comment for this type.
+ * Utility to make bundles. Should be areplace for jar and much more.
  * 
  * @version $Revision: 1.14 $
  */
 public class bnd extends Processor {
-	Settings		settings	= new Settings();
-	PrintStream		out			= System.out;
-	static boolean	exceptions	= false;
+	static Pattern				ASSIGNMENT	= Pattern.compile("\\s*([-\\w\\d_.]+)\\s*(?:=\\s*([^\\s]+)\\s*)?");
+	Settings					settings	= new Settings();
+	final PrintStream			err			= System.err;
+	final public PrintStream	out			= System.out;
+	Justif						justif		= new Justif(80, 40, 42, 70);
+	BndMessages					messages	= ReporterMessages.base(this, BndMessages.class);
 
-	static boolean	failok		= false;
-	private Project	project;
+	static Pattern				JARCOMMANDS	= Pattern.compile("(cv?0?(m|M)?f?)|(uv?0?M?f?)|(xv?f?)|(tv?f?)|(i)");
 
-	public static void main(String args[]) {
-		bnd main = new bnd();
+	static Pattern				COMMAND		= Pattern.compile("\\w[\\w\\d]+");
 
-		try {
-			main.run(args);
-			if (bnd.failok)
-				return;
+	@Description("OSGi Bundle Tool")
+	interface bndOptions extends Options {
+		@Description("Turns errors into warnings so command always succeeds")
+		boolean failok();
 
-			System.exit(main.getErrors().size());
+		@Description("Report errors pedantically")
+		boolean pedantic();
 
-		} catch (Exception e) {
-			System.err.println("Software error occurred " + e);
-			if (exceptions)
-				e.printStackTrace();
-		}
-		System.exit(-1);
-	}
+		@Description("Print out stack traces when there is an unexpected exception")
+		boolean exceptions();
 
-	void run(String[] args) throws Exception {
-		int i = 0;
+		@Description("Redirect output")
+		File output();
 
-		try {
-			for (; i < args.length; i++) {
-				if ("-failok".equals(args[i])) {
-					failok = true;
-				} else if ("-exceptions".equals(args[i])) {
-					exceptions = true;
-				} else if ("-trace".equals(args[i])) {
-					setTrace(true);
-				} else if ("-pedantic".equals(args[i])) {
-					setPedantic(true);
-				} else if (args[i].indexOf('=') > 0) {
-					String parts[] = args[i].split("\\s*(?!\\\\)=\\s*");
-					if (parts.length == 2)
-						setProperty(parts[0], parts[1]);
-					else
-						error("invalid property def: %s", args[i]);
-				} else if ("-base".equals(args[i])) {
-					setBase(new File(args[++i]).getAbsoluteFile());
-					if (!getBase().isDirectory()) {
-						out.println("-base must be a valid directory");
-					} else if (args[i].startsWith("-"))
-						error("Invalid option: ", args[i]);
-				} else
-					break;
-			}
+		@Description("Use as base directory")
+		String base();
 
-			project = getProject();
-			if (project != null) {
-				setParent(project);
-				project.setPedantic(isPedantic());
-				project.setTrace(isTrace());
-			}
-			trace("project = %s", project);
+		@Description("Trace progress")
+		boolean trace();
 
-			if (i >= args.length) {
-				if (project != null && project.isValid()) {
-					trace("default build of current project");
-					project.build();
-				} else
-					doHelp();
-			} else {
-				if (!doProject(project, args, i)) {
-					if (!doCommand(args, i)) {
-						doFiles(args, i);
-					}
-				}
-			}
-		} catch (Throwable t) {
-			if (exceptions)
-				t.printStackTrace();
-			error("exception %s", t, t);
-		}
-
-		int n = 1;
-		switch (getErrors().size()) {
-		case 0:
-			// System.err.println("No errors");
-			break;
-		case 1:
-			System.err.println("One error");
-			break;
-		default:
-			System.err.println(getErrors().size() + " errors");
-		}
-		for (String msg : getErrors()) {
-			System.err.println(n++ + " : " + msg);
-		}
-		n = 1;
-		switch (getWarnings().size()) {
-		case 0:
-			// System.err.println("No warnings");
-			break;
-		case 1:
-			System.err.println("One warning");
-			break;
-		default:
-			System.err.println(getWarnings().size() + " warnings");
-		}
-		for (String msg : getWarnings()) {
-			System.err.println(n++ + " : " + msg);
-		}
-
-		if (getErrors().size() != 0) {
-			System.err.flush();
-			System.out.flush();
-			Thread.sleep(1000);
-			System.exit(getErrors().size());
-		}
-	}
+		@Description("Error/Warning ignore patterns")
+		String[] ignore();
 
-	boolean doProject(Project project, String[] args, int i) throws Exception {
-		if (project != null) {
-			trace("project command %s", args[i]);
-			Action a = project.getActions().get(args[i]);
-			if (a != null) {
-				a.execute(project, args[i++]);
-				getInfo(project);
-				return true;
-			}
-		}
-		return false;
-	}
-
-	boolean doCommand(String args[], int i) throws Exception {
-		String cmd = args[i];
-		trace("command %s", cmd);
-		if ("wrap".equals(args[i])) {
-			doWrap(args, ++i);
-		} else if ("maven".equals(args[i])) {
-			MavenCommand maven = new MavenCommand(this);
-			maven.setTrace(isTrace());
-			maven.setPedantic(isPedantic());
-			maven.run(args, ++i);
-			getInfo(maven);
-		} else if ("global".equals(args[i])) {
-			global(args, ++i);
-		} else if ("exec".equals(args[i])) {
-			doRun(args[++i]);
-		} else if ("print".equals(args[i])) {
-			doPrint(args, ++i);
-		} else if ("lib".equals(args[i])) {
-			doLib(args, ++i);
-		} else if ("graph".equals(args[i])) {
-			doDot(args, ++i);
-		} else if ("create-repo".equals(args[i])) {
-			createRepo(args, ++i);
-		} else if ("release".equals(args[i])) {
-			doRelease(args, ++i);
-		} else if ("debug".equals(args[i])) {
-			debug(args, ++i);
-		} else if ("bump".equals(args[i])) {
-			bump(args, ++i);
-		} else if ("deliverables".equals(args[i])) {
-			deliverables(args, ++i);
-		} else if ("view".equals(args[i])) {
-			doView(args, ++i);
-		} else if ("buildx".equals(args[i])) {
-			doBuild(args, ++i);
-		} else if ("extract".equals(args[i])) {
-			doExtract(args, ++i);
-		} else if ("patch".equals(args[i])) {
-			patch(args, ++i);
-		} else if ("runtests".equals(args[i])) {
-			runtests(args, ++i);
-		} else if ("xref".equals(args[i])) {
-			doXref(args, ++i);
-		} else if ("eclipse".equals(args[i])) {
-			doEclipse(args, ++i);
-		} else if ("repo".equals(args[i])) {
-			repo(args, ++i);
-		} else if ("diff".equals(args[i])) {
-			doDiff(args, ++i);
-		} else if ("help".equals(args[i])) {
-			doHelp(args, ++i);
-		} else if ("macro".equals(args[i])) {
-			doMacro(args, ++i);
-		} else if ("multibuild".equals(args[i])) {
-			doMulti(args, ++i);
-		} else if ("merge".equals(args[i])) {
-			doMerge(args, ++i);
-		} else {
-			trace("command %s not found", cmd);
-			return false;
-		}
-
-		trace("command %s executed", cmd);
-		return true;
-	}
-
-	private void doMulti(String[] args, int i) throws Exception {
-//		Project p = getProject();
-//		Workspace workspace;
-//
-//		if (p != null)
-//			workspace = p.getWorkspace();
-//		else
-//			workspace = Workspace.getWorkspace(getBase());
-//
-//		trace("Starting multibuild");
-//		MultiBuilder multiBuilder = new MultiBuilder(workspace);
-//		multiBuilder.startBuild();
-//		
-//		trace("Syncing multibuild");
-//		multiBuilder.syncBuild();
-//		trace("Synced");
-//		if ( p != null) {
-//			trace("Build %s", (Object) p.build());
-//		}
-	}
-
-	boolean doFiles(String args[], int i) throws Exception {
-		while (i < args.length) {
-			String path = args[i];
-			if (path.endsWith(Constants.DEFAULT_BND_EXTENSION))
-				doBuild(getFile(path), new File[0], new File[0], null, "",
-						new File(path).getParentFile(), 0, new HashSet<File>());
-			else if (path.endsWith(Constants.DEFAULT_JAR_EXTENSION)
-					|| path.endsWith(Constants.DEFAULT_BAR_EXTENSION))
-				doPrint(path, -1);
-			else if (path.endsWith(Constants.DEFAULT_BNDRUN_EXTENSION))
-				doRun(path);
-			else
-				error("Unknown file %s", path);
-			i++;
-		}
-		return true;
 	}
 
-	private void doRun(String path) throws Exception {
-		File file = getFile(path);
-		if (!file.isFile())
-			throw new FileNotFoundException(path);
-
-		File projectDir = file.getParentFile();
-		File workspaceDir = projectDir.getParentFile();
-		if (workspaceDir == null) {
-			workspaceDir = new File(System.getProperty("user.home") + File.separator + ".bnd");
-		}
-		Workspace ws = Workspace.getWorkspace(workspaceDir);
-
-		File bndbnd = new File(projectDir, Project.BNDFILE);
-		Project project;
-		if (bndbnd.isFile()) {
-			project = new Project(ws, projectDir, bndbnd);
-			project.doIncludeFile(file, true, project.getProperties());
-		} else
-			project = new Project(ws, projectDir, file);
-
-		project.setTrace(isTrace());
-		project.setPedantic(isPedantic());
+	public static void main(String args[]) throws Exception {
+		bnd main = new bnd();
 		try {
-			project.run();
-
-		} catch (Exception e) {
-			error("Failed to run %s: %s", project, e);
-		}
-		getInfo(project);
-	}
-
-	private void bump(String[] args, int i) throws Exception {
-		if (getProject() == null) {
-			error("No project found, use -base <dir> bump");
-			return;
+			main.start(args);
 		}
-
-		String mask = null;
-		if (args.length > i) {
-			mask = args[i];
-			if (mask.equalsIgnoreCase("major"))
-				mask = "+00";
-			else if (mask.equalsIgnoreCase("minor"))
-				mask = "=+0";
-			else if (mask.equalsIgnoreCase("micro"))
-				mask = "==+";
-			else if (!mask.matches("(+=0){1,3}")) {
-				error("Invalid mask for version bump %s, is (minor|major|micro|<mask>), see $version for mask",
-						mask);
-				return;
-			}
+		finally {
+			main.close();
 		}
-		if (mask == null)
-			getProject().bump();
-		else
-			getProject().bump(mask);
+	}
 
-		out.println(getProject().getProperty(BUNDLE_VERSION, "No version found"));
+	public void start(String args[]) throws Exception {
+		CommandLine cl = new CommandLine(this);
+		String help = cl.execute(this, "bnd", new ExtList<String>(args));
+		check();
+		if (help != null)
+			err.println(help);
 	}
 
 	/**
-	 * Take the current project, calculate its dependencies from the repo and
-	 * create a mini-repo from it that can easily be unzipped.
+	 * Rewrite the command line to mimic the jar command
 	 * 
 	 * @param args
-	 * @param i
 	 * @throws Exception
 	 */
-	private void createRepo(String[] args, int i) throws Exception {
-		Project project = getProject();
-		if (project == null) {
-			error("not in a proper bnd project ... " + getBase());
+	private void rewrite(List<String> args) throws Exception {
+		if (args.isEmpty())
 			return;
-		}
 
-		File out = getFile(project.getName() + ".repo.jar");
-		List<Instruction> skip = Create.list();
-
-		while (i < args.length) {
-			if (args[i].equals("-o")) {
-				i++;
-				if (i < args.length)
-					out = getFile(args[i]);
-				else
-					error("No arg for -out");
-			} else if (args[i].equals("-skip")) {
-				i++;
-				if (i < args.length) {
-					Instruction instr = Instruction.getPattern(args[i]);
-					skip.add(instr);
-				} else
-					error("No arg for -skip");
-			} else
-				error("invalid arg for create-repo %s", args[i]);
-			i++;
-		}
-
-		Jar output = new Jar(project.getName());
-		output.setDoNotTouchManifest();
-		addClose(output);
-		getInfo(project);
-		if (isOk()) {
-			for (Container c : project.getBuildpath()) {
-				addContainer(skip, output, c);
-			}
-			for (Container c : project.getRunbundles()) {
-				addContainer(skip, output, c);
-			}
-			if (isOk()) {
-				try {
-					output.write(out);
-				} catch (Exception e) {
-					error("Could not write mini repo %s", e);
-				}
-			}
+		String arg = args.get(0);
+		if (arg.equals("maven")) {
+			// ensure that we do not much with options
+			// because the maven command does not like
+			// that
+			args.add(0, "maven");
+			return;
 		}
-	}
-
-	private void addContainer(Collection<Instruction> skip, Jar output, Container c)
-			throws Exception {
-		trace("add container " + c);
-		String prefix = "cnf/repo/";
-
-		switch (c.getType()) {
-		case ERROR:
-			error("Dependencies include %s", c.getError());
+		Matcher m = JARCOMMANDS.matcher(arg);
+		if (m.matches()) {
+			rewriteJarCmd(args);
 			return;
+		}
 
-		case REPO:
-		case EXTERNAL: {
-			String name = getName(skip, prefix, c, ".jar");
-			if (name != null)
-				output.putResource(name, new FileResource(c.getFile()));
-			trace("storing %s in %s", c, name);
-			break;
-		}
-
-		case PROJECT:
-			trace("not storing project " + c);
-			break;
-
-		case LIBRARY: {
-			String name = getName(skip, prefix, c, ".lib");
-			if (name != null) {
-				output.putResource(name, new FileResource(c.getFile()));
-				trace("store library %s", name);
-				for (Container child : c.getMembers()) {
-					trace("store member %s", child);
-					addContainer(skip, output, child);
-				}
+		Project project = getProject();
+		if (project != null) {
+			Action a = project.getActions().get(arg);
+			if (a != null) {
+				args.add(0, "project");
 			}
 		}
+
+		m = COMMAND.matcher(args.get(0));
+		if (!m.matches()) {
+			args.add(0, "do");
 		}
+
 	}
 
-	String getName(Collection<Instruction> skip, String prefix, Container c, String extension)
-			throws Exception {
-		Manifest m = c.getManifest();
-		try {
-			if (m == null) {
-				error("No manifest found for %s", c);
-				return null;
-			}
-			String bsn = m.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME);
-			if (bsn == null) {
-				error("No bsn in manifest: %s", c);
-				return null;
-			}
-			for (Instruction instr : skip) {
-				if (instr.matches(bsn)) {
-					if (instr.isNegated()) // - * - = +!
-						break;
-					else
-						return null; // skip it
-				}
-			}
+	private void rewriteJarCmd(List<String> args) {
+		String jarcmd = args.remove(0);
 
-			int n = bsn.indexOf(';');
-			if (n > 0) {
-				bsn = bsn.substring(0, n).trim();
-			}
-			String version = m.getMainAttributes().getValue(BUNDLE_VERSION);
-			if (version == null)
-				version = "0";
+		char cmd = jarcmd.charAt(0);
+		switch (cmd) {
+			case 'c' :
+				args.add(0, "create");
+				break;
 
-			Version v = new Version(version);
-			version = v.getMajor() + "." + v.getMinor() + "." + v.getMicro();
-			if (c.getFile() != null && c.getFile().getName().endsWith("-latest.jar"))
-				version = "latest";
-			return prefix + bsn + "/" + bsn + "-" + version + extension;
+			case 'u' :
+				args.add(0, "update");
+				break;
 
-		} catch (Exception e) {
-			error("Could not store repo file %s", c);
-		}
-		return null;
-	}
+			case 'x' :
+				args.add(0, "extract");
+				break;
 
-	private void deliverables(String[] args, int i) throws Exception {
-		Project project = getProject();
-		long start = System.currentTimeMillis();
-		Collection<Project> projects = project.getWorkspace().getAllProjects();
-		List<Container> containers = new ArrayList<Container>();
-		for (Project p : projects) {
-			containers.addAll(p.getDeliverables());
-		}
-		long duration = System.currentTimeMillis() - start;
-		System.out.println("Took " + duration + " ms");
+			case 't' :
+				args.add(0, "type");
+				break;
 
-		for (Container c : containers) {
-			Version v = new Version(c.getVersion());
-			System.out.printf("%-40s %d.%d.%d %s\n", c.getBundleSymbolicName(), v.getMajor(),
-					v.getMinor(), v.getMicro(), c.getFile());
+			case 'i' :
+				args.add(0, "index");
+				break;
 		}
+		int start = 1;
+		for (int i = 1; i < jarcmd.length(); i++) {
+			switch (jarcmd.charAt(i)) {
+				case 'v' :
+					args.add(start++, "--verbose");
+					break;
 
-	}
+				case '0' :
+					args.add(start++, "--nocompression");
+					break;
 
-	private int doMacro(String[] args, int i) throws Exception {
-		String result;
-		for (; i < args.length; i++) {
-			String cmd = args[i];
-			cmd = cmd.replaceAll("@\\{([^}])\\}", "\\${$1}");
-			cmd = cmd.replaceAll(":", ";");
-			cmd = cmd.replaceAll("[^$](.*)", "\\${$0}");
-			result = getReplacer().process(cmd);
-			if (result != null && result.length() != 0) {
-				Collection<String> parts = split(result);
-				for (String s : parts) {
-					out.println(s);
-				}
-			} else
-				out.println("No result for " + cmd);
+				case 'm' :
+					args.add(start++, "--manifest");
+					start++; // make the manifest file the parameter
+					break;
 
-		}
-		return i;
-	}
+				case 'M' :
+					args.add(start++, "--nomanifest");
+					break;
 
-	private void doRelease(String[] args, int i) throws Exception {
-		Project project = getProject();
-		project.release(false);
-		getInfo(project);
+				case 'f' :
+					args.add(start++, "--file");
+					break;
+			}
+		}
 	}
 
 	/**
-	 * Cross reference every class in the jar file to the files it references
+	 * Main command. This has options the bnd base options and will then run
+	 * another command.
 	 * 
-	 * @param args
-	 * @param i
+	 * @param options
+	 * @throws Exception
 	 */
+	@Description("The swiss army tool for OSGi")
+	public void _bnd(bndOptions options) throws Exception {
+		try {
+			set(FAIL_OK, options.failok() + "");
+			setExceptions(options.exceptions());
+			setTrace(options.trace());
+			setPedantic(options.pedantic());
 
-	private void doXref(String[] args, int i) {
-		for (; i < args.length; i++) {
-			try {
-				File file = new File(args[i]);
-				Jar jar = new Jar(file.getName(), file);
-				try {
-					for (Map.Entry<String, Resource> entry : jar.getResources().entrySet()) {
-						String key = entry.getKey();
-						Resource r = entry.getValue();
-						if (key.endsWith(".class")) {
-							InputStream in = r.openInputStream();
-							Clazz clazz = new Clazz(key, r);
-							out.print(key);
-							Set<String> xref = clazz.parseClassFile();
-							in.close();
-							for (String element : xref) {
-								out.print("\t");
-								out.print(element);
-							}
-							out.println();
-						}
-					}
-				} finally {
-					jar.close();
-				}
-			} catch (Exception e) {
-				e.printStackTrace();
-			}
-		}
-
-	}
-
-	private void doEclipse(String[] args, int i) throws Exception {
-		File dir = new File("").getAbsoluteFile();
-		if (args.length == i)
-			doEclipse(dir);
-		else {
-			for (; i < args.length; i++) {
-				doEclipse(new File(dir, args[i]));
-			}
-		}
-	}
+			if (options.base() != null)
+				setBase(getFile(getBase(), options.base()));
 
-	private void doEclipse(File file) throws Exception {
-		if (!file.isDirectory())
-			error("Eclipse requires a path to a directory: " + file.getAbsolutePath());
-		else {
-			File cp = new File(file, ".classpath");
-			if (!cp.exists()) {
-				error("Cannot find .classpath in project directory: " + file.getAbsolutePath());
-			} else {
-				EclipseClasspath eclipse = new EclipseClasspath(this, file.getParentFile(), file);
-				out.println("Classpath    " + eclipse.getClasspath());
-				out.println("Dependents   " + eclipse.getDependents());
-				out.println("Sourcepath   " + eclipse.getSourcepath());
-				out.println("Output       " + eclipse.getOutput());
-				out.println();
+			// And the properties
+			for (Entry<String,String> entry : options._properties().entrySet()) {
+				setProperty(entry.getKey(), entry.getValue());
 			}
-		}
 
-	}
+			CommandLine handler = options._command();
+			List<String> arguments = options._();
 
-	final static int	BUILD_SOURCES	= 1;
-	final static int	BUILD_POM		= 2;
-	final static int	BUILD_FORCE		= 4;
+			// Rewrite command line to match jar commands and
+			// handle commands that provide file names
 
-	private void doBuild(String[] args, int i) throws Exception {
-		File classpath[] = new File[0];
-		File workspace = null;
-		File sourcepath[] = new File[0];
-		File output = null;
-		String eclipse = "";
-		int options = 0;
-
-		for (; i < args.length; i++) {
-			if ("-workspace".startsWith(args[i])) {
-				workspace = new File(args[++i]);
-			} else if ("-classpath".startsWith(args[i])) {
-				classpath = getClasspath(args[++i]);
-			} else if ("-sourcepath".startsWith(args[i])) {
-				String arg = args[++i];
-				String spaces[] = arg.split("\\s*,\\s*");
-				sourcepath = new File[spaces.length];
-				for (int j = 0; j < spaces.length; j++) {
-					File f = new File(spaces[j]);
-					if (!f.exists())
-						error("No such sourcepath entry: " + f.getAbsolutePath());
-					sourcepath[j] = f;
-				}
-			} else if ("-eclipse".startsWith(args[i])) {
-				eclipse = args[++i];
-			} else if ("-noeclipse".startsWith(args[i])) {
-				eclipse = null;
-			} else if ("-output".startsWith(args[i])) {
-				output = new File(args[++i]);
-			} else if ("-sources".startsWith(args[i])) {
-				options |= BUILD_SOURCES;
-			} else if ("-pom".startsWith(args[i])) {
-				options |= BUILD_POM;
-			} else if ("-force".startsWith(args[i])) {
-				options |= BUILD_FORCE;
-			} else {
-				if (args[i].startsWith("-"))
-					error("Invalid option for bnd: " + args[i]);
-				else {
-					File properties = new File(args[i]);
+			rewrite(arguments);
 
-					if (!properties.exists())
-						error("Cannot find bnd file: " + args[i]);
-					else {
-						if (workspace == null)
-							workspace = properties.getParentFile();
+			trace("rewritten %s", arguments);
 
-						doBuild(properties, classpath, sourcepath, output, eclipse, workspace,
-								options, new HashSet<File>());
-					}
-					output = null;
+			if (arguments.isEmpty()) {
+				Justif f = new Justif(80, 20, 22, 72);
+				handler.help(f.formatter(), this);
+				err.append(f.wrap());
+			} else {
+				String cmd = arguments.remove(0);
+				String help = handler.execute(this, cmd, arguments);
+				if (help != null) {
+					err.println(help);
 				}
 			}
 		}
-
-	}
-
-	private File[] getClasspath(String string) {
-		String spaces[] = string.split("\\s*,\\s*");
-		File classpath[] = new File[spaces.length];
-		for (int j = 0; j < spaces.length; j++) {
-			File f = new File(spaces[j]);
-			if (!f.exists())
-				error("No such classpath entry: " + f.getAbsolutePath());
-			classpath[j] = f;
+		catch (Throwable t) {
+			if (t instanceof InvocationTargetException)
+				t = t.getCause();
+			exception(t, "%s", t.getMessage());
+		}
+		out.flush();
+		err.flush();
+		if (!check(options.ignore())) {
+			System.err.flush();
+			System.err.flush();
+			Thread.sleep(1000);
+			System.exit(getErrors().size());
 		}
-		return classpath;
 	}
 
-	private void doBuild(File properties, File classpath[], File sourcepath[], File output,
-			String eclipse, File workspace, int options, Set<File> building) throws Exception {
-
-		properties = properties.getAbsoluteFile();
-		if (building.contains(properties)) {
-			error("Circular dependency in pre build " + properties);
-			return;
-		}
-		building.add(properties);
+	/**
+	 * Options for the jar create command.
+	 */
+	@Description("Equivalent jar command c[v0mf] command (supports the jar tool's syntax). Will wrap the bundle unless --wrapnot is specified")
+	interface createOptions extends Options {
+		@Description("Verbose (v option)")
+		boolean verbose();
 
-		Builder builder = new Builder();
-		try {
-			builder.setPedantic(isPedantic());
-			builder.setProperties(properties);
-
-			if (output == null) {
-				String out = builder.getProperty("-output");
-				if (out != null) {
-					output = getFile(properties.getParentFile(), out);
-					if (!output.getName().endsWith(".jar"))
-						output.mkdirs();
-				} else
-					output = properties.getAbsoluteFile().getParentFile();
-			}
+		@Description("No compression (0 option)")
+		boolean nocompression();
 
-			String prebuild = builder.getProperty("-prebuild");
-			if (prebuild != null)
-				prebuild(prebuild, properties.getParentFile(), classpath, sourcepath, output,
-						eclipse, workspace, options, building);
+		@Description("No manifest (M option)")
+		boolean Manifest();
 
-			doEclipse(builder, properties, classpath, sourcepath, eclipse, workspace);
+		@Description("Use manifest (m option)")
+		String manifest();
 
-			if ((options & BUILD_SOURCES) != 0)
-				builder.getProperties().setProperty("-sources", "true");
+		@Description("Jar file (f option)")
+		String file();
 
-			if (failok)
-				builder.setProperty(Analyzer.FAIL_OK, "true");
-			Jar jar = builder.build();
-			getInfo(builder);
-			if (getErrors().size() > 0 && !failok)
-				return;
+		@Description("Directory (-C option)")
+		String Cdir();
 
-			String name = builder.getBsn() + DEFAULT_JAR_EXTENSION;
+		@Description("Wrap")
+		boolean wrap();
 
-			if (output.isDirectory())
-				output = new File(output, name);
+		@Description("Properties for wrapping")
+		String properties();
 
-			output.getParentFile().mkdirs();
+		@Description("Bundle Symbolic Name for wrap")
+		String bsn();
 
-			if ((options & BUILD_POM) != 0) {
-				Resource r = new PomFromManifest(jar.getManifest());
-				jar.putResource("pom.xml", r);
-				String path = output.getName().replaceAll("\\.jar$", ".pom");
-				if (path.equals(output.getName()))
-					path = output.getName() + ".pom";
-				File pom = new File(output.getParentFile(), path);
-				OutputStream out = new FileOutputStream(pom);
-				try {
-					r.write(out);
-				} finally {
-					out.close();
-				}
-			}
-			jar.setName(output.getName());
+		@Description("Bundle Version for wrap")
+		Version version();
 
-			String msg = "";
-			if (!output.exists() || output.lastModified() <= jar.lastModified()
-					|| (options & BUILD_FORCE) != 0) {
-				jar.write(output);
-			} else {
-				msg = "(not modified)";
-			}
-			statistics(jar, output, msg);
-		} finally {
-			builder.close();
-		}
+		@Description("Force write event if there are errors")
+		boolean force();
 	}
 
-	private void prebuild(String prebuild, File base, File[] classpath, File[] sourcepath,
-			File output, String eclipse2, File workspace, int options, Set<File> building)
-			throws Exception {
+	/**
+	 * Create jar file
+	 * 
+	 * <pre>
+	 *     jar c[v0M]f jarfile [-C dir] inputfiles [-Joption] 
+	 *     jar c[v0]mf manifest jarfile [-C dir] inputfiles [-Joption] 
+	 *     jar c[v0M] [-C dir] inputfiles [-Joption] 
+	 *     jar c[v0]m manifest [-C dir] inputfiles [-Joption]
+	 * </pre>
+	 * 
+	 * @param options
+	 * @throws Exception
+	 */
+	@Description("Create jar, used to support backward compatible java jar commands")
+	public void _create(createOptions options) throws Exception {
+		Jar jar = new Jar("dot");
 
-		// Force the output a directory
-		if (output.isFile())
-			output = output.getParentFile();
+		File dir = getBase().getAbsoluteFile();
+		String sdir = options.Cdir();
+		if (sdir != null)
+			dir = getFile(sdir);
 
-		Collection<String> parts = Processor.split(prebuild);
-		for (String part : parts) {
-			File f = new File(part);
-			if (!f.exists())
-				f = new File(base, part);
-			if (!f.exists()) {
-				error("Trying to build a non-existent file: " + parts);
-				continue;
+		if (options._().isEmpty())
+			add(jar, dir, ".", options.verbose());
+		else
+			for (String f : options._()) {
+				f = f.replace(File.separatorChar, '/');
+				add(jar, dir, f, options.verbose());
 			}
-			try {
-				doBuild(f, classpath, sourcepath, output, eclipse2, workspace, options, building);
-			} catch (Exception e) {
-				error("Trying to build: " + part + " " + e);
+
+		String manifest = options.manifest();
+		if (manifest != null) {
+			if (options.verbose())
+				err.printf("Adding manifest from %s\n", manifest);
+
+			jar.setManifest(getFile(manifest));
+		}
+
+		if (options.Manifest()) {
+			jar.setManifest((Manifest) null);
+		} else {
+			if (options.wrap()) {
+				Analyzer w = new Analyzer(this);
+				addClose(w);
+				w.setBase(getBase());
+				w.use(this);
+				w.setDefaults(options.bsn(), options.version());
+				w.calcManifest();
+				getInfo(w);
+				w.setJar((Jar) null);
+				w.close();
 			}
 		}
-	}
 
-	private void statistics(Jar jar, File output, String msg) {
-		out.println(jar.getName() + " " + jar.getResources().size() + " " + output.length() + msg);
+		if (options.nocompression())
+			jar.setCompression(Jar.Compression.STORE);
+
+		if (isOk()) {
+			String jarFile = options.file();
+			if (jarFile == null)
+				jar.write(System.out);
+			else
+				jar.write(jarFile);
+		}
+		jar.close();
+
 	}
 
 	/**
-	 * @param properties
-	 * @param classpath
-	 * @param eclipse
-	 * @return
-	 * @throws IOException
+	 * Helper for the jar create function, adds files to the jar
+	 * 
+	 * @param jar
+	 * @param base
+	 * @param path
+	 * @param report
 	 */
-	void doEclipse(Builder builder, File properties, File[] classpath, File sourcepath[],
-			String eclipse, File workspace) throws IOException {
-		if (eclipse != null) {
-			File project = new File(workspace, eclipse).getAbsoluteFile();
-			if (project.exists() && project.isDirectory()) {
-				try {
+	private void add(Jar jar, File base, String path, boolean report) {
+		if (path.endsWith("/"))
+			path = path.substring(0, path.length() - 1);
 
-					EclipseClasspath path = new EclipseClasspath(this, project.getParentFile(),
-							project);
-					List<File> newClasspath = Create.copy(Arrays.asList(classpath));
-					newClasspath.addAll(path.getClasspath());
-					classpath = (File[]) newClasspath.toArray(classpath);
-
-					List<File> newSourcepath = Create.copy(Arrays.asList(sourcepath));
-					newSourcepath.addAll(path.getSourcepath());
-					sourcepath = (File[]) newSourcepath.toArray(sourcepath);
-				} catch (Exception e) {
-					if (eclipse.length() > 0)
-						error("Eclipse specified (" + eclipse + ") but getting error processing: "
-								+ e);
-				}
-			} else {
-				if (eclipse.length() > 0)
-					error("Eclipse specified (" + eclipse + ") but no project directory found");
+		File f;
+		if (path.equals("."))
+			f = base;
+		else
+			f = getFile(base, path);
+
+		err.printf("Adding: %s\n", path);
+
+		if (f.isFile()) {
+			jar.putResource(path, new FileResource(f));
+		} else if (f.isDirectory()) {
+			if (path.equals("."))
+				path = "";
+			else
+				path += "/";
+
+			String[] subs = f.list();
+			for (String sub : subs) {
+
+				add(jar, base, path + sub, report);
 			}
 		}
-		builder.setClasspath(classpath);
-		builder.setSourcepath(sourcepath);
 	}
 
-	private void doHelp() {
-		doHelp(new String[0], 0);
+	/**
+	 * Extract a file from the JAR
+	 */
+
+	@Description("Extract files from a JAR file, equivalent jar command x[vf] (syntax supported)")
+	interface extractOptions extends Options {
+		@Description("Verbose (v option)")
+		boolean verbose();
+
+		@Description("Jar file (f option)")
+		String file();
+
+		@Description("Directory where to store")
+		String CDir();
 	}
 
-	private void doHelp(String[] args, int i) {
-		if (args.length <= i) {
-			out.println("bnd -failok? -exceptions? ( wrap | print | build | eclipse | xref | view )?");
-			out.println("See http://www.aQute.biz/Code/Bnd");
+	@Description("Extract files from a JAR file, equivalent jar command x[vf] (syntax supported)")
+	public void _extract(extractOptions opts) throws Exception {
+		Jar jar;
+
+		if (opts.file() != null) {
+			File f = getFile(opts.file());
+			if (!f.isFile()) {
+				messages.NoSuchFile_(f);
+				return;
+			}
+			jar = new Jar(f);
 		} else {
-			while (args.length > i) {
-				if ("wrap".equals(args[i])) {
-					out.println("bnd wrap (-output <file|dir>)? (-properties <file>)? <jar-file>");
-				} else if ("print".equals(args[i])) {
-					out.println("bnd wrap -verify? -manifest? -list? -eclipse <jar-file>");
-				} else if ("build".equals(args[i])) {
-					out.println("bnd build (-output <file|dir>)? (-classpath <list>)? (-sourcepath <list>)? ");
-					out.println("    -eclipse? -noeclipse? -sources? <bnd-file>");
-				} else if ("eclipse".equals(args[i])) {
-					out.println("bnd eclipse");
-				} else if ("view".equals(args[i])) {
-					out.println("bnd view <file> <resource-names>+");
+			jar = new Jar("cin", System.in);
+		}
+		try {
+			Instructions instructions = new Instructions(opts._());
+			Collection<String> selected = instructions.select(jar.getResources().keySet(), true);
+			File store = getBase();
+			if (opts.CDir() != null)
+				store = getFile(opts.CDir());
+
+			if (!store.exists() && !store.mkdirs()) {
+				throw new IOException("Could not create directory " + store);
+			}
+			Jar.Compression compression = jar.hasCompression();
+			for (String path : selected) {
+				if (opts.verbose())
+					System.err.printf("%8s: %s\n", compression.toString().toLowerCase(), path);
+
+				File f = getFile(store, path);
+				File pf = f.getParentFile();
+				if (!pf.exists() && !pf.mkdirs()) {
+					throw new IOException("Could not create directory " + pf);
 				}
-				i++;
+				Resource r = jar.getResource(path);
+				IO.copy(r.openInputStream(), f);
 			}
 		}
+		finally {
+			jar.close();
+		}
 	}
 
-	final static int	VERIFY		= 1;
+	/**
+	 * List the contents of the JAR
+	 */
 
-	final static int	MANIFEST	= 2;
+	@Description("List files int a JAR file, equivalent jar command t[vf] (syntax supported)")
+	interface typeOptions extends Options {
+		@Description("Verbose (v option)")
+		boolean verbose();
 
-	final static int	LIST		= 4;
+		@Description("Jar file (f option)")
+		String file();
 
-	final static int	ECLIPSE		= 8;
-	final static int	IMPEXP		= 16;
+	}
+
+	@Description("List files int a JAR file, equivalent jar command t[vf] (syntax supported)")
+	public void _type(typeOptions opts) throws Exception {
+		Jar jar;
+
+		if (opts.file() != null) {
+			File f = getFile(opts.file());
+			if (!f.isFile()) {
+				messages.NoSuchFile_(f);
+				return;
+			}
+			jar = new Jar(f);
+		} else {
+			jar = new Jar("cin", System.in);
+		}
+
+		try {
+			Instructions instructions = new Instructions(opts._());
+			Collection<String> selected = instructions.select(jar.getResources().keySet(), true);
+
+			for (String path : selected) {
+				if (opts.verbose()) {
+					Resource r = jar.getResource(path);
+					err.printf("%8s %-32s %s\n", r.size(), new Date(r.lastModified()), path);
+				} else
+					err.printf("%s\n", path);
+			}
+		}
+		finally {
+			jar.close();
+		}
+	}
+
+	/**
+	 * The do command interprets files and does a default action for each file
+	 * 
+	 * @param project
+	 * @param args
+	 * @param i
+	 * @return
+	 * @throws Exception
+	 */
+
+	@Description("Execute a file based on its extension. Supported extensions are: bnd (build), bndrun (run), and jar (print)")
+	interface dooptions extends Options {
+		@Description("The output file")
+		String output();
+
+		@Description("Force even when there are errors")
+		boolean force();
+	}
+
+	@Description("Execute a file based on its extension. Supported extensions are: bnd (build), bndrun (run), and jar (print)")
+	public void _do(dooptions options) throws Exception {
+		for (String path : options._()) {
+			if (path.endsWith(Constants.DEFAULT_BND_EXTENSION)) {
+				Builder b = new Builder();
+				b.setTrace(isTrace());
+				b.setPedantic(isPedantic());
+
+				File f = getFile(path);
+				b.setProperties(f);
+				b.build();
+
+				File out = b.getOutputFile(options.output());
+				getInfo(b, f.getName() + ": ");
+				if (isOk()) {
+					b.save(out, options.force());
+				}
+				getInfo(b, f.getName() + ": "); // pickup any save errors
+				if (!isOk()) {
+					out.delete();
+				}
+				b.close();
+			} else if (path.endsWith(Constants.DEFAULT_JAR_EXTENSION) || path.endsWith(Constants.DEFAULT_BAR_EXTENSION)) {
+				Jar jar = getJar(path);
+				doPrint(jar, MANIFEST, null);
+			} else if (path.endsWith(Constants.DEFAULT_BNDRUN_EXTENSION))
+				doRun(path);
+			else
+				messages.UnrecognizedFileType_(path);
+		}
+	}
+
+	/**
+	 * Project command, executes actions.
+	 */
+
+	@Description("Execute a Project action, or if no parms given, show information about the project")
+	@Arguments(arg = "")
+	interface projectOptions extends Options {
+		@Description("Identify another project")
+		String project();
+	}
+
+	@Description("Execute a Project action, or if no parms given, show information about the project")
+	public void _project(projectOptions options) throws Exception {
+		Project project = getProject(options.project());
+		if (project == null) {
+			messages.NoProject();
+			return;
+		}
+
+		List<String> l = new ArrayList<String>(options._());
+		if (l.isEmpty()) {
+			err.printf("Name         %s\n", project.getName());
+			err.printf("Actions      %s\n", project.getActions().keySet());
+			err.printf("Directory    %s\n", project.getBase());
+			err.printf("Depends on   %s\n", project.getDependson());
+			err.printf("Sub builders %s\n", project.getSubBuilders());
+			return;
+		}
+
+		String cmd = null;
+		String arg = null;
+
+		if (!l.isEmpty())
+			cmd = l.remove(0);
+		if (!l.isEmpty())
+			arg = l.remove(0);
+
+		if (!l.isEmpty()) {
+			messages.MoreArgumentsThanNeeded_(options._());
+			return;
+		}
+
+		if (cmd == null) {
+			messages.NoCommandForProject(project);
+			return;
+		}
+
+		Action a = project.getActions().get(cmd);
+		if (a != null) {
+			a.execute(project, arg);
+			getInfo(project);
+			return;
+		}
+	}
+
+	/**
+	 * Bump a version number
+	 * 
+	 * @param args
+	 * @param i
+	 * @throws Exception
+	 */
+	@Description("Bumps the version of a project. Will take the current version and then increment "
+			+ "with a major, minor, or micro increment. The default bump is minor.")
+	@Arguments(arg = "<major|minor|micro>")
+	interface bumpoptions extends Options {
+		@Description("Path to another project than the current project")
+		String project();
+	}
+
+	@Description("Bumps the version of a project")
+	public void _bump(bumpoptions options) throws Exception {
+		Project project = getProject(options.project());
+
+		if (project == null) {
+			messages.NoProject();
+			return;
+		}
+
+		String mask = null;
+		if (!options._().isEmpty()) {
+			mask = options._().get(0);
+			if (mask.equalsIgnoreCase("major"))
+				mask = "+00";
+			else if (mask.equalsIgnoreCase("minor"))
+				mask = "=+0";
+			else if (mask.equalsIgnoreCase("micro"))
+				mask = "==+";
+			else if (!mask.matches("[+=0]{1,3}")) {
+				messages.InvalidBumpMask_(mask);
+				return;
+			}
+		}
+
+		if (mask == null)
+			project.bump();
+		else
+			project.bump(mask);
+
+		getInfo(project);
+		err.println(project.getProperty(BUNDLE_VERSION, "No version found"));
+	}
+
+	@Description("Build a project. This will create the jars defined in the bnd.bnd and sub-builders.")
+	@Arguments(arg = {})
+	interface buildoptions extends Options {
+		@Description("Path to another project than the current project")
+		String project();
+
+		@Description("Build for test")
+		boolean test();
+	}
+
+	@Description("Build a project. This will create the jars defined in the bnd.bnd and sub-builders.")
+	public void _build(buildoptions opts) throws Exception {
+		Project project = getProject(opts.project());
+		if (project == null) {
+			messages.NoProject();
+			return;
+		}
+		project.build(opts.test());
+	}
+
+	@Description("Test a project according to an OSGi test")
+	@Arguments(arg = {})
+	interface testOptions extends Options {
+		@Description("Path to another project than the current project")
+		String project();
+	}
+
+	@Description("Test a project according to an OSGi test")
+	public void _test(testOptions opts) throws Exception {
+		Project project = getProject(opts.project());
+		if (project == null) {
+			messages.NoProject();
+			return;
+		}
+		project.test();
+	}
+
+	@Description("Run a project in the OSGi launcher")
+	interface runOptions extends Options {
+		@Description("Path to another project than the current project")
+		String project();
+	}
+
+	@Description("Run a project in the OSGi launcher")
+	public void _run(runOptions opts) throws Exception {
+		Project project = getProject(opts.project());
+		if (project == null) {
+			messages.NoProject();
+			return;
+		}
+		project.run();
+	}
+
+	@Description("Clean a project")
+	interface cleanOptions extends Options {
+		@Description("Path to another project than the current project")
+		String project();
+	}
+
+	@Description("Clean a project")
+	public void _clean(cleanOptions opts) throws Exception {
+		Project project = getProject(opts.project());
+		if (project == null) {
+			messages.NoProject();
+			return;
+		}
+		project.clean();
+	}
+
+	@Description("Access the internal bnd database of keywords and options")
+	@Arguments(arg = {
+			"header|instruction", "..."
+	})
+	interface syntaxOptions extends Options {
+		@Description("The width of the printout")
+		int width();
+	}
+
+	@Description("Access the internal bnd database of keywords and options")
+	public void _syntax(syntaxOptions opts) throws Exception {
+		int w = opts.width() < 80 ? 120 : opts.width();
+		Justif justif = new Justif(w, opts.width(), 40, 42, w - 10);
+		List<String> args = opts._();
+		StringBuilder sb = new StringBuilder();
+		Formatter f = new Formatter(sb);
+		for (String s : args) {
+			f.format(" \n[%s]\n", s);
+			Syntax sx = Syntax.HELP.get(s);
+			if (s == null)
+				f.format("Unknown");
+			else {
+				print(f, sx, "  ");
+			}
+		}
+		f.flush();
+		justif.wrap(sb);
+		err.println(sb);
+	}
+
+	private void print(Formatter f, Syntax sx, String indent) {
+		if (sx == null)
+			return;
+
+		f.format("%s%s\n\n", indent, sx.getLead());
+		if (sx.getValues() != null)
+			f.format("%sValues\t1:\t2%s\n", indent, sx.getValues());
+
+		if (sx.getPattern() != null)
+			f.format("%sPattern  \t1:\t2%s\n", indent, sx.getPattern());
+		if (sx.getExample() != null)
+			f.format("%sExample  \t1:\t2%s\n", indent, sx.getExample());
+		if (sx.getChildren() != null) {
+
+			for (Syntax child : sx.getChildren()) {
+				f.format("\n%s[%s]\t1:\t2", indent, child.getHeader());
+				print(f, child, indent + "  ");
+			}
+		}
+	}
+
+	private void doRun(String path) throws Exception {
+		File file = getFile(path);
+		if (!file.isFile())
+			throw new FileNotFoundException(path);
+
+		File projectDir = file.getParentFile();
+		File workspaceDir = projectDir.getParentFile();
+		if (workspaceDir == null) {
+			workspaceDir = new File(System.getProperty("user.home") + File.separator + ".bnd");
+		}
+		Workspace ws = Workspace.getWorkspace(workspaceDir);
+
+		Project project = new Project(ws, projectDir, file);
+
+		project.setTrace(isTrace());
+		project.setPedantic(isPedantic());
+		try {
+			project.run();
+
+		}
+		catch (Exception e) {
+			messages.Project_RunFailed_(project, e);
+		}
+		getInfo(project);
+	}
+
+	/**
+	 * Package a bnd or bndrun file for packaging.
+	 * 
+	 * @param path
+	 * @throws Exception
+	 */
+	@Description("Package a bnd or bndrun file into a single jar that executes with java -jar <>.jar. The JAR contains all dependencies, including the framework and the launcher. "
+			+ "A profile can be specified which will be used to find properties. If a property is not found, a property with the name [<profile>]NAME will be looked up. This allows "
+			+ "you to make different profiles for testing and runtime.")
+	@Arguments(arg = {
+			"<bnd|bndrun>", "[...]"
+	})
+	interface packageOptions extends Options {
+		@Description("Where to store the resulting file. Default the name of the bnd file with a .jar extension.")
+		String output();
+
+		@Description("Profile name. Default no profile")
+		String profile();
+	}
+
+	@Description("Package a bnd or bndrun file into a single jar that executes with java -jar <>.jar")
+	public void _package(packageOptions opts) throws Exception {
+		Project project = getProject(); // default project
+		if (project == null) {
+			error("Packaging only works inside a project directory (needs bnd.bnd file)");
+			return;
+		}
+
+		List<String> cmdline = opts._();
+		File output = null;
+
+		if (opts.output() != null) {
+			output = getFile(opts.output());
+		} else
+			output = getBase();
+
+		if (opts._().size() > 1) {
+			if (!output.exists() && !output.mkdirs()) {
+				throw new IOException("Could not create directory " + output);
+			}
+		} else {
+			File pf = output.getParentFile();
+			if (!pf.exists() && !pf.mkdirs()) {
+				throw new IOException("Could not create directory " + pf);
+			}
+		}
+
+		project.build();
+
+		if (cmdline.isEmpty())
+			cmdline.add(Project.BNDFILE); // default project itself
+
+		for (String path : opts._()) {
+
+			File file = getFile(path);
+			if (!file.isFile()) {
+				messages.NoSuchFile_(file);
+			} else {
+
+				// Tricky because we can be run inside the context of a
+				// project (in which case
+				// we need to inherit from the project or outside.
+
+				Workspace ws = project.getWorkspace();
+				project = new Project(ws, getBase(), file);
+
+				String profile = opts.profile() == null ? "exec" : opts.profile();
+
+				pack(project, output, path.replaceAll(".bnd(run)?$", "") + ".jar", profile);
+			}
+		}
+	}
+
+	/*
+	 * Pack the project (could be a bndrun file) and save it on disk. Report
+	 * errors if they happen.
+	 */
+	static List<String>	ignore	= new ExtList<String>(BUNDLE_SPECIFIC_HEADERS);
+
+	private void pack(Project project, File output, String path, String profile) throws Exception {
+		Collection< ? extends Builder> subBuilders = project.getSubBuilders();
+
+		if (subBuilders.size() != 1) {
+			error("Project has multiple bnd files, please select one of the bnd files");
+			return;
+		}
+
+		Builder b = subBuilders.iterator().next();
+
+		ignore.remove(BUNDLE_SYMBOLICNAME);
+		ignore.remove(BUNDLE_VERSION);
+		ignore.add(SERVICE_COMPONENT);
+
+		try {
+			project.use(this);
+			ProjectLauncher launcher = project.getProjectLauncher();
+			launcher.getRunProperties().put("profile", profile);
+			Jar jar = launcher.executable();
+			Manifest m = jar.getManifest();
+			Attributes main = m.getMainAttributes();
+			for (String key : project.getPropertyKeys(true)) {
+				if (Character.isUpperCase(key.charAt(0)) && !ignore.contains(key)) {
+					main.putValue(key, project.getProperty(key));
+				}
+			}
+
+			if (main.getValue(BUNDLE_SYMBOLICNAME) == null)
+				main.putValue(BUNDLE_SYMBOLICNAME, b.getBsn());
+
+			if (main.getValue(BUNDLE_SYMBOLICNAME) == null)
+				main.putValue(BUNDLE_SYMBOLICNAME, project.getName());
+
+			if (main.getValue(BUNDLE_VERSION) == null) {
+				main.putValue(BUNDLE_VERSION, Version.LOWEST.toString());
+				warning("No version set, uses 0.0.0");
+			}
+
+			jar.setManifest(m);
+			jar.calcChecksums(new String[] {
+					"SHA1", "MD5"
+			});
+			File out = output;
+			if (output.isDirectory())
+				out = new File(output, path);
+			jar.write(out);
+		}
+		catch (Exception e) {
+			messages.ForProject_File_FailedToCreateExecutableException_(project, path, e);
+		}
+		getInfo(project);
+	}
+
+	/**
+	 * List all deliverables for this workspace.
+	 */
+	@Description("Show all deliverables from this workspace. with their current version and path.")
+	@Arguments(arg = {})
+	interface deliverableOptions extends Options {
+		@Description("Path to project, default current directory")
+		String project();
+
+		@Description("Only provide deliverables of this project")
+		boolean limit();
+	}
+
+	@Description("Show all deliverables from this workspace. with their current version and path.")
+	public void _deliverables(deliverableOptions options) throws Exception {
+		Project project = getProject(options.project());
+		if (project == null) {
+			messages.NoProject();
+			return;
+		}
+
+		Collection<Project> projects;
+		if (options.limit())
+			projects = Arrays.asList(project);
+		else
+			projects = project.getWorkspace().getAllProjects();
+
+		List<Container> containers = new ArrayList<Container>();
+
+		for (Project p : projects) {
+			containers.addAll(p.getDeliverables());
+		}
+
+		for (Container c : containers) {
+			Version v = new Version(c.getVersion());
+			err.printf("%-40s %8s  %s\n", c.getBundleSymbolicName(), v.getWithoutQualifier(), c.getFile());
+		}
+		getInfo(project);
+	}
+
+	/**
+	 * Show the value of a macro
+	 * 
+	 * @param args
+	 * @param i
+	 * @return
+	 * @throws Exception
+	 */
+	@Description("Show macro value. Macro can contain the ${ and } parentheses but it is also ok without. You can use the ':' instead of the ';' in a macro")
+	@Arguments(arg = {
+			"<macro>", "[...]"
+	})
+	interface macroOptions extends Options {
+		@Description("Path to project, default current directory")
+		String project();
+	}
+
+	@Description("Show macro value")
+	public void _macro(macroOptions options) throws Exception {
+		Project project = getProject(options.project());
+
+		if (project == null) {
+			messages.NoProject();
+			return;
+		}
+
+		StringBuilder sb = new StringBuilder();
+		Macro r = project.getReplacer();
+		getInfo(project);
+
+		String del = "";
+		for (String s : options._()) {
+			if (!s.startsWith("${")) {
+				s = "${" + s;
+			}
+			if (!s.endsWith("}")) {
+				s += "}";
+			}
+			s = s.replace(':', ';');
+			String p = r.process(s);
+			sb.append(del);
+			sb.append(p);
+			del = " ";
+		}
+		getInfo(project);
+		err.println(sb);
+	}
+
+	/**
+	 * Release the project
+	 * 
+	 * @param args
+	 * @param i
+	 * @throws Exception
+	 */
+	@Description("Release this project")
+	interface releaseOptions extends Options {
+		@Description("Path to project, default is current project")
+		String project();
+
+		@Description("Release with test build")
+		boolean test();
+	}
+
+	@Description("Release this project")
+	public void _release(releaseOptions options) throws Exception {
+		Project project = getProject(options.project());
+		if (project == null)
+			return;
+
+		project.release(options.test());
+		getInfo(project);
+	}
+
+	/**
+	 * Cross reference every class in the jar file to the files it references
+	 * 
+	 * @param args
+	 * @param i
+	 */
+	@Description("Show a cross references for all classes in a set of jars.")
+	@Arguments(arg = {
+			"<jar path>", "[...]"
+	})
+	interface xrefOptions extends Options {
+		@Description("Show classes instead of packages")
+		boolean classes();
+
+		@Description("Show references to other classes/packages (>)")
+		boolean to();
+
+		@Description("Show references from other classes/packages (<)")
+		boolean from();
+
+		@Description("Filter for class names, a globbing expression")
+		List<String> match();
+
+	}
+
+	static public class All {
+		public Map<TypeRef,List<TypeRef>>		classes		= new HashMap<Descriptors.TypeRef,List<TypeRef>>();
+		public Map<PackageRef,List<PackageRef>>	packages	= new HashMap<Descriptors.PackageRef,List<PackageRef>>();
+	}
+
+	@Description("Show a cross references for all classes in a set of jars.")
+	public void _xref(xrefOptions options) throws IOException, Exception {
+		Analyzer analyzer = new Analyzer();
+		final MultiMap<TypeRef,TypeRef> table = new MultiMap<TypeRef,TypeRef>();
+		final MultiMap<PackageRef,PackageRef> packages = new MultiMap<PackageRef,PackageRef>();
+		Set<TypeRef> set = Create.set();
+		Instructions filter = new Instructions(options.match());
+		for (String arg : options._()) {
+			try {
+				File file = new File(arg);
+				Jar jar = new Jar(file.getName(), file);
+				try {
+					for (Map.Entry<String,Resource> entry : jar.getResources().entrySet()) {
+						String key = entry.getKey();
+						Resource r = entry.getValue();
+						if (key.endsWith(".class")) {
+							TypeRef ref = analyzer.getTypeRefFromPath(key);
+							if (filter.matches(ref.toString())) {
+								set.add(ref);
+
+								InputStream in = r.openInputStream();
+								Clazz clazz = new Clazz(analyzer, key, r);
+
+								// TODO use the proper bcp instead
+								// of using the default layout
+								Set<TypeRef> s = clazz.parseClassFile();
+								for (Iterator<TypeRef> t = s.iterator(); t.hasNext();) {
+									TypeRef tr = t.next();
+									if (tr.isJava() || tr.isPrimitive())
+										t.remove();
+									else
+										packages.add(ref.getPackageRef(), tr.getPackageRef());
+								}
+								table.addAll(ref, s);
+								set.addAll(s);
+								in.close();
+							}
+						}
+					}
+				}
+				finally {
+					jar.close();
+				}
+			}
+			catch (Exception e) {
+				e.printStackTrace();
+			}
+		}
+
+		boolean to = options.to();
+		boolean from = options.from();
+		if (to == false && from == false)
+			to = from = true;
+
+		if (options.classes()) {
+			if (to)
+				printxref(table, ">");
+			if (from)
+				printxref(table.transpose(), "<");
+		} else {
+			if (to)
+				printxref(packages, ">");
+			if (from)
+				printxref(packages.transpose(), "<");
+		}
+	}
+
+	private void printxref(MultiMap< ? , ? > map, String direction) {
+		SortedList< ? > labels = new SortedList<Comparable< ? >>((Collection< ? extends Comparable< ? >>) map.keySet());
+		for (Object element : labels) {
+			List< ? > e = map.get(element);
+			if (e == null) {
+				// ignore
+			} else {
+				Set<Object> set = new HashSet<Object>(e);
+				set.remove(element);
+				Iterator< ? > row = set.iterator();
+				String first = "";
+				if (row.hasNext())
+					first = row.next().toString();
+				err.printf("%50s %s %s\n", element, direction, first);
+				while (row.hasNext()) {
+					err.printf("%50s   %s\n", "", row.next());
+				}
+			}
+		}
+	}
+
+	@Description("Show info about the current directory's eclipse project")
+	@Arguments(arg = {})
+	interface eclipseOptions extends Options {
+		@Description("Path to the project")
+		String dir();
+	}
+
+	@Description("Show info about the current directory's eclipse project")
+	public void _eclipse(eclipseOptions options) throws Exception {
+
+		File dir = getBase();
+		if (options.dir() != null)
+			dir = getFile(options.dir());
+
+		if (!dir.isDirectory())
+			error("Eclipse requires a path to a directory: " + dir.getAbsolutePath());
+
+		if (options._().size() != 0)
+			error("Unnecessary arguments %s", options._());
+
+		if (!isOk())
+			return;
+
+		File cp = new File(dir, ".classpath");
+		if (!cp.exists()) {
+			error("Cannot find .classpath in project directory: " + dir.getAbsolutePath());
+		} else {
+			EclipseClasspath eclipse = new EclipseClasspath(this, dir.getParentFile(), dir);
+			err.println("Classpath    " + eclipse.getClasspath());
+			err.println("Dependents   " + eclipse.getDependents());
+			err.println("Sourcepath   " + eclipse.getSourcepath());
+			err.println("Output       " + eclipse.getOutput());
+			err.println();
+		}
+	}
+
+	/**
+	 * Buildx
+	 */
+	final static int	BUILD_SOURCES	= 1;
+	final static int	BUILD_POM		= 2;
+	final static int	BUILD_FORCE		= 4;
+
+	@Description("Build project, is deprecated but here for backward compatibility. If you use it, you should know how to use it so no more info is provided.")
+	interface buildxOptions extends Options {
+		String output();
+
+		List<String> classpath();
+
+		List<String> sourcepath();
+
+		boolean eclipse();
+
+		boolean noeclipse();
+
+		boolean sources();
+
+		boolean pom();
+
+		boolean force();
+	}
+
+	@Description("Build project, is deprecated but here for backward compatibility")
+	public void _buildx(buildxOptions options) throws Exception {
+
+		// Create a build order
+
+		List<Builder> builders = new ArrayList<Builder>();
+		List<String> order = new ArrayList<String>();
+		List<String> active = new ArrayList<String>();
+
+		for (String s : options._()) {
+			prebuild(active, order, builders, s);
+		}
+
+		for (Builder b : builders) {
+			if (options.classpath() != null) {
+				for (String f : options.classpath()) {
+					b.addClasspath(getFile(f));
+				}
+			}
+
+			if (options.sourcepath() != null) {
+				for (String f : options.sourcepath()) {
+					b.addSourcepath(getFile(f));
+				}
+			}
+
+			if (options.sources())
+				b.setSources(true);
+
+			if (options.eclipse()) {
+				EclipseClasspath ep = new EclipseClasspath(this, getBase().getParentFile(), getBase());
+
+				b.addClasspath(ep.getClasspath());
+				b.addClasspath(ep.getBootclasspath());
+				b.addSourcepath(ep.getSourcepath());
+			}
+
+			Jar jar = b.build();
+
+			File outputFile = b.getOutputFile(options.output());
+
+			if (options.pom()) {
+				Resource r = new PomFromManifest(jar.getManifest());
+				jar.putResource("pom.xml", r);
+				String path = outputFile.getName().replaceAll("\\.jar$", ".pom");
+				if (path.equals(outputFile.getName()))
+					path = outputFile.getName() + ".pom";
+				File pom = new File(outputFile.getParentFile(), path);
+				OutputStream out = new FileOutputStream(pom);
+				try {
+					r.write(out);
+				}
+				finally {
+					out.close();
+				}
+			}
+
+			getInfo(b, b.getPropertiesFile().getName());
+			if (isOk()) {
+				b.save(outputFile, options.force());
+			}
+			b.close();
+		}
+	}
+
+	// Find the build order
+	// by recursively passing
+	// through the builders.
+	private void prebuild(List<String> set, List<String> order, List<Builder> builders, String s) throws IOException {
+		if (order.contains(s)) // Already done
+			return;
+
+		if (set.contains(s))
+			error("Cyclic -prebuild dependency %s from %s", s, set);
+
+		Builder b = new Builder(this);
+		b.setProperties(getFile(s));
+
+		String prebuild = b.get("prebuild");
+		if (prebuild != null) {
+			set.add(s);
+			try {
+				Collection<String> parts = split(prebuild);
+				for (String p : parts) {
+					prebuild(set, order, builders, p);
+				}
+			}
+			finally {
+				set.remove(s);
+			}
+		}
+		order.add(s);
+		builders.add(b);
+	}
+
+	/**
+	 * View files from JARs We parse the commandline and print each file on it.
+	 * 
+	 * @param args
+	 * @param i
+	 * @throws Exception
+	 */
+	@Description("View a resource from a JAR file. Manifest will be pretty printed and class files are shown disassembled.")
+	@Arguments(arg = {
+			"<jar-file>", "<resource>", "[...]"
+	})
+	interface viewOptions extends Options {
+		@Description("Character set to use for viewing")
+		String charset();
+	}
+
+	@Description("View a resource from a JAR file.")
+	public void _view(viewOptions options) throws Exception {
+		String charset = "UTF-8";
+		if (options.charset() != null)
+			charset = options.charset();
+
+		if (options._().isEmpty()) {
+			error("Need a jarfile as source");
+			return;
+		}
+		List<String> args = options._();
+		File file = getFile(args.remove(0));
+		if (!file.isFile()) {
+			error("File does not exist %s", file);
+			return;
+		}
+
+		Jar jar = new Jar(file);
+		try {
+			if (args.isEmpty())
+				args.add("*");
+
+			Instructions instructions = new Instructions(args);
+			Collection<String> selected = instructions.select(jar.getResources().keySet(), true);
+			for (String selection : selected) {
+				Resource r = jar.getResource(selection);
+
+				if (selection.endsWith(".MF")) {
+					Manifest m = new Manifest(r.openInputStream());
+					printManifest(m);
+				} else if (selection.endsWith(".class")) {
+					ClassDumper clsd = new ClassDumper(selection, r.openInputStream());
+					clsd.dump(err);
+				} else {
+					InputStreamReader isr = new InputStreamReader(r.openInputStream(), charset);
+					IO.copy(isr, err);
+				}
+			}
+		}
+		finally {
+			jar.close();
+		}
+	}
+
+	/**
+	 * Wrap a jar to a bundle.
+	 * 
+	 * @param args
+	 * @param i
+	 * @throws Exception
+	 */
+	@Description("Wrap a jar into a bundle. This is a poor man's facility to " +
+			"quickly turn a non-OSGi JAR into an OSGi bundle. " +
+			"It is usually better to write a bnd file and use the bnd <file>.bnd " +
+			"command because that has greater control. Even better is to wrap in bndtools.")
+	@Arguments(arg={"<jar-file>", "[...]"})
+	interface wrapOptions extends Options {
+		@Description("Path to the output, default the name of the input jar with the '.bar' extension. If this is a directory, the output is place there.")
+		String output();
+
+		@Description("A file with properties in bnd format.")
+		String properties();
+
+		@Description("A classpath specification")
+		List<String> classpath();
+
+		@Description("Allow override of an existing file")
+		boolean force();
+
+		@Description("Set the bundle symbolic name to use")
+		String bsn();
+
+		@Description("Set the version to use")
+		Version version();
+	}
+
+	@Description("Wrap a jar")
+	public void _wrap(wrapOptions options) throws Exception {
+		List<File> classpath = Create.list();
+		File properties = getBase();
+
+		if (options.properties() != null) {
+			properties = getFile(options.properties());
+		}
+
+		if (options.classpath() != null)
+			for (String cp : options.classpath()) {
+				classpath.add(getFile(cp));
+			}
+
+		for (String j : options._()) {
+			File file = getFile(j);
+			if (!file.isFile()) {
+				error("File does not exist %s", file);
+				continue;
+			}
+
+			Analyzer wrapper = new Analyzer(this);
+			try {
+				wrapper.use(this);
+				addClose(wrapper);
+
+				for (File f : classpath)
+					wrapper.addClasspath(f);
+
+				wrapper.setJar(file);
+
+				File outputFile = wrapper.getOutputFile(options.output());
+				if (outputFile.getCanonicalFile().equals(file.getCanonicalFile())) {
+					// #267: CommandLine wrap deletes target even if file equals
+					// source
+					error("Output file %s and source file %s are the same file, they must be different", outputFile,
+							file);
+					return;
+				}
+				outputFile.delete();
+
+				String stem = file.getName();
+				if (stem.endsWith(".jar"))
+					stem = stem.substring(0, stem.length() - 4) + ".bnd";
+
+				File p = getPropertiesFile(properties, file, stem);
+
+				if (p == null) {
+					wrapper.setImportPackage("*;resolution:=optional");
+					wrapper.setExportPackage("*");
+					warning("Using defaults for wrap, which means no export versions");
+
+				} else if (p.isFile())
+					wrapper.setProperties(p);
+				else {
+					error("No valid property file: %s", p);
+				}
+
+				if (options.bsn() != null)
+					wrapper.setBundleSymbolicName(options.bsn());
+
+				if (options.version() != null)
+					wrapper.setBundleVersion(options.version());
+
+				Manifest m = wrapper.calcManifest();
+
+				if (wrapper.isOk()) {
+					wrapper.getJar().setManifest(m);
+					wrapper.save(outputFile, options.force());
+				}
+				getInfo(wrapper, file.toString());
+			}
+			finally {
+				wrapper.close();
+			}
+		}
+	}
+
+	private File getPropertiesFile(File properties, File file, String stem) {
+		if (properties.isFile())
+			return properties;
+
+		File p = getFile(file.getParentFile(), stem);
+		if (p.isFile())
+			return p;
+
+		if (properties.isDirectory()) {
+			p = getFile(properties, stem);
+			if (p.isFile())
+				return p;
+		}
+
+		return null;
+	}
+
+	/**
+	 * Printout all the variables in scope.
+	 * 
+	 * @param args
+	 * @param i
+	 * @throws Exception
+	 */
+	@Description("Show a lot of info about the project you're in")
+	interface debugOptions extends Options {
+		@Description("Path to a project, default is current directory")
+		String project();
+	}
+
+	@Description("Show a lot of info about the project you're in")
+	public void _debug(debugOptions options) throws Exception {
+		Project project = getProject(options.project());
+		Processor target = project;
+		if (project != null) {
+			getInfo(project.getWorkspace());
+
+			MultiMap<String,Object> table = new MultiMap<String,Object>();
+			table.add("Workspace", project.getWorkspace().toString());
+			table.addAll("Plugins", project.getPlugins(Object.class));
+			table.addAll("Repos", project.getWorkspace().getRepositories());
+			printxref(table, "|");
+		} else
+			err.println("No project");
+
+		target = this;
+
+		MultiMap<String,String> table = new MultiMap<String,String>();
+
+		for (Iterator<String> i = target.iterator(); i.hasNext();) {
+			String key = i.next();
+			String s = target.get(key);
+			Collection<String> set = split(s);
+			table.addAll(key, set);
+		}
+		printxref(table, "|");
+
+	}
+
+	/**
+	 * Manage the repo.
+	 * 
+	 * <pre>
+	 * out.println(" bnd repo [--repo|-r ('maven'| <dir>)]*");
+	 * out.println("        repos                          # list the repositories");
+	 * out.println("        list                           # list all content (not always possible)");
+	 * out.println("        get <bsn> <version> <file>?    # get an artifact");
+	 * out.println("        put <file>+                    # put in artifacts");
+	 * out.println("        help");
+	 * </pre>
+	 */
+
+	@Description("Manage the repositories")
+	public void _repo(repoOptions opts) throws Exception {
+		new RepoCommand(this, opts);
+	}
+
+
+	/**
+	 * Print out a JAR
+	 */
+
+	final static int	VERIFY		= 1;
+
+	final static int	MANIFEST	= 2;
+
+	final static int	LIST		= 4;
+
+	final static int	IMPEXP		= 16;
 	final static int	USES		= 32;
 	final static int	USEDBY		= 64;
 	final static int	COMPONENT	= 128;
 	final static int	METATYPE	= 256;
+	final static int	API			= 512;
 
 	static final int	HEX			= 0;
 
-	private void doPrint(String[] args, int i) throws Exception {
-		int options = 0;
-
-		for (; i < args.length; i++) {
-			if ("-verify".startsWith(args[i]))
-				options |= VERIFY;
-			else if ("-manifest".startsWith(args[i]))
-				options |= MANIFEST;
-			else if ("-list".startsWith(args[i]))
-				options |= LIST;
-			else if ("-eclipse".startsWith(args[i]))
-				options |= ECLIPSE;
-			else if ("-impexp".startsWith(args[i]))
-				options |= IMPEXP;
-			else if ("-uses".startsWith(args[i]))
-				options |= USES;
-			else if ("-usedby".startsWith(args[i]))
-				options |= USEDBY;
-			else if ("-component".startsWith(args[i]))
-				options |= COMPONENT;
-			else if ("-metatype".startsWith(args[i]))
-				options |= METATYPE;
-			else if ("-all".startsWith(args[i]))
-				options = -1;
-			else {
-				if (args[i].startsWith("-"))
-					error("Invalid option for print: " + args[i]);
-				else
-					doPrint(args[i], options);
-			}
-		}
+	@Arguments(arg = "jar-file...")
+	@Description("Provides detailed view of the bundle. It will analyze the bundle and then show its contents from different perspectives. If no options are specified, prints the manifest.")
+	interface printOptions extends Options {
+		@Description("Print the api usage. This shows the usage constraints on exported packages when only public API is used.")
+		boolean api();
+
+		@Description("Before printing, verify that the bundle is correct.")
+		boolean verify();
+
+		@Description("Print the manifest.")
+		boolean manifest();
+
+		@Description("List the resources")
+		boolean list();
+
+		@Description("List the imports exports, versions and ranges")
+		boolean impexp();
+
+		@Description("Show for each contained package, what other package it uses. Is either an private, exported, or imported package")
+		boolean uses();
+
+		@Description("Transposed uses. Will show for each known package who it is used by.")
+		boolean by();
+
+		@Description("Show components in detail")
+		boolean component();
+
+		@Description("Show any metatype data")
+		boolean typemeta();
+
+		@Description("Keep references to java in --api, --uses, and --usedby.")
+		boolean java();
+
+		@Description("Show all packages, not just exported, in the API view")
+		boolean xport();
 	}
 
-	public void doPrint(String string, int options) throws Exception {
-		File file = new File(string);
-		if (!file.exists())
-			error("File to print not found: " + string);
-		else {
-			if (options == 0)
-				options = VERIFY | MANIFEST | IMPEXP | USES;
-			doPrint(file, options);
+	@Description("Printout the JAR")
+	public void _print(printOptions options) throws Exception {
+		for (String s : options._()) {
+			int opts = 0;
+			if (options.verify())
+				opts |= VERIFY;
+
+			if (options.manifest())
+				opts |= MANIFEST;
+
+			if (options.api())
+				opts |= API;
+
+			if (options.list())
+				opts |= LIST;
+
+			if (options.impexp())
+				opts |= IMPEXP;
+
+			if (options.uses())
+				opts |= USES;
+
+			if (options.by())
+				opts |= USEDBY;
+
+			if (options.component())
+				opts |= COMPONENT;
+
+			if (options.typemeta())
+				opts |= METATYPE;
+
+			if (opts == 0)
+				opts = MANIFEST | IMPEXP;
+
+			Jar jar = getJar(s);
+			try {
+				doPrint(jar, opts, options);
+			}
+			finally {
+				jar.close();
+			}
 		}
 	}
 
-	private void doPrint(File file, int options) throws ZipException, IOException, Exception {
+	private void doPrint(Jar jar, int options, printOptions po) throws ZipException, IOException, Exception {
 
-		Jar jar = new Jar(file.getName(), file);
 		try {
 			if ((options & VERIFY) != 0) {
 				Verifier verifier = new Verifier(jar);
@@ -903,56 +1694,96 @@ public class bnd extends Processor {
 			if ((options & MANIFEST) != 0) {
 				Manifest manifest = jar.getManifest();
 				if (manifest == null)
-					warning("JAR has no manifest " + file);
+					warning("JAR has no manifest " + jar);
 				else {
-					out.println("[MANIFEST " + jar.getName() + "]");
-					SortedSet<String> sorted = new TreeSet<String>();
-					for (Object element : manifest.getMainAttributes().keySet()) {
-						sorted.add(element.toString());
-					}
-					for (String key : sorted) {
-						Object value = manifest.getMainAttributes().getValue(key);
-						format("%-40s %-40s\r\n", new Object[] { key, value });
-					}
+					err.println("[MANIFEST " + jar.getName() + "]");
+					printManifest(manifest);
 				}
 				out.println();
 			}
 			if ((options & IMPEXP) != 0) {
 				out.println("[IMPEXP]");
 				Manifest m = jar.getManifest();
+				Domain domain = Domain.domain(m);
+
 				if (m != null) {
-					Map<String, Map<String, String>> imports = parseHeader(m.getMainAttributes()
-							.getValue(Analyzer.IMPORT_PACKAGE));
-					Map<String, Map<String, String>> exports = parseHeader(m.getMainAttributes()
-							.getValue(Analyzer.EXPORT_PACKAGE));
+					Parameters imports = domain.getImportPackage();
+					Parameters exports = domain.getExportPackage();
 					for (String p : exports.keySet()) {
 						if (imports.containsKey(p)) {
-							Map<String, String> attrs = imports.get(p);
-							if (attrs.containsKey(Constants.VERSION_ATTRIBUTE)) {
+							Attrs attrs = imports.get(p);
+							if (attrs.containsKey(VERSION_ATTRIBUTE)) {
 								exports.get(p).put("imported-as", attrs.get(VERSION_ATTRIBUTE));
 							}
 						}
 					}
-					print("Import-Package", new TreeMap<String, Map<String, String>>(imports));
-					print("Export-Package", new TreeMap<String, Map<String, String>>(exports));
+					print("Import-Package", new TreeMap<String,Attrs>(imports));
+					print("Export-Package", new TreeMap<String,Attrs>(exports));
 				} else
 					warning("File has no manifest");
 			}
 
-			if ((options & (USES | USEDBY)) != 0) {
+			if ((options & (USES | USEDBY | API)) != 0) {
 				out.println();
 				Analyzer analyzer = new Analyzer();
 				analyzer.setPedantic(isPedantic());
 				analyzer.setJar(jar);
+				Manifest m = jar.getManifest();
+				if (m != null) {
+					String s = m.getMainAttributes().getValue(Constants.EXPORT_PACKAGE);
+					if (s != null)
+						analyzer.setExportPackage(s);
+				}
 				analyzer.analyze();
+
+				boolean java = po.java();
+
+				Packages exports = analyzer.getExports();
+
+				if ((options & API) != 0) {
+					Map<PackageRef,List<PackageRef>> apiUses = analyzer.cleanupUses(analyzer.getAPIUses(), !po.java());
+					if (!po.xport()) {
+						if (exports.isEmpty())
+							warning("Not filtering on exported only since exports are empty");
+						else
+							apiUses.keySet().retainAll(analyzer.getExports().keySet());
+					}
+					out.println("[API USES]");
+					printMultiMap(apiUses);
+
+					Set<PackageRef> privates = analyzer.getPrivates();
+					for (PackageRef export : exports.keySet()) {
+						Map<Def,List<TypeRef>> xRef = analyzer.getXRef(export, privates, Modifier.PROTECTED
+								+ Modifier.PUBLIC);
+						if (!xRef.isEmpty()) {
+							out.println();
+							out.printf("%s refers to private Packages (not good)\n\n", export);
+							for (Entry<Def,List<TypeRef>> e : xRef.entrySet()) {
+								TreeSet<PackageRef> refs = new TreeSet<Descriptors.PackageRef>();
+								for (TypeRef ref : e.getValue())
+									refs.add(ref.getPackageRef());
+
+								refs.retainAll(privates);
+								out.printf("%60s %-40s %s\n", e.getKey().getOwnerType().getFQN() //
+										, e.getKey().getName(), refs);
+							}
+							out.println();
+						}
+					}
+					out.println();
+				}
+
+				Map<PackageRef,List<PackageRef>> uses = analyzer.cleanupUses(analyzer.getUses(), !po.java());
 				if ((options & USES) != 0) {
 					out.println("[USES]");
-					printMapOfSets(new TreeMap<String, Set<String>>(analyzer.getUses()));
+					printMultiMap(uses);
 					out.println();
 				}
 				if ((options & USEDBY) != 0) {
 					out.println("[USEDBY]");
-					printMapOfSets(invertMapOfCollection(analyzer.getUses()));
+					MultiMap<PackageRef,PackageRef> usedBy = new MultiMap<Descriptors.PackageRef,Descriptors.PackageRef>(
+							uses).transpose();
+					printMultiMap(usedBy);
 				}
 			}
 
@@ -966,10 +1797,9 @@ public class bnd extends Processor {
 
 			if ((options & LIST) != 0) {
 				out.println("[LIST]");
-				for (Map.Entry<String, Map<String, Resource>> entry : jar.getDirectories()
-						.entrySet()) {
+				for (Map.Entry<String,Map<String,Resource>> entry : jar.getDirectories().entrySet()) {
 					String name = entry.getKey();
-					Map<String, Resource> contents = entry.getValue();
+					Map<String,Resource> contents = entry.getValue();
 					out.println(name);
 					if (contents != null) {
 						for (String element : contents.keySet()) {
@@ -997,11 +1827,26 @@ public class bnd extends Processor {
 				}
 				out.println();
 			}
-		} finally {
+		}
+		finally {
 			jar.close();
 		}
 	}
 
+	/**
+	 * @param manifest
+	 */
+	void printManifest(Manifest manifest) {
+		SortedSet<String> sorted = new TreeSet<String>();
+		for (Object element : manifest.getMainAttributes().keySet()) {
+			sorted.add(element.toString());
+		}
+		for (String key : sorted) {
+			Object value = manifest.getMainAttributes().getValue(key);
+			out.printf("%-40s %-40s\n", key, value);
+		}
+	}
+
 	private final char nibble(int i) {
 		return "0123456789ABCDEF".charAt(i & 0xF);
 	}
@@ -1037,18 +1882,18 @@ public class bnd extends Processor {
 		}
 
 		String componentHeader = manifest.getMainAttributes().getValue(Constants.SERVICE_COMPONENT);
-		Map<String, Map<String, String>> clauses = parseHeader(componentHeader);
+		Parameters clauses = new Parameters(componentHeader);
 		for (String path : clauses.keySet()) {
 			out.println(path);
 
 			Resource r = jar.getResource(path);
 			if (r != null) {
-				InputStreamReader ir = new InputStreamReader(r.openInputStream(),
-						Constants.DEFAULT_CHARSET);
+				InputStreamReader ir = new InputStreamReader(r.openInputStream(), Constants.DEFAULT_CHARSET);
 				OutputStreamWriter or = new OutputStreamWriter(out, Constants.DEFAULT_CHARSET);
 				try {
-					copy(ir, or);
-				} finally {
+					IO.copy(ir, or);
+				}
+				finally {
 					or.flush();
 					ir.close();
 				}
@@ -1073,9 +1918,9 @@ public class bnd extends Processor {
 			return;
 		}
 
-		Map<String, Resource> map = jar.getDirectories().get("OSGI-INF/metatype");
+		Map<String,Resource> map = jar.getDirectories().get("OSGI-INF/metatype");
 		if (map != null) {
-			for (Map.Entry<String, Resource> entry : map.entrySet()) {
+			for (Map.Entry<String,Resource> entry : map.entrySet()) {
 				out.println(entry.getKey());
 				IO.copy(entry.getValue().openInputStream(), out);
 				out.println();
@@ -1084,48 +1929,22 @@ public class bnd extends Processor {
 		}
 	}
 
-	Map<String, Set<String>> invertMapOfCollection(Map<String, Set<String>> map) {
-		Map<String, Set<String>> result = new TreeMap<String, Set<String>>();
-		for (Map.Entry<String, Set<String>> entry : map.entrySet()) {
-			String name = entry.getKey();
-			if (name.startsWith("java.") && !name.equals("java.sql"))
-				continue;
-
-			Collection<String> used = entry.getValue();
-			for (String n : used) {
-				if (n.startsWith("java.") && !n.equals("java.sql"))
-					continue;
-				Set<String> set = result.get(n);
-				if (set == null) {
-					set = new TreeSet<String>();
-					result.put(n, set);
-				}
-				set.add(name);
-			}
-		}
-		return result;
-	}
-
-	void printMapOfSets(Map<String, Set<String>> map) {
-		for (Map.Entry<String, Set<String>> entry : map.entrySet()) {
-			String name = entry.getKey();
-			Set<String> used = new TreeSet<String>(entry.getValue());
+	<T extends Comparable< ? >> void printMultiMap(Map<T, ? extends Collection< ? >> map) {
+		SortedList<Object> keys = new SortedList<Object>(map.keySet());
+		for (Object key : keys) {
+			String name = key.toString();
 
-			for (Iterator<String> k = used.iterator(); k.hasNext();) {
-				String n = (String) k.next();
-				if (n.startsWith("java.") && !n.equals("java.sql"))
-					k.remove();
-			}
-			String list = vertical(40, used);
-			format("%-40s %s", new Object[] { name, list });
+			SortedList<Object> values = new SortedList<Object>(map.get(key));
+			String list = vertical(40, values);
+			out.printf("%-40s %s\n", name, list);
 		}
 	}
 
-	String vertical(int padding, Set<String> used) {
-		StringBuffer sb = new StringBuffer();
+	String vertical(int padding, Collection< ? > used) {
+		StringBuilder sb = new StringBuilder();
 		String del = "";
-		for (Iterator<String> u = used.iterator(); u.hasNext();) {
-			String name = (String) u.next();
+		for (Object s : used) {
+			String name = s.toString();
 			sb.append(del);
 			sb.append(name);
 			sb.append("\r\n");
@@ -1137,1215 +1956,1054 @@ public class bnd extends Processor {
 	}
 
 	String pad(int i) {
-		StringBuffer sb = new StringBuffer();
+		StringBuilder sb = new StringBuilder();
 		while (i-- > 0)
 			sb.append(' ');
 		return sb.toString();
 	}
 
 	/**
-	 * View files from JARs
-	 * 
-	 * We parse the commandline and print each file on it.
+	 * @param msg
+	 * @param ports
+	 */
+
+	private void print(String msg, Map< ? , ? extends Map< ? , ? >> ports) {
+		if (ports.isEmpty())
+			return;
+		out.println(msg);
+		for (Entry< ? , ? extends Map< ? , ? >> entry : ports.entrySet()) {
+			Object key = entry.getKey();
+			Map< ? , ? > clause = Create.copy(entry.getValue());
+			clause.remove("uses:");
+			out.printf("  %-38s %s\n", key.toString().trim(), clause.isEmpty() ? "" : clause.toString());
+		}
+	}
+
+	/**
+	 * Patch
+	 */
+
+	interface patchOptions extends Options {
+
+	}
+
+	public void patch(patchOptions opts) throws Exception {
+		PatchCommand pcmd = new PatchCommand(this);
+		List<String> args = opts._();
+		opts._command().execute(pcmd, args.remove(0), args);
+	}
+
+	/**
+	 * Run the tests from a prepared bnd file.
 	 * 
 	 * @param args
 	 * @param i
 	 * @throws Exception
 	 */
-	private void doView(String[] args, int i) throws Exception {
-		int options = 0;
-		String charset = "UTF-8";
-		File output = null;
 
-		for (; i < args.length; i++) {
-			if ("-charset".startsWith(args[i]))
-				charset = args[++i];
-			else if ("-output".startsWith(args[i])) {
-				output = new File(args[++i]);
-			} else
-				break;
-		}
+	@Description("Run OSGi tests and create report")
+	interface runtestsOptions extends Options {
+		@Description("Report directory")
+		String reportdir();
 
-		if (i >= args.length) {
-			error("Insufficient arguments for view, no JAR");
-			return;
-		}
-		String jar = args[i++];
-		if (i >= args.length) {
-			error("No Files to view");
-			return;
-		}
+		@Description("Title in the report")
+		String title();
+
+		@Description("Path to work directory")
+		String dir();
 
-		doView(jar, args, i, charset, options, output);
+		@Description("Path to workspace")
+		String workspace();
 	}
 
-	private void doView(String jar, String[] args, int i, String charset, int options, File output) {
-		File path = new File(jar).getAbsoluteFile();
-		File dir = path.getParentFile();
-		if (dir == null) {
-			dir = new File("");
+	@Description("Run OSGi tests and create report")
+	public void _runtests(runtestsOptions opts) throws Exception {
+		int errors = 0;
+		File cwd = new File("").getAbsoluteFile();
+
+		Workspace ws = new Workspace(cwd);
+		File reportDir = getFile("reports");
+
+		IO.delete(reportDir);
+
+		Tag summary = new Tag("summary");
+		summary.addAttribute("date", new Date());
+		summary.addAttribute("ws", ws.getBase());
+
+		if (opts.reportdir() != null) {
+			reportDir = getFile(opts.reportdir());
 		}
-		if (!dir.exists()) {
-			error("No such file: " + dir.getAbsolutePath());
-			return;
+		if (!reportDir.exists() && !reportDir.mkdirs()) {
+			throw new IOException("Could not create directory " + reportDir);
 		}
 
-		String name = path.getName();
-		if (name == null)
-			name = "META-INF/MANIFEST.MF";
+		if (!reportDir.isDirectory())
+			error("reportdir must be a directory %s (tried to create it ...)", reportDir);
+
+		if (opts.title() != null)
+			summary.addAttribute("title", opts.title());
 
-		Instruction instruction = Instruction.getPattern(path.getName());
+		if (opts.dir() != null)
+			cwd = getFile(opts.dir());
 
-		File[] children = dir.listFiles();
-		for (int j = 0; j < children.length; j++) {
-			String base = children[j].getName();
-			// out.println("Considering: " +
-			// children[j].getAbsolutePath() + " " +
-			// instruction.getPattern());
-			if (instruction.matches(base) ^ instruction.isNegated()) {
-				for (; i < args.length; i++) {
-					doView(children[j], args[i], charset, options, output);
+		if (opts.workspace() != null)
+			ws = Workspace.getWorkspace(getFile(opts.workspace()));
+
+		// TODO check all the arguments
+
+		boolean hadOne = false;
+		try {
+			for (String arg : opts._()) {
+				trace("will run test %s", arg);
+				File f = getFile(arg);
+				errors += runtTest(f, ws, reportDir, summary);
+				hadOne = true;
+			}
+
+			if (!hadOne) {
+				// See if we had any, if so, just use all files in
+				// the current directory
+				File[] files = cwd.listFiles();
+				for (File f : files) {
+					if (f.getName().endsWith(".bnd")) {
+						errors += runtTest(f, ws, reportDir, summary);
+					}
 				}
 			}
 		}
-	}
+		catch (Throwable e) {
+			if (isExceptions())
+				e.printStackTrace();
 
-	private void doView(File file, String resource, String charset, int options, File output) {
-		// out.println("doView:" + file.getAbsolutePath() );
-		try {
-			Instruction instruction = Instruction.getPattern(resource);
-			FileInputStream fin = new FileInputStream(file);
-			ZipInputStream in = new ZipInputStream(fin);
-			ZipEntry entry = in.getNextEntry();
-			while (entry != null) {
-				// out.println("view " + file + ": "
-				// + instruction.getPattern() + ": " + entry.getName()
-				// + ": " + output + ": "
-				// + instruction.matches(entry.getName()));
-				if (instruction.matches(entry.getName()) ^ instruction.isNegated())
-					doView(entry.getName(), in, charset, options, output);
-				in.closeEntry();
-				entry = in.getNextEntry();
-			}
-			in.close();
-			fin.close();
-		} catch (Exception e) {
-			out.println("Can not process: " + file.getAbsolutePath());
-			e.printStackTrace();
+			error("FAILURE IN RUNTESTS", e);
+			errors++;
 		}
-	}
 
-	private void doView(String name, ZipInputStream in, String charset, int options, File output)
-			throws Exception {
-		int n = name.lastIndexOf('/');
-		name = name.substring(n + 1);
+		if (errors > 0)
+			summary.addAttribute("errors", errors);
 
-		InputStreamReader rds = new InputStreamReader(in, charset);
-		OutputStreamWriter wrt = new OutputStreamWriter(out, Constants.DEFAULT_CHARSET);
-		if (output != null)
-			if (output.isDirectory())
-				wrt = new FileWriter(new File(output, name));
-			else
-				wrt = new FileWriter(output);
+		for (String error : getErrors()) {
+			Tag e = new Tag("error");
+			e.addContent(error);
+		}
 
-		copy(rds, wrt);
-		// rds.close(); also closes the stream which closes our zip it
-		// seems
-		if (output != null)
-			wrt.close();
-		else
-			wrt.flush();
+		for (String warning : getWarnings()) {
+			Tag e = new Tag("warning");
+			e.addContent(warning);
+		}
+
+		File r = getFile(reportDir, "summary.xml");
+		FileOutputStream out = new FileOutputStream(r);
+		PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, "UTF-8"));
+
+		try {
+			summary.print(0, pw);
+		}
+		finally {
+			pw.close();
+			out.close();
+		}
+		if (errors != 0)
+			error("Errors found %s", errors);
 	}
 
-	private void copy(Reader rds, Writer wrt) throws IOException {
-		char buffer[] = new char[1024];
-		int size = rds.read(buffer);
-		while (size > 0) {
-			wrt.write(buffer, 0, size);
-			size = rds.read(buffer);
+	/**
+	 * Help function to run the tests
+	 */
+	private int runtTest(File testFile, Workspace ws, File reportDir, Tag summary) throws Exception {
+		File tmpDir = new File(reportDir, "tmp");
+		if (!tmpDir.exists() && !tmpDir.mkdirs()) {
+			throw new IOException("Could not create directory " + tmpDir);
 		}
-	}
+		tmpDir.deleteOnExit();
 
-	private void print(String msg, Map<String, Map<String, String>> ports) {
-		if (ports.isEmpty())
-			return;
-		out.println(msg);
-		for (Map.Entry<String, Map<String, String>> entry : ports.entrySet()) {
-			String key = entry.getKey();
-			Map<String, String> clause = Create.copy(entry.getValue());
-			clause.remove("uses:");
-			format("  %-38s %s\r\n", key.trim(), clause.isEmpty() ? "" : clause.toString());
+		Tag test = new Tag(summary, "test");
+		test.addAttribute("path", testFile.getAbsolutePath());
+		if (!testFile.isFile()) {
+			error("No bnd file: %s", testFile);
+			test.addAttribute("exception", "No bnd file found");
+			error("No bnd file found for %s", testFile.getAbsolutePath());
+			return 1;
 		}
-	}
 
-	private void format(String string, Object... objects) {
-		if (objects == null || objects.length == 0)
-			return;
-
-		StringBuffer sb = new StringBuffer();
-		int index = 0;
-		for (int i = 0; i < string.length(); i++) {
-			char c = string.charAt(i);
-			switch (c) {
-			case '%':
-				String s = objects[index++] + "";
-				int width = 0;
-				int justify = -1;
-
-				i++;
-
-				c = string.charAt(i++);
-				switch (c) {
-				case '-':
-					justify = -1;
-					break;
-				case '+':
-					justify = 1;
-					break;
-				case '|':
-					justify = 0;
-					break;
-				default:
-					--i;
-				}
-				c = string.charAt(i++);
-				while (c >= '0' && c <= '9') {
-					width *= 10;
-					width += c - '0';
-					c = string.charAt(i++);
-				}
-				if (c != 's') {
-					throw new IllegalArgumentException("Invalid sprintf format:  " + string);
-				}
+		Project project = new Project(ws, testFile.getAbsoluteFile().getParentFile(), testFile.getAbsoluteFile());
+		project.setTrace(isTrace());
+		project.setProperty(NOBUNDLES, "true");
 
-				if (s.length() > width)
-					sb.append(s);
-				else {
-					switch (justify) {
-					case -1:
-						sb.append(s);
-						for (int j = 0; j < width - s.length(); j++)
-							sb.append(" ");
-						break;
-
-					case 1:
-						for (int j = 0; j < width - s.length(); j++)
-							sb.append(" ");
-						sb.append(s);
-						break;
-
-					case 0:
-						int spaces = (width - s.length()) / 2;
-						for (int j = 0; j < spaces; j++)
-							sb.append(" ");
-						sb.append(s);
-						for (int j = 0; j < width - s.length() - spaces; j++)
-							sb.append(" ");
-						break;
-					}
-				}
-				break;
+		ProjectTester tester = project.getProjectTester();
 
-			default:
-				sb.append(c);
-			}
+		if (!project.isOk()) {
+			getInfo(project, project.toString() + ": " + testFile.getName() + ":");
+			return 1; // Indicate failure but do not abort
 		}
-		out.print(sb);
-	}
 
-	private void doWrap(String[] args, int i) throws Exception {
-		int options = 0;
-		File properties = null;
-		File output = null;
-		File classpath[] = null;
-		for (; i < args.length; i++) {
-			if ("-output".startsWith(args[i]))
-				output = new File(args[++i]);
-			else if ("-properties".startsWith(args[i]))
-				properties = new File(args[++i]);
-			else if ("-classpath".startsWith(args[i])) {
-				classpath = getClasspath(args[++i]);
-			} else {
-				File bundle = new File(args[i]);
-				doWrap(properties, bundle, output, classpath, options, null);
-			}
-		}
-	}
+		tester.setContinuous(false);
+		tester.setReportDir(tmpDir);
+		test.addAttribute("title", project.toString());
+		long start = System.currentTimeMillis();
+		try {
+			int errors = tester.test();
 
-	public boolean doWrap(File properties, File bundle, File output, File classpath[], int options,
-			Map<String, String> additional) throws Exception {
-		if (!bundle.exists()) {
-			error("No such file: " + bundle.getAbsolutePath());
-			return false;
-		} else {
-			Analyzer analyzer = new Analyzer();
-			try {
-				analyzer.setPedantic(isPedantic());
-				analyzer.setJar(bundle);
-				Jar dot = analyzer.getJar();
+			Collection<File> reports = tester.getReports();
+			for (File report : reports) {
+				Tag bundle = new Tag(test, "bundle");
+				File dest = new File(reportDir, report.getName());
+				report.renameTo(dest);
+				bundle.addAttribute("file", dest.getAbsolutePath());
+				doPerReport(bundle, dest);
+			}
 
-				if (properties != null) {
-					analyzer.setProperties(properties);
-				}
-				if (additional != null)
-					analyzer.putAll(additional, false);
-
-				if (analyzer.getProperty(Analyzer.IMPORT_PACKAGE) == null)
-					analyzer.setProperty(Analyzer.IMPORT_PACKAGE, "*;resolution:=optional");
-
-				if (analyzer.getProperty(Analyzer.BUNDLE_SYMBOLICNAME) == null) {
-					Pattern p = Pattern.compile("(" + Verifier.SYMBOLICNAME.pattern()
-							+ ")(-[0-9])?.*\\.jar");
-					String base = bundle.getName();
-					Matcher m = p.matcher(base);
-					base = "Untitled";
-					if (m.matches()) {
-						base = m.group(1);
-					} else {
-						error("Can not calculate name of output bundle, rename jar or use -properties");
-					}
-					analyzer.setProperty(Analyzer.BUNDLE_SYMBOLICNAME, base);
-				}
+			switch (errors) {
+				case ProjectLauncher.OK :
+					return 0;
 
-				if (analyzer.getProperty(Analyzer.EXPORT_PACKAGE) == null) {
-					String export = analyzer.calculateExportsFromContents(dot);
-					analyzer.setProperty(Analyzer.EXPORT_PACKAGE, export);
-				}
+				case ProjectLauncher.CANCELED :
+					test.addAttribute("failed", "canceled");
+					return 1;
 
-				if (classpath != null)
-					analyzer.setClasspath(classpath);
+				case ProjectLauncher.DUPLICATE_BUNDLE :
+					test.addAttribute("failed", "duplicate bundle");
+					return 1;
 
-				analyzer.mergeManifest(dot.getManifest());
+				case ProjectLauncher.ERROR :
+					test.addAttribute("failed", "unknown reason");
+					return 1;
 
-				//
-				// Cleanup the version ..
-				//
-				String version = analyzer.getProperty(Analyzer.BUNDLE_VERSION);
-				if (version != null) {
-					version = Builder.cleanupVersion(version);
-					analyzer.setProperty(Analyzer.BUNDLE_VERSION, version);
-				}
+				case ProjectLauncher.RESOLVE_ERROR :
+					test.addAttribute("failed", "resolve error");
+					return 1;
 
-				if (output == null)
-					if (properties != null)
-						output = properties.getAbsoluteFile().getParentFile();
-					else
-						output = bundle.getAbsoluteFile().getParentFile();
-
-				String path = bundle.getName();
-				if (path.endsWith(DEFAULT_JAR_EXTENSION))
-					path = path.substring(0, path.length() - DEFAULT_JAR_EXTENSION.length())
-							+ DEFAULT_BAR_EXTENSION;
-				else
-					path = bundle.getName() + DEFAULT_BAR_EXTENSION;
-
-				if (output.isDirectory())
-					output = new File(output, path);
-
-				analyzer.calcManifest();
-				Jar jar = analyzer.getJar();
-				getInfo(analyzer);
-				statistics(jar, output, "");
-				File f = File.createTempFile("tmpbnd", ".jar");
-				f.deleteOnExit();
-				try {
-					jar.write(f);
-					jar.close();
-					if (!f.renameTo(output)) {
-						copy(f, output);
-					}
-				} finally {
-					f.delete();
-				}
-				return getErrors().size() == 0;
-			} finally {
-				analyzer.close();
-			}
-		}
-	}
+				case ProjectLauncher.TIMEDOUT :
+					test.addAttribute("failed", "timed out");
+					return 1;
+				case ProjectLauncher.WARNING :
+					test.addAttribute("warning", "true");
+					return 1;
 
-	void doDiff(String args[], int first) throws Exception {
-		File base = new File("");
-		boolean strict = false;
-		Jar targets[] = new Jar[2];
-		int n = 0;
+				case ProjectLauncher.ACTIVATOR_ERROR :
+					test.addAttribute("failed", "activator error");
+					return 1;
 
-		for (int i = first; i < args.length; i++) {
-			if ("-d".equals(args[i]))
-				base = getFile(base, args[++i]);
-			else if ("-strict".equals(args[i]))
-				strict = "true".equalsIgnoreCase(args[++i]);
-			else if (args[i].startsWith("-"))
-				error("Unknown option for diff: " + args[i]);
-			else {
-				if (n >= 2)
-					System.err.println("Must have 2 files ... not more");
-				else {
-					File f = getFile(base, args[i]);
-					if (!f.isFile())
-						System.err.println("Not a file: " + f);
-					else {
-						try {
-							Jar jar = new Jar(f);
-							targets[n++] = jar;
-						} catch (Exception e) {
-							System.err.println("Not a JAR: " + f);
-						}
+				default :
+					if (errors > 0) {
+						test.addAttribute("errors", errors);
+						return errors;
 					}
-				}
+					test.addAttribute("failed", "unknown reason");
+					return errors;
 			}
 		}
-		if (n != 2) {
-			System.err.println("Must have 2 files ...");
-			return;
+		catch (Exception e) {
+			test.addAttribute("failed", e);
+			error("Exception in run %s", e);
+			return 1;
 		}
-		Diff diff = new Diff();
-
-		Map<String, Object> map = diff.diff(targets[0], targets[1], strict);
-		diff.print(System.out, map, 0);
-
-		for (Jar jar : targets) {
-			jar.close();
+		finally {
+			long duration = System.currentTimeMillis() - start;
+			test.addAttribute("duration", (duration + 500) / 1000);
+			getInfo(project, project.toString() + ": ");
 		}
-		diff.close();
 	}
 
-	void copy(File a, File b) {
+	/**
+	 * Calculate the coverage if there is coverage info in the test file.
+	 */
+
+	private void doPerReport(Tag report, File file) throws Exception {
 		try {
-			InputStream in = new FileInputStream(a);
-			OutputStream out = new FileOutputStream(b);
-			byte[] buffer = new byte[8196];
-			int size = in.read(buffer);
-			while (size > 0) {
-				out.write(buffer, 0, size);
-				size = in.read(buffer);
-			}
-			in.close();
-			out.close();
-		} catch (IOException e) {
-			error("While copying the output: %s -> %s", e, a, b);
+			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+			factory.setNamespaceAware(true); // never forget this!
+			DocumentBuilder builder = factory.newDocumentBuilder();
+			Document doc = builder.parse(file);
+
+			XPathFactory xpathFactory = XPathFactory.newInstance();
+			XPath xpath = xpathFactory.newXPath();
+
+			doCoverage(report, doc, xpath);
+			doHtmlReport(report, file, doc, xpath);
+
+		}
+		catch (Exception e) {
+			report.addAttribute("coverage-failed", e.getMessage());
 		}
 	}
 
-	public void setOut(PrintStream out) {
-		this.out = out;
+	private void doCoverage(Tag report, Document doc, XPath xpath) throws XPathExpressionException {
+		int bad = Integer.parseInt(xpath.evaluate("count(//method[count(ref)<2])", doc));
+		int all = Integer.parseInt(xpath.evaluate("count(//method)", doc));
+		report.addAttribute("coverage-bad", bad);
+		report.addAttribute("coverage-all", all);
 	}
 
-	public Project getProject() throws Exception {
-		if (project != null)
-			return project;
-
-		try {
-			project = Workspace.getProject(getBase());
-			if (project == null)
-				return null;
+	private void doHtmlReport(@SuppressWarnings("unused")
+	Tag report, File file, Document doc, @SuppressWarnings("unused")
+	XPath xpath) throws Exception {
+		String path = file.getAbsolutePath();
+		if (path.endsWith(".xml"))
+			path = path.substring(0, path.length() - 4);
+		path += ".html";
+		File html = new File(path);
+		trace("Creating html report: %s", html);
 
-			if (!project.isValid())
-				return null;
+		TransformerFactory fact = TransformerFactory.newInstance();
 
-			return project;
-		} catch (IllegalArgumentException e) {
-			return null;
+		InputStream in = getClass().getResourceAsStream("testreport.xsl");
+		if (in == null) {
+			warning("Resource not found: test-report.xsl, no html report");
+		} else {
+			OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(html), "UTF-8");
+			try {
+				Transformer transformer = fact.newTransformer(new StreamSource(in));
+				transformer.transform(new DOMSource(doc), new StreamResult(out));
+				trace("Transformed");
+			}
+			finally {
+				in.close();
+				out.close();
+			}
 		}
 	}
 
 	/**
-	 * Printout all the variables.
+	 * Merge a bundle with its source.
 	 * 
-	 * @param args
-	 * @param i
 	 * @throws Exception
 	 */
-	public void debug(String args[], int i) throws Exception {
-		Project project = getProject();
-		System.out.println("Project: " + project);
-		Properties p = project.getFlattenedProperties();
-		for (Object k : p.keySet()) {
-			String key = (String) k;
-			String s = p.getProperty(key);
-			Collection<String> l = null;
-
-			if (s.indexOf(',') > 0)
-				l = split(s);
-			else if (s.indexOf(':') > 0)
-				l = split(s, "\\s*:\\s*");
-			if (l != null) {
-				String del = key;
-				for (String ss : l) {
-					System.out.printf("%-40s %s\n", del, ss);
-					del = "";
+
+	@Description("Verify jars")
+	@Arguments(arg={"<jar path>", "[...]"})
+	interface verifyOptions extends Options {}
+
+	@Description("Verify jars")
+	public void _verify(verifyOptions opts) throws Exception {
+		for (String path : opts._()) {
+			File f = getFile(path);
+			if (!f.isFile()) {
+				error("No such file: %ss", f);
+			} else {
+				Jar jar = new Jar(f);
+				if (jar.getManifest() == null || jar.getBsn() == null)
+					error("Not a bundle %s", f);
+				else {
+					Verifier v = new Verifier(jar);
+					getInfo(v, f.getName());
+					v.close();
 				}
-			} else
-				System.out.printf("%-40s %s\n", key, s);
+				jar.close();
+			}
 		}
 	}
 
 	/**
-	 * Manage the repo.
+	 * Merge a bundle with its source.
 	 * 
-	 * <pre>
-	 *  repo
-	 *      list
-	 *      put <file|url>
-	 *      get <bsn> (<version>)?
-	 *      fetch <file|url>
-	 * </pre>
+	 * @throws Exception
 	 */
 
-	public void repo(String args[], int i) throws Exception {
-		String bsn = null;
-		String version = null;
-		List<RepositoryPlugin> repos = new ArrayList<RepositoryPlugin>();
-		RepositoryPlugin writable = null;
-
-		Project p = Workspace.getProject(getBase());
-		if (p != null) {
-			repos.addAll(p.getWorkspace().getRepositories());
-			for (Iterator<RepositoryPlugin> rp = repos.iterator(); rp.hasNext();) {
-				RepositoryPlugin rpp = rp.next();
-				if (rpp.canWrite()) {
-					writable = rpp;
-					break;
-				}
-			}
-		}
-
-		for (; i < args.length; i++) {
-			if ("repos".equals(args[i])) {
-				int n = 0;
-				for (RepositoryPlugin repo : repos) {
-					out.printf("%3d. %s\n", n++, repo);
-				}
-			} else if ("list".equals(args[i])) {
-				String mask = null;
-				if (i < args.length - 1) {
-					mask = args[++i];
-				}
-				repoList(repos, mask);
-			} else if ("-repo".equals(args[i])) {
-				String location = args[++i];
-				if (location.equals("maven")) {
-					System.out.println("Maven");
-					MavenRepository maven = new MavenRepository();
-					maven.setProperties(new HashMap<String, String>());
-					maven.setReporter(this);
-					repos = Arrays.asList((RepositoryPlugin) maven);
-				} else {
-					FileRepo repo = new FileRepo();
-					repo.setReporter(this);
-					repo.setLocation(location);
-					repos = Arrays.asList((RepositoryPlugin) repo);
-					writable = repo;
-				}
-			} else if ("-bsn".equals(args[i])) {
-				bsn = args[++i];
-			} else if ("-version".equals(args[i])) {
-				version = args[++i];
-			} else if ("spring".equals(args[i])) {
-				if (bsn == null || version == null) {
-					error("-bsn and -version must be set before spring command is used");
-				} else {
-					String url = String
-							.format("http://www.springsource.com/repository/app/bundle/version/download?name=%s&version=%s&type=binary",
-									bsn, version);
-					repoPut(writable, p, url, bsn, version);
-				}
-			} else if ("put".equals(args[i]))
-				while (++i < args.length) {
-					repoPut(writable, p, args[i], bsn, version);
-				}
-			else if ("get".equals(args[i]))
-				repoGet(repos, args[++i]);
-			else
-				repoFetch(repos, args[++i]);
-		}
+	@Description("Merge a binary jar with its sources. It is possible to specify  source path")
+	//
+	@Arguments(arg = {
+			"<jar path>", "<source path>"
+	})
+	//
+	interface sourceOptions extends Options {
+		@Description("The output file")
+		String output();
 	}
 
-	private void repoGet(List<RepositoryPlugin> writable, String string) {
-
-	}
+	@Description("Merge a binary jar with its sources. It is possible to specify  source path")
+	public void _source(sourceOptions opts) throws Exception {
+		List<String> arguments = opts._();
+		File jarFile = getFile(arguments.remove(0));
 
-	private void repoPut(RepositoryPlugin writable, Project project, String file, String bsn,
-			String version) throws Exception {
-		Jar jar = null;
-		int n = file.indexOf(':');
-		if (n > 1 && n < 10) {
-			jar = project.getValidJar(new URL(file));
-		} else {
-			File f = getFile(file);
-			if (f.isFile()) {
-				jar = project.getValidJar(f);
-			}
+		if (!jarFile.exists()) {
+			error("File %s does not exist ", jarFile);
+			return;
 		}
 
-		if (jar != null) {
-			Manifest manifest = jar.getManifest();
-			if (bsn != null)
-				manifest.getMainAttributes().putValue(Constants.BUNDLE_SYMBOLICNAME, bsn);
-			if (version != null)
-				manifest.getMainAttributes().putValue(Constants.BUNDLE_VERSION, version);
+		File sourceFile = getFile(arguments.remove(0));
+		if (!sourceFile.exists()) {
+			error("Source file %s does not exist ", sourceFile);
+			return;
+		}
 
-			writable.put(jar);
+		File output = jarFile;
+		if (opts.output() != null)
+			output = getFile(opts.output());
 
-		} else
-			error("There is no such file or url: " + file);
+		Jar bin = new Jar(jarFile);
+		File tmp = File.createTempFile("tmp", ".jar", jarFile.getParentFile());
+		tmp.deleteOnExit();
+		try {
+			Jar src = new Jar(sourceFile);
+			try {
+				for (String path : src.getResources().keySet())
+					bin.putResource("OSGI-OPT/src/" + path, src.getResource(path));
+				bin.write(tmp);
+			}
+			finally {
+				src.close();
+			}
+		}
+		finally {
+			bin.close();
+		}
+		tmp.renameTo(output);
 	}
 
-	private void repoFetch(List<RepositoryPlugin> repos, String string) {
-		File f = getFile(string);
-		if (f.isFile()) {
-		} else {
-			// try {
-			// URL url = new URL(string);
-			// } catch (MalformedURLException mue) {
-			//
-			// }
-		}
+	/**
+	 * Diff two jar files
+	 * 
+	 * @return
+	 * @throws Exception
+	 */
 
+	@Description("Diff jars")
+	public void _diff(diffOptions opts) throws Exception {
+		DiffCommand diff = new DiffCommand(this);
+		diff.diff(opts);
 	}
 
-	void repoList(List<RepositoryPlugin> repos, String mask) throws Exception {
-		trace("list repo " + repos + " " + mask);
-		Set<String> bsns = new TreeSet<String>();
-		for (RepositoryPlugin repo : repos) {
-			bsns.addAll(repo.list(mask));
-		}
+	/**
+	 * Baseline
+	 * 
+	 * @return
+	 * @throws Exception
+	 */
 
-		for (String bsn : bsns) {
-			Set<Version> versions = new TreeSet<Version>();
-			for (RepositoryPlugin repo : repos) {
-				List<Version> result = repo.versions(bsn);
-				if (result != null)
-					versions.addAll(result);
-			}
-			out.printf("%-40s %s\n", bsn, versions);
-		}
+	@Description("Compare a newer bundle to a baselined bundle and provide versioning advice")
+	public void _baseline(baseLineOptions opts) throws Exception {
+		BaselineCommands baseliner = new BaselineCommands(this);
+		baseliner._baseline(opts);
 	}
 
 	/**
-	 * Patch
+	 * Create a schema of package deltas and versions
+	 * 
+	 * @return
+	 * @throws Exception
 	 */
 
-	void patch(String args[], int i) throws Exception {
-		for (; i < args.length; i++) {
-			if ("create".equals(args[i]) && i + 3 < args.length) {
-				createPatch(args[++i], args[++i], args[++i]);
-			} else if ("apply".equals(args[i]) && i + 3 < args.length) {
-				applyPatch(args[++i], args[++i], args[++i]);
-			} else if ("help".equals(args[i])) {
-				out.println("patch (create <old> <new> <patch> | patch <old> <patch> <new>)");
-			} else
-				out.println("Patch does not recognize command? " + Arrays.toString(args));
-		}
+	@Description("Highly specialized function to create an overview of package deltas in ees")
+	public void _schema(schemaOptions opts) throws Exception {
+		BaselineCommands baseliner = new BaselineCommands(this);
+		baseliner._schema(opts);
 	}
 
-	void createPatch(String old, String newer, String patch) throws Exception {
-		Jar a = new Jar(new File(old));
-		Manifest am = a.getManifest();
-		Jar b = new Jar(new File(newer));
-		Manifest bm = b.getManifest();
+	public Project getProject() throws Exception {
+		return getProject(null);
+	}
 
-		Set<String> delete = newSet();
+	public Project getProject(String where) throws Exception {
+		if (where == null || where.equals("."))
+			where = Project.BNDFILE;
 
-		for (String path : a.getResources().keySet()) {
-			Resource br = b.getResource(path);
-			if (br == null) {
-				trace("DELETE    %s", path);
-				delete.add(path);
-			} else {
-				Resource ar = a.getResource(path);
-				if (isEqual(ar, br)) {
-					trace("UNCHANGED %s", path);
-					b.remove(path);
-				} else
-					trace("UPDATE    %s", path);
+		File f = getFile(where);
+		if (f.isDirectory()) {
+			f = new File(f, Project.BNDFILE);
+		}
+
+		if (f.isFile()) {
+			File projectDir = f.getParentFile();
+			File workspaceDir = projectDir.getParentFile();
+			Workspace ws = Workspace.getWorkspace(workspaceDir);
+			Project project = ws.getProject(projectDir.getName());
+			if (project.isValid()) {
+				project.setTrace(isTrace());
+				project.setPedantic(isPedantic());
+				return project;
 			}
 		}
 
-		bm.getMainAttributes().putValue("Patch-Delete", join(delete, ", "));
-		bm.getMainAttributes().putValue("Patch-Version",
-				am.getMainAttributes().getValue("Bundle-Version"));
+		if (where.equals(Project.BNDFILE)) {
+			return null;
+		}
+		error("Project not found: " + f);
 
-		b.write(new File(patch));
-		a.close();
-		a.close();
+		return null;
 	}
 
-	private boolean isEqual(Resource ar, Resource br) throws Exception {
-		InputStream ain = ar.openInputStream();
-		try {
-			InputStream bin = br.openInputStream();
+	/**
+	 * Convert files
+	 */
+	@Description("Converter to different formats")
+	@Arguments(arg = {
+			"from", "to"
+	})
+	interface convertOptions extends Options {
+		@Config(description = "Convert a manifest to a properties files")
+		boolean m2p();
+
+		@Config(description = "Save as xml")
+		boolean xml();
+	}
+
+	@Description("Converter to different formats")
+	public void _convert(convertOptions opts) throws IOException {
+		File from = getFile(opts._().get(0));
+		File to = getFile(opts._().get(1));
+		if (opts.m2p()) {
+			FileInputStream in = new FileInputStream(from);
 			try {
-				while (true) {
-					int an = ain.read();
-					int bn = bin.read();
-					if (an == bn) {
-						if (an == -1)
-							return true;
-					} else
-						return false;
+				Properties p = new Properties();
+				Manifest m = new Manifest(in);
+				Attributes attrs = m.getMainAttributes();
+				for (Map.Entry<Object,Object> i : attrs.entrySet()) {
+					p.put(i.getKey().toString(), i.getValue().toString());
+				}
+				FileOutputStream fout = new FileOutputStream(to);
+				try {
+					if (opts.xml())
+						p.storeToXML(fout, "converted from " + from);
+					else
+						p.store(fout, "converted from " + from);
 				}
-			} finally {
-				bin.close();
+				finally {
+					fout.close();
+				}
+			}
+			finally {
+				in.close();
 			}
-		} finally {
-			ain.close();
+			return;
 		}
+		error("no conversion specified");
 	}
 
-	void applyPatch(String old, String patch, String newer) throws Exception {
-		Jar a = new Jar(new File(old));
-		Jar b = new Jar(new File(patch));
-		Manifest bm = b.getManifest();
+	/**
+	 * Create a list of file names that match manifest headers bnd select -h
+	 * Bundle-SymbolicName --where (...) *
+	 */
+	@Description("Helps finding information in a set of JARs by filtering on manifest data and printing out selected information.")
+	@Arguments(arg = {
+		"<jar-path>", "[...]"
+	})
+	interface selectOptions extends Options {
+		@Description("A simple assertion on a manifest header (e.g. Bundle-Version=1.0.1) or an OSGi filter that is asserted on all manifest headers. Comparisons are case insensitive. The key 'resources' holds the pathnames of all resources and can also be asserted to check for the presence of a header.")
+		String where();
 
-		String patchDelete = bm.getMainAttributes().getValue("Patch-Delete");
-		String patchVersion = bm.getMainAttributes().getValue("Patch-Version");
-		if (patchVersion == null) {
-			error("To patch, you must provide a patch bundle.\nThe given " + patch
-					+ " bundle does not contain the Patch-Version header");
-			return;
-		}
+		@Description("A manifest header to print or: path, name, size, length, modified for information about the file, wildcards are allowed to print multiple headers. ")
+		Collection<String> header();
 
-		Collection<String> delete = split(patchDelete);
-		Set<String> paths = new HashSet<String>(a.getResources().keySet());
-		paths.removeAll(delete);
+		@Description("Print the key before the value")
+		boolean key();
 
-		for (String path : paths) {
-			Resource br = b.getResource(path);
-			if (br == null)
-				b.putResource(path, a.getResource(path));
-		}
+		@Description("Print the file name before the value")
+		boolean name();
 
-		bm.getMainAttributes().putValue("Bundle-Version", patchVersion);
-		b.write(new File(newer));
-		a.close();
-		b.close();
+		@Description("Print the file path before the value")
+		boolean path();
 	}
 
-	/**
-	 * Run the tests from a prepared bnd file.
-	 * 
-	 * @param args
-	 * @param i
-	 * @throws Exception
-	 */
-	public void runtests(String args[], int i) throws Exception {
-		int errors = 0;
-		File cwd = new File("").getAbsoluteFile();
-		Workspace ws = new Workspace(cwd);
-		File reportDir = getFile("reports");
+	@Description("Helps finding information in a set of JARs by filtering on manifest data and printing out selected information.")
+	public void _select(selectOptions opts) throws Exception {
+		PrintStream out = this.out;
 
-		IO.delete(reportDir);
-		reportDir.mkdirs();
+		Filter filter = null;
+		if (opts.where() != null) {
+			String w = opts.where();
+			if (!w.startsWith("("))
+				w = "(" + w + ")";
+			filter = new Filter(w);
+		}
 
-		Tag summary = new Tag("summary");
-		summary.addAttribute("date", new Date());
-		summary.addAttribute("ws", ws.getBase());
+		Instructions instructions = new Instructions(opts.header());
 
-		try {
-			boolean hadOne = false;
-
-			for (; i < args.length; i++) {
-				if (args[i].startsWith("-reportdir")) {
-					reportDir = getFile(args[++i]).getAbsoluteFile();
-					if (!reportDir.isDirectory())
-						error("reportdir must be a directory " + reportDir);
-				} else if (args[i].startsWith("-title")) {
-					summary.addAttribute("title", args[++i]);
-				} else if (args[i].startsWith("-dir")) {
-					cwd = getFile(args[++i]).getAbsoluteFile();
-				} else if (args[i].startsWith("-workspace")) {
-					File tmp = getFile(args[++i]).getAbsoluteFile();
-					ws = Workspace.getWorkspace(tmp);
-				} else {
-					File f = getFile(args[i]);
-					errors += runtTest(f, ws, reportDir, summary);
-					hadOne = true;
-				}
+		for (String s : opts._()) {
+			Jar jar = getJar(s);
+			if (jar == null) {
+				err.println("no file " + s);
+				continue;
+			}
+
+			Domain domain = Domain.domain(jar.getManifest());
+			Hashtable<String,Object> ht = new Hashtable<String,Object>();
+			Iterator<String> i = domain.iterator();
+			Set<String> realNames = new HashSet<String>();
+
+			while (i.hasNext()) {
+				String key = i.next();
+				String value = domain.get(key).trim();
+				ht.put(key.trim().toLowerCase(), value);
+				realNames.add(key);
+			}
+			ht.put("resources", jar.getResources().keySet());
+			realNames.add("resources");
+			if (filter != null) {
+				if (!filter.match(ht))
+					continue;
 			}
 
-			if (!hadOne) {
-				// See if we had any, if so, just use all files in
-				// the current directory
-				File[] files = cwd.listFiles();
-				for (File f : files) {
-					if (f.getName().endsWith(".bnd")) {
-						errors += runtTest(f, ws, reportDir, summary);
-					}
+			Set<Instruction> unused = new HashSet<Instruction>();
+			Collection<String> select = instructions.select(realNames, unused, true);
+			for (String h : select) {
+				if (opts.path()) {
+					out.print(jar.getSource().getAbsolutePath() + ":");
 				}
+				if (opts.name()) {
+					out.print(jar.getSource().getName() + ":");
+				}
+				if (opts.key()) {
+					out.print(h + ":");
+				}
+				out.println(ht.get(h.toLowerCase()));
+			}
+			for (Instruction ins : unused) {
+				String literal = ins.getLiteral();
+				if (literal.equals("name"))
+					out.println(jar.getSource().getName());
+				else if (literal.equals("path"))
+					out.println(jar.getSource().getAbsolutePath());
+				else if (literal.equals("size") || literal.equals("length"))
+					out.println(jar.getSource().length());
+				else if (literal.equals("modified"))
+					out.println(new Date(jar.getSource().lastModified()));
 			}
-		} catch (Throwable e) {
-			e.printStackTrace();
-			error("FAILURE IN RUNTESTS", e);
-			errors++;
 		}
-		if (errors > 0)
-			summary.addAttribute("errors", errors);
+	}
 
-		for (String error : getErrors()) {
-			Tag e = new Tag("error");
-			e.addContent(error);
-		}
+		/**
+	 * Central routine to get a JAR with error checking
+	 * 
+	 * @param s
+	 * @return
+	 */
+	Jar getJar(String s) {
 
-		for (String warning : getWarnings()) {
-			Tag e = new Tag("warning");
-			e.addContent(warning);
+		File f = getFile(s);
+		if (f.isFile()) {
+			try {
+				return new Jar(f);
+			}
+			catch (ZipException e) {
+				error("Not a jar/zip file: %s", f);
+			}
+			catch (Exception e) {
+				error("Opening file: %s", e, f);
+			}
+			return null;
 		}
 
-		File r = getFile(reportDir + "/summary.xml");
-		FileOutputStream out = new FileOutputStream(r);
-		PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, Constants.DEFAULT_CHARSET));
 		try {
-			summary.print(0, pw);
-		} finally {
-			pw.close();
-			out.close();
+			URL url = new URL(s);
+			return new Jar(s, url.openStream());
 		}
-		if (errors != 0)
-			error("Errors found %s", errors);
-	}
-
-	private int runtTest(File testFile, Workspace ws, File reportDir, Tag summary) throws Exception {
-		File tmpDir = new File(reportDir, "tmp");
-		tmpDir.mkdirs();
-		tmpDir.deleteOnExit();
-
-		Tag test = new Tag(summary, "test");
-		test.addAttribute("path", testFile.getAbsolutePath());
-		if (!testFile.isFile()) {
-			error("No bnd file: %s", testFile);
-			test.addAttribute("exception", "No bnd file found");
-			throw new FileNotFoundException("No bnd file found for " + testFile.getAbsolutePath());
+		catch (Exception e) {
+			// Ignore
 		}
 
-		Project project = new Project(ws, testFile.getAbsoluteFile().getParentFile(),
-				testFile.getAbsoluteFile());
-		project.setTrace(isTrace());
-		project.setProperty(NOBUNDLES, "true");
-
-		ProjectTester tester = project.getProjectTester();
+		error("Not a file or proper url: %s", f);
+		return null;
+	}
 
-		getInfo(project, project.toString() + ": ");
+	/**
+	 * Show the version of this bnd
+	 * 
+	 * @throws IOException
+	 */
 
-		if (!isOk())
-			throw new IllegalStateException("Errors found while creating the bnd test project "
-					+ testFile.getAbsolutePath());
+	@Description("Show version information about bnd")
+	@Arguments(arg={})
+	public interface versionOptions extends Options {
+		@Description("Show licensing, copyright, sha, scm, etc")
+		boolean xtra();
+	}
 
-		tester.setContinuous(false);
-		tester.setReportDir(tmpDir);
-		test.addAttribute("title", project.toString());
-		long start = System.currentTimeMillis();
-		try {
-			int errors = tester.test();
+	@Description("Show version information about bnd")
+	public void _version(versionOptions o) throws IOException {
+		if (!o.xtra()) {
+			Analyzer a = new Analyzer();
+			out.println(a.getBndVersion());
+			a.close();
+			return;
+		}
+		Enumeration<URL> e = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF");
+		while (e.hasMoreElements()) {
+			URL u = e.nextElement();
 
-			Collection<File> reports = tester.getReports();
-			for (File report : reports) {
-				Tag bundle = new Tag(test, "bundle");
-				File dest = new File(reportDir, report.getName());
-				report.renameTo(dest);
-				bundle.addAttribute("file", dest.getAbsolutePath());
-				doPerReport(bundle, dest);
-			}
+			Manifest m = new Manifest(u.openStream());
+			String bsn = m.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
+			if (bsn != null && bsn.equals("biz.aQute.bnd")) {
+				Attributes attrs = m.getMainAttributes();
 
-			switch (errors) {
-			case ProjectLauncher.OK:
-				return 0;
-
-			case ProjectLauncher.CANCELED:
-				test.addAttribute("failed", "canceled");
-				return 1;
-
-			case ProjectLauncher.DUPLICATE_BUNDLE:
-				test.addAttribute("failed", "duplicate bundle");
-				return 1;
-
-			case ProjectLauncher.ERROR:
-				test.addAttribute("failed", "unknown reason");
-				return 1;
-
-			case ProjectLauncher.RESOLVE_ERROR:
-				test.addAttribute("failed", "resolve error");
-				return 1;
-
-			case ProjectLauncher.TIMEDOUT:
-				test.addAttribute("failed", "timed out");
-				return 1;
-			case ProjectLauncher.WARNING:
-				test.addAttribute("warning", "true");
-				return 1;
-
-			case ProjectLauncher.ACTIVATOR_ERROR:
-				test.addAttribute("failed", "activator error");
-				return 1;
-
-			default:
-				if (errors > 0) {
-					test.addAttribute("errors", errors);
-					return errors;
-				} else {
-					test.addAttribute("failed", "unknown reason");
-					return 1;
+				long lastModified = 0;
+				try {
+					lastModified = Long.parseLong(attrs.getValue("Bnd-LastModified"));
 				}
+				catch (Exception ee) {
+					// Ignore
+				}
+				out.printf("%-40s %s\n", "Version", attrs.getValue(Constants.BUNDLE_VERSION));
+				if (lastModified > 0)
+					out.printf("%-40s %s\n", "From", new Date(lastModified));
+				Parameters p = OSGiHeader.parseHeader(attrs.getValue(Constants.BUNDLE_LICENSE));
+				for (String l : p.keySet())
+					out.printf("%-40s %s\n", "License", p.get(l).get("description"));
+				out.printf("%-40s %s\n", "Copyright", attrs.getValue(Constants.BUNDLE_COPYRIGHT));
+				out.printf("%-40s %s\n", "Git-SHA", attrs.getValue("Git-SHA"));
+				out.printf("%-40s %s\n", "Git-Descriptor", attrs.getValue("Git-Descriptor"));
+				out.printf("%-40s %s\n", "Sources", attrs.getValue("Bundle-SCM"));
+				return;
 			}
-		} catch (Exception e) {
-			test.addAttribute("failed", e);
-			throw e;
-		} finally {
-			long duration = System.currentTimeMillis() - start;
-			test.addAttribute("duration", (duration + 500) / 1000);
-			getInfo(project, project.toString() + ": ");
 		}
+		error("Could not locate version");
 	}
 
 	/**
-	 * Calculate the coverage if there is coverage info in the test file.
+	 * Show some key info of the project
 	 */
+	@Arguments(arg = {})
+	@Description("Show key project variables")
+	interface infoOptions extends Options {
+		boolean runbundles();
 
-	private void doPerReport(Tag report, File file) throws Exception {
-		try {
-			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-			factory.setNamespaceAware(true); // never forget this!
-			DocumentBuilder builder = factory.newDocumentBuilder();
-			Document doc = builder.parse(file);
+		boolean buildpath();
 
-			XPathFactory xpathFactory = XPathFactory.newInstance();
-			XPath xpath = xpathFactory.newXPath();
+		boolean dependsOn();
 
-			doCoverage(report, doc, xpath);
-			doHtmlReport(report, file, doc, xpath);
+		boolean sourcepath();
 
-		} catch (Exception e) {
-			report.addAttribute("coverage-failed", e.getMessage());
-		}
-	}
+		boolean classpath();
 
-	private void doCoverage(Tag report, Document doc, XPath xpath) throws XPathExpressionException {
-		int bad = Integer.parseInt(xpath.evaluate("count(//method[count(ref)<2])", doc));
-		int all = Integer.parseInt(xpath.evaluate("count(//method)", doc));
-		report.addAttribute("coverage-bad", bad);
-		report.addAttribute("coverage-all", all);
+		boolean vmpath();
+
+		String project();
 	}
 
-	private void doHtmlReport(Tag report, File file, Document doc, XPath xpath) throws Exception {
-		String path = file.getAbsolutePath();
-		if (path.endsWith(".xml"))
-			path = path.substring(0, path.length() - 4);
-		path += ".html";
-		File html = new File(path);
-		trace("Creating html report: %s", html);
+	@Description("Show key project variables")
+	public void _info(infoOptions options) throws Exception {
+		Project p = getProject(options.project());
+		if (p == null) {
+			messages.NoProject();
+			return;
+		}
+		boolean any = options.runbundles() || options.buildpath() || options.classpath() || options.dependsOn()
+				|| options.vmpath();
 
-		TransformerFactory fact = TransformerFactory.newInstance();
+		MultiMap<String,Object> table = new MultiMap<String,Object>();
+		if (any || options.runbundles()) {
+			table.addAll("Run", p.getRunbundles());
+		}
+		if (any || options.buildpath()) {
+			table.addAll("Build", p.getBuildpath());
+		}
+		if (any || options.buildpath()) {
+			table.addAll("Depends on", p.getDependson());
+		}
+		if (any || options.sourcepath()) {
+			table.addAll("Source", p.getSourcePath());
+		}
+		if (any || options.classpath()) {
+			table.addAll("Class path", p.getClasspath());
+		}
 
-		InputStream in = getClass().getResourceAsStream("testreport.xsl");
-		if (in == null) {
-			warning("Resource not found: test-report.xsl, no html report");
-		} else {
-			FileWriter out = new FileWriter(html);
-			try {
-				Transformer transformer = fact.newTransformer(new StreamSource(in));
-				transformer.transform(new DOMSource(doc), new StreamResult(out));
-				trace("Transformed");
-			} finally {
-				in.close();
-				out.close();
-			}
+		if (any || options.vmpath()) {
+			table.addAll("Run path", p.getRunpath());
 		}
+
+		printMultiMap(table);
 	}
 
 	/**
-	 * Extract a file from the JAR
+	 * Grep in jars
 	 */
+	@Arguments(arg = {
+			"pattern", "file..."
+	})
+	@Description("Grep the manifest of bundles/jar files. ")
+	interface grepOptions extends Options {
 
-	public void doExtract(String args[], int i) throws Exception {
-		if (i >= args.length) {
-			error("No arguments for extract");
-			return;
-		}
+		@Description("Search in exports")
+		boolean exports();
+
+		@Description("Search in imports")
+		boolean imports();
+
+		@Description("Search in bsn")
+		boolean bsn();
+
+		@Description("Set header(s) to search, can be wildcarded. The default is all headers (*).")
+		Set<String> headers();
+
+	}
 
-		File f = getFile(args[i++]);
-		if (!f.isFile()) {
-			error("No JAR file to extract from: %s", f);
+	@Description("Grep the manifest of bundles/jar files. ")
+	public void _grep(grepOptions opts) throws Exception {
+		List<String> args = opts._();
+		String s = args.remove(0);
+		Pattern pattern = Glob.toPattern(s);
+		if (pattern == null) {
+			messages.InvalidGlobPattern_(s);
 			return;
 		}
 
-		if (i == args.length) {
-			System.out.println("FILES:");
-			doPrint(f, LIST);
-			return;
+		if (args.isEmpty()) {
+			args = new ExtList<String>(getBase().list(new FilenameFilter() {
+
+				public boolean accept(File dir, String name) {
+					return name.endsWith(".jar");
+				}
+			}));
 		}
-		Jar j = new Jar(f);
-		try {
-			Writer output = new OutputStreamWriter(out, Constants.DEFAULT_CHARSET);
-			while (i < args.length) {
-				String path = args[i++];
 
-				Resource r = j.getResource(path);
-				if (r == null)
-					error("No such resource: %s in %s", path, f);
-				else {
-					InputStream in = r.openInputStream();
-					try {
-						InputStreamReader rds = new InputStreamReader(in, Constants.DEFAULT_CHARSET);
-						copy(rds, output);
-						output.flush();
-					} finally {
-						in.close();
+		Set<String> headers = opts.headers();
+		if (headers == null)
+			headers = new TreeSet<String>();
+
+		if (opts.exports())
+			headers.add(Constants.EXPORT_PACKAGE);
+		if (opts.bsn())
+			headers.add(Constants.BUNDLE_SYMBOLICNAME);
+		if (opts.imports())
+			headers.add(Constants.IMPORT_PACKAGE);
+
+		Instructions instructions = new Instructions(headers);
+
+		for (String fileName : args) {
+			File file = getFile(fileName);
+			if (!file.isFile()) {
+				messages.NoSuchFile_(file);
+				continue;
+			}
+
+			JarInputStream in = new JarInputStream(new FileInputStream(file));
+			try {
+				Manifest m = in.getManifest();
+				for (Object header : m.getMainAttributes().keySet()) {
+					Attributes.Name name = (Name) header;
+					if (instructions.isEmpty() || instructions.matches(name.toString())) {
+						String h = m.getMainAttributes().getValue(name);
+						QuotedTokenizer qt = new QuotedTokenizer(h, ",;=");
+						for (String value : qt.getTokenSet()) {
+							Matcher matcher = pattern.matcher(value);
+							while (matcher.find()) {
+								int start = matcher.start() - 8;
+								if (start < 0)
+									start = 0;
+
+								int end = matcher.end() + 8;
+								if (end > value.length())
+									end = value.length();
+
+								out.printf("%40s : %20s ...%s[%s]%s...\n", fileName, name,
+										value.substring(start, matcher.start()),
+										value.substring(matcher.start(), matcher.end()),
+										value.substring(matcher.end(), end));
+							}
+						}
 					}
 				}
 			}
-		} finally {
-			j.close();
+			finally {
+				in.close();
+			}
 		}
-
 	}
 
-	void doDot(String args[], int i) throws Exception {
-		File out = getFile("graph.gv");
-		Builder b = new Builder();
+	/**
+	 * Handle the global settings
+	 */
+	@Description("Set bnd/jpm global variables. The key can be wildcard.")
+	@Arguments(arg={"<key>[=<value>]..."})
+	interface settingOptions extends Options {
+		@Description("Clear all the settings, including the public and private key")
+		boolean clear();
 
-		for (; i < args.length; i++) {
-			if ("-o".equals(args[i]))
-				out = getFile(args[++i]);
-			else if (args[i].startsWith("-"))
-				error("Unknown option for dot: %s", args[i]);
-			else
-				b.addClasspath(getFile(args[i]));
-		}
-		b.setProperty(EXPORT_PACKAGE, "*");
-		b.setPedantic(isPedantic());
-		b.build();
-		FileWriter os = new FileWriter(out);
-		PrintWriter pw = new PrintWriter(os);
-		try {
-			pw.println("digraph bnd {");
-			pw.println("  size=\"6,6\";");
-			pw.println("node [color=lightblue2, style=filled,shape=box];");
-			for (Map.Entry<String, Set<String>> uses : b.getUses().entrySet()) {
-				for (String p : uses.getValue()) {
-					if (!p.startsWith("java."))
-						pw.printf("\"%s\" -> \"%s\";\n", uses.getKey(), p);
-				}
-			}
-			pw.println("}");
+		@Description("Show the public key")
+		boolean publicKey();
 
-		} finally {
-			pw.close();
-		}
+		@Description("Show the private secret key")
+		boolean secretKey();
 
+		@Description("Sign the strings on the commandline")
+		boolean mac();
+
+		@Description("Show key in hex")
+		boolean hex();
 	}
 
-	private void traverse(List<File> files, File f) {
-		if (f.isFile()) {
-			if (f.getName().endsWith(".jar"))
-				files.add(f);
-		} else if (f.isDirectory()) {
-			File[] subs = f.listFiles();
-			for (File sub : subs) {
-				traverse(files, sub);
+	@Description("Set bnd/jpm global variables")
+	public void _settings(settingOptions opts) throws Exception {
+		try {
+			trace("settings %s", opts.clear());
+			List<String> rest = opts._();
+
+			if (opts.clear()) {
+				settings.clear();
+				trace("clear %s", settings.entrySet());
 			}
-		}
-	}
 
-	public void global(String args[], int i) throws BackingStoreException {
-		Settings settings = new Settings();
+			if (opts.publicKey()) {
+				out.println(tos(opts.hex(), settings.getPublicKey()));
+				return;
+			}
+			if (opts.secretKey()) {
+				out.println(tos(opts.hex(), settings.getPrivateKey()));
+				return;
+			}
 
-		if (args.length == i) {
-			for (String key : settings.getKeys())
-				System.out.printf("%-30s %s\n", key, settings.globalGet(key, "<>"));
-		} else {
-			while (i < args.length) {
-				boolean remove = false;
-				if ("-remove".equals(args[i])) {
-					remove = true;
-					i++;
-				}
-				if (i + 1 == args.length) {
-					if (remove)
-						settings.globalRemove(args[i]);
-					else
-						System.out.printf("%-30s %s\n", args[i], settings.globalGet(args[i], "<>"));
-					i++;
-				} else {
-					settings.globalSet(args[i], args[i + 1]);
-					i += 2;
+			if (opts.mac()) {
+				for (String s : rest) {
+					byte[] data = s.getBytes("UTF-8");
+					byte[] signature = settings.sign(data);
+					out.printf("%s\n", tos(opts.hex(), signature));
 				}
+				return;
 			}
-		}
-	}
-
-	/**
-	 * Merge a bundle with its source.
-	 * 
-	 * @throws Exception
-	 */
 
-	public void doMerge(String args[], int i) throws Exception {
-		File out = null;
-		// String prefix = "";
-		// boolean maven;
-
-		List<Jar> sourcePath = new ArrayList<Jar>();
-		while (i < args.length - 1) {
-			String arg = args[i++];
-			if (arg.equals("-o")) {
-				out = getFile(arg);
-			} else if (arg.equals("-maven")) {
-				// maven = true;
+			if (rest.isEmpty()) {
+				list(null, settings);
 			} else {
-				File source = getFile(arg);
-				if (source.exists()) {
-					Jar jar = new Jar(source);
-					addClose(jar);
-					sourcePath.add(jar);
-				} else {
-					error("Sourec file/dir does not exist");
+				boolean set = false;
+				for (String s : rest) {
+					Matcher m = ASSIGNMENT.matcher(s);
+					trace("try %s", s);
+					if (m.matches()) {
+						trace("matches %s %s %s", s, m.group(1), m.group(2));
+						String key = m.group(1);
+						Instructions instr = new Instructions(key);
+						Collection<String> select = instr.select(settings.keySet(), true);
+
+						String value = m.group(2);
+						if (value == null) {
+							trace("list wildcard " + instr + " " + select + " " + settings.keySet());
+							list(select, settings);
+						} else {
+							trace("assignment 	");
+							settings.put(key, value);
+							set = true;
+						}
+					} else {
+						err.printf("Cannot assign %s\n", s);
+
+					}
+				}
+				if (set) {
+					trace("saving");
+					settings.save();
 				}
 			}
 		}
-		if (i >= args.length) {
-			error("No binary file specified");
-			return;
+		catch (Exception e) {
+			e.printStackTrace();
 		}
+	}
 
-		File binary = getFile(args[i]);
-		Jar output = new Jar(binary);
-		try {
-			Analyzer analyzer = new Analyzer();
-			analyzer.setJar(output);
-			analyzer.analyze();
-
-			outer: for (Clazz clazz : analyzer.getClassspace().values()) {
-				String sourcename = clazz.getSourceFile();
-				String path = clazz.getPath();
-				int n = path.lastIndexOf('/');
-				if (n >= 0) {
-					path = path.substring(0, n + 1);
-				} else
-					path = "";
-
-				String cname = path + sourcename;
-				for (Jar source : sourcePath) {
-					Resource r = source.getResource(cname);
-					if (r != null) {
-						output.putResource("OSGI-OPT/src/" + cname, r);
-						continue outer;
-					}
-				}
-				error("Source not found %s", cname);
-			}
+	private String tos(boolean hex, byte[] data) {
+		return hex ? Hex.toHexString(data) : Base64.encodeBase64(data);
+	}
 
-			if (out == null) {
-				File backup = new File(binary.getAbsolutePath() + ".bak");
-				binary.renameTo(backup);
-				out = binary;
-			}
-			output.write(out);
-		} finally {
-			output.close();
-			for (Jar jar : sourcePath)
-				jar.close();
+	private void list(Collection<String> keys, Map<String,String> map) {
+		for (Entry<String,String> e : map.entrySet()) {
+			if (keys == null || keys.contains(e.getKey()))
+				out.printf("%-40s = %s\n", e.getKey(), e.getValue());
 		}
 	}
 
+	enum Alg {
+		SHA1, MD5
+	};
+
 	/**
-	 * Create lib file on a directory.
-	 * 
-	 * @throws Exception
+	 * hash a file
 	 * 
 	 * @throws Exception
+	 * @throws NoSuchAlgorithmException
 	 */
+	@Description("Digest a number of files")
+	@Arguments(arg = "file...")
+	interface hashOptions extends Options {
 
-	public void doLib(String args[], int i) throws Exception {
-		File out = null;
-		List<File> files = new ArrayList<File>();
+		@Description("Show hex output (default)")
+		boolean hex();
 
-		while (i < args.length) {
-			String arg = args[i++];
-			if ("-o".equals(arg)) {
-				out = getFile(args[i++]);
-			} else if (arg.startsWith("-")) {
-				error("Unknown option: %s", arg);
-			} else
-				files.add(getFile(arg));
-		}
-		if (files.isEmpty()) {
-			error("No files specified for lib");
-			return;
-		}
+		@Description("Show base64 output")
+		boolean b64();
 
-		if (out == null) {
-			out = getFile(files.get(0).getName() + ".lib");
-		}
+		@Description("Show process info")
+		boolean process();
 
-		System.out.println("Using " + out);
-		Writer w = new FileWriter(out);
-		try {
-			for (File file : files) {
-				System.out.println("And using " + file);
-				if (file.isDirectory())
-					doLib(file, w);
-				else if (file.isFile())
-					doSingleFileLib(file, w);
-				else if (!file.equals(out))
-					error("Not a file %s", file);
-			}
-		} finally {
-			w.close();
-		}
+		@Description("Show the file name")
+		boolean name();
+
+		@Description("Specify the algorithms")
+		List<Alg> algorithm();
 	}
 
-	public void doLib(File dir, Appendable out) throws Exception {
-		for (File file : dir.listFiles()) {
-			doSingleFileLib(file, out);
+	@Description("Digests a number of files")
+	public void _digest(hashOptions o) throws NoSuchAlgorithmException, Exception {
+		long start = System.currentTimeMillis();
+		long total = 0;
+		List<Alg> algs = o.algorithm();
+		if (algs == null)
+			algs = Arrays.asList(Alg.SHA1);
+
+		for (String s : o._()) {
+			File f = getFile(s);
+			if (f.isFile()) {
+
+				outer: for (Alg alg : algs) {
+					long now = System.currentTimeMillis();
+					Digest digest;
+
+					switch (alg) {
+						default :
+							error("no such algorithm %s", alg);
+							continue outer;
+
+						case SHA1 :
+							digest = SHA1.digest(f);
+							break;
+						case MD5 :
+							digest = MD5.digest(f);
+							break;
+					}
+
+					StringBuilder sb = new StringBuilder();
+					String del = "";
+
+					if (o.hex() || !o.b64()) {
+						sb.append(del).append(digest.asHex());
+						del = " ";
+					}
+					if (o.b64()) {
+						sb.append(del).append(Base64.encodeBase64(digest.digest()));
+						del = " ";
+					}
+					if (o.name()) {
+						sb.append(del).append(f.getAbsolutePath());
+						del = " ";
+					}
+					if (o.process()) {
+						sb.append(del).append(System.currentTimeMillis() - now).append(" ms ")
+								.append(f.length() / 1000).append(" Kb");
+						total += f.length();
+					}
+					out.println(sb);
+				}
+			} else
+				error("file does not exist %s", f);
+		}
+		if (o.process()) {
+			long time = (System.currentTimeMillis() - start);
+			float mb = total / 1000000;
+			out.format("Total %s Mb, %s ms, %s Mb/sec %s files\n", mb, time, (total / time) / 1024, o._().size());
 		}
 	}
 
 	/**
-	 * @param out
-	 * @param file
-	 * @throws IOException
+	 * Maven command
+	 * 
 	 * @throws Exception
 	 */
-	void doSingleFileLib(File file, Appendable out) throws IOException, Exception {
-		Jar jar = new Jar(file);
-		String bsn = jar.getBsn();
-		System.out.println(bsn);
-		String version = jar.getVersion();
-		jar.close();
-		if (bsn == null) {
-			error("No valid bsn for %s", file);
-			bsn = "not set";
-		}
-		if (version == null)
-			version = "0";
-
-		Version v = new Version(version);
-		v = new Version(v.getMajor(), v.getMinor(), v.getMicro());
-		out.append(bsn);
-		out.append(";version=" + v + "\n"); // '[" + v + "," + v + "]'\n");
-	}
 
-	/**
-	 * @return
-	 * @throws IOException
-	 * @throws MalformedURLException
-	 */
-	protected Jar getJarFromFileOrURL(String spec) throws IOException, MalformedURLException {
-		Jar jar;
-		File jarFile = getFile(spec);
-		if (jarFile.exists()) {
-			jar = new Jar(jarFile);
-		} else {
-			URL url = new URL(spec);
-			InputStream in = url.openStream();
-			try {
-				jar = new Jar(url.getFile(), in);
-			} finally {
-				in.close();
-			}
-		}
-		addClose(jar);
-		return jar;
+	@Description("Maven bundle command")
+	public void _maven(Options options) throws Exception {
+		MavenCommand mc = new MavenCommand(this);
+		mc.setTrace(isTrace());
+		mc.setExceptions(isExceptions());
+		mc.setPedantic(isPedantic());
+		mc.run(options._().toArray(new String[0]), 1);
+		getInfo(mc);
 	}
-
 }
diff --git a/biz.aQute.bnd/src/aQute/bnd/main/schema.xsl b/biz.aQute.bnd/src/aQute/bnd/main/schema.xsl
new file mode 100644
index 0000000..f0480e3
--- /dev/null
+++ b/biz.aQute.bnd/src/aQute/bnd/main/schema.xsl
@@ -0,0 +1,346 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0"
+	xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+	<xsl:output method="html" />
+	<xsl:template match="/">
+		<html>
+			<head>
+				<link rel="stylesheet"
+					href="http://twitter.github.com/bootstrap/1.4.0/bootstrap.min.css" />
+				<title>Package Overview</title>
+			</head>
+			<body>
+				<div class="span16">
+					<h1>Overview of Packages</h1>
+					<h2>Included JARs</h2>
+					<p>This page contains an overview of packages that were found in
+						the following jars</p>
+					<table>
+						<tr>
+							<th>Name</th>
+							<th>Title</th>
+							<th>JAR</th>
+						</tr>
+						<xsl:for-each select="//specification">
+							<tr>
+								<td>
+									<a href="#{@id}">
+										<xsl:value-of select="@name" />
+										<xsl:value-of select="@version" />
+									</a>
+								</td>
+								<td>
+									<xsl:value-of select="@title" />
+								</td>
+								<td>
+									<xsl:value-of select="@jar" />
+								</td>
+							</tr>
+						</xsl:for-each>
+					</table>
+					<hr />
+
+					<h2>Baselining</h2>
+					<p>
+						The following table contains the result of listing all found
+						packages. If a package has a prior then it will be compared to
+						this prior version. The version column will show the result:
+						<table>
+							<tr>
+								<td>Δ</td>
+								<td>Indicates there was a delta.</td>
+							</tr>
+							<tr>
+								<td>Δ=</td>
+								<td>Indicates that the package and version are the same</td>
+							</tr>
+							<tr>
+								<td>
+									<span class="label important">Δ!</span>
+								</td>
+								<td>There was a delta but a semantic version mismatch</td>
+							</tr>
+							<tr>
+								<td>
+									<span class="label warning">Δ=</span>
+								</td>
+								<td>There was no delta but the version differed</td>
+							</tr>
+						</table>
+						The Δ is a link to the details of the baseline comparison.
+					</p>
+					<table>
+						<thead>
+							<tr>
+
+								<th>Name</th>
+								<th>Delta</th>
+								<th>Version</th>
+								<th>Specification</th>
+								<th>Version</th>
+								<th>JSR</th>
+							</tr>
+						</thead>
+						<xsl:variable name="all" select="//package" />
+						<xsl:for-each select="$all">
+							<xsl:sort select="@name" />
+							<xsl:sort select="@version" />
+							<xsl:variable name="id" select="@spec" />
+							<xsl:variable name="ref" select="//specification[@id=$id]" />
+
+							<tr>
+								<td>
+									<xsl:choose>
+										<xsl:when test="@name=preceding-sibling::node()/@name" />
+										<xsl:otherwise>
+											<xsl:value-of select="@name" />
+										</xsl:otherwise>
+									</xsl:choose>
+								</td>
+								<td>
+									<xsl:if test="@delta">
+										<a href="#{@delta}">
+											<xsl:if
+												test="normalize-space(//info[@id=current()/@delta]/@warning)">
+												<xsl:attribute name="alt"><xsl:value-of
+													select="//info[@id=current()/@delta]/@warning" /></xsl:attribute>
+												<xsl:attribute name="class">label warning</xsl:attribute>
+											</xsl:if>
+											<xsl:if test="//info[@id=current()/@delta and @mismatch='true']">
+												<xsl:attribute name="class">label important</xsl:attribute>
+											</xsl:if>
+											Δ
+											<xsl:if test="//info[@id=current()/@delta and @equals]">
+												=
+											</xsl:if>
+											<xsl:if test="//info[@id=current()/@delta and @mismatch='true']">
+												!
+											</xsl:if>
+										</a>
+									</xsl:if>
+								</td>
+								<td>
+									<xsl:value-of select="@version" />
+								</td>
+								<td>
+									<a href="#{$id}">
+										<xsl:value-of select="$ref/@name" />
+									</a>
+								</td>
+								<td>
+									<xsl:value-of select="$ref/@version" />
+								</td>
+								<td>
+									<a href="{$ref/@url}">
+										<xsl:value-of select="$ref/@jsr" />
+									</a>
+								</td>
+							</tr>
+						</xsl:for-each>
+					</table>
+					<hr />
+					<h2>Specification Releases</h2>
+					<table>
+						<thead>
+							<tr>
+								<th>Name</th>
+								<th>Version</th>
+								<th>JSR</th>
+								<th>Description</th>
+							</tr>
+						</thead>
+						<xsl:for-each select="//specification">
+							<xsl:sort select="@name" />
+							<xsl:sort select="@version" />
+							<tr>
+								<td>
+									<a name="{@id}" />
+									<xsl:value-of select="@name" />
+								</td>
+								<td>
+									<xsl:value-of select="@version" />
+								</td>
+								<td>
+									<a href="{@url}">
+										<xsl:value-of select="@jsr" />
+									</a>
+								</td>
+								<td>
+									<b>
+										<xsl:value-of select="@title" />
+									</b>
+									<br />
+									<p>
+										<xsl:value-of select="." />
+									</p>
+
+									<b>Packages</b>
+									<br />
+									<table class="100%">
+										<xsl:for-each select="//package[@spec=current()/@id]">
+											<tr>
+												<td class="span3">
+													<xsl:value-of select="@name" />
+												</td>
+												<td class="span3">
+													<xsl:value-of select="@version" />
+												</td>
+												<td>
+												</td>
+											</tr>
+										</xsl:for-each>
+									</table>
+
+									<xsl:variable name="imports"
+										select="//package[current()/@id=@spec]/import" />
+									<xsl:if test="$imports">
+
+										<b>XRef</b>
+										<br />
+										<table class="100%">
+											<xsl:for-each select="$imports">
+												<tr>
+													<td class="span3">
+														<xsl:value-of select="@name" />
+													</td>
+													<td class="span3">
+														<xsl:value-of select="@version" />
+													</td>
+													<td>
+														<xsl:for-each select="//package[@name=current()/@name]">
+															<xsl:if test="not(position()=1)">
+																,
+															</xsl:if>
+															<a href="#{@spec}">
+																<xsl:value-of
+																	select="//specification[@id=current()/@spec]/@name" />
+																-
+																<xsl:value-of
+																	select="//specification[@id=current()/@spec]/@version" />
+															</a>
+														</xsl:for-each>
+													</td>
+												</tr>
+											</xsl:for-each>
+										</table>
+									</xsl:if>
+								</td>
+							</tr>
+						</xsl:for-each>
+					</table>
+					<hr />
+					<h2>Deltas</h2>
+					<p>The following table details the delta. The version of the newer
+						(left) package can be marked in different colors:
+					</p>
+					<table>
+						<tr>
+							<td>1.0.0</td>
+							<td>Ok, no issues</td>
+						</tr>
+						<tr>
+							<td><span class="label important">1.0.0</span></td>
+							<td>Semantic version mismatch</td>
+						</tr>
+						<tr>
+							<td>
+								<span class="label important">Δ!</span>
+							</td>
+							<td>There was a delta but a semantic version mismatch</td>
+						</tr>
+						<tr>
+							<td>
+								<span class="label warning">Δ=</span>
+							</td>
+							<td>There was no delta but the version differed</td>
+						</tr>
+					</table>
+					<br/>
+					<table>
+						<thead>
+							<tr>
+								<th>Package</th>
+								<th>Newer</th>
+								<th>Older</th>
+								<th>Delta</th>
+							</tr>
+						</thead>
+						<xsl:for-each select="//info">
+							<xsl:sort select="@name" />
+							<tr>
+								<td>
+									<a name="{@id}" />
+									<xsl:value-of select="@name" />
+								</td>
+								<td>
+									<span>
+										<xsl:if test="@mismatch='true'">
+											<xsl:attribute name="class">label important</xsl:attribute>
+										</xsl:if>
+										<xsl:value-of select="@newerVersion" />
+									</span>
+									<xsl:if test="not(@newerVersion=@suggestedVersion)">
+										<br />
+										<span class="label success">
+											<xsl:value-of select="@suggestedVersion" />
+										</span>
+										<xsl:if
+											test="@suggestedIfProviders and not(@suggestedIfProviders=@suggestedVersion)">
+											<br />
+											<span class="label success">
+												<xsl:value-of select="@suggestedIfProviders" />
+											</span>
+
+											<ul>
+												<xsl:for-each select="provider">
+													<li>
+														<xsl:value-of select="@provider" />
+													</li>
+												</xsl:for-each>
+											</ul>
+										</xsl:if>
+									</xsl:if>
+								</td>
+								<td>
+									<xsl:call-template name="specref">
+										<xsl:with-param name="id" select="@newerSpec" />
+									</xsl:call-template>
+								</td>
+								<td>
+									<xsl:value-of select="@olderVersion" />
+								</td>
+								<td>
+									<xsl:call-template name="specref">
+										<xsl:with-param name="id" select="@olderSpec" />
+									</xsl:call-template>
+								</td>
+								<td>
+									<pre style="font-size:10px;">
+										<xsl:value-of select="diff" />
+									</pre>
+									<pre>
+										<xsl:for-each select="provider">
+											<xsl:value-of select="@provider" />
+
+										</xsl:for-each>
+									</pre>
+								</td>
+							</tr>
+						</xsl:for-each>
+					</table>
+				</div>
+			</body>
+		</html>
+	</xsl:template>
+
+	<xsl:template name="specref">
+		<xsl:param name="id" />
+		<xsl:variable name="ns" select="//specification[@id=$id]" />
+		<a href="#{$id}">
+			<xsl:value-of select="$ns/@name" />
+			-
+			<xsl:value-of select="$ns/@version" />
+		</a>
+	</xsl:template>
+</xsl:stylesheet>
+
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/ActionWrapper.java b/biz.aQute.bnd/src/aQute/bnd/plugin/ActionWrapper.java
deleted file mode 100644
index ccb6511..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/ActionWrapper.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package aQute.bnd.plugin;
-
-import org.osgi.framework.*;
-
-import aQute.bnd.build.*;
-import aQute.bnd.service.action.*;
-
-public class ActionWrapper implements Action {
-    ServiceReference ref;
-    BundleContext context;
-    
-    public ActionWrapper(BundleContext context, ServiceReference ref) {
-        this.ref = ref;
-        this.context = context;
-    }
-
-    public void execute(Project project, String action) throws Exception {
-        Action a = (Action) context.getService(ref);
-        if ( a == null )
-            throw new IllegalStateException("Command provider is gone");
-        
-        try {
-            a.execute(project, action);
-        } finally {
-            context.ungetService(ref);
-        }
-    }
-
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/Activator.java b/biz.aQute.bnd/src/aQute/bnd/plugin/Activator.java
deleted file mode 100755
index 415922d..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/Activator.java
+++ /dev/null
@@ -1,225 +0,0 @@
-package aQute.bnd.plugin;
-
-import java.io.*;
-import java.util.*;
-import java.util.List;
-
-import org.eclipse.core.runtime.*;
-import org.eclipse.jface.dialogs.*;
-import org.eclipse.jface.resource.*;
-import org.eclipse.swt.widgets.*;
-import org.eclipse.ui.plugin.*;
-import org.osgi.framework.*;
-
-import aQute.bnd.build.*;
-import aQute.bnd.service.action.*;
-import aQute.lib.osgi.*;
-
-/**
- * The activator class controls the plug-in life cycle
- */
-public class Activator extends AbstractUIPlugin {
-
-    // The plug-in ID
-    public static final String PLUGIN_ID = "aQute.bmaker";
-
-    // The shared instance
-    private static Activator   plugin;
-    BundleContext              context;
-    Central central;
-    
-    /**
-     * The constructor
-     */
-    public Activator() {
-        plugin = this;
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
-     */
-    public void start(BundleContext context) throws Exception {
-        super.start(context);
-        plugin = this;
-        this.context = context;
-        this.central = new Central(context);
-        
-        Hashtable<String,Object> p = new Hashtable<String, Object>();
-        // p.put(Action.ACTION_MENU, new String[] {"a:b", "a:c", "a:d", "a:d:e"});
-        context.registerService(Action.class.getName(), new ReflectAction(""), p);
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
-     */
-    public void stop(BundleContext context) throws Exception {
-        plugin = null;
-        super.stop(context);
-        central.close();
-    }
-
-    /**
-     * Returns the shared instance
-     * 
-     * @return the shared instance
-     */
-    public static Activator getDefault() {
-        return plugin;
-    }
-
-    /**
-     * Returns an image descriptor for the image file at the given plug-in
-     * relative path
-     * 
-     * @param path
-     *            the path
-     * @return the image descriptor
-     */
-    public static ImageDescriptor getImageDescriptor(String path) {
-        return imageDescriptorFromPlugin(PLUGIN_ID, path);
-    }
-
-    static volatile boolean busy;
-    public void error(final String msg, final Throwable t) {
-        Status s = new Status(Status.ERROR, PLUGIN_ID, 0, msg, t);
-        getLog().log(s);
-        async(new Runnable() {
-            public void run() {
-                synchronized(this) {
-                    if  ( busy )
-                        return;
-                    busy = true;
-                }
-                Status s = new Status(Status.ERROR, PLUGIN_ID, 0, "", null);
-                ErrorDialog.openError(null, "Errors during bundle generation",
-                        msg + " " + t.getMessage(), s);
-                
-                busy = false;
-            }
-        });
-    }
-
-    public void info(String msg) {
-        Status s = new Status(Status.INFO, PLUGIN_ID, 0, msg, null);
-        getLog().log(s);
-    }
-
-    public void error(List<String> errors) {
-        final StringBuffer sb = new StringBuffer();
-        for (String msg : errors) {
-            sb.append(msg);
-            sb.append("\n");
-        }
-
-        async(new Runnable() {
-            public void run() {
-                Status s = new Status(Status.ERROR, PLUGIN_ID, 0, "", null);
-                ErrorDialog.openError(null, "Errors during bundle generation",
-                        sb.toString(), s);
-            }
-        });
-    }
-
-    public void message(final String msg) {
-        async(new Runnable() {
-            public void run() {
-                MessageDialog.openInformation(null, "Bnd", msg);
-            }
-        });
-    }
-
-    public void warning(List<String> errors) {
-        final StringBuffer sb = new StringBuffer();
-        for (String msg : errors) {
-            sb.append(msg);
-            sb.append("\n");
-        }
-        async(new Runnable() {
-            public void run() {
-                Status s = new Status(Status.WARNING, PLUGIN_ID, 0, "", null);
-                ErrorDialog.openError(null,
-                        "Warnings during bundle generation", sb.toString(), s);
-            }
-        });
-    }
-
-    void async(Runnable run) {
-        if (Display.getCurrent() == null) {
-            Display.getDefault().asyncExec(run);
-        } else
-            run.run();
-    }
-
-    public boolean getReportDone() {
-        return true;
-        // return
-        // getPreferenceStore().getBoolean(PreferenceConstants.P_REPORT_DONE);
-    }
-
-    public File getCopy() {
-        return null;
-
-        // String path =
-        // getPreferenceStore().getString(PreferenceConstants.P_COPY);
-        // if ( path == null )
-        // return null;
-
-        // File file = new File(path);
-        // if ( !file.exists() || file.isFile() )
-        // return null;
-
-        // return file;
-    }
-
-    public boolean isPedantic() {
-        return false;
-        // IPreferenceStore store = getPreferenceStore();
-        // return store.getBoolean(PreferenceConstants.P_PEDANTIC);
-    }
-
-    public BundleContext getBundleContext() {
-        return context;
-    }
-
-    public void report(boolean warnings, boolean acknowledge , Processor reporter, final String title, final String extra ) {
-        if (reporter.getErrors().size() > 0
-                || (warnings && reporter.getWarnings().size() > 0)) {
-            final StringBuffer sb = new StringBuffer();
-            sb.append("\n");
-            if (reporter.getErrors().size() > 0) {
-                sb.append("[Errors]\n");
-                for (String msg : reporter.getErrors()) {
-                    sb.append(msg);
-                    sb.append("\n");
-                }
-            }
-            sb.append("\n");
-            if (reporter.getWarnings().size() > 0) {
-                sb.append("[Warnings]\n");
-                for (String msg : reporter.getWarnings()) {
-                    sb.append(msg);
-                    sb.append("\n");
-                }
-            }
-            final Status s = new Status(Status.ERROR, PLUGIN_ID, 0, sb.toString(), null);
-            reporter.clear();
-            
-            async(new Runnable() {
-                public void run() {
-                    ErrorDialog.openError(null, title, title + "\n" + extra, s);
-                }
-            });
-
-        } else {
-            message(title+ " : ok");
-        }
-    }
-
-    public Central getCentral() {
-        return central;
-    }
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/Central.java b/biz.aQute.bnd/src/aQute/bnd/plugin/Central.java
deleted file mode 100644
index 2c87346..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/Central.java
+++ /dev/null
@@ -1,268 +0,0 @@
-package aQute.bnd.plugin;
-
-import java.io.File;
-import java.util.*;
-import java.util.concurrent.*;
-
-import org.eclipse.core.internal.resources.*;
-import org.eclipse.core.resources.*;
-import org.eclipse.core.runtime.*;
-import org.eclipse.jdt.core.*;
-import org.osgi.framework.*;
-
-import aQute.bnd.build.Project;
-import aQute.bnd.build.Workspace;
-import aQute.bnd.classpath.*;
-import aQute.bnd.service.*;
-
-public class Central implements IResourceChangeListener {
-    static IWorkspace                iworkspace;
-    final Map<IJavaProject, Project> javaProjectToModel = new HashMap<IJavaProject, Project>();
-    final List<ModelListener>        listeners          = new CopyOnWriteArrayList<ModelListener>();
-    static Workspace                 workspace;
-    final BundleContext              context;
-    final Workspace                  ws;
-
-    Central(BundleContext context) throws Exception {
-        this.context = context;
-        // Add a resource change listener if this is
-        // the first project
-        iworkspace = ResourcesPlugin.getWorkspace();
-        iworkspace.addResourceChangeListener(this);
-
-        ws = getWorkspace();
-        context.registerService(Workspace.class.getName(), ws, null);
-    }
-
-    public Project getModel(IJavaProject project) {
-        try {
-            Project model = javaProjectToModel.get(project);
-            if (model == null) {
-                File projectDir = project.getProject().getLocation()
-                        .makeAbsolute().toFile();
-                model = Workspace.getProject(projectDir);
-                if (workspace == null) {
-                    model.getWorkspace();
-                }
-                if (model != null) {
-                    javaProjectToModel.put(project, model);
-                }
-            }
-            return model;
-        } catch (Exception e) {
-            // TODO do something more useful here
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Implementation of the resource changed interface. We are checking in the
-     * POST_CHANGE phase if one of our tracked models needs to be updated.
-     */
-    public synchronized void resourceChanged(IResourceChangeEvent event) {
-        if (event.getType() != IResourceChangeEvent.POST_CHANGE)
-            return;
-
-        long now = System.currentTimeMillis();
-        
-        IResourceDelta rootDelta = event.getDelta();
-        try {
-            final Set<Project> changed = new HashSet<Project>();
-            rootDelta.accept(new IResourceDeltaVisitor() {
-                public boolean visit(IResourceDelta delta) throws CoreException {
-                    try {
-
-                        IPath location = delta.getResource().getLocation();
-                        if (location == null) {
-                            System.out
-                                    .println("Cannot convert resource to file: "
-                                            + delta.getResource());
-                        } else {
-                            File file = location.toFile();
-                            File parent = file.getParentFile();
-                            boolean parentIsWorkspace = parent
-                                    .equals(getWorkspace().getBase());
-
-                            // file
-                            // /development/osgi/svn/build/org.osgi.test.cases.distribution/bnd.bnd
-                            // parent
-                            // /development/osgi/svn/build/org.osgi.test.cases.distribution
-                            // workspace /development/amf/workspaces/osgi
-                            // false
-
-                            if (parent != null && parentIsWorkspace) {
-                                // We now are on project level, we do not go
-                                // deeper
-                                // because projects/workspaces should check for
-                                // any
-                                // changes.
-                                // We are careful not to create unnecessary
-                                // projects
-                                // here.
-                                if (file.getName().equals(Workspace.CNFDIR)) {
-                                    if (workspace.refresh()) {
-                                        changed.addAll(workspace
-                                                .getCurrentProjects());
-                                    }
-                                    return false;
-                                }
-                                if (workspace.isPresent(file.getName())) {
-                                    Project project = workspace.getProject(file
-                                            .getName());
-                                    changed.add(project);
-                                } else {
-                                    ; // Project not created yet, so we
-                                    // have
-                                    // no cached results
-
-                                }
-                                return false;
-                            }
-                        }
-                        return true;
-                    } catch (Exception e) {
-                        e.printStackTrace();
-                        throw new CoreException(new Status(Status.ERROR,
-                                Activator.PLUGIN_ID,
-                                "During checking project changes", e));
-                    }
-                }
-
-            });
-
-            for (Project p : changed) {
-            	//p.updateModified(now, "Eclipse resource listener");
-                p.refresh();
-                changed(p);
-            }
-        } catch (CoreException e) {
-            Activator.getDefault().error("While handling changes", e);
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-    }
-
-    public static Workspace getWorkspace() throws Exception {
-        if (workspace != null)
-            return workspace;
-
-        IResource resource = iworkspace.getRoot().findMember("/cnf/build.bnd");
-        if (resource != null) {
-            IPath path = resource.getLocation();
-            if (path != null) {
-                File f = path.toFile();
-                workspace = Workspace.getWorkspace(f.getAbsoluteFile()
-                        .getParentFile().getParentFile().getAbsoluteFile());
-                // workspace.setBundleContex(context);
-                return workspace;
-            }
-        }
-
-        workspace = Workspace.getWorkspace(iworkspace.getRoot().getLocation()
-                .toFile());
-        return workspace;
-    }
-
-    public void changed(Project model) {
-        model.setChanged();
-        for (ModelListener m : listeners)
-            try {
-                m.modelChanged(model);
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
-    }
-
-    public void addModelListener(ModelListener m) {
-        if (!listeners.contains(m)) {
-            listeners.add(m);
-        }
-    }
-
-    public void removeModelListener(ModelListener m) {
-        listeners.remove(m);
-    }
-
-    public IJavaProject getJavaProject(Project model) {
-        for (IProject iproj : iworkspace.getRoot().getProjects()) {
-            if (iproj.getName().equals(model.getName())) {
-                IJavaProject ij = JavaCore.create(iproj);
-                if (ij != null && ij.exists()) {
-                    return ij;
-                }
-                // current project is not a Java project
-            }
-        }
-        return null;
-    }
-
-    public static IPath toPath(Project project, File file) {
-        String path = file.getAbsolutePath();
-        String workspace = project.getWorkspace().getBase().getAbsolutePath();
-        if (path.startsWith(workspace))
-            path = path.substring(workspace.length());
-        else
-            return null;
-
-        IPath p = new Path(path);
-        return p;
-    }
-
-    public static void refresh(IPath path) {
-        try {
-            IResource r = ResourcesPlugin.getWorkspace().getRoot().findMember(
-                    path);
-            if (r != null)
-                return;
-
-            IPath p = (IPath) path.clone();
-            while (p.segmentCount() > 0) {
-                p = p.removeLastSegments(1);
-                IResource resource = ResourcesPlugin.getWorkspace().getRoot()
-                        .findMember(p);
-                if (resource != null) {
-                    resource.refreshLocal(2, null);
-                    return;
-                }
-            }
-        } catch( ResourceException re ) {
-            // TODO Ignore for now
-        }
-        catch (Exception e) {
-            Activator.getDefault().error("While refreshing path " + path, e);
-        }
-    }
-
-    public void refreshPlugins() throws Exception {
-        List<Refreshable> rps = getWorkspace().getPlugins(Refreshable.class);
-        for (Refreshable rp : rps) {
-            if (rp.refresh()) {
-                File dir = rp.getRoot();
-                refreshFile(dir);
-            }
-        }
-    }
-
-    public void refreshFile(File f) throws Exception {
-        String path = toLocal(f);
-        IResource r = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
-        if (r != null) {
-            r.refreshLocal(IResource.DEPTH_INFINITE, null);
-        }
-    }
-
-    public void refresh(Project p) throws Exception {
-        IJavaProject jp = getJavaProject(p);
-        if (jp != null)
-            jp.getProject().refreshLocal(IResource.DEPTH_INFINITE, null);
-    }
-
-    private String toLocal(File f) throws Exception {
-        String root = getWorkspace().getBase().getAbsolutePath();
-        String path = f.getAbsolutePath().substring(root.length());
-        return path;
-    }
-
-    public void close() {
-    }
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/builder/BndBuilder.java b/biz.aQute.bnd/src/aQute/bnd/plugin/builder/BndBuilder.java
deleted file mode 100755
index b5f2de0..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/builder/BndBuilder.java
+++ /dev/null
@@ -1,134 +0,0 @@
-package aQute.bnd.plugin.builder;
-
-import java.util.*;
-
-import org.eclipse.core.resources.*;
-import org.eclipse.core.runtime.*;
-
-import aQute.bnd.plugin.*;
-import aQute.bnd.plugin.popup.actions.*;
-import aQute.lib.osgi.*;
-
-public class BndBuilder extends IncrementalProjectBuilder {
-
-	class DeltaVisitor implements IResourceDeltaVisitor {
-		/*
-		 * (non-Javadoc)
-		 * 
-		 * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
-		 */
-		public boolean visit(IResourceDelta delta) throws CoreException {
-			IResource resource = delta.getResource();
-			switch (delta.getKind()) {
-			case IResourceDelta.ADDED:
-				// handle added resource
-				checkBnd(resource);
-				break;
-			case IResourceDelta.REMOVED:
-				// handle removed resource
-				break;
-			case IResourceDelta.CHANGED:
-				// handle changed resource
-				checkBnd(resource);
-				break;
-			}
-			// return true to continue visiting children.
-			return true;
-		}
-	}
-
-	class ResourceVisitor implements IResourceVisitor {
-		public boolean visit(IResource resource) {
-			checkBnd(resource);
-			// return true to continue visiting children.
-			return true;
-		}
-	}
-
-	public static final String	BUILDER_ID	= "biz.aQute.bnd.BndBuilder";
-
-	private static final String	MARKER_TYPE	= "biz.aQute.bnd.xmlProblem";
-
-	private void addMarker(IFile file, String message, int lineNumber,
-			int severity) {
-		try {
-			IMarker marker = file.createMarker(MARKER_TYPE);
-			marker.setAttribute(IMarker.MESSAGE, message);
-			marker.setAttribute(IMarker.SEVERITY, severity);
-			if (lineNumber == -1) {
-				lineNumber = 1;
-			}
-			marker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
-		} catch (CoreException e) {
-		}
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.eclipse.core.internal.events.InternalBuilder#build(int,
-	 *      java.util.Map, org.eclipse.core.runtime.IProgressMonitor)
-	 */
-    protected IProject[] build(int kind, Map args, IProgressMonitor monitor)
-			throws CoreException {
-		if (kind == FULL_BUILD) {
-			fullBuild(monitor);
-		} else {
-			IResourceDelta delta = getDelta(getProject());
-			if (delta == null) {
-				fullBuild(monitor);
-			} else {
-				incrementalBuild(delta, monitor);
-			}
-		}
-		return null;
-	}
-
-	void checkBnd(IResource resource) {
-		if (resource instanceof IFile && resource.getName().endsWith(".bnd")) {
-			IFile file = (IFile) resource;
-			deleteMarkers(file);
-			try {
-				Builder builder = MakeBundle.setBuilder(Activator.getDefault(),
-						resource.getProject(), file.getLocation().toFile());
-				try {
-					builder.build();
-					builder.close();
-				} catch (Exception e1) {
-					addMarker(file, "Unexpected exception: " + e1, 1,
-							Status.ERROR);
-				}
-				for (Iterator<String> i = builder.getErrors().iterator(); i.hasNext();) {
-					addMarker(file, i.next(), 1, Status.ERROR);
-				}
-				for (Iterator<String> i = builder.getWarnings().iterator(); i.hasNext();) {
-					addMarker(file, i.next(), 1, Status.WARNING);
-				}
-			} catch (Exception e) {
-				addMarker(file, "Really bad exception: " + e, 1,
-						Status.ERROR);
-			}
-		}
-	}
-
-	private void deleteMarkers(IFile file) {
-		try {
-			file.deleteMarkers(MARKER_TYPE, false, IResource.DEPTH_ZERO);
-		} catch (CoreException ce) {
-		}
-	}
-
-	protected void fullBuild(final IProgressMonitor monitor)
-			throws CoreException {
-		try {
-			getProject().accept(new ResourceVisitor());
-		} catch (CoreException e) {
-		}
-	}
-
-	protected void incrementalBuild(IResourceDelta delta,
-			IProgressMonitor monitor) throws CoreException {
-		// the visitor does the work.
-		delta.accept(new DeltaVisitor());
-	}
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/builder/BndNature.java b/biz.aQute.bnd/src/aQute/bnd/plugin/builder/BndNature.java
deleted file mode 100755
index 528f84c..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/builder/BndNature.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package aQute.bnd.plugin.builder;
-
-import org.eclipse.core.resources.ICommand;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IProjectDescription;
-import org.eclipse.core.resources.IProjectNature;
-import org.eclipse.core.runtime.CoreException;
-
-public class BndNature implements IProjectNature {
-
-	/**
-	 * ID of this project nature
-	 */
-	public static final String NATURE_ID = "biz.aQute.bnd.BndNature";
-
-	private IProject project;
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.eclipse.core.resources.IProjectNature#configure()
-	 */
-	public void configure() throws CoreException {
-		IProjectDescription desc = project.getDescription();
-		ICommand[] commands = desc.getBuildSpec();
-
-		for (int i = 0; i < commands.length; ++i) {
-			if (commands[i].getBuilderName().equals(BndBuilder.BUILDER_ID)) {
-				return;
-			}
-		}
-
-		ICommand[] newCommands = new ICommand[commands.length + 1];
-		System.arraycopy(commands, 0, newCommands, 0, commands.length);
-		ICommand command = desc.newCommand();
-		command.setBuilderName(BndBuilder.BUILDER_ID);
-		newCommands[newCommands.length - 1] = command;
-		desc.setBuildSpec(newCommands);
-		project.setDescription(desc, null);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.eclipse.core.resources.IProjectNature#deconfigure()
-	 */
-	public void deconfigure() throws CoreException {
-		IProjectDescription description = getProject().getDescription();
-		ICommand[] commands = description.getBuildSpec();
-		for (int i = 0; i < commands.length; ++i) {
-			if (commands[i].getBuilderName().equals(BndBuilder.BUILDER_ID)) {
-				ICommand[] newCommands = new ICommand[commands.length - 1];
-				System.arraycopy(commands, 0, newCommands, 0, i);
-				System.arraycopy(commands, i + 1, newCommands, i,
-						commands.length - i - 1);
-				description.setBuildSpec(newCommands);
-				return;
-			}
-		}
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.eclipse.core.resources.IProjectNature#getProject()
-	 */
-	public IProject getProject() {
-		return project;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.eclipse.core.resources.IProjectNature#setProject(org.eclipse.core.resources.IProject)
-	 */
-	public void setProject(IProject project) {
-		this.project = project;
-	}
-
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/builder/ToggleNatureAction.java b/biz.aQute.bnd/src/aQute/bnd/plugin/builder/ToggleNatureAction.java
deleted file mode 100755
index ae706de..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/builder/ToggleNatureAction.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package aQute.bnd.plugin.builder;
-
-import java.util.Iterator;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IProjectDescription;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IAdaptable;
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.ui.IObjectActionDelegate;
-import org.eclipse.ui.IWorkbenchPart;
-
-public class ToggleNatureAction implements IObjectActionDelegate {
-
-	private ISelection selection;
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
-	 */
-	public void run(IAction action) {
-		if (selection instanceof IStructuredSelection) {
-			for (Iterator<?> it = ((IStructuredSelection) selection).iterator(); it
-					.hasNext();) {
-				Object element = it.next();
-				IProject project = null;
-				if (element instanceof IProject) {
-					project = (IProject) element;
-				} else if (element instanceof IAdaptable) {
-					project = (IProject) ((IAdaptable) element)
-							.getAdapter(IProject.class);
-				}
-				if (project != null) {
-					toggleNature(project);
-				}
-			}
-		}
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction,
-	 *      org.eclipse.jface.viewers.ISelection)
-	 */
-	public void selectionChanged(IAction action, ISelection selection) {
-		this.selection = selection;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.action.IAction,
-	 *      org.eclipse.ui.IWorkbenchPart)
-	 */
-	public void setActivePart(IAction action, IWorkbenchPart targetPart) {
-	}
-
-	/**
-	 * Toggles sample nature on a project
-	 * 
-	 * @param project
-	 *            to have sample nature added or removed
-	 */
-	private void toggleNature(IProject project) {
-		try {
-			IProjectDescription description = project.getDescription();
-			String[] natures = description.getNatureIds();
-
-			for (int i = 0; i < natures.length; ++i) {
-				if (BndNature.NATURE_ID.equals(natures[i])) {
-					// Remove the nature
-					String[] newNatures = new String[natures.length - 1];
-					System.arraycopy(natures, 0, newNatures, 0, i);
-					System.arraycopy(natures, i + 1, newNatures, i,
-							natures.length - i - 1);
-					description.setNatureIds(newNatures);
-					project.setDescription(description, null);
-					return;
-				}
-			}
-
-			// Add the nature
-			String[] newNatures = new String[natures.length + 1];
-			System.arraycopy(natures, 0, newNatures, 0, natures.length);
-			newNatures[natures.length] = BndNature.NATURE_ID;
-			description.setNatureIds(newNatures);
-			project.setDescription(description, null);
-		} catch (CoreException e) {
-		}
-	}
-
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/editors/BndCompletionProcessor.java b/biz.aQute.bnd/src/aQute/bnd/plugin/editors/BndCompletionProcessor.java
deleted file mode 100644
index 7bb0db6..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/editors/BndCompletionProcessor.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package aQute.bnd.plugin.editors;
-
-import org.eclipse.jface.text.*;
-import org.eclipse.jface.text.contentassist.*;
-
-import aQute.bnd.help.*;
-
-public class BndCompletionProcessor implements IContentAssistProcessor {
-
-    public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer,
-            int offset) {
-        ICompletionProposal[] result= new ICompletionProposal[Syntax.HELP.size()];
-            int i=0;
-        for ( Syntax s : Syntax.HELP.values()) {
-            IContextInformation info= new ContextInformation(
-                    s.getHeader(), s.getHeader());
-            result[i++]= new CompletionProposal(s.getHeader()+": ", offset-1, 1, s.getHeader().length()+2, null, s.getHeader(), info, s.getLead()); //$NON-NLS-1$
-        }
-        return result;
-    }
-
-    public IContextInformation[] computeContextInformation(ITextViewer viewer,
-            int offset) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    public char[] getCompletionProposalAutoActivationCharacters() {
-        return new char[] {'-'};
-    }
-
-    public char[] getContextInformationAutoActivationCharacters() {
-        return new char[] {'-'};
-    }
-
-    public IContextInformationValidator getContextInformationValidator() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    public String getErrorMessage() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/editors/BndHover.java b/biz.aQute.bnd/src/aQute/bnd/plugin/editors/BndHover.java
deleted file mode 100644
index 5529848..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/editors/BndHover.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package aQute.bnd.plugin.editors;
-
-import org.eclipse.jface.text.*;
-
-import aQute.bnd.help.*;
-
-public class BndHover implements ITextHover {
-    static class DocString implements CharSequence {
-        IDocument doc;
-
-        public char charAt(int index) {
-            try {
-                return doc.getChar(index);
-            } catch (BadLocationException e) {
-                throw new IndexOutOfBoundsException();
-            }
-        }
-
-        public int length() {
-            return doc.getLength();
-        }
-
-        public CharSequence subSequence(int start, int end) {
-            return doc.get().subSequence(start, end);
-        }
-
-    };
-
-    public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
-        if (hoverRegion != null) {
-            IDocument doc = textViewer.getDocument();
-            try {
-                String key = doc.get(hoverRegion.getOffset(), hoverRegion
-                        .getLength());
-
-                Syntax syntax = Syntax.HELP.get(key);
-                if (syntax == null)
-                    return null;
-
-                StringBuilder sb = new StringBuilder();
-                sb.append(syntax.getLead());
-                sb.append("\nE.g. ");
-                sb.append(syntax.getExample());
-
-                String text = sb.toString();
-                if (text == null)
-                    return null;
-
-                if (text.length() > 30) {
-                    text = wrap(text, 30);
-                }
-                return text;
-            } catch (Exception e) {
-                return e + "";
-            }
-        }
-        return null;
-    }
-
-    public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
-        IDocument doc = textViewer.getDocument();
-        try {
-            int start = offset;
-            int end = offset;
-            while (start >= 0 && isWordChar(doc.getChar(start)))
-                start--;
-
-            while (end < doc.getLength() && isWordChar(doc.getChar(end)))
-                end++;
-
-            start++;
-            int length = Math.min(doc.getLength(), end - start);
-            start = Math.max(0,start);
-            return new Region(start, length);
-        } catch (BadLocationException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-        return null;
-    }
-
-    boolean isWordChar(char c) {
-        return Character.isJavaIdentifierPart(c) || c == '-' || c == '.';
-    }
-
-    String wrap(String text, int width) {
-        StringBuilder sb = new StringBuilder();
-        int n = 0;
-        int r = 0;
-        while (r < text.length()) {
-            char c = text.charAt(r++);
-            switch (c) {
-            case '\r':
-            case '\n':
-                if (n != 0)
-                    sb.append('\n');
-                n = 0;
-                break;
-            case ' ':
-            case '\t':
-                if (n > 20) {
-                    sb.append("\n");
-                    n = 0;
-                } else {
-                    sb.append(" ");
-                    n++;
-                }
-                break;
-            default:
-                sb.append(c);
-                n++;
-            }
-        }
-        return sb.toString();
-    }
-
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/editors/BndMultiPageEditor.java b/biz.aQute.bnd/src/aQute/bnd/plugin/editors/BndMultiPageEditor.java
deleted file mode 100755
index 511daf7..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/editors/BndMultiPageEditor.java
+++ /dev/null
@@ -1,237 +0,0 @@
-package aQute.bnd.plugin.editors;
-
-import java.io.*;
-import java.text.*;
-import java.util.*;
-
-import org.eclipse.core.resources.*;
-import org.eclipse.core.runtime.*;
-import org.eclipse.jface.dialogs.*;
-import org.eclipse.jface.viewers.*;
-import org.eclipse.swt.*;
-import org.eclipse.swt.custom.*;
-import org.eclipse.swt.layout.*;
-import org.eclipse.swt.widgets.*;
-import org.eclipse.ui.*;
-import org.eclipse.ui.editors.text.*;
-import org.eclipse.ui.ide.*;
-import org.eclipse.ui.part.*;
-
-/**
- */
-public class BndMultiPageEditor extends MultiPageEditorPart implements
-        IResourceChangeListener {
-
-    private Table table;
-    /** The text editor used in page 0. */
-    private TextEditor editor;
-
-
-    /** The text widget used in page 2. */
-    private StyledText text;
-
-    /**
-     * Creates a multi-page editor example.
-     */
-    public BndMultiPageEditor() {
-        super();
-        ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
-    }
-
-    /**
-     * Creates page 0 of the multi-page editor, which contains a text editor.
-     */
-    void createTextEditor() {
-        try {
-            editor = new BndTextEditor();
-
-            int index = addPage(editor, getEditorInput());
-            setPageText(index, editor.getTitle());
-        } catch (PartInitException e) {
-            ErrorDialog.openError(getSite().getShell(),
-                    "Error creating nested text editor", null, e.getStatus());
-        }
-    }
-
-    /**
-     * Creates page 1 of the multi-page editor, which allows you to change the
-     * font used in page 2.
-     */
-    void createPage1() {
-
-        Composite composite = new Composite(getContainer(), SWT.NONE);
-        GridLayout layout = new GridLayout();
-        composite.setLayout(layout);
-
-        int index = addPage(composite);
-
-        final TableViewer tableViewer = new TableViewer(composite, SWT.BORDER);
-        table = tableViewer.getTable();
-        table.setLinesVisible(true);
-        table.setHeaderVisible(true);
-        table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-
-        final TableColumn tableColumn = new TableColumn(table, SWT.NONE);
-        tableColumn.setWidth(100);
-        tableColumn.setText("Key");
-
-        final TableColumn tableColumn_1 = new TableColumn(table, SWT.NONE);
-        tableColumn_1.setWidth(1000);
-        tableColumn_1.setText("Value");
-        setPageText(index, "Properties");
-    }
-
-    /**
-     * Creates page 2 of the multi-page editor, which shows the sorted text.
-     */
-    void createPage2() {
-        Composite composite = new Composite(getContainer(), SWT.NONE);
-        FillLayout layout = new FillLayout();
-        composite.setLayout(layout);
-        text = new StyledText(composite, SWT.H_SCROLL | SWT.V_SCROLL);
-        text.setEditable(false);
-
-        int index = addPage(composite);
-        setPageText(index, "Preview");
-    }
-
-    
-    
-    
-    void createPage3() {
-        
-    }
-    /**
-     * Creates the pages of the multi-page editor.
-     */
-    protected void createPages() {
-        createTextEditor();
-        createPage1();
-        createPage2();
-    }
-
-    /**
-     * The <code>MultiPageEditorPart</code> implementation of this
-     * <code>IWorkbenchPart</code> method disposes all nested editors.
-     * Subclasses may extend.
-     */
-    public void dispose() {
-        ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
-        super.dispose();
-    }
-
-    /**
-     * Saves the multi-page editor's document.
-     */
-    public void doSave(IProgressMonitor monitor) {
-        getEditor(0).doSave(monitor);
-    }
-
-    /**
-     * Saves the multi-page editor's document as another file. Also updates the
-     * text for page 0's tab, and updates this multi-page editor's input to
-     * correspond to the nested editor's.
-     */
-    public void doSaveAs() {
-        IEditorPart editor = getEditor(0);
-        editor.doSaveAs();
-        setPageText(0, editor.getTitle());
-        setInput(editor.getEditorInput());
-    }
-
-    public void setInput(IEditorInput iei ) {
-	    super.setInput(iei);
-	    setPartName( iei.getName());
-	    setContentDescription(iei.getToolTipText());
-	    if ( iei instanceof IFileEditorInput ) {
-	        IFileEditorInput in = (IFileEditorInput) iei;
-	        IProject project = in.getFile().getProject();
-	        setPartName(project.getName());
-	    }
-	}
-
-    /*
-     * (non-Javadoc) Method declared on IEditorPart
-     */
-    public void gotoMarker(IMarker marker) {
-        setActivePage(0);
-        IDE.gotoMarker(getEditor(0), marker);
-    }
-
-    /**
-     * The <code>MultiPageEditorExample</code> implementation of this method
-     * checks that the input is an instance of <code>IFileEditorInput</code>.
-     */
-    public void init(IEditorSite site, IEditorInput editorInput)
-            throws PartInitException {
-        if (!(editorInput instanceof IFileEditorInput))
-            throw new PartInitException(
-                    "Invalid Input: Must be IFileEditorInput");
-        super.init(site, editorInput);
-    }
-
-    /*
-     * (non-Javadoc) Method declared on IEditorPart.
-     */
-    public boolean isSaveAsAllowed() {
-        return true;
-    }
-
-    /**
-     * Calculates the contents of page 2 when the it is activated.
-     */
-    protected void pageChange(int newPageIndex) {
-        super.pageChange(newPageIndex);
-        if (newPageIndex == 2) {
-            sortWords();
-        }
-    }
-
-    /**
-     * Closes all project files on project close.
-     */
-    public void resourceChanged(final IResourceChangeEvent event) {
-        if (event.getType() == IResourceChangeEvent.PRE_CLOSE) {
-            Display.getDefault().asyncExec(new Runnable() {
-                public void run() {
-                    IWorkbenchPage[] pages = getSite().getWorkbenchWindow()
-                            .getPages();
-                    for (int i = 0; i < pages.length; i++) {
-                        if (((FileEditorInput) editor.getEditorInput())
-                                .getFile().getProject().equals(
-                                        event.getResource())) {
-                            IEditorPart editorPart = pages[i].findEditor(editor
-                                    .getEditorInput());
-                            pages[i].closeEditor(editorPart, true);
-                        }
-                    }
-                }
-            });
-        }
-    }
-
-
-    /**
-     * Sorts the words in page 0, and shows them in page 2.
-     */
-    void sortWords() {
-
-        String editorText = editor.getDocumentProvider().getDocument(
-                editor.getEditorInput()).get();
-
-        StringTokenizer tokenizer = new StringTokenizer(editorText,
-                " \t\n\r\f!@#\u0024%^&*()-_=+`~[]{};:'\",.<>/?|\\");
-        ArrayList<String> editorWords = new ArrayList<String>();
-        while (tokenizer.hasMoreTokens()) {
-            editorWords.add(tokenizer.nextToken());
-        }
-
-        Collections.sort(editorWords, Collator.getInstance());
-        StringWriter displayText = new StringWriter();
-        for (int i = 0; i < editorWords.size(); i++) {
-            displayText.write(((String) editorWords.get(i)));
-            displayText.write(System.getProperty("line.separator"));
-        }
-        text.setText(displayText.toString());
-    }
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/editors/BndMultiPageEditorContributor.java b/biz.aQute.bnd/src/aQute/bnd/plugin/editors/BndMultiPageEditorContributor.java
deleted file mode 100755
index 606bc9f..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/editors/BndMultiPageEditorContributor.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package aQute.bnd.plugin.editors;
-
-import org.eclipse.jface.action.*;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.ui.IActionBars;
-import org.eclipse.ui.IEditorPart;
-import org.eclipse.ui.IWorkbenchActionConstants;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.actions.ActionFactory;
-import org.eclipse.ui.ide.IDE;
-import org.eclipse.ui.ide.IDEActionFactory;
-import org.eclipse.ui.part.MultiPageEditorActionBarContributor;
-import org.eclipse.ui.texteditor.ITextEditor;
-import org.eclipse.ui.texteditor.ITextEditorActionConstants;
-
-/**
- * Manages the installation/deinstallation of global actions for multi-page editors.
- * Responsible for the redirection of global actions to the active editor.
- * Multi-page contributor replaces the contributors for the individual editors in the multi-page editor.
- */
-public class BndMultiPageEditorContributor extends MultiPageEditorActionBarContributor {
-	private IEditorPart activeEditorPart;
-	private Action sampleAction;
-	/**
-	 * Creates a multi-page contributor.
-	 */
-	public BndMultiPageEditorContributor() {
-		super();
-		createActions();
-	}
-	/**
-	 * Returns the action registed with the given text editor.
-	 * @return IAction or null if editor is null.
-	 */
-	protected IAction getAction(ITextEditor editor, String actionID) {
-		return (editor == null ? null : editor.getAction(actionID));
-	}
-	/* (non-JavaDoc)
-	 * Method declared in AbstractMultiPageEditorActionBarContributor.
-	 */
-
-	public void setActivePage(IEditorPart part) {
-		if (activeEditorPart == part)
-			return;
-
-		activeEditorPart = part;
-
-		IActionBars actionBars = getActionBars();
-		if (actionBars != null) {
-
-			ITextEditor editor = (part instanceof ITextEditor) ? (ITextEditor) part : null;
-
-			actionBars.setGlobalActionHandler(
-				ActionFactory.DELETE.getId(),
-				getAction(editor, ITextEditorActionConstants.DELETE));
-			actionBars.setGlobalActionHandler(
-				ActionFactory.UNDO.getId(),
-				getAction(editor, ITextEditorActionConstants.UNDO));
-			actionBars.setGlobalActionHandler(
-				ActionFactory.REDO.getId(),
-				getAction(editor, ITextEditorActionConstants.REDO));
-			actionBars.setGlobalActionHandler(
-				ActionFactory.CUT.getId(),
-				getAction(editor, ITextEditorActionConstants.CUT));
-			actionBars.setGlobalActionHandler(
-				ActionFactory.COPY.getId(),
-				getAction(editor, ITextEditorActionConstants.COPY));
-			actionBars.setGlobalActionHandler(
-				ActionFactory.PASTE.getId(),
-				getAction(editor, ITextEditorActionConstants.PASTE));
-			actionBars.setGlobalActionHandler(
-				ActionFactory.SELECT_ALL.getId(),
-				getAction(editor, ITextEditorActionConstants.SELECT_ALL));
-			actionBars.setGlobalActionHandler(
-				ActionFactory.FIND.getId(),
-				getAction(editor, ITextEditorActionConstants.FIND));
-			actionBars.setGlobalActionHandler(
-				IDEActionFactory.BOOKMARK.getId(),
-				getAction(editor, IDEActionFactory.BOOKMARK.getId()));
-			actionBars.updateActionBars();
-		}
-	}
-	private void createActions() {
-		sampleAction = new Action() {
-			public void run() {
-				MessageDialog.openInformation(null, "aQute Bnd PRO", "Sample Action Executed");
-			}
-		};
-		sampleAction.setText("Sample Action");
-		sampleAction.setToolTipText("Sample Action tool tip");
-		sampleAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().
-				getImageDescriptor(IDE.SharedImages.IMG_OBJS_TASK_TSK));
-	}
-	public void contributeToMenu(IMenuManager manager) {
-		IMenuManager menu = new MenuManager("Editor &Menu");
-		manager.prependToGroup(IWorkbenchActionConstants.MB_ADDITIONS, menu);
-		menu.add(sampleAction);
-	}
-	public void contributeToToolBar(IToolBarManager manager) {
-		manager.add(new Separator());
-		manager.add(sampleAction);
-	}
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/editors/BndScanner.java b/biz.aQute.bnd/src/aQute/bnd/plugin/editors/BndScanner.java
deleted file mode 100755
index 0d77706..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/editors/BndScanner.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package aQute.bnd.plugin.editors;
-
-import java.util.*;
-
-import org.eclipse.jface.text.rules.*;
-
-import aQute.bnd.make.component.*;
-import aQute.lib.osgi.*;
-
-public class BndScanner extends RuleBasedScanner {
-    BndSourceViewerConfiguration bsvc;
-    
-
-    public BndScanner(BndSourceViewerConfiguration manager) {
-        bsvc = manager;
-        IRule[] rules = new IRule[] {
-                new WhitespaceRule(new IWhitespaceDetector() {
-                    public boolean isWhitespace(char c) {
-                        return (c == ' ' || c == '\t' || c == '\n' || c == '\r');
-                    }
-                }), new BndWordRule(), new MacroRule(bsvc.T_MACRO),
-                new EndOfLineRule("#", bsvc.T_COMMENT),
-                new EndOfLineRule("\\ ", bsvc.T_ERROR),
-                new EndOfLineRule("\\\t", bsvc.T_ERROR), };
-
-        setRules(rules);
-        setDefaultReturnToken(bsvc.T_DEFAULT);
-    }
-    
-    class BndWordRule implements IRule {
-
-        Map<String, IToken> keyWords = new HashMap<String, IToken>();
-
-        public BndWordRule() {
-            addWords(Analyzer.headers, bsvc.T_INSTRUCTION);
-            addWords(Analyzer.options, bsvc.T_OPTION);
-            addWords(Analyzer.directives, bsvc.T_DIRECTIVE);
-            addWords(Constants.componentDirectives, bsvc.T_COMPONENT);
-        }
-
-        private boolean isWordStart(char c) {
-            return Character.isJavaIdentifierStart(c);
-        }
-
-        private boolean isWordPart(char c) {
-            return Character.isJavaIdentifierPart(c) || c == '-';
-        }
-
-        public IToken evaluate(ICharacterScanner scanner) {
-            StringBuffer sb = new StringBuffer();
-
-            int c = scanner.read();
-            if (isWordStart((char) c) || c == '-') {
-                do {
-                    sb.append((char) c);
-                    c = scanner.read();
-                } while (c != ICharacterScanner.EOF && isWordPart((char) c));
-                scanner.unread();
-
-                IToken token = (IToken) keyWords.get(sb.toString());
-                if (token != null)
-                    return token;
-                return bsvc.T_DEFAULT;
-            }
-            scanner.unread();
-            return Token.UNDEFINED;
-
-        }
-
-        private void addWords(String[] words, IToken token) {
-            for (int i = 0; i < words.length; ++i) {
-                keyWords.put(words[i], token);
-            }
-        }
-    }
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/editors/BndSourceViewerConfiguration.java b/biz.aQute.bnd/src/aQute/bnd/plugin/editors/BndSourceViewerConfiguration.java
deleted file mode 100755
index 6588ef9..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/editors/BndSourceViewerConfiguration.java
+++ /dev/null
@@ -1,129 +0,0 @@
-package aQute.bnd.plugin.editors;
-
-import java.util.*;
-
-import org.eclipse.jface.text.*;
-import org.eclipse.jface.text.contentassist.*;
-import org.eclipse.jface.text.presentation.*;
-import org.eclipse.jface.text.rules.*;
-import org.eclipse.jface.text.source.*;
-import org.eclipse.swt.*;
-import org.eclipse.swt.graphics.*;
-
-public class BndSourceViewerConfiguration extends SourceViewerConfiguration {
-
-    Token T_DEFAULT;
-    Token T_MACRO;
-    Token T_ERROR;
-    Token T_COMMENT;
-    Token T_INSTRUCTION;
-    Token T_OPTION;
-    Token T_DIRECTIVE;
-    Token T_PROPERTY;
-    Token T_COMPONENT;
-    
-    static final String SINGLELINE_COMMENT_TYPE = "___slc";
-    static Properties   syntax                  = null;
-
-    class BndPartitionScanner extends RuleBasedPartitionScanner {
-        public BndPartitionScanner() {
-            IToken singleLineComment = new Token(SINGLELINE_COMMENT_TYPE);
-
-            IPredicateRule[] rules = new IPredicateRule[] { new EndOfLineRule(
-                    "#", singleLineComment), };
-            setPredicateRules(rules);
-        }
-    }
-
-    BndScanner              scanner;
-    MultiLineCommentScanner multiLineCommentScanner;
-    ISharedTextColors       colors;
-
-    public BndSourceViewerConfiguration(ISharedTextColors colors) {
-        this.colors = colors;
-        T_DEFAULT = new Token(new TextAttribute(colors.getColor(new RGB(0, 0,
-                0))));
-        T_MACRO = new Token(new TextAttribute(colors.getColor(new RGB(0, 255,
-                0)), null, SWT.BOLD));
-        T_ERROR = new Token(new TextAttribute(colors.getColor(new RGB(255, 0,
-                0)), null, SWT.BOLD));
-        T_COMMENT = new Token(new TextAttribute(colors.getColor(new RGB(128,
-                0, 0))));
-        T_INSTRUCTION = new Token(new TextAttribute(colors.getColor(new RGB(0,
-                0, 255)), null, SWT.BOLD));
-        T_OPTION = new Token(new TextAttribute(colors.getColor(new RGB(0, 0,
-                255))));
-        T_DIRECTIVE = new Token(new TextAttribute(colors.getColor(new RGB(60,
-                60, 255)), null, SWT.BOLD));
-        T_PROPERTY = new Token(new TextAttribute(colors.getColor(new RGB(60,
-                60, 255)), null, SWT.BOLD));
-        T_COMPONENT = new Token(new TextAttribute(colors.getColor(new RGB(60,
-                60, 255)), null, SWT.BOLD));
-    }
-
-    public IPresentationReconciler getPresentationReconciler(
-            ISourceViewer sourceViewer) {
-        PresentationReconciler reconciler = new PresentationReconciler();
-        configureReconciler(reconciler, IDocument.DEFAULT_CONTENT_TYPE,
-                getBndScanner());
-        configureReconciler(reconciler, SINGLELINE_COMMENT_TYPE,
-                getMultiLineCommentScanner());
-        return reconciler;
-    }
-
-    private void configureReconciler(PresentationReconciler reconciler,
-            String partitionType, ITokenScanner scanner) {
-        DefaultDamagerRepairer dr;
-        dr = new DefaultDamagerRepairer(scanner);
-        reconciler.setDamager(dr, partitionType);
-        reconciler.setRepairer(dr, partitionType);
-    }
-
-    protected BndScanner getBndScanner() {
-        if (scanner == null) {
-            scanner = new BndScanner(this);
-        }
-        return scanner;
-    }
-
-    class MultiLineCommentScanner extends RuleBasedScanner {
-
-        public MultiLineCommentScanner() {
-            setDefaultReturnToken(T_COMMENT);
-        }
-
-    }
-
-    protected MultiLineCommentScanner getMultiLineCommentScanner() {
-        if (multiLineCommentScanner == null) {
-            multiLineCommentScanner = new MultiLineCommentScanner();
-        }
-        return multiLineCommentScanner;
-    }
-
-    public String[] getDefaultPrefixes(ISourceViewer sourceViewer,
-            String contentType) {
-        if (IDocument.DEFAULT_CONTENT_TYPE == contentType
-                || SINGLELINE_COMMENT_TYPE == contentType) {
-            return new String[] { "#", "//" };
-        }
-        return null;
-    }
-
-    @Override
-    public ITextHover getTextHover(ISourceViewer sourceViewer,
-            String contentType) {
-        return new BndHover();
-    }
-
-    @Override
-    public IContentAssistant getContentAssistant(ISourceViewer viewer) {
-        ContentAssistant assistant = new ContentAssistant();
-        assistant.setContentAssistProcessor(new BndCompletionProcessor(),
-                IDocument.DEFAULT_CONTENT_TYPE);
-        assistant.setContentAssistProcessor(new BndCompletionProcessor(),
-                SINGLELINE_COMMENT_TYPE);
-        assistant.enableAutoActivation(true);
-        return assistant;
-    }
-}
\ No newline at end of file
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/editors/BndTextEditor.java b/biz.aQute.bnd/src/aQute/bnd/plugin/editors/BndTextEditor.java
deleted file mode 100755
index 59258b8..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/editors/BndTextEditor.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package aQute.bnd.plugin.editors;
-
-import org.eclipse.ui.editors.text.*;
-
-public class BndTextEditor extends TextEditor {
-    
-	BndTextEditor() {
-		setSourceViewerConfiguration(new BndSourceViewerConfiguration(getSharedColors()));
-	}
-	
-	protected void createActions() {
-        super.createActions();
-        
-//        IAction contentAssistAction = new ContentAssistAction(null, "ContentAssistProposal.", this); //$NON-NLS-1$
-//        contentAssistAction.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
-//        setAction("ContentAssistProposal", contentAssistAction);
-//        markAsStateDependentAction("ContentAssistProposal", true);
-	}
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/editors/MacroRule.java b/biz.aQute.bnd/src/aQute/bnd/plugin/editors/MacroRule.java
deleted file mode 100644
index 9302975..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/editors/MacroRule.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package aQute.bnd.plugin.editors;
-
-import org.eclipse.jface.text.rules.*;
-
-import aQute.lib.osgi.*;
-
-public class MacroRule implements IRule {
-
-    private StringBuffer buffer = new StringBuffer();
-    private IToken       token;
-
-    public MacroRule(IToken token) {
-        this.token = token;
-    }
-
-    public IToken evaluate(ICharacterScanner scanner) {
-        int c = scanner.read();
-        if (c == '$') {
-            buffer.setLength(0);
-            buffer.append('$');
-            if ( scan(scanner, buffer) )
-                return token;
-        }
-        scanner.unread();
-        return Token.UNDEFINED;
-
-    }
-
-    boolean scan( ICharacterScanner scanner, StringBuffer buffer ) {
-        int c = scanner.read();
-        if (c == ICharacterScanner.EOF)
-            return false;
-        int terminator = Macro.getTerminator((char) c);
-        
-        if (terminator == 0)
-            return false;
-
-
-        while(true) {
-            c = scanner.read();
-            buffer.append((char)c);
-            if ( c == terminator )
-                return true;
-            else
-            if ( c == '$') {
-                if ( !scan(scanner, buffer) )
-                    return false;
-            }
-            else         
-            if ( c == '\\') {
-                c = scanner.read();
-                if ( c == ICharacterScanner.EOF)
-                    return false;
-                buffer.append((char)c);
-            }
-        }
-   }
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/popup/Scripts.java b/biz.aQute.bnd/src/aQute/bnd/plugin/popup/Scripts.java
deleted file mode 100644
index ffd969d..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/popup/Scripts.java
+++ /dev/null
@@ -1,139 +0,0 @@
-package aQute.bnd.plugin.popup;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jface.action.IContributionItem;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.ui.ISelectionService;
-import org.eclipse.ui.actions.CompoundContributionItem;
-
-import aQute.bnd.build.Project;
-import aQute.bnd.plugin.Activator;
-
-public class Scripts extends CompoundContributionItem {
-	final List<Project>	projects	= new ArrayList<Project>();
-
-	public Scripts() {
-		ISelectionService is = Activator.getDefault().getWorkbench().getActiveWorkbenchWindow()
-				.getSelectionService();
-		ISelection s = is.getSelection();
-		if (s != null && s instanceof IStructuredSelection) {
-			IStructuredSelection ss = (IStructuredSelection) s;
-			for (Iterator<?> i = ss.iterator(); i.hasNext();) {
-				Object oo = i.next();
-				IJavaProject jp = null;
-				if (oo instanceof IResource) {
-					IResource r = (IResource) oo;
-					IProject iproject = r.getProject();
-					jp = JavaCore.create(iproject);
-				} else if (oo instanceof IJavaProject) {
-					jp = (IJavaProject) oo;
-				}
-
-				if (jp != null) {
-					if (!jp.getProject().isAccessible()) {
-						continue;
-					}
-
-					Project project = Activator.getDefault().getCentral().getModel(jp);
-					if (project != null) {
-						File bndFile = project.getFile("bnd.bnd");
-						if (!bndFile.exists()) {
-							continue;
-						}
-						projects.add(project);
-					}
-				}
-			}
-		}
-	}
-
-	public Scripts(String id) {
-		super(id);
-	}
-
-	@Override protected IContributionItem[] getContributionItems() {
-		if (projects.isEmpty())
-			return new IContributionItem[0];
-
-		Set<String> titles = new HashSet<String>();
-		boolean first = true;
-		for (Project project : projects) {
-			if (first) {
-				titles.addAll(project.getActions().keySet());
-				first = false;
-			} else {
-				titles.retainAll(project.getActions().keySet());
-			}
-		}
-
-		SubMenu root = new SubMenu("root");
-
-		SubMenu sub = new SubMenu("Bnd");
-
-		root.add(sub);
-
-		for (final String title : titles) {
-			sub.add(this, title, title);
-		}
-
-		return root.getItems();
-	}
-
-	void exec(final String label) {
-		Job job = new Job(label) {
-			protected IStatus run(IProgressMonitor monitor) {
-
-				for (Project project : projects) {
-					if (monitor != null) {
-						if (monitor.isCanceled())
-							break;
-						monitor.subTask("" + project + " " + label);
-					}
-
-					Map<String, aQute.bnd.service.action.Action> actions = project.getActions();
-					aQute.bnd.service.action.Action cmd = actions.get(label);
-					try {
-						project.action(label);
-						monitor.worked(1);
-
-						Activator.getDefault().getCentral().refresh(project);
-						if (!project.isPerfect()) {
-
-							// We had errors or warnings
-							Activator.getDefault().report(true, true, project,
-									"During execution of " + label, "");
-							return Status.CANCEL_STATUS;
-						}
-					} catch (Throwable e) {
-						Activator.getDefault().error("While executing action: " + cmd, e);
-					}
-				}
-				try {
-					Activator.getDefault().getCentral().refreshPlugins();
-					return Status.OK_STATUS;
-				} catch (Exception e) {
-					return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Failed to refresh: " + e);
-				}
-			}
-		};
-		job.setPriority(Job.SHORT);
-		job.schedule(); // start as soon as possible
-	}
-
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/popup/SubMenu.java b/biz.aQute.bnd/src/aQute/bnd/plugin/popup/SubMenu.java
deleted file mode 100644
index 938a127..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/popup/SubMenu.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package aQute.bnd.plugin.popup;
-
-import java.util.*;
-
-import org.eclipse.jface.action.*;
-
-public class SubMenu extends MenuManager {
-    Map<String, IContributionItem> items = new LinkedHashMap<String, IContributionItem>();
-
-    SubMenu(String name) {
-        super(name);
-    }
-
-    @Override
-    public IContributionItem[] getItems() {
-        return items.values().toArray(new IContributionItem[items.size()]);
-    }
-
-    void add(final Scripts script, final String s, final String full) {
-        int n = s.indexOf(':');
-        if (n < 0) {
-            n = s.indexOf(">");
-            if (n < 0) {
-                items.put(s, new ActionContributionItem(new Action() {
-                    {
-                        setText(s);
-                    }
-
-                    public void run() {
-                        script.exec(full);
-                    }
-                }));
-            } else {
-                String name = s.substring(0,n);
-                String remainder = s.substring(n+1);
-                IContributionItem ici = items.get(name);
-                if (ici == null) {
-                    ici = new SubMenu(name);
-                    items.put(name, ici);
-                }
-                if (!(ici instanceof SubMenu)) {
-                    // A leaf & node ... :-(
-                } else {
-                    SubMenu sub = (SubMenu) ici;
-                    String parts[] = remainder.split(",");
-                    for ( String part : parts ) {
-                        sub.add(script, part, full);
-                    }
-                }
-                
-            }
-        } else {
-            String name = s.substring(0, n);
-            IContributionItem ici = items.get(name);
-            if (ici == null) {
-                ici = new SubMenu(name);
-                items.put(name, ici);
-            }
-            if (!(ici instanceof SubMenu)) {
-                // A leaf & node ... :-(
-            } else {
-                SubMenu sub = (SubMenu) ici;
-                sub.add(script, s.substring(n + 1), full);
-            }
-        }
-    }
-    
-    void add(SubMenu subMenu) {
-    	IContributionItem ici = items.get(subMenu.getMenuText());
-        if (ici == null) {
-            items.put(subMenu.getMenuText(), subMenu);
-        }
-   }
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/popup/actions/AddToRepo.java b/biz.aQute.bnd/src/aQute/bnd/plugin/popup/actions/AddToRepo.java
deleted file mode 100644
index fab4933..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/popup/actions/AddToRepo.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package aQute.bnd.plugin.popup.actions;
-
-import java.io.*;
-import java.util.*;
-
-import org.eclipse.core.resources.*;
-import org.eclipse.jface.action.*;
-import org.eclipse.jface.viewers.*;
-import org.eclipse.ui.*;
-
-import aQute.bnd.build.*;
-import aQute.bnd.plugin.*;
-import aQute.bnd.plugin.popup.actions.repo.*;
-import aQute.bnd.service.*;
-import aQute.lib.osgi.*;
-
-public class AddToRepo implements IObjectActionDelegate {
-    IFile[] locations;
-
-    public AddToRepo() {
-    }
-
-    /**
-     * @see IActionDelegate#run(IAction)
-     */
-    public void run(IAction action) {
-        try {
-            if (locations != null) {
-                for (int i = 0; i < locations.length; i++) {
-                    File mf = locations[i].getLocation().toFile();
-                    try {
-
-                        Jar jar = new Jar(mf.getName(), mf);
-
-                        try {
-                            Verifier verifier = new Verifier(jar);
-                            verifier.verify();
-                            if (verifier.getErrors().size()
-                                    + verifier.getWarnings().size() > 0) {
-                                List<String> info = new ArrayList<String>(
-                                        verifier.getErrors());
-                                info.addAll(verifier.getWarnings());
-                                Activator.getDefault().error(info);
-                            } else {
-                                Workspace ws = Central.getWorkspace();
-                                List<RepositoryPlugin> repos = ws
-                                        .getPlugins(RepositoryPlugin.class);
-                                RepoDialog d = new RepoDialog(null, jar, repos);
-                                d.setBlockOnOpen(true);
-                                if (d.open() == 0)
-                                    try {
-                                        RepositoryPlugin repo = d
-                                                .getRepository();
-                                         repo.put(jar);
-                                  //      Central.refresh(Path.fromOSString(f
-                                  //              .getAbsolutePath()));
-                                    } finally {
-                                        d.close();
-                                    }
-                            }
-                        } finally {
-                            jar.close();
-                        }
-
-                    } catch (Exception e) {
-                        Activator.getDefault().error(
-                                "While verifying JAR " + locations[i], e);
-                    }
-                    locations[i].getParent().refreshLocal(1, null);
-                }
-            }
-        } catch (Exception e) {
-            Activator.getDefault().error("Could not start verification", e);
-        }
-    }
-
-    /**
-     * @see IActionDelegate#selectionChanged(IAction, ISelection)
-     */
-    public void selectionChanged(IAction action, ISelection selection) {
-        locations = getLocations(selection);
-    }
-
-    @SuppressWarnings("unchecked")
-    IFile[] getLocations(ISelection selection) {
-        if (selection != null && (selection instanceof StructuredSelection)) {
-            StructuredSelection ss = (StructuredSelection) selection;
-            IFile[] result = new IFile[ss.size()];
-            int n = 0;
-            for (Iterator<IFile> i = ss.iterator(); i.hasNext();) {
-                result[n++] = i.next();
-            }
-            return result;
-        }
-        return null;
-    }
-
-    public void setActivePart(IAction action, IWorkbenchPart targetPart) {
-    }
-
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/popup/actions/InstallBundle.java b/biz.aQute.bnd/src/aQute/bnd/plugin/popup/actions/InstallBundle.java
deleted file mode 100644
index 9296e5c..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/popup/actions/InstallBundle.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package aQute.bnd.plugin.popup.actions;
-
-import java.io.*;
-import java.util.*;
-
-import org.eclipse.core.resources.*;
-import org.eclipse.jface.action.*;
-import org.eclipse.jface.viewers.*;
-import org.eclipse.ui.*;
-import org.osgi.framework.*;
-import org.osgi.service.packageadmin.*;
-
-import aQute.bnd.plugin.*;
-
-public class InstallBundle implements IObjectActionDelegate {
-	IFile[]	locations;
-
-	public InstallBundle() {
-	}
-
-	/**
-	 * @see IActionDelegate#run(IAction)
-	 */
-	public void run(IAction action) {
-		Activator activator = Activator.getDefault();
-		Map<String,Bundle> map = new HashMap<String, Bundle>();
-		BundleContext context = activator.getBundle().getBundleContext();
-		Bundle bundles[] = context.getBundles();
-		for (int i = 0; i < bundles.length; i++) {
-			map.put(bundles[i].getLocation(), bundles[i]);
-		}
-
-		if (locations != null) {
-			List<Bundle> installed = new ArrayList<Bundle>();
-			List<Bundle> updated = new ArrayList<Bundle>();
-			int errors = 0;
-			for (int i = 0; i < locations.length; i++) {
-				try {
-					File mf = locations[i].getLocation().toFile();
-					String url = mf.toURI().toURL().toExternalForm();
-					Bundle b = (Bundle) map.get(url);
-					if (b != null) {
-						b.update();
-						updated.add(b);
-					} else {
-						b = context.installBundle(url);
-						installed.add(b);
-					}
-				} catch (Exception e) {
-					errors++;
-					Activator.getDefault()
-							.error("Error during install/update ", e);
-				}
-			}
-			if ( !updated.isEmpty()) {
-				ServiceReference ref = context.getServiceReference(PackageAdmin.class.getName());
-				if ( ref != null ) {
-					PackageAdmin packageAdmin = (PackageAdmin) context.getService(ref);
-					if ( packageAdmin != null ) {
-						packageAdmin.refreshPackages((Bundle[])updated.toArray(new Bundle[updated.size()]));
-					} else
-						activator.error("Can't get Package Admin service to refresh", null);
-				}  else
-					activator.error("No Package Admin to refresh", null);
-			}
-			StringBuffer sb = new StringBuffer();
-			printBundles("Installed Bundles", installed, sb);		
-			printBundles("Updated Bundles", updated, sb);
-			switch(errors) {
-			case 0: break;
-			case 1: sb.append("One Error\n"); break;
-			default: sb.append(errors); sb.append(" Errors\n");
-			}
-			activator.message(sb.toString());
-		}
-	}
-
-	private void printBundles(String msg, List<Bundle> list, StringBuffer sb) {
-		if ( list.isEmpty() )
-			return;
-		
-		sb.append(msg);
-		sb.append('\n');
-		for ( Bundle  b : list ) {
-			String version = (String) b.getHeaders().get("Bundle-Version");
-			if ( version == null )
-				version = "0.0.0";
-			
-			String name = b.getSymbolicName();
-			if ( name == null )
-				name = b.getLocation();
-			
-			sb.append("  ");
-			sb.append(name);
-			for ( int p = name.length(); p<20; p++ )
-				sb.append(" ");
-			sb.append("- ");
-			sb.append(version);
-			sb.append("\n");
-		}
-	}
-
-	/**
-	 * @see IActionDelegate#selectionChanged(IAction, ISelection)
-	 */
-	public void selectionChanged(IAction action, ISelection selection) {
-		locations = getLocations(selection);
-	}
-
-	@SuppressWarnings("unchecked")
-    IFile[] getLocations(ISelection selection) {
-		if (selection != null && (selection instanceof StructuredSelection)) {
-			StructuredSelection ss = (StructuredSelection) selection;
-			IFile[] result = new IFile[ss.size()];
-			int n = 0;
-			for (Iterator<IFile> i = ss.iterator(); i.hasNext();) {
-				result[n++] = (IFile) i.next();
-			}
-			return result;
-		}
-		return null;
-	}
-
-	public void setActivePart(IAction action, IWorkbenchPart targetPart) {
-	}
-
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/popup/actions/MakeBundle.java b/biz.aQute.bnd/src/aQute/bnd/plugin/popup/actions/MakeBundle.java
deleted file mode 100755
index 374bcb9..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/popup/actions/MakeBundle.java
+++ /dev/null
@@ -1,168 +0,0 @@
-package aQute.bnd.plugin.popup.actions;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.Iterator;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.StructuredSelection;
-import org.eclipse.ui.IActionDelegate;
-import org.eclipse.ui.IObjectActionDelegate;
-import org.eclipse.ui.IWorkbenchPart;
-
-import aQute.bnd.build.Project;
-import aQute.bnd.build.Workspace;
-import aQute.bnd.plugin.Activator;
-import aQute.lib.osgi.Builder;
-import aQute.lib.osgi.Jar;
-import aQute.lib.osgi.eclipse.EclipseClasspath;
-
-public class MakeBundle implements IObjectActionDelegate {
-    IFile[] locations;
-
-    public MakeBundle() {
-    }
-
-    /**
-     * @see IActionDelegate#run(IAction)
-     */
-    public void run(IAction action) {
-        Activator activator = Activator.getDefault();
-
-        try {
-            if (locations != null) {
-                for (int i = 0; i < locations.length; i++) {
-                    try {
-                        File mf = locations[i].getLocation().toFile();
-                        if (mf.getName().equals(Project.BNDFILE)) {
-                            Project project = Workspace.getProject(mf
-                                    .getParentFile());
-                            File[] files = project.build();
-                            String target = "";
-                            if ( files != null ) {
-                                for ( File f : files ) {
-                                    target += f + " ";
-                                    
-                                }
-                            }
-                            activator.report(true, true, project, "Building "
-                                    + project, "Created files " + target );
-                        } else {
-                            Builder builder = setBuilder(activator,
-                                    locations[i].getProject(), mf);
-
-                            File cwd = mf.getAbsoluteFile().getParentFile();
-                            File target;
-
-                            builder.build();
-                            String name = builder.getBsn() + ".jar";
-
-                            Jar jar = builder.getJar();
-
-                            String path = builder.getProperty("-output");
-                            if (path == null) {
-                                target = new File(cwd, name);
-                            } else {
-                                target = new File(path);
-                                if (!target.isAbsolute())
-                                    target = new File(cwd, path);
-                                if (target.isDirectory()) {
-                                    target = new File(target, name);
-                                }
-                            }
-
-                            target.delete();
-                            if (builder.getErrors().size() > 0) {
-                                activator.error(builder.getErrors());
-                            } else {
-                                jar.write(target);
-
-                                File copy = activator.getCopy();
-                                if (copy != null) {
-                                    copy = new File(copy, target.getName());
-                                    jar.write(copy);
-                                }
-                                if (builder.getWarnings().size() > 0) {
-                                    activator.warning(builder.getWarnings());
-                                } else {
-                                    if (activator.getReportDone()) {
-                                        String p = target.getPath();
-                                        if (p.startsWith(cwd.getAbsolutePath()))
-                                            p = p
-                                                    .substring(cwd
-                                                            .getAbsolutePath()
-                                                            .length() + 1);
-                                        String msg = "Saved as " + p;
-                                        if (copy != null)
-                                            msg += " and copied to " + copy;
-                                        activator.message(msg);
-                                    }
-                                }
-                            }
-                            builder.close();
-                        }
-                    } catch (Exception e) {
-                        e.printStackTrace();
-                        activator.error("While generating JAR " + locations[i],
-                                e);
-                    }
-                    locations[i].getParent().refreshLocal(1, null);
-                }
-            }
-        } catch (Exception e) {
-            activator.error("Error in bnd", e);
-        }
-    }
-
-    static public Builder setBuilder(Activator activator, IProject project,
-            File mf) throws Exception, IOException, FileNotFoundException {
-        Builder builder = new Builder();
-        builder.setPedantic(activator.isPedantic() || activator.isDebugging());
-
-        // TODO of course we should get the classpath from
-        // inside API ...
-        File p = project.getLocation().toFile();
-
-        // TODO for now we ignore the workspace and use the
-        // project parent directory
-
-        EclipseClasspath ecp = new EclipseClasspath(builder, p.getParentFile(),
-                p);
-
-        builder.setClasspath((File[]) ecp.getClasspath().toArray(new File[0]));
-        builder
-                .setSourcepath((File[]) ecp.getSourcepath()
-                        .toArray(new File[0]));
-        builder.setProperties(mf);
-        return builder;
-    }
-
-    /**
-     * @see IActionDelegate#selectionChanged(IAction, ISelection)
-     */
-    public void selectionChanged(IAction action, ISelection selection) {
-        locations = getLocations(selection);
-    }
-
-    @SuppressWarnings("unchecked")
-    IFile[] getLocations(ISelection selection) {
-        if (selection != null && (selection instanceof StructuredSelection)) {
-            StructuredSelection ss = (StructuredSelection) selection;
-            IFile[] result = new IFile[ss.size()];
-            int n = 0;
-            for (Iterator<IFile> i = ss.iterator(); i.hasNext();) {
-                result[n++] = i.next();
-            }
-            return result;
-        }
-        return null;
-    }
-
-    public void setActivePart(IAction action, IWorkbenchPart targetPart) {
-    }
-
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/popup/actions/VerifyBundle.java b/biz.aQute.bnd/src/aQute/bnd/plugin/popup/actions/VerifyBundle.java
deleted file mode 100755
index f8d0a06..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/popup/actions/VerifyBundle.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package aQute.bnd.plugin.popup.actions;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.StructuredSelection;
-import org.eclipse.ui.IActionDelegate;
-import org.eclipse.ui.IObjectActionDelegate;
-import org.eclipse.ui.IWorkbenchPart;
-
-import aQute.bnd.plugin.Activator;
-import aQute.lib.osgi.Jar;
-import aQute.lib.osgi.Verifier;
-
-public class VerifyBundle implements IObjectActionDelegate {
-    IFile[] locations;
-
-    public VerifyBundle() {
-    }
-
-    /**
-     * @see IActionDelegate#run(IAction)
-     */
-    public void run(IAction action) {
-        try {
-            if (locations != null) {
-                for (int i = 0; i < locations.length; i++) {
-                    File mf = locations[i].getLocation().toFile();
-                    try {
-                        Jar jar = new Jar(mf.getName(), mf);
-                        Verifier verifier = new Verifier(jar);
-                        try {
-                            verifier.verify();
-                            if (verifier.getErrors().size()
-                                    + verifier.getWarnings().size() > 0) {
-                                List<String> info = new ArrayList<String>(verifier.getErrors());
-                                info.addAll(verifier.getWarnings());
-                                Activator.getDefault().error(info);
-                            }
-                        } finally {
-                            jar.close();
-                            verifier.close();
-                        }
-
-                    } catch (Exception e) {
-                        Activator.getDefault().error(
-                                "While verifying JAR " + locations[i], e);
-                    }
-                    locations[i].getParent().refreshLocal(1, null);
-                }
-            }
-        } catch (Exception e) {
-            Activator.getDefault().error("Could not start verification", e);
-        }
-    }
-
-    /**
-     * @see IActionDelegate#selectionChanged(IAction, ISelection)
-     */
-    public void selectionChanged(IAction action, ISelection selection) {
-        locations = getLocations(selection);
-    }
-
-    @SuppressWarnings("unchecked")
-    IFile[] getLocations(ISelection selection) {
-        if (selection != null && (selection instanceof StructuredSelection)) {
-            StructuredSelection ss = (StructuredSelection) selection;
-            IFile[] result = new IFile[ss.size()];
-            int n = 0;
-            for (Iterator<IFile> i = ss.iterator(); i.hasNext();) {
-                result[n++] = i.next();
-            }
-            return result;
-        }
-        return null;
-    }
-
-    public void setActivePart(IAction action, IWorkbenchPart targetPart) {
-    }
-
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/popup/actions/WrapBundle.java b/biz.aQute.bnd/src/aQute/bnd/plugin/popup/actions/WrapBundle.java
deleted file mode 100755
index b2328ef..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/popup/actions/WrapBundle.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package aQute.bnd.plugin.popup.actions;
-
-import java.util.*;
-
-import org.eclipse.core.resources.*;
-import org.eclipse.jface.action.*;
-import org.eclipse.jface.dialogs.*;
-import org.eclipse.jface.viewers.*;
-import org.eclipse.ui.*;
-
-import aQute.bnd.plugin.*;
-
-public class WrapBundle implements IObjectActionDelegate {
-	IFile[]		locations;
-	public WrapBundle(){}
-
-	/**
-	 * @see IActionDelegate#run(IAction)
-	 */
-	public void run(IAction action) {
-		try {
-			if ( locations!= null) {
-				for (int i = 0; i < locations.length; i++) {
-					// TODO
-					MessageDialog.openInformation(null,"Not Implemented Yet", "TODO implement wrapping");
-				}
-			}
-		}
-		catch( Exception e ) {
-			Activator.getDefault().error("Could not start Test View", e );
-		}
-	}
-
-	 
-	 /**
-		 * @see IActionDelegate#selectionChanged(IAction, ISelection)
-		 */
-	public void selectionChanged(IAction action, ISelection selection) {
-		locations = getLocations(selection);
-	}
-
-
-	@SuppressWarnings("unchecked")
-    IFile[] getLocations(ISelection selection) {
-		if (selection != null && (selection instanceof StructuredSelection)) {
-			StructuredSelection ss = (StructuredSelection) selection;
-			IFile[] result = new IFile[ss.size()];
-			int n = 0;
-			for (Iterator<IFile> i = ss.iterator(); i.hasNext();) {
-				result[n++] = i.next();
-			}
-			return result;
-		}
-		return null;
-	}
-
-	public void setActivePart(IAction action, IWorkbenchPart targetPart) {
-	}
-
-}
diff --git a/biz.aQute.bnd/src/aQute/bnd/plugin/popup/actions/repo/RepoDialog.java b/biz.aQute.bnd/src/aQute/bnd/plugin/popup/actions/repo/RepoDialog.java
deleted file mode 100644
index fa66f15..0000000
--- a/biz.aQute.bnd/src/aQute/bnd/plugin/popup/actions/repo/RepoDialog.java
+++ /dev/null
@@ -1,158 +0,0 @@
-package aQute.bnd.plugin.popup.actions.repo;
-
-import java.util.*;
-
-import org.eclipse.jface.dialogs.*;
-import org.eclipse.jface.dialogs.Dialog;
-import org.eclipse.swt.*;
-import org.eclipse.swt.events.*;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.*;
-
-import aQute.bnd.service.*;
-import aQute.lib.osgi.*;
-
-public class RepoDialog extends Dialog {
-    private Text                             bsn;
-    private Text                             version;
-
-    private Label                            lblRepository;
-    private Combo                            repositories;
-    private java.util.List<RepositoryPlugin> repos;
-    private Jar                              jar;
-    private Label                            lblBundleDescription;
-    private Text                             description;
-    private RepositoryPlugin                 selected;
-
-    /**
-     * Create the dialog.
-     * 
-     * @param parentShell
-     */
-    public RepoDialog(Shell parentShell, Jar jar,
-            java.util.List<RepositoryPlugin> repos) {
-        super(parentShell);
-        setShellStyle(SWT.DIALOG_TRIM);
-        this.repos = repos;
-        this.jar = jar;
-    }
-
-    /**
-     * Create contents of the dialog.
-     * 
-     * @param parent
-     */
-    @Override
-    protected Control createDialogArea(Composite parent) {
-
-        Composite container = (Composite) super.createDialogArea(parent);
-        container.setLayout(null);
-        {
-            lblRepository = new Label(container, SWT.NONE);
-            lblRepository.setBounds(8, 8, 160, 24);
-            lblRepository.setText("Repository");
-        }
-        {
-            repositories = new Combo(container, SWT.READ_ONLY);
-            repositories.setBounds(168, 3, 272, 30);
-            repositories.addSelectionListener(new SelectionAdapter() {
-
-                public void widgetSelected(SelectionEvent e) {
-                    selected = repos.get(repositories.getSelectionIndex());
-                }
-
-            });
-        }
-        {
-            bsn = new Text(container, SWT.BORDER);
-            bsn.setEditable(false);
-            bsn.setBounds(168, 39, 272, 28);
-        }
-        {
-            version = new Text(container, SWT.BORDER);
-            version.setEditable(false);
-            version.setBounds(168, 67, 272, 28);
-        }
-        {
-            Label lblBundleSymbolicName = new Label(container, SWT.NONE);
-            lblBundleSymbolicName.setBounds(8, 40, 160, 24);
-            lblBundleSymbolicName.setText("Bundle Symbolic Name");
-        }
-        {
-            Label lblVersion = new Label(container, SWT.NONE);
-            lblVersion.setBounds(8, 72, 160, 24);
-            lblVersion.setText("Bundle Version");
-        }
-        {
-            lblBundleDescription = new Label(container, SWT.NONE);
-            lblBundleDescription.setBounds(8, 105, 160, 24);
-            lblBundleDescription.setText("Bundle Description");
-        }
-        {
-            description = new Text(container, SWT.BORDER | SWT.V_SCROLL
-                    | SWT.MULTI);
-            description.setEditable(false);
-            description.setBounds(168, 101, 272, 117);
-        }
-
-        setup();
-        return container;
-    }
-
-    private void setup() {
-        try {
-            bsn.setText(jar.getManifest().getMainAttributes().getValue(
-                    Constants.BUNDLE_SYMBOLICNAME));
-            String v = jar.getManifest().getMainAttributes().getValue(
-                    Constants.BUNDLE_VERSION);
-            if (v == null)
-                v = "0.0.0";
-            version.setText(v);
-
-            v = jar.getManifest().getMainAttributes().getValue(
-                    Constants.BUNDLE_DESCRIPTION);
-            if (v == null)
-                v = "";
-            description.setText(v);
-
-            for (Iterator<RepositoryPlugin> i = repos.iterator(); i.hasNext();) {
-                RepositoryPlugin plugin = i.next();
-                if (plugin.canWrite())
-                    repositories.add(plugin.getName());
-                else
-                    i.remove();
-            }
-            repositories.select(0);
-            selected = repos.get(0);
-            
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-
-    /**
-     * Create contents of the button bar.
-     * 
-     * @param parent
-     */
-    @Override
-    protected void createButtonsForButtonBar(Composite parent) {
-        Button button = createButton(parent, IDialogConstants.OK_ID,
-                IDialogConstants.OK_LABEL, true);
-        button.setText("Deploy");
-        createButton(parent, IDialogConstants.CANCEL_ID,
-                IDialogConstants.CANCEL_LABEL, false);
-    }
-
-    /**
-     * Return the initial size of the dialog.
-     */
-    @Override
-    protected Point getInitialSize() {
-        return new Point(450, 300);
-    }
-
-    public RepositoryPlugin getRepository() {
-        return selected;
-    }
-}
diff --git a/biz.aQute.bnd/src/biz/aqute/bnd/eclipse/popup/Refresh.java b/biz.aQute.bnd/src/biz/aqute/bnd/eclipse/popup/Refresh.java
deleted file mode 100644
index b237470..0000000
--- a/biz.aQute.bnd/src/biz/aqute/bnd/eclipse/popup/Refresh.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package biz.aqute.bnd.eclipse.popup;
-
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.IObjectActionDelegate;
-import org.eclipse.ui.IWorkbenchPart;
-
-public class Refresh implements IObjectActionDelegate {
-
-	/**
-	 * Constructor for Action1.
-	 */
-	public Refresh() {
-		super();
-	}
-
-	/**
-	 * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
-	 */
-	public void setActivePart(IAction action, IWorkbenchPart targetPart) {
-	}
-
-	/**
-	 * @see IActionDelegate#run(IAction)
-	 */
-	public void run(IAction action) {
-		Shell shell = new Shell();
-		MessageDialog.openInformation(
-			shell,
-			"aQute Bundle Tool",
-			"New Action was executed.");
-	}
-
-	/**
-	 * @see IActionDelegate#selectionChanged(IAction, ISelection)
-	 */
-	public void selectionChanged(IAction action, ISelection selection) {
-	}
-
-}
diff --git a/biz.aQute.bnd/src/bnd.java b/biz.aQute.bnd/src/bnd.java
new file mode 100644
index 0000000..9935fb2
--- /dev/null
+++ b/biz.aQute.bnd/src/bnd.java
@@ -0,0 +1,5 @@
+public class bnd {
+	public static void main(String args[]) throws Exception {
+		aQute.bnd.main.bnd.main(args);
+	}
+}
diff --git a/biz.aQute.bnd/src/swing2swt/layout/AWTLayout.java b/biz.aQute.bnd/src/swing2swt/layout/AWTLayout.java
deleted file mode 100644
index 20b8bc3..0000000
--- a/biz.aQute.bnd/src/swing2swt/layout/AWTLayout.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- -----------------------------------------------------------------------------
-  (c) Copyright IBM Corp. 2003  All rights reserved.
-
- The sample program(s) is/are owned by International Business Machines
- Corporation or one of its subsidiaries ("IBM") and is/are copyrighted and
- licensed, not sold.
-
- You may copy, modify, and distribute this/these sample program(s) in any form
- without payment to IBM, for any purpose including developing, using, marketing
- or distributing programs that include or are derivative works of the sample
- program(s).
-
- The sample program(s) is/are provided to you on an "AS IS" basis, without
- warranty of any kind.  IBM HEREBY EXPRESSLY DISCLAIMS ALL WARRANTIES, EITHER
- EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  Some jurisdictions do
- not allow for the exclusion or limitation of implied warranties, so the above
- limitations or exclusions may not apply to you.  IBM shall not be liable for
- any damages you suffer as a result of using, modifying or distributing the
- sample program(s) or its/their derivatives.
-
- Each copy of any portion of this/these sample program(s) or any derivative
- work, must include the above copyright notice and disclaimer of warranty.
-
- -----------------------------------------------------------------------------
-*/
-
-package swing2swt.layout;
-
-import java.awt.Dimension;
-
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Layout;
-
-/**
- * Superclass for all the AWT layouts ported to SWT.
- * @author Yannick Saillet
- */
-public abstract class AWTLayout extends Layout {
-
-   /** 
-   * Key under which an eventual preferred size (set with setPreferredSize)
-   * is stored as a user data in the SWT control.
-   */
-  public final static String KEY_PREFERRED_SIZE = "preferredSize";
-
-  /**
-   * Gets the preferred size of a component.
-   * If a preferred size has been set with setPreferredSize, returns it, 
-   * otherwise returns the component computed preferred size.
-   */
-  protected Point getPreferredSize(
-    Control control,
-    int wHint,
-    int hHint,
-    boolean changed) {
-    // check if a preferred size was set on the control with 
-    // SWTComponent.setPreferredSize(Dimension)
-    Dimension d = (Dimension)control.getData(KEY_PREFERRED_SIZE);
-    if (d != null)
-      return new Point(d.width, d.height);
-    return control.computeSize(wHint, hHint, changed);
-  }
-}
diff --git a/biz.aQute.bnd/src/swing2swt/layout/GridLayout.java b/biz.aQute.bnd/src/swing2swt/layout/GridLayout.java
deleted file mode 100644
index b11944f..0000000
--- a/biz.aQute.bnd/src/swing2swt/layout/GridLayout.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- -----------------------------------------------------------------------------
-  (c) Copyright IBM Corp. 2003  All rights reserved.
-
- The sample program(s) is/are owned by International Business Machines
- Corporation or one of its subsidiaries ("IBM") and is/are copyrighted and
- licensed, not sold.
-
- You may copy, modify, and distribute this/these sample program(s) in any form
- without payment to IBM, for any purpose including developing, using, marketing
- or distributing programs that include or are derivative works of the sample
- program(s).
-
- The sample program(s) is/are provided to you on an "AS IS" basis, without
- warranty of any kind.  IBM HEREBY EXPRESSLY DISCLAIMS ALL WARRANTIES, EITHER
- EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  Some jurisdictions do
- not allow for the exclusion or limitation of implied warranties, so the above
- limitations or exclusions may not apply to you.  IBM shall not be liable for
- any damages you suffer as a result of using, modifying or distributing the
- sample program(s) or its/their derivatives.
-
- Each copy of any portion of this/these sample program(s) or any derivative
- work, must include the above copyright notice and disclaimer of warranty.
-
- -----------------------------------------------------------------------------
-*/
-
-package swing2swt.layout;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.*;
-
-/**
- * Port of AWT GridLayout to SWT.
- * @author Yannick Saillet
- */
-public class GridLayout extends AWTLayout {
-  private int rows, columns, hgap, vgap;
-
-  public GridLayout() {
-    this(1, 0);
-  }
-
-  public GridLayout(int rows, int columns) {
-    this(rows, columns, 0, 0);
-  }
-
-  public GridLayout(int rows, int columns, int hgap, int vgap) {
-    if (rows == 0 && columns == 0)
-      throw new IllegalArgumentException("rows and cols cannot both be zero");
-
-    if (rows > 0 && columns > 0)
-      columns = 0;
-
-    this.rows = rows;
-    this.columns = columns;
-    this.hgap = hgap;
-    this.vgap = vgap;
-  }
-
-  public int getColumns() {
-    return columns;
-  }
-
-  public int getHgap() {
-    return hgap;
-  }
-
-  public int getRows() {
-    return rows;
-  }
-
-  public int getVgap() {
-    return vgap;
-  }
-
-  public void setColumns(int cols) {
-    if (rows == 0 && columns == 0)
-      throw new IllegalArgumentException("rows and cols cannot both be zero");
-
-    this.columns = cols;
-  }
-
-  public void setHgap(int hgap) {
-    this.hgap = hgap;
-  }
-
-  public void setRows(int rows) {
-    if (rows == 0 && columns == 0)
-      throw new IllegalArgumentException("rows and cols cannot both be zero");
-
-    this.rows = rows;
-  }
-
-  public void setVgap(int vgap) {
-    this.vgap = vgap;
-  }
-
-  //----------
-
-  protected Point computeSize(
-    Composite composite,
-    int wHint,
-    int hHint,
-    boolean flushCache) {
-    Control[] children = composite.getChildren();
-    int nbOfVisibleChildren = 0;
-    for (int i = 0; i < children.length; i++) {
-      //if (children[i].isVisible())
-        nbOfVisibleChildren++;
-    }
-
-    if (nbOfVisibleChildren == 0)
-      return new Point(0, 0);
-    int r = rows;
-    int c = columns;
-    if (r == 0)
-      r = nbOfVisibleChildren / c + ((nbOfVisibleChildren % c) == 0 ? 0 : 1);
-    else if (c == 0)
-      c = nbOfVisibleChildren / r + ((nbOfVisibleChildren % r) == 0 ? 0 : 1);
-    int width = 0;
-    int height = 0;
-    for (int i = 0; i < children.length; i++) {
-      //if (!children[i].isVisible())
-        //continue;
-      Point size =
-        getPreferredSize(children[i], SWT.DEFAULT, SWT.DEFAULT, flushCache);
-      if (size.x > width)
-        width = size.x;
-      if (size.y > height)
-        height = size.y;
-    }
-    return new Point(c * width + (c - 1) * hgap, r * height + (r - 1) * vgap);
-  }
-
-  protected void layout(Composite composite, boolean flushCache) {
-    Rectangle clientArea = composite.getClientArea();
-    Control[] children = composite.getChildren();
-    int nbOfVisibleChildren = 0;
-    for (int i = 0; i < children.length; i++) {
-      //if (children[i].isVisible())
-        nbOfVisibleChildren++;
-    }
-    if (nbOfVisibleChildren == 0)
-      return ;
-
-    int r = rows;
-    int c = columns;
-    if (r == 0)
-      r = nbOfVisibleChildren / c + ((nbOfVisibleChildren % c) == 0 ? 0 : 1);
-    else if (c == 0)
-      c = nbOfVisibleChildren / r + ((nbOfVisibleChildren % r) == 0 ? 0 : 1);
-    int width = (clientArea.width - (c - 1) * hgap) / c;
-    int height = (clientArea.height - (r - 1) * vgap) / r;
-
-    int x = clientArea.x;
-    int y = clientArea.y;
-    for (int i = 0; i < children.length; i++) {
-      //if (!children[i].isVisible())
-        //continue;
-      children[i].setBounds(x, y, width, height);
-      if (((i + 1) % c) == 0) // if new line
-        {
-        x = clientArea.x;
-        y += height + vgap;
-      } else
-        x += width + hgap;
-    }
-  }
-}
diff --git a/biz.aQute.bnd/src/test/TestBuild.java b/biz.aQute.bnd/src/test/TestBuild.java
index 9e64791..e20a3fa 100644
--- a/biz.aQute.bnd/src/test/TestBuild.java
+++ b/biz.aQute.bnd/src/test/TestBuild.java
@@ -1,13 +1,18 @@
 package test;
 
-import aQute.bnd.main.*;
 import junit.framework.*;
+import aQute.bnd.main.*;
 
 public class TestBuild extends TestCase {
 
 	public void testX() {}
-	
-//	public void testBndBuild() {
-//		bnd.main(new String[] {"build"});
-//	}
+
+	public void testBndBuild() throws Exception {
+		bnd.main(new String[] {
+			"version"
+		});
+		// bnd.main(new String[] {"-etb",
+		// "/Ws/osgi/master/osgi.ct/generated/osgi.ct.cmpn", "runtests",
+		// "org.osgi.test.cases.log.bnd", "org.osgi.test.cases.metatype.bnd"});
+	}
 }
diff --git a/biz.aQute.bnd/test.bnd b/biz.aQute.bnd/test.bnd
new file mode 100755
index 0000000..de5f3eb
--- /dev/null
+++ b/biz.aQute.bnd/test.bnd
@@ -0,0 +1,4 @@
+Bundle-Name:            bnd Test Library
+Bundle-Description:     Contains only the test functions for bnd.
+Bundle-DocURL:          http://www.aQute.biz/Code/Bnd
+Export-Package:         aQute.bnd.test.*
diff --git a/biz.aQute.bndlib.tests/.classpath b/biz.aQute.bndlib.tests/.classpath
new file mode 100644
index 0000000..6d3c62a
--- /dev/null
+++ b/biz.aQute.bndlib.tests/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/biz.aQute.bndlib.tests/.project b/biz.aQute.bndlib.tests/.project
new file mode 100644
index 0000000..35ee6fc
--- /dev/null
+++ b/biz.aQute.bndlib.tests/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>biz.aQute.bndlib.tests</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>bndtools.core.bndbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>bndtools.core.bndnature</nature>
+	</natures>
+</projectDescription>
diff --git a/biz.aQute.bndlib.tests/.settings/org.eclipse.core.resources.prefs b/biz.aQute.bndlib.tests/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..f6822ac
--- /dev/null
+++ b/biz.aQute.bndlib.tests/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Mon Sep 19 11:00:09 EDT 2005
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/biz.aQute.bndlib.tests/.settings/org.eclipse.core.runtime.prefs b/biz.aQute.bndlib.tests/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..d7b5655
--- /dev/null
+++ b/biz.aQute.bndlib.tests/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Tue Dec 14 12:22:25 EST 2010
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/biz.aQute.bndlib.tests/.settings/org.eclipse.jdt.core.prefs b/biz.aQute.bndlib.tests/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..150b1af
--- /dev/null
+++ b/biz.aQute.bndlib.tests/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,361 @@
+#Fri Aug 10 14:01:08 CEST 2012
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=ignore
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=true
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/biz.aQute.bndlib.tests/.settings/org.eclipse.jdt.ui.prefs b/biz.aQute.bndlib.tests/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..f5e8897
--- /dev/null
+++ b/biz.aQute.bndlib.tests/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,61 @@
+#Fri Aug 10 13:48:46 CEST 2012
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=false
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=false
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=false
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
+cleanup_settings_version=2
+eclipse.preferences.version=1
+formatter_profile=_bnd(tools)
+formatter_settings_version=12
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=1
+org.eclipse.jdt.ui.staticondemandthreshold=1
diff --git a/biz.aQute.bndlib.tests/bnd.bnd b/biz.aQute.bndlib.tests/bnd.bnd
new file mode 100644
index 0000000..cad98e5
--- /dev/null
+++ b/biz.aQute.bndlib.tests/bnd.bnd
@@ -0,0 +1,13 @@
+-dependson: demo
+-nobundles: true
+
+-buildpath: biz.aQute.bndlib;version=project,\
+	aQute.libg;version=project,\
+	osgi.cmpn;version=4.3.0,\
+	osgi.core;version=4.2.1,\
+	junit.osgi;version=3.8.2,\
+	ee.j2se;version=${javac.ee},\
+	org.mockito.mockito-all;version=1.9.0
+
+-runtrace: true
+
diff --git a/biz.aQute.bndlib/bnd/makesondemand.bnd b/biz.aQute.bndlib.tests/bnd/makesondemand.bnd
similarity index 100%
rename from biz.aQute.bndlib/bnd/makesondemand.bnd
rename to biz.aQute.bndlib.tests/bnd/makesondemand.bnd
diff --git a/biz.aQute.bndlib.tests/bnd/ondemand.bnd b/biz.aQute.bndlib.tests/bnd/ondemand.bnd
new file mode 100644
index 0000000..fddbb64
--- /dev/null
+++ b/biz.aQute.bndlib.tests/bnd/ondemand.bnd
@@ -0,0 +1 @@
+Export-Package: test.activator
diff --git a/biz.aQute.bndlib.tests/build.xml b/biz.aQute.bndlib.tests/build.xml
new file mode 100644
index 0000000..23063e2
--- /dev/null
+++ b/biz.aQute.bndlib.tests/build.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="project" default="build"> 
+	<import file="../cnf/build.xml"/>
+</project>
diff --git a/biz.aQute.bndlib/compilerversions/compile.sh b/biz.aQute.bndlib.tests/compilerversions/compile.sh
similarity index 100%
rename from biz.aQute.bndlib/compilerversions/compile.sh
rename to biz.aQute.bndlib.tests/compilerversions/compile.sh
diff --git a/biz.aQute.bndlib/compilerversions/compilerversions.bnd b/biz.aQute.bndlib.tests/compilerversions/compilerversions.bnd
similarity index 100%
rename from biz.aQute.bndlib/compilerversions/compilerversions.bnd
rename to biz.aQute.bndlib.tests/compilerversions/compilerversions.bnd
diff --git a/biz.aQute.bndlib/compilerversions/download_bundle.gif b/biz.aQute.bndlib.tests/compilerversions/download_bundle.gif
similarity index 100%
rename from biz.aQute.bndlib/compilerversions/download_bundle.gif
rename to biz.aQute.bndlib.tests/compilerversions/download_bundle.gif
diff --git a/biz.aQute.bndlib/compilerversions/src/eclipse_1_1/ClassRef.java b/biz.aQute.bndlib.tests/compilerversions/src/eclipse_1_1/ClassRef.java
similarity index 100%
rename from biz.aQute.bndlib/compilerversions/src/eclipse_1_1/ClassRef.java
rename to biz.aQute.bndlib.tests/compilerversions/src/eclipse_1_1/ClassRef.java
diff --git a/biz.aQute.bndlib/compilerversions/src/eclipse_1_2/ClassRef.java b/biz.aQute.bndlib.tests/compilerversions/src/eclipse_1_2/ClassRef.java
similarity index 100%
rename from biz.aQute.bndlib/compilerversions/src/eclipse_1_2/ClassRef.java
rename to biz.aQute.bndlib.tests/compilerversions/src/eclipse_1_2/ClassRef.java
diff --git a/biz.aQute.bndlib/compilerversions/src/eclipse_1_3/ClassRef.java b/biz.aQute.bndlib.tests/compilerversions/src/eclipse_1_3/ClassRef.java
similarity index 100%
rename from biz.aQute.bndlib/compilerversions/src/eclipse_1_3/ClassRef.java
rename to biz.aQute.bndlib.tests/compilerversions/src/eclipse_1_3/ClassRef.java
diff --git a/biz.aQute.bndlib/compilerversions/src/eclipse_1_4/ClassRef.java b/biz.aQute.bndlib.tests/compilerversions/src/eclipse_1_4/ClassRef.java
similarity index 100%
rename from biz.aQute.bndlib/compilerversions/src/eclipse_1_4/ClassRef.java
rename to biz.aQute.bndlib.tests/compilerversions/src/eclipse_1_4/ClassRef.java
diff --git a/biz.aQute.bndlib/compilerversions/src/eclipse_1_5/ClassRef.java b/biz.aQute.bndlib.tests/compilerversions/src/eclipse_1_5/ClassRef.java
similarity index 100%
rename from biz.aQute.bndlib/compilerversions/src/eclipse_1_5/ClassRef.java
rename to biz.aQute.bndlib.tests/compilerversions/src/eclipse_1_5/ClassRef.java
diff --git a/biz.aQute.bndlib/compilerversions/src/eclipse_1_6/ClassRef.java b/biz.aQute.bndlib.tests/compilerversions/src/eclipse_1_6/ClassRef.java
similarity index 100%
rename from biz.aQute.bndlib/compilerversions/src/eclipse_1_6/ClassRef.java
rename to biz.aQute.bndlib.tests/compilerversions/src/eclipse_1_6/ClassRef.java
diff --git a/biz.aQute.bndlib/compilerversions/src/eclipse_jsr14/ClassRef.java b/biz.aQute.bndlib.tests/compilerversions/src/eclipse_jsr14/ClassRef.java
similarity index 100%
rename from biz.aQute.bndlib/compilerversions/src/eclipse_jsr14/ClassRef.java
rename to biz.aQute.bndlib.tests/compilerversions/src/eclipse_jsr14/ClassRef.java
diff --git a/biz.aQute.bndlib/compilerversions/src/sun_1_1/ClassRef.java b/biz.aQute.bndlib.tests/compilerversions/src/sun_1_1/ClassRef.java
similarity index 100%
rename from biz.aQute.bndlib/compilerversions/src/sun_1_1/ClassRef.java
rename to biz.aQute.bndlib.tests/compilerversions/src/sun_1_1/ClassRef.java
diff --git a/biz.aQute.bndlib/compilerversions/src/sun_1_2/ClassRef.java b/biz.aQute.bndlib.tests/compilerversions/src/sun_1_2/ClassRef.java
similarity index 100%
rename from biz.aQute.bndlib/compilerversions/src/sun_1_2/ClassRef.java
rename to biz.aQute.bndlib.tests/compilerversions/src/sun_1_2/ClassRef.java
diff --git a/biz.aQute.bndlib/compilerversions/src/sun_1_3/ClassRef.java b/biz.aQute.bndlib.tests/compilerversions/src/sun_1_3/ClassRef.java
similarity index 100%
rename from biz.aQute.bndlib/compilerversions/src/sun_1_3/ClassRef.java
rename to biz.aQute.bndlib.tests/compilerversions/src/sun_1_3/ClassRef.java
diff --git a/biz.aQute.bndlib/compilerversions/src/sun_1_4/ClassRef.java b/biz.aQute.bndlib.tests/compilerversions/src/sun_1_4/ClassRef.java
similarity index 100%
rename from biz.aQute.bndlib/compilerversions/src/sun_1_4/ClassRef.java
rename to biz.aQute.bndlib.tests/compilerversions/src/sun_1_4/ClassRef.java
diff --git a/biz.aQute.bndlib/compilerversions/src/sun_1_5/ClassRef.java b/biz.aQute.bndlib.tests/compilerversions/src/sun_1_5/ClassRef.java
similarity index 100%
rename from biz.aQute.bndlib/compilerversions/src/sun_1_5/ClassRef.java
rename to biz.aQute.bndlib.tests/compilerversions/src/sun_1_5/ClassRef.java
diff --git a/biz.aQute.bndlib/compilerversions/src/sun_1_6/ClassRef.java b/biz.aQute.bndlib.tests/compilerversions/src/sun_1_6/ClassRef.java
similarity index 100%
rename from biz.aQute.bndlib/compilerversions/src/sun_1_6/ClassRef.java
rename to biz.aQute.bndlib.tests/compilerversions/src/sun_1_6/ClassRef.java
diff --git a/biz.aQute.bndlib/compilerversions/src/sun_jsr14/ClassRef.java b/biz.aQute.bndlib.tests/compilerversions/src/sun_jsr14/ClassRef.java
similarity index 100%
rename from biz.aQute.bndlib/compilerversions/src/sun_jsr14/ClassRef.java
rename to biz.aQute.bndlib.tests/compilerversions/src/sun_jsr14/ClassRef.java
diff --git a/biz.aQute.bndlib.tests/jar/AnnotationWithJSR14.jclass b/biz.aQute.bndlib.tests/jar/AnnotationWithJSR14.jclass
new file mode 100644
index 0000000..185d366
Binary files /dev/null and b/biz.aQute.bndlib.tests/jar/AnnotationWithJSR14.jclass differ
diff --git a/biz.aQute.bndlib.tests/jar/AstNodeToScriptVisitor.jclass b/biz.aQute.bndlib.tests/jar/AstNodeToScriptVisitor.jclass
new file mode 100644
index 0000000..d582d06
Binary files /dev/null and b/biz.aQute.bndlib.tests/jar/AstNodeToScriptVisitor.jclass differ
diff --git a/biz.aQute.bndlib.tests/jar/DeploymentAdminPermission.1.jclass b/biz.aQute.bndlib.tests/jar/DeploymentAdminPermission.1.jclass
new file mode 100644
index 0000000..06bbd3c
Binary files /dev/null and b/biz.aQute.bndlib.tests/jar/DeploymentAdminPermission.1.jclass differ
diff --git a/biz.aQute.bndlib.tests/jar/WithAnnotations.jclass b/biz.aQute.bndlib.tests/jar/WithAnnotations.jclass
new file mode 100755
index 0000000..db11a06
Binary files /dev/null and b/biz.aQute.bndlib.tests/jar/WithAnnotations.jclass differ
diff --git a/biz.aQute.bndlib.tests/jar/mandatorynoversion.bnd b/biz.aQute.bndlib.tests/jar/mandatorynoversion.bnd
new file mode 100755
index 0000000..e1fa56b
--- /dev/null
+++ b/biz.aQute.bndlib.tests/jar/mandatorynoversion.bnd
@@ -0,0 +1,2 @@
+-classpath: mina.jar
+Export-Package: *;mandatory:="x,y";x=1;y=2
diff --git a/biz.aQute.bndlib.tests/jar/mina.bar b/biz.aQute.bndlib.tests/jar/mina.bar
new file mode 100755
index 0000000..0a1d77d
Binary files /dev/null and b/biz.aQute.bndlib.tests/jar/mina.bar differ
diff --git a/biz.aQute.bndlib.tests/jar/minax.bnd b/biz.aQute.bndlib.tests/jar/minax.bnd
new file mode 100755
index 0000000..87b789e
--- /dev/null
+++ b/biz.aQute.bndlib.tests/jar/minax.bnd
@@ -0,0 +1,4 @@
+-classpath: mina.jar
+Import-Package: org.apache.commons.collections.map,*
+Export-Package: !META-INF.*,*
+
diff --git a/biz.aQute.bndlib.tests/jar/rox.bnd b/biz.aQute.bndlib.tests/jar/rox.bnd
new file mode 100755
index 0000000..6abff91
--- /dev/null
+++ b/biz.aQute.bndlib.tests/jar/rox.bnd
@@ -0,0 +1,4 @@
+-classpath: ro.jar
+Export-Package: *
+Import-Package:
+
diff --git a/biz.aQute.bndlib.tests/src/DefaultPackage.java b/biz.aQute.bndlib.tests/src/DefaultPackage.java
new file mode 100644
index 0000000..5a6f5d8
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/DefaultPackage.java
@@ -0,0 +1,3 @@
+public class DefaultPackage {
+
+}
diff --git a/biz.aQute.bndlib.tests/src/UPPERCASEPACKAGE/MyClass.java b/biz.aQute.bndlib.tests/src/UPPERCASEPACKAGE/MyClass.java
new file mode 100644
index 0000000..422dc94
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/UPPERCASEPACKAGE/MyClass.java
@@ -0,0 +1,5 @@
+package UPPERCASEPACKAGE;
+
+public class MyClass {
+
+}
diff --git a/biz.aQute.bndlib/src/test/.classpath b/biz.aQute.bndlib.tests/src/test/.classpath
similarity index 100%
rename from biz.aQute.bndlib/src/test/.classpath
rename to biz.aQute.bndlib.tests/src/test/.classpath
diff --git a/biz.aQute.bndlib/src/test/.cvsignore b/biz.aQute.bndlib.tests/src/test/.cvsignore
similarity index 100%
rename from biz.aQute.bndlib/src/test/.cvsignore
rename to biz.aQute.bndlib.tests/src/test/.cvsignore
diff --git a/biz.aQute.bndlib.tests/src/test/AnalyzerTest.java b/biz.aQute.bndlib.tests/src/test/AnalyzerTest.java
new file mode 100755
index 0000000..18649eb
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/AnalyzerTest.java
@@ -0,0 +1,679 @@
+package test;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.jar.*;
+
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Clazz.Def;
+import aQute.bnd.osgi.Descriptors.TypeRef;
+import aQute.bnd.test.*;
+import aQute.lib.io.*;
+
+class T0 {}
+
+abstract class T1 extends T0 {}
+
+class T2 extends T1 {}
+
+class T3 extends T2 {}
+
+public class AnalyzerTest extends BndTestCase {
+	static File	cwd	= new File(System.getProperty("user.dir"));
+
+	/**
+	 * For the following annotation class in an OSGi bundle
+	 * 
+	 * @Retention(RetentionPolicy.RUNTIME)
+	 * @Target({ ElementType.TYPE, ElementType.METHOD }) public @interface
+	 *           Transactional {
+	 * @Nonbinding Class<? extends Annotation>[] qualifier() default Any.class;
+	 *             } maven-bundle-plugin fails to generate the package import
+	 *             for javax.enterprise.inject.Any, the default value of the
+	 *             annotation method. At runtime, this leads to a
+	 *             non-descriptive exception
+	 * 
+	 *             <pre>
+	 * Caused by: java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy 
+	 *         at sun.reflect.annotation.AnnotationParser.parseClassArray(AnnotationParser.java:673) ~[na:1.7.0_04] 
+	 *         at sun.reflect.annotation.AnnotationParser.parseArray(AnnotationParser.java:480) ~[na:1.7.0_04] 
+	 *         at sun.reflect.annotation.AnnotationParser.parseMemberValue(AnnotationParser.java:306) ~[na:1.7.0_04] 
+	 *         at java.lang.reflect.Method.getDefaultValue(Method.java:726) ~[na:1.7.0_04] 
+	 *         at sun.reflect.annotation.AnnotationType.<init>(AnnotationType.java:117) ~[na:1.7.0_04] 
+	 *         at sun.reflect.annotation.AnnotationType.getInstance(AnnotationType.java:84) ~[na:1.7.0_04] 
+	 *         at sun.reflect.annotation.AnnotationParser.parseAnnotation(AnnotationParser.java:221) ~[na:1.7.0_04] 
+	 *         at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:88) ~[na:1.7.0_04] 
+	 *         at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:70) ~[na:1.7.0_04] 
+	 *         at java.lang.Class.initAnnotationsIfNecessary(Class.java:3089) ~[na:1.7.0_04] 
+	 *         at java.lang.Class.getDeclaredAnnotations(Class.java:3077) ~[na:1.7.0_04]
+	 * </pre>
+	 */
+	public void testAnnotationWithDefaultClass() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(IO.getFile(cwd, "bin"));
+		b.setExportPackage("test.annotation");
+		b.build();
+		assertTrue(b.check());
+		assertTrue( b.getExports().containsKey(b.getPackageRef("test/annotation")));
+		assertFalse( b.getContained().containsKey(b.getPackageRef("test/annotation/any")));
+		assertTrue( b.getImports().containsKey(b.getPackageRef("test/annotation/any")));
+	}
+	 
+
+	/**
+	 * Check the cross references
+	 */
+
+	public static void testCrossReference() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(IO.getFile(cwd, "bin"));
+		b.addClasspath(IO.getFile(cwd, "../aQute.libg/bin"));
+		b.addClasspath(IO.getFile(cwd, "../biz.aQute.bndlib/bin"));
+		b.setExportPackage("aQute.bnd.build.model.conversions");
+		b.setConditionalPackage("aQute.lib*");
+		Jar jar = b.build();
+		assertTrue(b.check("((, )?(aQute.libg.tuple)){1,1}"));
+
+		Map<Def,List<TypeRef>> xRef = b.getXRef(b.getPackageRef("aQute.bnd.build.model.conversions"),
+				Arrays.asList(b.getPackageRef("aQute.libg.tuple")), Modifier.PUBLIC + Modifier.PROTECTED);
+
+		for (Clazz.Def def : xRef.keySet())
+			System.out.println(def.getOwnerType() + " " + def.getName() + " " + def.getType() + " : " + xRef.get(def));
+
+		assertEquals(5, xRef.size());
+	}
+
+	/**
+	 * The -removeheaders header can be used as a whitelist.
+	 */
+
+	public static void testRemoveheadersAsWhiteList() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/asm.jar"));
+		b.setExportPackage("*");
+		b.setImportPackage("something");
+		b.set("Foo", "Foo");
+		b.set("Bar", "Bar");
+		b.set(Constants.REMOVEHEADERS, "!Bundle-*,!*-Package,!Service-Component,*");
+		b.build();
+		assertTrue(b.check());
+		Manifest m = b.getJar().getManifest();
+
+		assertNotNull(m.getMainAttributes().getValue(Constants.BUNDLE_MANIFESTVERSION));
+		assertNotNull(m.getMainAttributes().getValue(Constants.BUNDLE_NAME));
+		assertNotNull(m.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME));
+		assertNotNull(m.getMainAttributes().getValue(Constants.IMPORT_PACKAGE));
+		assertNotNull(m.getMainAttributes().getValue(Constants.EXPORT_PACKAGE));
+		assertNull(m.getMainAttributes().getValue("Foo"));
+		assertNull(m.getMainAttributes().getValue("Bar"));
+	}
+
+	/**
+	 * Check if bnd detects references to private packages and gives a warning.
+	 */
+
+	public static void testExportReferencesToPrivatePackages() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.addClasspath(new File("bin"));
+		b.setExportPackage("test.referApi"); // refers to Event Admin
+		b.setConditionalPackage("org.osgi.service.*");
+		Jar jar = b.build();
+		assertTrue(b
+				.check("((, )?(org.osgi.service.event|org.osgi.service.component|org.osgi.service.http|org.osgi.service.log|org.osgi.service.condpermadmin|org.osgi.service.wireadmin|org.osgi.service.device)){7,7}"));
+	}
+
+	/**
+	 * Test basic functionality of he BCP
+	 */
+
+	public static void testBundleClasspath() throws Exception {
+		Builder b = new Builder();
+		b.setProperty(Constants.BUNDLE_CLASSPATH, "foo");
+		b.setProperty(Constants.INCLUDE_RESOURCE, "foo/test/refer=bin/test/refer");
+		b.setProperty(Constants.EXPORT_CONTENTS, "test.refer");
+		Jar jar = b.build();
+		Manifest m = jar.getManifest();
+		assertTrue(b.check());
+		m.write(System.err);
+	}
+
+	/**
+	 * Very basic sanity test
+	 */
+
+	public static void testSanity() throws Exception {
+		Builder b = new Builder();
+		b.set("Export-Package", "thinlet;version=1.0");
+		b.addClasspath(new File("jar/thinlet.jar"));
+		b.build();
+		assertTrue(b.check());
+		assertEquals("version=1.0", b.getExports().getByFQN("thinlet").toString());
+		assertTrue(b.getJar().getDirectories().containsKey("thinlet"));
+		assertTrue(b.getJar().getResources().containsKey("thinlet/Thinlet.class"));
+	}
+
+	/**
+	 * Fastest way to create a manifest
+	 * 
+	 * @throws Exception
+	 */
+
+	public static void testGenerateManifest() throws Exception {
+		Analyzer analyzer = new Analyzer();
+		Jar bin = new Jar(new File("jar/osgi.jar"));
+		bin.setManifest(new Manifest());
+		analyzer.setJar(bin);
+		analyzer.addClasspath(new File("jar/spring.jar"));
+		analyzer.setProperty("Bundle-SymbolicName", "org.osgi.core");
+		analyzer.setProperty("Export-Package", "org.osgi.framework,org.osgi.service.event");
+		analyzer.setProperty("Bundle-Version", "1.0.0.x");
+		analyzer.setProperty("Import-Package", "*");
+		Manifest manifest = analyzer.calcManifest();
+		assertTrue(analyzer.check());
+		manifest.write(System.err);
+		Domain main = Domain.domain(manifest);
+		Parameters export = main.getExportPackage();
+		Parameters expected = new Parameters(
+				"org.osgi.framework;version=\"1.3\",org.osgi.service.event;uses:=\"org.osgi.framework\";version=\"1.0.1\"");
+		assertTrue(expected.isEqual(export));
+		assertEquals("1.0.0.x", manifest.getMainAttributes().getValue("Bundle-Version"));
+	}
+
+	/**
+	 * Make sure packages from embedded directories referenced from
+	 * Bundle-Classpath are considered during import/export calculation.
+	 */
+
+	public static void testExportContentsDirectory() throws Exception {
+		Builder b = new Builder();
+		File embedded = new File("bin/test/refer").getCanonicalFile();
+		assertTrue(embedded.isDirectory()); // sanity check
+		b.setProperty("Bundle-ClassPath", ".,jars/some.jar");
+		b.setProperty("-includeresource", "jars/some.jar/test/refer=" + embedded.getAbsolutePath());
+		b.setProperty("-exportcontents", "test.refer");
+		b.build();
+		assertTrue(b.check("Bundle-ClassPath uses a directory 'jars/some.jar'"));
+		assertTrue(b.getImports().toString(), b.getImports().getByFQN("org.osgi.service.event") != null);
+	}
+
+	/**
+	 * Uses constraints must be filtered by imports or exports.
+	 * 
+	 * @throws Exception
+	 */
+
+	public static void testUsesFiltering() throws Exception {
+		Builder b = new Builder();
+		b.setTrace(true);
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.setProperty("Export-Package", "org.osgi.service.event");
+		Jar jar = b.build();
+		assertTrue(b.check());
+
+		assertNotNull(jar.getResource("org/osgi/service/event/EventAdmin.class"));
+
+		String exports = jar.getManifest().getMainAttributes().getValue("Export-Package");
+		System.err.println(exports);
+		assertTrue(exports.contains("uses:=\"org.osgi.framework\""));
+
+		b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.setProperty("Import-Package", "");
+		b.setProperty("Export-Package", "org.osgi.service.event");
+		b.setPedantic(true);
+		jar = b.build();
+		exports = jar.getManifest().getMainAttributes().getValue("Export-Package");
+		System.err.println(exports);
+		assertTrue(b.check("Empty Import-Package header"));
+		exports = jar.getManifest().getMainAttributes().getValue("Export-Package");
+		assertFalse(exports.contains("uses:=\"org.osgi.framework\""));
+
+	}
+
+	/**
+	 * Test if require works
+	 * 
+	 * @throws Exception
+	 */
+
+	public static void testRequire() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.setProperty("Private-Package", "org.osgi.framework");
+		b.setProperty("-require-bnd", "10000");
+		b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(1, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+
+	}
+
+	public static void testComponentImportReference() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.setProperty("Private-Package", "org.osgi.framework");
+		b.setProperty("Import-Package", "not.here,*");
+		b.setProperty("Service-Component", "org.osgi.framework.Bundle;ref=not.here.Reference");
+		b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+	}
+
+	public static void testFindClass() throws Exception {
+		Builder a = new Builder();
+		a.setProperty("Export-Package", "org.osgi.service.io");
+		a.addClasspath(new File("jar/osgi.jar"));
+		a.build();
+		System.err.println(a.getErrors());
+		System.err.println(a.getWarnings());
+
+		Collection<Clazz> c = a.getClasses("", "IMPORTS", "javax.microedition.io");
+		System.err.println(c);
+	}
+
+	public static void testMultilevelInheritance() throws Exception {
+		Analyzer a = new Analyzer();
+		a.setJar(new File("bin"));
+		a.analyze();
+
+		String result = a._classes("cmd", "named", "*T?", "extends", "test.T0", "concrete");
+		System.err.println(result);
+		assertTrue(result.contains("test.T2"));
+		assertTrue(result.contains("test.T3"));
+	}
+
+	public static void testClassQuery() throws Exception {
+		Analyzer a = new Analyzer();
+		a.setJar(new File("jar/osgi.jar"));
+		a.analyze();
+
+		String result = a._classes("cmd", "named", "org.osgi.service.http.*", "abstract");
+		TreeSet<String> r = new TreeSet<String>(Processor.split(result));
+		assertEquals(
+				new TreeSet<String>(Arrays.asList("org.osgi.service.http.HttpContext",
+						"org.osgi.service.http.HttpService")), r);
+	}
+
+	/**
+	 * Use a private activator, check it is not imported.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testEmptyHeader() throws Exception {
+		Builder a = new Builder();
+		a.setProperty("Bundle-Blueprint", "  <<EMPTY>> ");
+		a.setProperty("Export-Package", "org.osgi.framework");
+		a.addClasspath(new File("jar/osgi.jar"));
+		a.build();
+		Manifest manifest = a.getJar().getManifest();
+		System.err.println(a.getErrors());
+		System.err.println(a.getWarnings());
+		assertEquals(0, a.getErrors().size());
+		assertEquals(0, a.getWarnings().size());
+		String bb = manifest.getMainAttributes().getValue("Bundle-Blueprint");
+		System.err.println(bb);
+		assertNotNull(bb);
+		assertEquals("", bb);
+	}
+
+	/**
+	 * Test name section.
+	 */
+
+	public static void testNameSection() throws Exception {
+		Builder a = new Builder();
+		a.setProperty("Export-Package", "org.osgi.service.event, org.osgi.service.io");
+		a.addClasspath(new File("jar/osgi.jar"));
+		a.setProperty("@org at osgi@service at event@Specification-Title", "spec title");
+		a.setProperty("@org at osgi@service at io@Specification-Title", "spec title io");
+		a.setProperty("@org at osgi@service at event@Specification-Version", "1.1");
+		a.setProperty("@org at osgi@service at event@Implementation-Version", "5.1");
+		Jar jar = a.build();
+		Manifest m = jar.getManifest();
+		Attributes attrs = m.getAttributes("org/osgi/service/event");
+		assertNotNull(attrs);
+		assertEquals("5.1", attrs.getValue("Implementation-Version"));
+		assertEquals("1.1", attrs.getValue("Specification-Version"));
+		assertEquals("spec title", attrs.getValue("Specification-Title"));
+
+		attrs = m.getAttributes("org/osgi/service/io");
+		assertNotNull(attrs);
+		assertEquals("spec title io", attrs.getValue("Specification-Title"));
+	}
+
+	/**
+	 * Check if calcManifest sets the version
+	 */
+
+	/**
+	 * Test if mandatory attributes are augmented even when the version is not
+	 * set.
+	 */
+	public static void testMandatoryWithoutVersion() throws Exception {
+		Builder a = new Builder();
+		Properties p = new Properties();
+		p.put("Import-Package", "*");
+		p.put("Private-Package", "org.apache.mina.management.*");
+		a.setClasspath(new Jar[] {
+			new Jar(new File("jar/mandatorynoversion.jar"))
+		});
+		a.setProperties(p);
+		Jar jar = a.build();
+		assertTrue(a.check());
+
+		String imports = jar.getManifest().getMainAttributes().getValue("Import-Package");
+		System.err.println(imports);
+		assertTrue(imports.indexOf("x=1") >= 0);
+		assertTrue(imports.indexOf("y=2") >= 0);
+	}
+
+	/**
+	 * Use a private activator, check it is not imported.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testPrivataBundleActivatorNotImported() throws Exception {
+		Builder a = new Builder();
+		Properties p = new Properties();
+		p.put("Import-Package", "*");
+		p.put("Private-Package", "org.objectweb.*");
+		p.put("Bundle-Activator", "org.objectweb.asm.Item");
+		a.setClasspath(new Jar[] {
+			new Jar(new File("jar/asm.jar"))
+		});
+		a.setProperties(p);
+		a.build();
+		Manifest manifest = a.getJar().getManifest();
+		System.err.println(a.getErrors());
+		System.err.println(a.getWarnings());
+		assertEquals(0, a.getErrors().size());
+		assertEquals(0, a.getWarnings().size());
+		String imports = manifest.getMainAttributes().getValue("Import-Package");
+		System.err.println(imports);
+		assertNull(imports);
+	}
+
+	/**
+	 * Use an activator that is not in the bundle but do not allow it to be
+	 * imported, this should generate an error.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testBundleActivatorNotImported() throws Exception {
+		Builder a = new Builder();
+		Properties p = new Properties();
+		p.put("Import-Package", "!org.osgi.framework,*");
+		p.put("Private-Package", "org.objectweb.*");
+		p.put("Bundle-Activator", "org.osgi.framework.BundleActivator");
+		a.setClasspath(new Jar[] {
+				new Jar(new File("jar/asm.jar")), new Jar(new File("jar/osgi.jar"))
+		});
+		a.setProperties(p);
+		a.build();
+		assertTrue(a.check("Bundle-Activator not found"));
+		Manifest manifest = a.getJar().getManifest();
+		String imports = manifest.getMainAttributes().getValue("Import-Package");
+		assertNull(imports);
+	}
+
+	/**
+	 * Use an activator that is on the class path but that is not in the bundle.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testBundleActivatorImport() throws Exception {
+		Builder a = new Builder();
+		Properties p = new Properties();
+		p.put("Private-Package", "org.objectweb.*");
+		p.put("Bundle-Activator", "org.osgi.framework.BundleActivator");
+		a.setClasspath(new Jar[] {
+				new Jar(new File("jar/asm.jar")), new Jar(new File("jar/osgi.jar"))
+		});
+		a.setProperties(p);
+		a.build();
+		Manifest manifest = a.getJar().getManifest();
+		System.err.println(a.getErrors());
+		System.err.println(a.getWarnings());
+		assertEquals(0, a.getErrors().size());
+		assertEquals(0, a.getWarnings().size());
+		String imports = manifest.getMainAttributes().getValue("Import-Package");
+		assertNotNull(imports);
+		assertTrue(imports.indexOf("org.osgi.framework") >= 0);
+	}
+
+	/**
+	 * The -removeheaders header removes any necessary after the manifest is
+	 * calculated.
+	 */
+
+	public static void testRemoveheaders() throws Exception {
+		Analyzer a = new Analyzer();
+		a.setJar(new File("jar/asm.jar"));
+		Manifest m = a.calcManifest();
+		assertNotNull(m.getMainAttributes().getValue("Implementation-Title"));
+		a = new Analyzer();
+		a.setJar(new File("jar/asm.jar"));
+		a.setProperty("-removeheaders", "Implementation-Title");
+		m = a.calcManifest();
+		assertNull(m.getMainAttributes().getValue("Implementation-Title"));
+	}
+
+	/**
+	 * There was an export generated for a jar file.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testExportForJar() throws Exception {
+		Jar jar = new Jar("dot");
+		jar.putResource("target/aopalliance.jar", new FileResource(new File("jar/asm.jar")));
+		Analyzer an = new Analyzer();
+		an.setJar(jar);
+		an.setProperty("Export-Package", "target");
+		Manifest manifest = an.calcManifest();
+		assertTrue(an.check());
+		String exports = manifest.getMainAttributes().getValue(Analyzer.EXPORT_PACKAGE);
+		Parameters map = Analyzer.parseHeader(exports, null);
+		assertEquals(1, map.size());
+		assertEquals("target", map.keySet().iterator().next());
+	}
+
+	/**
+	 * Test if version works
+	 */
+
+	public static void testVersion() {
+		Analyzer a = new Analyzer();
+		String v = a.getBndVersion();
+		assertNotNull(v);
+	}
+
+	/**
+	 * asm is a simple library with two packages. No imports are done.
+	 */
+	public static void testAsm() throws Exception {
+		Properties base = new Properties();
+		base.put(Analyzer.IMPORT_PACKAGE, "*");
+		base.put(Analyzer.EXPORT_PACKAGE, "*;-noimport:=true");
+
+		Analyzer analyzer = new Analyzer();
+		analyzer.setJar(new File("jar/asm.jar"));
+		analyzer.setProperties(base);
+		analyzer.calcManifest().write(System.err);
+		assertTrue(analyzer.check());
+
+		assertTrue(analyzer.getExports().getByFQN("org.objectweb.asm.signature") != null);
+		assertTrue(analyzer.getExports().getByFQN("org.objectweb.asm") != null);
+		assertFalse(analyzer.getImports().getByFQN("org.objectweb.asm.signature") != null);
+		assertFalse(analyzer.getImports().getByFQN("org.objectweb.asm") != null);
+
+		assertEquals("Expected size", 2, analyzer.getExports().size());
+	}
+
+	/**
+	 * See if we set attributes on export
+	 * 
+	 * @throws IOException
+	 */
+	public static void testAsm2() throws Exception {
+		Properties base = new Properties();
+		base.put(Analyzer.IMPORT_PACKAGE, "*");
+		base.put(Analyzer.EXPORT_PACKAGE, "org.objectweb.asm;name=short, org.objectweb.asm.signature;name=long");
+		Analyzer h = new Analyzer();
+		h.setJar(new File("jar/asm.jar"));
+		h.setProperties(base);
+		h.calcManifest().write(System.err);
+		assertTrue(h.check());
+		Packages exports = h.getExports();
+		assertTrue(exports.getByFQN("org.objectweb.asm.signature") != null);
+		assertTrue(exports.getByFQN("org.objectweb.asm") != null);
+		assertTrue(Arrays.asList("org.objectweb.asm", "org.objectweb.asm.signature").removeAll(h.getImports().keySet()) == false);
+		assertEquals("Expected size", 2, h.getExports().size());
+		assertEquals("short", get(h.getExports(), h.getPackageRef("org.objectweb.asm"), "name"));
+		assertEquals("long", get(h.getExports(), h.getPackageRef("org.objectweb.asm.signature"), "name"));
+	}
+
+	public static void testDs() throws Exception {
+		Properties base = new Properties();
+		base.put(Analyzer.IMPORT_PACKAGE, "*");
+		base.put(Analyzer.EXPORT_PACKAGE, "*;-noimport:=true");
+		File tmp = new File("jar/ds.jar");
+		Analyzer analyzer = new Analyzer();
+		analyzer.setJar(tmp);
+		analyzer.setProperties(base);
+		analyzer.calcManifest().write(System.err);
+		assertTrue(analyzer.check());
+		assertPresent(analyzer.getImports().keySet(), "org.osgi.service.packageadmin, "
+				+ "org.xml.sax, org.osgi.service.log," + " javax.xml.parsers," + " org.xml.sax.helpers,"
+				+ " org.osgi.framework," + " org.eclipse.osgi.util," + " org.osgi.util.tracker, "
+				+ "org.osgi.service.component, " + "org.osgi.service.cm");
+		assertPresent(analyzer.getExports().keySet(), "org.eclipse.equinox.ds.parser, "
+				+ "org.eclipse.equinox.ds.tracker, " + "org.eclipse.equinox.ds, " + "org.eclipse.equinox.ds.instance, "
+				+ "org.eclipse.equinox.ds.model, " + "org.eclipse.equinox.ds.resolver, "
+				+ "org.eclipse.equinox.ds.workqueue");
+
+	}
+
+	public static void testDsSkipOsgiImport() throws Exception {
+		Properties base = new Properties();
+		base.put(Analyzer.IMPORT_PACKAGE, "!org.osgi.*, *");
+		base.put(Analyzer.EXPORT_PACKAGE, "*;-noimport:=true");
+		File tmp = new File("jar/ds.jar");
+		Analyzer h = new Analyzer();
+		h.setJar(tmp);
+		h.setProperties(base);
+		h.calcManifest().write(System.err);
+		assertPresent(h.getImports().keySet(), "org.xml.sax, " + " javax.xml.parsers," + " org.xml.sax.helpers,"
+				+ " org.eclipse.osgi.util");
+
+		System.err.println("IMports " + h.getImports());
+		assertNotPresent(h.getImports().keySet(), "org.osgi.service.packageadmin, " + "org.osgi.service.log,"
+				+ " org.osgi.framework," + " org.osgi.util.tracker, " + "org.osgi.service.component, "
+				+ "org.osgi.service.cm");
+		assertPresent(h.getExports().keySet(), "org.eclipse.equinox.ds.parser, " + "org.eclipse.equinox.ds.tracker, "
+				+ "org.eclipse.equinox.ds, " + "org.eclipse.equinox.ds.instance, " + "org.eclipse.equinox.ds.model, "
+				+ "org.eclipse.equinox.ds.resolver, " + "org.eclipse.equinox.ds.workqueue");
+	}
+
+	public static void testDsNoExport() throws Exception {
+		Properties base = new Properties();
+		base.put(Analyzer.IMPORT_PACKAGE, "*");
+		base.put(Analyzer.EXPORT_PACKAGE, "!*");
+		File tmp = new File("jar/ds.jar");
+		Analyzer h = new Analyzer();
+		h.setJar(tmp);
+		h.setProperties(base);
+		h.calcManifest().write(System.err);
+		assertPresent(h.getImports().keySet(), "org.osgi.service.packageadmin, " + "org.xml.sax, org.osgi.service.log,"
+				+ " javax.xml.parsers," + " org.xml.sax.helpers," + " org.osgi.framework," + " org.eclipse.osgi.util,"
+				+ " org.osgi.util.tracker, " + "org.osgi.service.component, " + "org.osgi.service.cm");
+		assertNotPresent(h.getExports().keySet(), "org.eclipse.equinox.ds.parser, "
+				+ "org.eclipse.equinox.ds.tracker, " + "org.eclipse.equinox.ds, " + "org.eclipse.equinox.ds.instance, "
+				+ "org.eclipse.equinox.ds.model, " + "org.eclipse.equinox.ds.resolver, "
+				+ "org.eclipse.equinox.ds.workqueue");
+		System.err.println(h.getUnreachable());
+	}
+
+	public static void testClasspath() throws Exception {
+		Properties base = new Properties();
+		base.put(Analyzer.IMPORT_PACKAGE, "*");
+		base.put(Analyzer.EXPORT_PACKAGE, "*;-noimport:=true");
+		File tmp = new File("jar/ds.jar");
+		File osgi = new File("jar/osgi.jar");
+		Analyzer h = new Analyzer();
+		h.setJar(tmp);
+		h.setProperties(base);
+		h.setClasspath(new File[] {
+			osgi
+		});
+		h.calcManifest().write(System.err);
+		assertEquals("Version from osgi.jar", "[1.2,2)",
+				get(h.getImports(), h.getPackageRef("org.osgi.service.packageadmin"), "version"));
+		assertEquals("Version from osgi.jar", "[1.3,2)",
+				get(h.getImports(), h.getPackageRef("org.osgi.util.tracker"), "version"));
+		assertEquals("Version from osgi.jar", null, get(h.getImports(), h.getPackageRef("org.xml.sax"), "version"));
+
+	}
+
+	/**
+	 * We detect that there are instruction on im/export package headers that
+	 * are never used. This usually indicates a misunderstanding or a change in
+	 * the underlying classpath. These are reflected as warnings. If there is an
+	 * extra import, and it contains no wildcards, then it is treated as a
+	 * wildcard
+	 * 
+	 * @throws IOException
+	 */
+	public static void testSuperfluous() throws Exception {
+		Properties base = new Properties();
+		base.put(Analyzer.IMPORT_PACKAGE, "*, =com.foo, com.foo.bar.*");
+		base.put(Analyzer.EXPORT_PACKAGE, "*, com.bar, baz.*");
+		File tmp = new File("jar/ds.jar");
+		Analyzer h = new Analyzer();
+		h.setJar(tmp);
+		h.setProperties(base);
+		Manifest m = h.calcManifest();
+		m.write(System.err);
+		assertTrue(h.check( //
+				"Unused Export-Package instructions: \\[baz.*\\]", //
+				"Unused Import-Package instructions: \\[com.foo.bar.*\\]"));
+		assertTrue(h.getImports().getByFQN("com.foo") != null);
+		assertTrue(h.getExports().getByFQN("com.bar") != null);
+	}
+
+	static void assertNotPresent(Collection< ? > map, String string) {
+		Collection<String> ss = new HashSet<String>();
+		for (Object o : map)
+			ss.add(o + "");
+
+		StringTokenizer st = new StringTokenizer(string, ", ");
+		while (st.hasMoreTokens()) {
+			String member = st.nextToken();
+			assertFalse("Must not contain  " + member, map.contains(member));
+		}
+	}
+
+	static void assertPresent(Collection< ? > map, String string) {
+		Collection<String> ss = new HashSet<String>();
+		for (Object o : map)
+			ss.add(o + "");
+
+		StringTokenizer st = new StringTokenizer(string, ", ");
+		while (st.hasMoreTokens()) {
+			String member = st.nextToken();
+			assertTrue("Must contain  " + member, ss.contains(member));
+		}
+	}
+
+	static <K, V> V get(Map<K, ? extends Map<String,V>> headers, K key, String attr) {
+		Map<String,V> clauses = headers.get(key);
+		if (clauses == null)
+			return null;
+		return clauses.get(attr);
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/AnnotationsTest.java b/biz.aQute.bndlib.tests/src/test/AnnotationsTest.java
new file mode 100644
index 0000000..eeed350
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/AnnotationsTest.java
@@ -0,0 +1,133 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+
+import junit.framework.*;
+
+import org.osgi.service.log.*;
+import org.osgi.service.packageadmin.*;
+
+import aQute.bnd.annotation.component.*;
+import aQute.bnd.make.component.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Descriptors.TypeRef;
+
+public class AnnotationsTest extends TestCase {
+
+	@Component(name = "mycomp", enabled = true, factory = "abc", immediate = false, provide = LogService.class, servicefactory = true,
+			properties = {" aprop = a prop ", "    aprop2    =    really dumb value   ! "})
+	static class MyComponent implements Serializable {
+		private static final long	serialVersionUID	= 1L;
+		LogService					log;
+
+		@Activate
+		protected void activatex() {}
+
+		@Deactivate
+		protected void deactivatex() {}
+
+		@Modified
+		protected void modifiedx() {}
+
+		@Reference(type = '~', target = "(abc=3)")
+		protected void setLog(LogService log) {
+			this.log = log;
+		}
+
+		@Reference(type = '1')
+		protected void setPackageAdmin(@SuppressWarnings("unused") PackageAdmin pa) {}
+
+		protected void unsetLog(@SuppressWarnings("unused") LogService log) {
+			this.log = null;
+		}
+	}
+
+	public static void testComponentReader() throws Exception {
+		Analyzer analyzer = new Analyzer();
+		File f = new File("bin/test/AnnotationsTest$MyComponent.class");
+		Clazz c = new Clazz(analyzer, "test.AnnotationsTest.MyComponent", new FileResource(f));
+		Map<String,String> map = ComponentAnnotationReader.getDefinition(c);
+		System.err.println(map);
+		assertEquals("mycomp", map.get("name:"));
+		assertEquals("true", map.get("servicefactory:"));
+		assertEquals("activatex", map.get("activate:"));
+		assertEquals("deactivatex", map.get("deactivate:"));
+		assertEquals("modifiedx", map.get("modified:"));
+		assertEquals("org.osgi.service.log.LogService(abc=3)~", map.get("log/setLog"));
+		assertEquals("org.osgi.service.packageadmin.PackageAdmin", map.get("packageAdmin/setPackageAdmin"));
+		assertEquals("aprop= a prop ,aprop2=    really dumb value   ! ", map.get("properties:"));
+	}
+
+	public void testSimple() throws Exception {
+		Analyzer analyzer = new Analyzer();
+		Clazz clazz = new Clazz(analyzer, "", null);
+		ClassDataCollector cd = new ClassDataCollector() {
+			@Override
+			public void addReference(TypeRef token) {}
+
+			@Override
+			public void annotation(Annotation annotation) {
+				System.err.println("Annotation " + annotation);
+			}
+
+			@Override
+			public void classBegin(int access, TypeRef name) {
+				System.err.println("Class " + name);
+			}
+
+			@Override
+			public void classEnd() {
+				System.err.println("Class end ");
+			}
+
+			@Override
+			public void extendsClass(TypeRef name) {
+				System.err.println("extends " + name);
+			}
+
+			@Override
+			public void implementsInterfaces(TypeRef[] name) {
+				System.err.println("implements " + Arrays.toString(name));
+
+			}
+
+			@Override
+			public void parameter(int p) {
+				System.err.println("parameter " + p);
+			}
+
+		};
+
+		clazz.parseClassFile(getClass().getResourceAsStream("Target.class"), cd);
+	}
+}
+
+ at Component
+class Target implements Serializable {
+	private static final long	serialVersionUID	= 1L;
+
+	@Activate
+	void activate() {
+
+	}
+
+	@Deactivate
+	void deactivate() {
+
+	}
+
+	@Modified
+	void modified() {
+
+	}
+
+	@Reference
+	void setLog(@SuppressWarnings("unused") LogService log) {
+
+	}
+
+	void unsetLog(@SuppressWarnings("unused") LogService log) {
+
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/AttributesTest.java b/biz.aQute.bndlib.tests/src/test/AttributesTest.java
new file mode 100644
index 0000000..1aacb0a
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/AttributesTest.java
@@ -0,0 +1,148 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+
+import junit.framework.*;
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
+
+public class AttributesTest extends TestCase {
+
+	/**
+	 * Remove a version attribute A mandatory attribute adds the common and tst
+	 * properties to the import. We remove them using remove:=*
+	 * 
+	 * @throws Exception
+	 */
+	public static void testRemoveDirective() throws Exception {
+		Jar javax = new Jar("test");
+		Manifest m = new Manifest();
+		m.getMainAttributes().putValue("Export-Package",
+				"javax.microedition.io;a1=exp-1;a2=exp-2;a3=exp-3;x1=x1;x2=x2;x3=x3;mandatory:=\"a1,a2,a3,x1,x2,x3\"");
+		javax.setManifest(m);
+
+		Jar cp[] = {
+				javax, new Jar(new File("jar/osgi.jar"))
+		};
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.put("Import-Package", "javax.microedition.io;-remove-attribute:=a1|x?;a2=imp-2,*");
+		p.put("Export-Package", "org.osgi.service.io");
+		bmaker.setClasspath(cp);
+		bmaker.setProperties(p);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+		assertNotNull(bmaker.getImports());
+		assertNotNull(bmaker.getImports().getByFQN("javax.microedition.io"));
+		assertNotNull(bmaker.getImports().getByFQN("javax.microedition.io").get("a2"));
+		jar.getManifest().write(System.err);
+		Manifest manifest = jar.getManifest();
+		Attributes main = manifest.getMainAttributes();
+		String imprt = main.getValue("Import-Package");
+		assertNotNull("Import package header", imprt);
+		Parameters map = Processor.parseHeader(imprt, null);
+		System.err.println("** " + map);
+		Map<String,String> attrs = map.get("javax.microedition.io");
+		assertNotNull(attrs);
+		assertNull(attrs.get("a1"));
+		assertNull(attrs.get("x1"));
+		assertNull(attrs.get("x2"));
+		assertNull(attrs.get("x3"));
+		assertEquals("imp-2", attrs.get("a2"));
+		assertEquals("exp-3", attrs.get("a3"));
+	}
+
+	/**
+	 * Remove a version attribute
+	 * 
+	 * @throws Exception
+	 */
+	public static void testRemoveAttribute() throws Exception {
+		Jar javax = new Jar("test");
+		Manifest m = new Manifest();
+		m.getMainAttributes().putValue("Export-Package",
+				"javax.microedition.io;common=split;test=abc;mandatory:=\"common,test\"");
+		javax.setManifest(m);
+
+		Jar cp[] = {
+				javax, new Jar(new File("jar/osgi.jar"))
+		};
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.put("Import-Package", "javax.microedition.io;common=!;test=abc,*");
+		p.put("Export-Package", "org.osgi.service.io");
+		bmaker.setClasspath(cp);
+		bmaker.setProperties(p);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+
+		jar.getManifest().write(System.err);
+		Manifest manifest = jar.getManifest();
+		Attributes main = manifest.getMainAttributes();
+		String imprt = main.getValue("Import-Package");
+		assertNotNull("Import package header", imprt);
+		Parameters map = Processor.parseHeader(imprt, null);
+		Map<String,String> attrs = map.get("javax.microedition.io");
+		assertNotNull(attrs);
+		assertNull(attrs.get("common"));
+	}
+
+	/**
+	 * Override a version attribute
+	 * 
+	 * @throws Exception
+	 */
+	public static void testOverrideAttribute() throws Exception {
+		File cp[] = {
+			new File("jar/osgi.jar")
+		};
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.put("Export-Package", "org.osgi.framework;version=1.1");
+		bmaker.setClasspath(cp);
+		bmaker.setProperties(p);
+		Jar jar = bmaker.build();
+		System.err.println(jar.getResources());
+		// System.err.println(bmaker.getExports());
+		System.err.println("Warnings: " + bmaker.getWarnings());
+		System.err.println("Errors  : " + bmaker.getErrors());
+		jar.getManifest().write(System.err);
+		Manifest manifest = jar.getManifest();
+		Attributes main = manifest.getMainAttributes();
+		String export = main.getValue("Export-Package");
+		assertNotNull("Export package header", export);
+		Parameters map = Processor.parseHeader(export, null);
+		assertEquals("1.1", map.get("org.osgi.framework").get("version"));
+	}
+
+	/**
+	 * See if we inherit the version from the osgi.jar file.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testSimple() throws Exception {
+		File cp[] = {
+			new File("jar/osgi.jar")
+		};
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.put("Export-Package", "org.osgi.framework");
+		bmaker.setClasspath(cp);
+		bmaker.setProperties(p);
+		Jar jar = bmaker.build();
+		System.err.println(jar.getResources());
+		// System.err.println(bmaker.getExports());
+		System.err.println("Warnings: " + bmaker.getWarnings());
+		System.err.println("Errors  : " + bmaker.getErrors());
+		jar.getManifest().write(System.err);
+		Manifest manifest = jar.getManifest();
+		Attributes main = manifest.getMainAttributes();
+		String export = main.getValue("Export-Package");
+		assertNotNull("Export package header", export);
+		Parameters map = Processor.parseHeader(export, null);
+		assertEquals("1.3", map.get("org.osgi.framework").get("version"));
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/BuilderTest.java b/biz.aQute.bndlib.tests/src/test/BuilderTest.java
new file mode 100755
index 0000000..f334117
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/BuilderTest.java
@@ -0,0 +1,1923 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+
+import test.CompareTest.B;
+import test.CompareTest.B.C;
+import test.genericinterf.a.*;
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.test.*;
+import aQute.lib.collections.*;
+import aQute.lib.io.*;
+
+public class BuilderTest extends BndTestCase {
+
+	/**
+	 * https://github.com/bndtools/bnd/issues/315
+	 * Turns out bnd doesn't seem to support a class in a capitalized package
+	 * name. I accidentally called a package with a capital letter and I get the
+	 * strange error message and a refusal to build it. (See title for error
+	 * message) My package could be named "Coffee" and the package named
+	 * "CoffeeClient", The bnd.bnd file could have: Private-Package: Coffee I'm
+	 * running 2.0.0REL with Eclipse Juno.
+	 */
+	public static void testUpperCasePackage() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(IO.getFile("bin"));
+		b.setExportPackage("UPPERCASEPACKAGE");
+		b.build();
+		assertTrue(b.check());
+		b.getExports().containsFQN("UPPERCASEPACKAGE");
+	}	
+	
+	/**
+	 * Dave Smith <dave.smith at candata.com> I have pulled the latest from git and
+	 * am testing out 2.0 with our current application. I am getting the
+	 * following error message on the bnd.bnd file null, for cmd : classes,
+	 * arguments [classes;CONCRETE;ANNOTATION;javax.persistence.Entity] My bnd
+	 * file does have the following line ... Hibernate-Db =
+	 * ${classes;CONCRETE;ANNOTATION;javax.persistence.Entity}
+	 * 
+	 * @throws Exception
+	 */
+
+	public static void testClasses() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("x", "${classes;CONCRETE;ANNOTATION;aQute.bnd.annotation.component.Component}");
+		b.setProperty("y", "${classes;CONCRETE;ANNOTATED;aQute.bnd.annotation.component.Component}");
+		b.setProperty("z", "${classes;CONCRETE;ANNOTATEDX;x.y.Z}");
+		b.setPrivatePackage("test");
+		b.addClasspath(IO.getFile("bin"));
+		b.build();
+		String s = b.getProperty("x");
+		assertEquals(s, b.getProperty("y"));
+		assertTrue(s.contains("test.Target"));
+		assertEquals("${classes;CONCRETE;ANNOTATEDX;x.y.Z}", b.getProperty("z"));
+		assertTrue(b.check("ANNOTATEDX"));
+	}
+
+	/**
+	 * Check if we can create digests
+	 * 
+	 * @throws Exception
+	 */
+
+	public static void testDigests() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(IO.getFile(new File(""), "jar/osgi.jar"));
+		b.setExportPackage("org.osgi.framework");
+		b.setProperty(Constants.DIGESTS, "MD5, SHA1");
+		Jar jar = b.build();
+		assertTrue(b.check());
+		File f = File.createTempFile("test", ".jar");
+		jar.write(f);
+
+		Jar other = new Jar(f);
+		Manifest manifest = other.getManifest();
+		assertNotNull(manifest);
+		Attributes attrs = manifest.getAttributes("org/osgi/framework/BundleActivator.class");
+		assertNotNull(attrs);
+		assertEquals("RTRhr3kadnulINegRhpmog==", attrs.getValue("MD5-Digest"));
+		assertEquals("BfVfpnE3Srx/0UWwtzNecrAGf8A=", attrs.getValue("SHA-Digest"));
+
+		b.close();
+		other.close();
+	}
+
+	/**
+	 * Test the Include-Resource facility to generate resources on the fly. This
+	 * is a a case where multiple resources and up in a single combined
+	 * resource.
+	 */
+
+	public static void testOnTheFlyMerge() throws Exception {
+		Builder b = new Builder();
+		b.setIncludeResource("count;for='1,2,3';cmd='echo YES_${@}'");
+		b.setProperty("-resourceonly", "true");
+		Jar jar = b.build();
+		assertTrue(b.check());
+		Resource r = jar.getResource("count");
+		assertNotNull(r);
+
+		String s = IO.collect(r.openInputStream());
+		assertEquals("YES_1\nYES_2\nYES_3\n", s);
+	}
+
+	/**
+	 * Test the Include-Resource facility to generate resources on the fly. This
+	 * is a simple case of one resource.
+	 */
+
+	public static void testOnTheFlySingle() throws Exception {
+		// disable this test on windows
+		if (!"/".equals(File.separator))
+			return;
+
+		Builder b = new Builder();
+		b.setIncludeResource("test/ls;cmd='ls /etc | grep hosts'");
+		b.setProperty("-resourceonly", "true");
+		Jar jar = b.build();
+		assertTrue(b.check());
+		Resource r = jar.getResource("test/ls");
+		assertNotNull(r);
+		String s = IO.collect(r.openInputStream());
+		assertTrue(s.contains("hosts"));
+	}
+
+	/**
+	 * Test the Include-Resource facility to generate resources on the fly. This
+	 * is a a case where multiple resources and up in a single combined
+	 * resource.
+	 */
+
+	public static void testOnTheFlyMultiple() throws Exception {
+		Builder b = new Builder();
+		b.setIncludeResource("count/${@};for='1,2,3';cmd='echo YES_${@}'");
+		b.setProperty("-resourceonly", "true");
+		Jar jar = b.build();
+		assertTrue(b.check());
+		assertNotNull(jar.getResource("count/1"));
+		Resource r = jar.getResource("count/2");
+		assertNotNull(jar.getResource("count/3"));
+
+		String s = IO.collect(r.openInputStream());
+		assertEquals("YES_2\n", s);
+	}
+
+	/**
+	 * FELIX-3407 Utterly confusing example that states that generic references
+	 * are not picked up. The classes under test are in {@link A},{@link B}, and
+	 * {@link C}.
+	 */
+	public static void testGenericPickup() throws Exception {
+		Builder b = new Builder();
+		b.setPrivatePackage("test.genericinterf.a");
+		b.addClasspath(new File("bin"));
+		b.build();
+		assertTrue(b.check());
+		System.out.println(b.getImports());
+		assertTrue(b.getImports().containsFQN("test.genericinterf.b"));
+		assertTrue(b.getImports().containsFQN("test.genericinterf.c"));
+	}
+
+	/**
+	 * Github #130 Consider the following descriptor file: Bundle-Activator:
+	 * org.example.Activator Private-Package: org.example Now suppose that at
+	 * build time, bnd cannot find the package org.example, or it is empty. Bnd
+	 * sees the Bundle-Activator instruction as creating a dependency, so it
+	 * generates a manifest containing an import for that package:
+	 * Import-Package: org.example This is unexpected. If a Private-Package
+	 * instruction is given with a specific package name (i.e. not a wildcard),
+	 * and that package does not exist or is empty, then bnd should fail or
+	 * print an error.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testPrivatePackageNonExistent() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.setBundleActivator("com.example.Activator");
+		b.setPrivatePackage("com.example");
+		b.setIncludeResource("p;literal='x'");
+
+		b.build();
+		assertTrue(b.check("on the class path: \\[com.example\\]"));
+	}
+
+	/**
+	 * #41 Test the EE macro
+	 */
+
+	public static void testEEMacro() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("bin"));
+		b.addClasspath(new File("jar/ifc112.jar"));
+		b.setPrivatePackage("test.activator, netscape.util.*");
+		b.setBundleRequiredExecutionEnvironment("${ee}");
+		Jar jar = b.build();
+		assertTrue(b.check());
+
+		Domain domain = Domain.domain(jar.getManifest());
+		Parameters ee = domain.getBundleRequiredExecutionEnvironment();
+		System.err.println(ee);
+		assertTrue(ee.containsKey("JRE-1.1"));
+	}
+
+	public static void testEEMacro2() throws Exception {
+		String[] packages = {
+				"eclipse_1_1", "eclipse_1_2", "eclipse_1_3", "eclipse_1_4", "eclipse_1_5", "eclipse_1_6",
+				"eclipse_jsr14"
+		};
+
+		String[] ees = {
+				"JRE-1.1", "J2SE-1.2", "J2SE-1.3", "J2SE-1.4", "J2SE-1.5", "JavaSE-1.6", "J2SE-1.4"
+		};
+		for (int i = 0; i < packages.length; i++) {
+			Builder b = new Builder();
+			b.addClasspath(new File("compilerversions/compilerversions.jar"));
+			b.setPrivatePackage(packages[i]);
+			b.setBundleRequiredExecutionEnvironment("${ee}");
+			Jar jar = b.build();
+			assertTrue(b.check());
+			Domain domain = Domain.domain(jar.getManifest());
+			Parameters ee = domain.getBundleRequiredExecutionEnvironment();
+			System.err.println(ee);
+			assertEquals(ees[i], ee.toString());
+		}
+	}
+
+	/**
+	 * bnd issues Consider the following descriptor file:
+	 * 
+	 * <pre>
+	 * Bundle-Activator: org.example.Activator 
+	 * Private-Package: org.example
+	 * </pre>
+	 * 
+	 * Now suppose that at build time, bnd cannot find the package org.example,
+	 * or it is empty. Bnd sees the Bundle-Activator instruction as creating a
+	 * dependency, so it generates a manifest containing an import for that
+	 * package:
+	 * 
+	 * <pre>
+	 * Import-Package: org.example
+	 * </pre>
+	 * 
+	 * This is unexpected. If a Private-Package instruction is given with a
+	 * specific package name (i.e. not a wildcard), and that package does not
+	 * exist or is empty, then bnd should fail or print an error.
+	 */
+
+	public static void testReportEmptyPrivatePackage() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("bin"));
+		b.setPrivatePackage("does.not.exist");
+		b.build();
+		assertTrue(b.check("The JAR is empty", "Unused Private-Package instruction"));
+	}
+
+	/**
+	 * Test the name section
+	 */
+
+	public static void testNamesection() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.setProperty(Constants.NAMESECTION,
+				"org/osgi/service/event/*;MD5='${md5;${@}}';SHA1='${sha1;${@}}';MD5H='${md5;${@};hex}'");
+		b.setProperty(Constants.PRIVATE_PACKAGE, "org.osgi.service.event");
+		Jar build = b.build();
+		assertOk(b);
+		build.calcChecksums(new String[] {
+				"MD5", "SHA1"
+		});
+		assertTrue(b.check());
+		Manifest m = build.getManifest();
+		m.write(System.err);
+
+		assertNotNull(m.getAttributes("org/osgi/service/event/EventAdmin.class").getValue("MD5"));
+		assertNotNull(m.getAttributes("org/osgi/service/event/EventAdmin.class").getValue("SHA1"));
+		assertEquals(m.getAttributes("org/osgi/service/event/EventAdmin.class").getValue("MD5-Digest"), m
+				.getAttributes("org/osgi/service/event/EventAdmin.class").getValue("MD5"));
+
+	}
+
+	/**
+	 * Test the digests
+	 */
+
+	// public void testDigests() throws Exception {
+	// Builder b = new Builder();
+	// b.addClasspath(new File("jar/osgi.jar"));
+	// b.setProperty(Constants.DIGESTS, "MD5, SHA1");
+	// b.setProperty(Constants.PRIVATE_PACKAGE, "*");
+	// Jar build = b.build();
+	// assertOk(b);
+	//
+	// Manifest m = build.getManifest();
+	// assertEquals(261, build.getResources().size());
+	//
+	// for (Entry<String,Resource> e : build.getResources().entrySet()) {
+	// System.out.println("Path " + e.getKey());
+	//
+	// Attributes attrs = m.getAttributes(e.getKey());
+	// assertNotNull(e.getKey(), attrs);
+	// boolean md5 = false, sha1 = false;
+	//
+	// for (Entry<Object,Object> ee : attrs.entrySet()) {
+	// String name = ee.getKey().toString().toLowerCase();
+	// if (name.endsWith("-digest")) {
+	// String value = ee.getValue().toString().trim();
+	// assertNotNull("original digest", value);
+	//
+	// byte[] original = Base64.decodeBase64(value);
+	// assertNotNull("original digest", original);
+	//
+	// String alg = name.substring(0, name.length() - 7);
+	// if (alg.equals("md5"))
+	// md5 = true;
+	// if (alg.equals("sha1"))
+	// sha1 = true;
+	//
+	// MessageDigest md = MessageDigest.getInstance(alg);
+	// InputStream in = e.getValue().openInputStream();
+	// byte[] buffer = new byte[8000];
+	// int size = in.read(buffer);
+	// while (size > 0) {
+	// md.update(buffer, 0, size);
+	// size = in.read(buffer);
+	// }
+	// byte calculated[] = md.digest();
+	// assertTrue("comparing digests " + e.getKey() + " " + value + " " +
+	// Base64.encodeBase64(calculated),
+	// Arrays.equals(original, calculated));
+	// }
+	// }
+	// assertTrue("expected md5", md5);
+	// assertTrue("expected sha1", sha1);
+	// }
+	// }
+
+	/**
+	 * Check of the use of x- directives are not skipped. bnd allows x-
+	 * directives in the import/export clauses but strips other ones.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testXDirectives() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.setProperty("Export-Package", "org.osgi.framework;x-foo:=true;bar:=false");
+		Jar jar = b.build();
+		assertTrue(b.check("bar:"));
+		Manifest m = jar.getManifest();
+		String s = m.getMainAttributes().getValue("Export-Package");
+		assertTrue(s.contains("x-foo:"));
+	}
+
+	/**
+	 * Check of SNAPSHOT is replaced with the -snapshot instr
+	 * 
+	 * @throws Exception
+	 */
+	public static void testSnapshot() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("-resourceonly", "true");
+		b.setProperty("-snapshot", "TIMESTAMP");
+		b.setProperty("Bundle-Version", "1.0-SNAPSHOT");
+		Jar jar = b.build();
+		assertTrue(b.check("The JAR is empty"));
+		Manifest m = jar.getManifest();
+		assertEquals("1.0.0.TIMESTAMP", m.getMainAttributes().getValue("Bundle-Version"));
+	}
+
+	/**
+	 * Check if do not copy works on files
+	 */
+
+	public static void testDoNotCopy() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("-resourceonly", "true");
+		b.setProperty("-donotcopy", ".*\\.jar|\\..*");
+		b.setProperty("Include-Resource", "jar");
+		b.build();
+		assertTrue(b.check());
+
+		Set<String> names = b.getJar().getResources().keySet();
+		assertEquals(8, names.size());
+		assertTrue(names.contains("AnnotationWithJSR14.jclass"));
+		assertTrue(names.contains("mandatorynoversion.bnd"));
+		assertTrue(names.contains("mina.bar"));
+		assertTrue(names.contains("minax.bnd"));
+		assertTrue(names.contains("rox.bnd"));
+		assertTrue(names.contains("WithAnnotations.jclass"));
+	}
+
+	/**
+	 * Check if do not copy works on files
+	 */
+
+	public static void testDoNotCopyDS() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("-resourceonly", "true");
+		b.setProperty("Include-Resource", "jar/");
+		b.build();
+		assertTrue(b.check());
+
+		Set<String> names = b.getJar().getResources().keySet();
+		assertFalse(names.contains(".DS_Store"));
+	}
+
+	/**
+	 * No error is generated when a file is not found.
+	 */
+
+	public static void testFileNotFound() throws Exception {
+		Builder b = new Builder();
+		b.setPedantic(true);
+		b.setProperty("-classpath", "xyz.jar");
+		b.setProperty("Include-Resource", "lib=lib, jar/osgi.jar");
+		b.setProperty("-resourceonly", "true");
+		b.build();
+		assertTrue(b.check("Input file does not exist: lib", "Cannot find entry on -classpath: xyz.jar"));
+	}
+
+	/**
+	 * bnd seems to pick the wrong version if a packageinfo is available
+	 * multiple times.
+	 * 
+	 * @throws Exception
+	 */
+
+	public static void testMultiplePackageInfo() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.addClasspath(new File("jar/osgi.core.jar"));
+		b.setProperty(Constants.PRIVATE_PACKAGE, "org.osgi.service.packageadmin;-split-package:=first");
+		b.build();
+		assertTrue(b.check());
+		String version = b.getImports().getByFQN("org.osgi.framework").get(Constants.VERSION_ATTRIBUTE);
+		assertEquals("[1.3,2)", version);
+	}
+
+	/**
+	 * Test the from: directive on expanding packages.
+	 */
+	public static void testFromOSGiDirective() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.addClasspath(new File("jar/org.eclipse.osgi-3.5.0.jar"));
+		b.setProperty("Export-Package", "org.osgi.framework;from:=osgi");
+		b.build();
+		assertTrue(b.check());
+
+		assertEquals("1.3", b.getExports().getByFQN("org.osgi.framework").get("version"));
+	}
+
+	public static void testFromEclipseDirective() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.addClasspath(new File("jar/org.eclipse.osgi-3.5.0.jar"));
+		b.setProperty("Export-Package", "org.osgi.framework;from:=org.eclipse.osgi-3.5.0");
+		b.build();
+		assertTrue(b.check());
+
+		assertEquals("1.3", b.getExports().getByFQN("org.osgi.framework").get("version"));
+	}
+
+	/**
+	 * Test the provide package
+	 */
+	public static void testProvidedVersion() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.addClasspath(new File("bin"));
+		b.setProperty(Constants.EXPORT_PACKAGE, "org.osgi.service.event;provide:=true");
+		b.setProperty("Private-Package", "test.refer");
+		Jar jar = b.build();
+		assertTrue(b.check());
+		String ip = jar.getManifest().getMainAttributes().getValue(Constants.IMPORT_PACKAGE);
+		Parameters map = Processor.parseHeader(ip, null);
+		assertEquals("[1.0,1.1)", map.get("org.osgi.service.event").get("version"));
+
+	}
+
+	public static void testUnProvidedVersion() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.addClasspath(new File("bin"));
+		b.setProperty(Constants.EXPORT_PACKAGE, "org.osgi.service.event;provide:=false");
+		b.setProperty("Private-Package", "test.refer");
+		Jar jar = b.build();
+		assertTrue(b.check());
+		String ip = jar.getManifest().getMainAttributes().getValue(Constants.IMPORT_PACKAGE);
+		Parameters map = Processor.parseHeader(ip, null);
+		assertEquals("[1.0,2)", map.get("org.osgi.service.event").get("version"));
+	}
+
+	/**
+	 * Complaint that exported versions were not picked up from external bundle.
+	 */
+
+	public static void testExportedVersionsNotPickedUp() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/jsr311-api-1.1.1.jar"));
+		b.setProperty("Export-Package", "javax.ws.rs.core");
+		Jar jar = b.build();
+		assertTrue(b.check());
+		String ip = jar.getManifest().getMainAttributes().getValue(Constants.EXPORT_PACKAGE);
+		Parameters map = Processor.parseHeader(ip, null);
+		assertEquals("1.1.1", map.get("javax.ws.rs.core").get("version"));
+	}
+
+	/**
+	 * Test where the version comes from: Manifest or packageinfo
+	 * 
+	 * @throws Exception
+	 */
+	public static void testExportVersionSource() throws Exception {
+		Manifest manifest = new Manifest();
+		manifest.getMainAttributes().putValue("Export-Package", "org.osgi.service.event;version=100");
+
+		// Remove packageinfo
+		Jar manifestOnly = new Jar(new File("jar/osgi.jar"));
+		manifestOnly.remove("org/osgi/service/event/packageinfo");
+		manifestOnly.setManifest(manifest);
+
+		// Remove manifest
+		Jar packageInfoOnly = new Jar(new File("jar/osgi.jar"));
+		packageInfoOnly.setManifest(new Manifest());
+
+		Jar both = new Jar(new File("jar/osgi.jar"));
+		both.setManifest(manifest);
+
+		// Only version in manifest
+		Builder bms = new Builder();
+		bms.addClasspath(manifestOnly);
+		bms.setProperty("Export-Package", "org.osgi.service.event");
+		bms.build();
+		assertTrue(bms.check());
+
+		String s = bms.getExports().getByFQN("org.osgi.service.event").get("version");
+		assertEquals("100", s);
+
+		// Only version in packageinfo
+		Builder bpinfos = new Builder();
+		bpinfos.addClasspath(packageInfoOnly);
+		bpinfos.setProperty("Export-Package", "org.osgi.service.event");
+		bpinfos.build();
+		assertTrue(bpinfos.check());
+
+		s = bpinfos.getExports().getByFQN("org.osgi.service.event").get("version");
+		assertEquals("1.0.1", s);
+
+	}
+
+	/**
+	 * Test where the version comes from: Manifest or packageinfo
+	 * 
+	 * @throws Exception
+	 */
+	public static void testImportVersionSource() throws Exception {
+		Jar fromManifest = new Jar("manifestsource");
+		Jar fromPackageInfo = new Jar("packageinfosource");
+		Jar fromBoth = new Jar("both");
+
+		Manifest mms = new Manifest();
+		mms.getMainAttributes().putValue("Export-Package", "org.osgi.service.event; version=100");
+		fromManifest.setManifest(mms);
+
+		fromPackageInfo.putResource("org/osgi/service/event/packageinfo", new EmbeddedResource("version 99".getBytes(),
+				0));
+
+		Manifest mboth = new Manifest();
+		mboth.getMainAttributes().putValue("Export-Package", "org.osgi.service.event; version=101");
+		fromBoth.putResource("org/osgi/service/event/packageinfo", new EmbeddedResource("version 199".getBytes(), 0));
+		fromBoth.setManifest(mboth);
+
+		// Only version in manifest
+		Builder bms = new Builder();
+		bms.addClasspath(fromManifest);
+		bms.setProperty("Import-Package", "=org.osgi.service.event");
+		bms.build();
+		assertTrue(bms.check("The JAR is empty"));
+		String s = bms.getImports().getByFQN("org.osgi.service.event").get("version");
+		assertEquals("[100.0,101)", s);
+
+		// Only version in packageinfo
+		Builder bpinfos = new Builder();
+		bpinfos.addClasspath(fromPackageInfo);
+		bpinfos.setProperty("Import-Package", "org.osgi.service.event");
+		bpinfos.build();
+		assertTrue(bms.check());
+		s = bpinfos.getImports().getByFQN("org.osgi.service.event").get("version");
+		assertEquals("[99.0,100)", s);
+
+		// Version in manifest + packageinfo
+		Builder bboth = new Builder();
+		bboth.addClasspath(fromBoth);
+		bboth.setProperty("Import-Package", "org.osgi.service.event");
+		bboth.build();
+		assertTrue(bms.check());
+		s = bboth.getImports().getByFQN("org.osgi.service.event").get("version");
+		assertEquals("[101.0,102)", s);
+
+	}
+
+	public static void testNoImportDirective() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("Export-Package", "org.osgi.util.measurement, org.osgi.service.http;-noimport:=true");
+		b.setProperty("Private-Package", "org.osgi.framework, test.refer");
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.addClasspath(new File("bin"));
+		Jar jar = b.build();
+		assertTrue(b.check());
+
+		Manifest m = jar.getManifest();
+		String imports = m.getMainAttributes().getValue("Import-Package");
+		assertTrue(imports.contains("org.osgi.util.measurement")); // referred
+																	// to but no
+																	// private
+																	// references
+																	// (does not
+																	// use fw).
+		assertFalse(imports.contains("org.osgi.service.http")); // referred to
+																// but no
+																// private
+																// references
+																// (does not use
+																// fw).
+
+	}
+
+	public static void testNoImportDirective2() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("Export-Package", "org.osgi.util.measurement;-noimport:=true, org.osgi.service.http");
+		b.setProperty("Private-Package", "org.osgi.framework, test.refer");
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.addClasspath(new File("bin"));
+		Jar jar = b.build();
+		assertTrue(b.check());
+
+		Manifest m = jar.getManifest();
+		String imports = m.getMainAttributes().getValue("Import-Package");
+		assertFalse(imports.contains("org.osgi.util.measurement")); // referred
+																	// to but no
+																	// private
+																	// references
+																	// (does not
+																	// use fw).
+		assertTrue(imports.contains("org.osgi.service.http")); // referred to
+																// but no
+																// private
+																// references
+																// (does not use
+																// fw).
+
+	}
+
+	public static void testAutoNoImport() throws Exception {
+		Builder b = new Builder();
+		b.setProperty(
+				"Export-Package",
+				"org.osgi.service.event, org.osgi.service.packageadmin, org.osgi.util.measurement, org.osgi.service.http;-noimport:=true");
+		b.setProperty("Private-Package", "org.osgi.framework, test.refer");
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.addClasspath(new File("bin"));
+		Jar jar = b.build();
+		assertTrue(b.check("has 1,  private references"));
+
+		Manifest m = jar.getManifest();
+		String imports = m.getMainAttributes().getValue("Import-Package");
+		assertFalse(imports.contains("org.osgi.service.packageadmin")); // no
+																		// internal
+																		// references
+		assertFalse(imports.contains("org.osgi.util.event")); // refers to
+																// private
+																// framework
+		assertTrue(imports.contains("org.osgi.util.measurement")); // referred
+																	// to but no
+																	// private
+																	// references
+																	// (does not
+																	// use fw).
+		assertFalse(imports.contains("org.osgi.service.http")); // referred to
+																// but no
+																// private
+																// references
+																// (does not use
+																// fw).
+	}
+
+	public static void testSimpleWab() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("-wab", "");
+		b.setProperty("Private-Package", "org.osgi.service.event");
+		b.addClasspath(new File("jar/osgi.jar"));
+		Jar jar = b.build();
+		assertTrue(b.check());
+
+		Manifest m = jar.getManifest();
+		m.write(System.err);
+		assertNotNull(b.getImports().getByFQN("org.osgi.framework"));
+	}
+
+	public static void testWab() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("-wablib", "jar/asm.jar, jar/easymock.jar");
+		b.setProperty("-wab", "jar/osgi.jar");
+		b.setProperty("-includeresource", "OSGI-INF/xml/x.xml;literal=\"text\"");
+		b.setProperty("Private-Package", "org.osgi.framework");
+		b.addClasspath(new File("jar/osgi.jar"));
+		Jar jar = b.build();
+		assertTrue(b.check());
+
+		Manifest m = jar.getManifest();
+		assertNotNull(m);
+		assertEquals("WEB-INF/classes,WEB-INF/lib/asm.jar,WEB-INF/lib/easymock.jar",
+				m.getMainAttributes().getValue("Bundle-ClassPath"));
+		assertNotNull(jar.getResource("WEB-INF/lib/asm.jar"));
+		assertNotNull(jar.getResource("WEB-INF/classes/org/osgi/framework/BundleContext.class"));
+		assertNotNull(jar.getResource("osgi.jar"));
+		assertNotNull(jar.getResource("OSGI-INF/xml/x.xml"));
+	}
+
+	public static void testRemoveHeaders() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("Private-Package", "org.osgi.framework");
+		b.setProperty("T1", "1");
+		b.setProperty("T2", "1");
+		b.setProperty("T1_2", "1");
+		b.setProperty("-removeheaders", "!T1_2,T1*");
+		b.addClasspath(new File("jar/osgi.jar"));
+		Jar jar = b.build();
+		assertTrue(b.check());
+
+		Manifest m = jar.getManifest();
+		assertNotNull(m);
+		assertEquals("1", m.getMainAttributes().getValue("T2"));
+		assertEquals("1", m.getMainAttributes().getValue("T1_2"));
+		assertEquals(null, m.getMainAttributes().getValue("T1"));
+
+	}
+
+	public static void testNoManifest() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("-nomanifest", "true");
+		b.setProperty(Constants.BUNDLE_CLASSPATH, "WEB-INF/classes");
+		b.setProperty("Include-Resource", "WEB-INF/classes=@jar/asm.jar");
+		Jar jar = b.build();
+		assertTrue(b.check());
+
+		File f = new File("tmp.jar");
+		f.deleteOnExit();
+		jar.write(f);
+
+		JarInputStream jin = new JarInputStream(new FileInputStream(f));
+		Manifest m = jin.getManifest();
+		assertNull(m);
+
+	}
+
+	public static void testClassesonNoBCP() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("-resourceonly", "true");
+		b.setProperty("Include-Resource", "WEB-INF/classes=@jar/asm.jar");
+		b.setProperty("-nomanifest", "true");
+		b.build();
+		assertTrue(b.check("Classes found in the wrong directory"));
+	}
+
+	public static void testClassesonBCP() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("-resourceonly", "true");
+		b.setProperty("Include-Resource", "WEB-INF/classes=@jar/asm.jar");
+		b.setProperty("Bundle-ClassPath", "WEB-INF/classes");
+		b.build();
+		assertTrue(b.check());
+	}
+
+	/**
+	 * #196 StringIndexOutOfBoundsException in Builder.getClasspathEntrySuffix
+	 * If a class path entry was changed the isInScope threw an exception
+	 * because it assumed all cpes were directories.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testInScopeClasspathEntry() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("Export-Package", "aQute.bnd.*");
+		b.addClasspath(new File("bin"));
+		b.addClasspath(new File("jar/osgi.jar"));
+
+		List<File> project = Arrays.asList(b.getFile("bin/aQute/bnd/build/Project.class"));
+		assertTrue(b.isInScope(project));
+		List<File> cpe = Arrays.asList(b.getFile("jar/osgi.jar"));
+		assertTrue(b.isInScope(cpe));
+	}
+
+	public static void testInScopeExport() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("Export-Package", "aQute.bnd.*");
+		b.addClasspath(new File("bin"));
+		List<File> project = Arrays.asList(b.getFile("bin/aQute/bnd/build/Project.class"));
+		assertTrue(b.isInScope(project));
+		List<File> nonexistent = Arrays.asList(b.getFile("bin/aQute/bnd/build/Abc.xyz"));
+		assertTrue(b.isInScope(nonexistent));
+		List<File> outside = Arrays.asList(b.getFile("bin/test/AnalyzerTest.class"));
+		assertFalse(b.isInScope(outside));
+	}
+
+	public static void testInScopePrivate() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("Private-Package", "!aQute.bnd.build,aQute.bnd.*");
+		b.addClasspath(new File("bin"));
+		List<File> project = Arrays.asList(b.getFile("bin/aQute/bnd/build/Project.class"));
+		assertFalse(b.isInScope(project));
+		List<File> nonexistent = Arrays.asList(b.getFile("bin/aQute/bnd/acb/Def.xyz"));
+		assertTrue(b.isInScope(nonexistent));
+		List<File> outside = Arrays.asList(b.getFile("bin/test/AnalyzerTest.class"));
+		assertFalse(b.isInScope(outside));
+	}
+
+	public static void testInScopeResources() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("Include-Resource", "@a.jar/!xya.txt,{@b.jar/!xya.txt}, - at c.jar/!xya.txt, dir, x=dirb, {-x=dirc}");
+		assertFalse(b.isInScope(Arrays.asList(b.getFile("x.jar"))));
+		assertTrue(b.isInScope(Arrays.asList(b.getFile("a.jar"))));
+		assertTrue(b.isInScope(Arrays.asList(b.getFile("b.jar"))));
+		assertTrue(b.isInScope(Arrays.asList(b.getFile("dir/a.jar"))));
+		assertTrue(b.isInScope(Arrays.asList(b.getFile("dir/x.jar"))));
+		assertTrue(b.isInScope(Arrays.asList(b.getFile("dir/x.jar"))));
+		assertTrue(b.isInScope(Arrays.asList(b.getFile("dirb/x.jar"))));
+		assertTrue(b.isInScope(Arrays.asList(b.getFile("dirb/x.jar"))));
+		assertTrue(b.isInScope(Arrays.asList(b.getFile("dirc/x.jar"))));
+	}
+
+	public static void testExtra() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("Include-Resource", "jar/osgi.jar;extra=itworks, www/xyz.jar=jar/osgi.jar;extra='italsoworks'");
+		b.setProperty("-resourceonly", "true");
+		Jar jar = b.build();
+		assertTrue(b.check());
+
+		Resource r = jar.getResource("osgi.jar");
+		assertNotNull(r);
+		assertEquals("itworks", r.getExtra());
+		Resource r2 = jar.getResource("www/xyz.jar");
+		assertNotNull(r2);
+		assertEquals("italsoworks", r2.getExtra());
+	}
+
+	/**
+	 * Got a split package warning during verify when private overlaps with
+	 * export
+	 */
+	public static void testSplitWhenPrivateOverlapsExport() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.setProperty("Private-Package", "org.osgi.service.*");
+		b.setProperty("Export-Package", "org.osgi.service.event");
+		b.build();
+		assertTrue(b.check());
+	}
+
+	/**
+	 * This test checks if
+	 * 
+	 * @throws Exception
+	 */
+
+	public static void testMacroBasedExpansion() throws Exception {
+		Processor proc = new Processor();
+
+		Builder builder = new Builder(proc);
+		builder.setProperty("Export-Package", "${spec.packages}");
+		proc.setProperty("spec.packages", "${core.packages}, ${cmpn.packages}, ${mobile.packages}");
+		proc.setProperty("core.specs", "org.osgi.service.packageadmin, org.osgi.service.permissionadmin");
+		proc.setProperty("core.packages", "${replace;${core.specs};.+;$0.*}");
+		proc.setProperty("cmpn.specs", "org.osgi.service.event, org.osgi.service.cu");
+		proc.setProperty("cmpn.packages", "${replace;${cmpn.specs};.+;$0.*}");
+		proc.setProperty("mobile.specs", "org.osgi.service.wireadmin, org.osgi.service.log, org.osgi.service.cu");
+		proc.setProperty("mobile.packages", "${replace;${mobile.specs};.+;$0.*}");
+		builder.addClasspath(new File("jar/osgi.jar"));
+
+		Jar jar = builder.build();
+		// The total set is not uniqued so we're having an unused pattern
+		// this could be solved with ${uniq;${spec.packages}} but this is just
+		// another test
+		assertTrue(builder.check("Unused Export-Package instructions: \\[org.osgi.service.cu.\\*~\\]"));
+		Domain domain = Domain.domain(jar.getManifest());
+
+		Parameters h = domain.getExportPackage();
+		assertTrue(h.containsKey("org.osgi.service.cu"));
+		assertTrue(h.containsKey("org.osgi.service.cu.admin"));
+	}
+
+	/**
+	 * Make resolution dependent on the fact that a package is on the classpath
+	 * or not
+	 */
+
+	public static void testConditionalResolution() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("res", "${if;${exporters;${@package}};mandatory;optional}");
+		b.setProperty("Import-Package", "*;resolution:=\\${res}");
+		b.setProperty("Export-Package", "org.osgi.service.io, org.osgi.service.log");
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.build();
+		assertTrue(b.check());
+
+		Map<String,String> ioimports = b.getImports().getByFQN("javax.microedition.io");
+		Map<String,String> fwimports = b.getImports().getByFQN("org.osgi.framework");
+
+		assertNotNull(ioimports);
+		assertNotNull(fwimports);
+		assertTrue(ioimports.containsKey("resolution:"));
+		assertTrue(fwimports.containsKey("resolution:"));
+		assertEquals("optional", ioimports.get("resolution:"));
+		assertEquals("mandatory", fwimports.get("resolution:"));
+	}
+
+	/**
+	 * Test private imports. We first build a jar with a import:=private packge.
+	 * Then place it
+	 * 
+	 * @throws Exception
+	 */
+
+	public static void testClassnames() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.addClasspath(new File("jar/ds.jar"));
+		b.addClasspath(new File("jar/ifc112.jar"));
+		b.setProperty("Export-Package", "*");
+		b.setProperty("C1", "${classes;implementing;org.osgi.service.component.*}");
+		b.setProperty("C2", "${classes;extending;org.xml.sax.helpers.*}");
+		b.setProperty("C3", "${classes;importing;org.xml.sax}");
+		b.setProperty("C3", "${classes;importing;org.xml.sax}");
+		b.setProperty("C4", "${classes;named;*Parser*}");
+		b.setProperty("C5", "${classes;named;*Parser*;version;45.*}");
+		Jar jar = b.build();
+		assertTrue(b.check());
+
+		Manifest m = jar.getManifest();
+		m.write(System.err);
+		Attributes main = m.getMainAttributes();
+		assertList(
+				asl("org.eclipse.equinox.ds.service.ComponentContextImpl,org.eclipse.equinox.ds.service.ComponentFactoryImpl,org.eclipse.equinox.ds.service.ComponentInstanceImpl"),
+				asl(main.getValue("C1")));
+		assertList(asl("org.eclipse.equinox.ds.parser.ElementHandler, "
+				+ "org.eclipse.equinox.ds.parser.IgnoredElement,"
+				+ "org.eclipse.equinox.ds.parser.ImplementationElement,"
+				+ "org.eclipse.equinox.ds.parser.ParserHandler, " + "org.eclipse.equinox.ds.parser.PropertiesElement,"
+				+ "org.eclipse.equinox.ds.parser.PropertyElement, " + "org.eclipse.equinox.ds.parser.ProvideElement, "
+				+ "org.eclipse.equinox.ds.parser.ReferenceElement, " + "org.eclipse.equinox.ds.parser.ServiceElement,"
+				+ "org.eclipse.equinox.ds.parser.ComponentElement"), asl(main.getValue("C2")));
+		assertList(
+				asl("org.eclipse.equinox.ds.parser.ComponentElement,org.eclipse.equinox.ds.parser.ElementHandler,org.eclipse.equinox.ds.parser.IgnoredElement,org.eclipse.equinox.ds.parser.ImplementationElement,org.eclipse.equinox.ds.parser.Parser,org.eclipse.equinox.ds.parser.ParserHandler,org.eclipse.equinox.ds.parser.PropertiesElement,org.eclipse.equinox.ds.parser.PropertyElement,org.eclipse.equinox.ds.parser.ProvideElement,org.eclipse.equinox.ds.parser.ReferenceElement,org.eclipse.equinox.ds.pars [...]
+				asl(main.getValue("C3")));
+		assertList(
+				asl("org.eclipse.equinox.ds.parser.XMLParserNotAvailableException,org.eclipse.equinox.ds.parser.Parser,org.eclipse.equinox.ds.parser.ParserHandler,netscape.application.HTMLParser,org.eclipse.equinox.ds.parser.ParserConstants,org.osgi.util.xml.XMLParserActivator"),
+				asl(main.getValue("C4")));
+		assertEquals("netscape.application.HTMLParser", main.getValue("C5"));
+	}
+
+	static void assertList(Collection<String> a, Collection<String> b) {
+		List<String> onlyInA = new ArrayList<String>();
+		onlyInA.addAll(a);
+		onlyInA.removeAll(b);
+
+		List<String> onlyInB = new ArrayList<String>();
+		onlyInB.addAll(b);
+		onlyInB.removeAll(a);
+
+		if (onlyInA.isEmpty() && onlyInB.isEmpty())
+			return;
+
+		fail("Lists are not equal, only in A: " + onlyInA + ",\n   and only in B: " + onlyInB);
+	}
+
+	static Collection<String> asl(String s) {
+		return new TreeSet<String>(Processor.split(s));
+	}
+
+	public static void testImportMicroNotTruncated() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.setProperty("Import-Package", "org.osgi.service.event;version=${@}");
+		b.build();
+		assertTrue(b.check("The JAR is empty"));
+		String s = b.getImports().getByFQN("org.osgi.service.event").get("version");
+		assertEquals("1.0.1", s);
+	}
+
+	public static void testImportMicroTruncated() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.setProperty("Import-Package", "org.osgi.service.event");
+		b.build();
+		assertTrue(b.check("The JAR is empty"));
+
+		String s = b.getImports().getByFQN("org.osgi.service.event").get("version");
+		assertEquals("[1.0,2)", s);
+	}
+
+	public static void testMultipleExport2() throws Exception {
+		File cp[] = {
+			new File("jar/asm.jar")
+		};
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.setProperty("Export-Package",
+				"org.objectweb.asm;version=1.1, org.objectweb.asm;version=1.2, org.objectweb.asm;version=2.3");
+		bmaker.setProperties(p);
+		bmaker.setClasspath(cp);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+		jar.getManifest().write(System.err);
+		Manifest m = jar.getManifest();
+		m.write(System.err);
+		String ip = m.getMainAttributes().getValue("Export-Package");
+		assertTrue(ip.indexOf("org.objectweb.asm;version=\"1.1\"") >= 0);
+		assertTrue(ip.indexOf("org.objectweb.asm;version=\"1.2\"") >= 0);
+		assertTrue(ip.indexOf("org.objectweb.asm;version=\"2.3\"") >= 0);
+	}
+
+	public static void testBsnAssignmentNoFile() throws Exception {
+		Properties p = new Properties();
+		p.setProperty("Private-Package", "org.objectweb.asm");
+		Attributes m = setup(p, null).getMainAttributes();
+
+		// We use properties so the default BSN is then the project name
+		// because that is the base directory
+		assertEquals(m.getValue("Bundle-SymbolicName"), "biz.aQute.bndlib.tests");
+
+		// The file name for the properties is not bnd.bnd, so the
+		// name of the properties file is the default bsn
+		m = setup(null, new File("src/test/com.acme/defaultbsn.bnd")).getMainAttributes();
+		assertEquals("com.acme.defaultbsn", m.getValue("Bundle-SymbolicName"));
+
+		// If the file is called bnd.bnd, then we take the parent directory
+		m = setup(null, new File("src/test/com.acme/bnd.bnd")).getMainAttributes();
+		assertEquals("com.acme", m.getValue("Bundle-SymbolicName"));
+
+		// If the file is called bnd.bnd, then we take the parent directory
+		m = setup(null, new File("src/test/com.acme/setsbsn.bnd")).getMainAttributes();
+		assertEquals("is.a.set.bsn", m.getValue("Bundle-SymbolicName"));
+
+		// This sets the bsn, se we should see it back
+		p.setProperty("Bundle-SymbolicName", "this.is.my.test");
+		m = setup(p, null).getMainAttributes();
+		assertEquals(m.getValue("Bundle-SymbolicName"), "this.is.my.test");
+	}
+
+	public static Manifest setup(Properties p, File f) throws Exception {
+		File cp[] = {
+			new File("jar/asm.jar")
+		};
+		Builder bmaker = new Builder();
+		if (f != null)
+			bmaker.setProperties(f);
+		else
+			bmaker.setProperties(p);
+		bmaker.setClasspath(cp);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+		Manifest m = jar.getManifest();
+		return m;
+	}
+
+	public static void testDuplicateExport() throws Exception {
+		File cp[] = {
+			new File("jar/asm.jar")
+		};
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.setProperty("Import-Package", "*");
+		p.setProperty("Export-Package", "org.*;version=1.2,org.objectweb.asm;version=1.3");
+		bmaker.setProperties(p);
+		bmaker.setClasspath(cp);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+		Manifest m = jar.getManifest();
+		m.write(System.err);
+		String ip = m.getMainAttributes().getValue("Export-Package");
+		assertTrue(ip.indexOf("org.objectweb.asm;version=\"1.2\"") >= 0);
+	}
+
+	public static void testNoExport() throws Exception {
+		File cp[] = {
+			new File("jar/asm.jar")
+		};
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.setProperty("Import-Package", "*");
+		p.setProperty("Export-Package", "org.*'");
+		bmaker.setProperties(p);
+		bmaker.setClasspath(cp);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+
+		jar.getManifest().write(System.err);
+		Manifest m = jar.getManifest();
+		String ip = m.getMainAttributes().getValue("Export-Package");
+		assertTrue(ip.indexOf("org.objectweb.asm") >= 0);
+	}
+
+	public static void testHardcodedImport() throws Exception {
+		File cp[] = {
+			new File("jar/asm.jar")
+		};
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.setProperty("Import-Package", "whatever,*");
+		p.setProperty("Export-Package", "org.*");
+		bmaker.setProperties(p);
+		bmaker.setClasspath(cp);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+
+		Manifest m = jar.getManifest();
+		String ip = m.getMainAttributes().getValue("Import-Package");
+		assertTrue(ip.indexOf("whatever") >= 0);
+	}
+
+	public static void testCopyDirectory() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.setProperty("-resourceonly", "true");
+		p.setProperty("Include-Resource", "bnd=bnd");
+		bmaker.setProperties(p);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+
+		Map<String,Resource> map = jar.getDirectories().get("bnd");
+		assertNotNull(map);
+		assertEquals(2, map.size());
+	}
+
+	/**
+	 * There is an error that gives a split package when you export a package
+	 * that is also private I think.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testSplitOnExportAndPrivate() throws Exception {
+		File cp[] = {
+			new File("jar/asm.jar")
+		};
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.setProperty("Export-Package", "org.objectweb.asm.signature");
+		p.setProperty("Private-Package", "org.objectweb.asm");
+		bmaker.setProperties(p);
+		bmaker.setClasspath(cp);
+		bmaker.build();
+		assertTrue(bmaker.check());
+	}
+
+	public static void testConduit() throws Exception {
+		Properties p = new Properties();
+		p.setProperty("-conduit", "jar/asm.jar");
+		Builder b = new Builder();
+		b.setProperties(p);
+		Jar jars[] = b.builds();
+		assertTrue(b.check());
+		assertNotNull(jars);
+		assertEquals(1, jars.length);
+		assertEquals("ASM", jars[0].getManifest().getMainAttributes().getValue("Implementation-Title"));
+	}
+
+	/**
+	 * Export a package that was loaded with resources
+	 * 
+	 * @throws Exception
+	 */
+	public static void testExportSyntheticPackage() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.setProperty("-resourceonly", "true");
+		p.setProperty("Include-Resource", "resources=jar");
+		p.setProperty("-exportcontents", "resources");
+		bmaker.setProperties(p);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+
+		Manifest manifest = jar.getManifest();
+		String header = manifest.getMainAttributes().getValue("Export-Package");
+		System.err.println(header);
+		assertTrue(header.indexOf("resources") >= 0);
+	}
+
+	/**
+	 * Exporting packages in META-INF
+	 * 
+	 * @throws Exception
+	 */
+	public static void testMETAINF() throws Exception {
+		File cp[] = {
+				new File("src"), new File("jar/asm.jar")
+		};
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.setProperty("Include-Resource", "META-INF/xyz/asm.jar=jar/asm.jar");
+		p.setProperty("Export-Package", "META-INF/xyz, org.*");
+		bmaker.setProperties(p);
+		bmaker.setClasspath(cp);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check("Invalid package name: 'META-INF"));
+
+		jar.getManifest().write(System.err);
+		Manifest manifest = jar.getManifest();
+		String header = manifest.getMainAttributes().getValue("Export-Package");
+		assertTrue(header.indexOf("META-INF.xyz") >= 0);
+	}
+
+	/**
+	 * Bnd cleans up versions if they do not follow the OSGi rule. Check a
+	 * number of those versions.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testVersionCleanup() throws Exception {
+		assertVersion("1.201209072340200", "1.0.0.201209072340200");
+		assertVersion("000001.0003.00000-SNAPSHOT", "1.3.0.SNAPSHOT");
+		assertVersion("000000.0000.00000-SNAPSHOT", "0.0.0.SNAPSHOT");
+		assertVersion("0-SNAPSHOT", "0.0.0.SNAPSHOT");
+		assertVersion("1.3.0.0-0-01-0-SNAPSHOT", "1.3.0.0-0-01-0-SNAPSHOT");
+		assertVersion("1.3.0.0-0-01-0", "1.3.0.0-0-01-0");
+		assertVersion("0.9.0.1.2.3.4.5-incubator-SNAPSHOT", "0.9.0.incubator-SNAPSHOT");
+		assertVersion("0.4aug123", "0.0.0.4aug123");
+		assertVersion("0.9.4aug123", "0.9.0.4aug123");
+		assertVersion("0.9.0.4aug123", "0.9.0.4aug123");
+
+		assertVersion("1.2.3", "1.2.3");
+		assertVersion("1.2.3-123", "1.2.3.123");
+		assertVersion("1.2.3.123", "1.2.3.123");
+		assertVersion("1.2.3.123x", "1.2.3.123x");
+		assertVersion("1.123x", "1.0.0.123x");
+
+		assertVersion("0.9.0.4.3.2.1.0.4aug123", "0.9.0.4aug123");
+		assertVersion("0.9.0.4aug123", "0.9.0.4aug123");
+
+		assertVersion("0.9.0.4.3.4.5.6.6", "0.9.0.6");
+
+		assertVersion("0.9.0-incubator-SNAPSHOT", "0.9.0.incubator-SNAPSHOT");
+		assertVersion("1.2.3.x", "1.2.3.x");
+		assertVersion("1.2.3", "1.2.3");
+		assertVersion("1.2", "1.2");
+		assertVersion("1", "1");
+		assertVersion("1.2.x", "1.2.0.x");
+		assertVersion("1.x", "1.0.0.x");
+		assertVersion("1.2.3-x", "1.2.3.x");
+		assertVersion("1.2:x", "1.2.0.x");
+		assertVersion("1.2-snapshot", "1.2.0.snapshot");
+		assertVersion("1#x", "1.0.0.x");
+		assertVersion("1.&^%$#date2007/03/04", "1.0.0.date20070304");
+	}
+
+	static void assertVersion(String input, String expected) {
+		assertEquals(expected, Builder.cleanupVersion(input));
+	}
+
+	/**
+	 * -exportcontents provides a header that is only relevant in the analyze
+	 * phase, it augments the Export-Package header.
+	 */
+
+	public static void testExportContents() throws Exception {
+		Builder builder = new Builder();
+		builder.setProperty(Analyzer.INCLUDE_RESOURCE, "test/activator/inherits=src/test/activator/inherits");
+		builder.setProperty("-exportcontents", "*;x=true;version=1");
+		builder.build();
+		assertTrue(builder.check());
+		Manifest manifest = builder.calcManifest();
+		Attributes main = manifest.getMainAttributes();
+		Parameters map = OSGiHeader.parseHeader(main.getValue("Export-Package"));
+		Map<String,String> export = map.get("test.activator.inherits");
+		assertNotNull(export);
+		assertEquals("1", export.get("version"));
+		assertEquals("true", export.get("x"));
+	}
+
+	/**
+	 * I am having some problems with split packages in 170. I get this output:
+	 * [java] 1 : There are split packages, use directive split-package:=merge
+	 * on instruction to get rid of this warning: my.package First of all, this
+	 * warning is falsely occurring. The classpath to the bnd task contains
+	 * something like: my/package/foo.class my/package/sub/bar.class and the
+	 * export is: Export-Package: my.package*;version=${version} so my.package
+	 * and my.package.sub are being incorrectly considered as the same package
+	 * by bnd.
+	 */
+	public static void testSplitOverlappingPackages() throws Exception {
+		Builder b = new Builder();
+		b.setClasspath(new File[] {
+			new File("bin")
+		});
+		Properties p = new Properties();
+		p.put("build", "xyz");
+		p.put("Export-Package", "test*;version=3.1");
+		b.setProperties(p);
+		b.setPedantic(true);
+		b.build();
+		assertTrue(b.check("Imports that lack version ranges", "Invalid package name"));
+	}
+
+	/**
+	 * Check Conditional package. First import a subpackage then let the
+	 * subpackage import a super package. This went wrong in the OSGi build. We
+	 * see such a pattern in the Spring jar. The package
+	 * org.springframework.beans.factory.access refers to
+	 * org.springframework.beans.factory and org.springframework.beans. The
+	 */
+	public static void testConditionalBaseSuper() throws Exception {
+		Builder b = new Builder();
+		b.setProperty(Constants.CONDITIONAL_PACKAGE, "test.top.*");
+		b.setProperty(Constants.PRIVATE_PACKAGE, "test.top.middle.bottom");
+		b.addClasspath(new File("bin"));
+		Jar dot = b.build();
+		assertTrue(b.check());
+
+		assertNotNull(dot.getResource("test/top/middle/bottom/Bottom.class"));
+		assertNotNull(dot.getResource("test/top/middle/Middle.class"));
+		assertNotNull(dot.getResource("test/top/Top.class"));
+
+		assertFalse(b.getImports().getByFQN("test.top") != null);
+		assertFalse(b.getImports().getByFQN("test.top.middle") != null);
+		assertFalse(b.getImports().getByFQN("test.top.middle.bottom") != null);
+	}
+
+	/**
+	 * It looks like Conditional-Package can add the same package multiple
+	 * times. So lets test this.
+	 */
+	public static void testConditional2() throws Exception {
+		Properties base = new Properties();
+		base.put(Analyzer.EXPORT_PACKAGE, "org.osgi.service.log");
+		base.put(Analyzer.CONDITIONAL_PACKAGE, "org.osgi.*");
+		Builder analyzer = new Builder();
+		analyzer.setProperties(base);
+		analyzer.setClasspath(new File[] {
+			new File("jar/osgi.jar")
+		});
+		analyzer.build();
+		assertTrue(analyzer.check("private references"));
+		Jar jar = analyzer.getJar();
+		assertTrue(analyzer.check());
+		assertNotNull(analyzer.getExports().getByFQN("org.osgi.service.log"));
+		assertNotNull(jar.getDirectories().get("org/osgi/framework"));
+	}
+
+	/**
+	 * Test the strategy: error
+	 */
+	public static void testStrategyError() throws Exception {
+		Properties base = new Properties();
+		base.put(Analyzer.EXPORT_PACKAGE, "*;-split-package:=error");
+		Builder analyzer = new Builder();
+		analyzer.setClasspath(new File[] {
+				new File("jar/asm.jar"), new File("jar/asm.jar")
+		});
+		analyzer.setProperties(base);
+		analyzer.build();
+		assertTrue(analyzer.check("The JAR is empty", "Split package"));
+	}
+
+	/**
+	 * Test the strategy: default
+	 */
+	public static void testStrategyDefault() throws Exception {
+		Properties base = new Properties();
+		base.put(Analyzer.EXPORT_PACKAGE, "*");
+		Builder analyzer = new Builder();
+		analyzer.setClasspath(new File[] {
+				new File("jar/asm.jar"), new File("jar/asm.jar")
+		});
+		analyzer.setProperties(base);
+		analyzer.build();
+		assertEquals(2, analyzer.getWarnings().size());
+		assertTrue(analyzer.check("Split package"));
+	}
+
+	/**
+	 * Test the strategy: merge-first
+	 */
+	public static void testStrategyMergeFirst() throws Exception {
+		Properties base = new Properties();
+		base.put(Analyzer.EXPORT_PACKAGE, "*;-split-package:=merge-first");
+		Builder analyzer = new Builder();
+		analyzer.setClasspath(new File[] {
+				new File("jar/asm.jar"), new File("jar/asm.jar")
+		});
+		analyzer.setProperties(base);
+		analyzer.build();
+		assertTrue(analyzer.check());
+	}
+
+	/**
+	 * Test the strategy: merge-last
+	 */
+	public static void testStrategyMergeLast() throws Exception {
+		Properties base = new Properties();
+		base.put(Analyzer.EXPORT_PACKAGE, "*;-split-package:=merge-last");
+		Builder analyzer = new Builder();
+		analyzer.setClasspath(new File[] {
+				new File("jar/asm.jar"), new File("jar/asm.jar")
+		});
+		analyzer.setProperties(base);
+		analyzer.build();
+		assertTrue(analyzer.check());
+	}
+
+	/**
+	 * Test Resource inclusion that do not exist
+	 * 
+	 * @throws Exception
+	 */
+	public static void testResourceNotFound() throws Exception {
+		Properties base = new Properties();
+		base.put(Analyzer.EXPORT_PACKAGE, "*;x-test:=true");
+		base.put(Analyzer.INCLUDE_RESOURCE, "does_not_exist");
+		Builder analyzer = new Builder();
+		analyzer.setClasspath(new File[] {
+			new File("jar/asm.jar")
+		});
+		analyzer.setProperties(base);
+		analyzer.build();
+		assertTrue(analyzer.check("file does not exist: does_not_exist"));
+
+	}
+
+	/**
+	 * Spaces at the end of a clause cause the preprocess to fail.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testPreProcess() throws Exception {
+		Properties base = new Properties();
+		base.put(Analyzer.INCLUDE_RESOURCE, "{src/test/top.mf}     ");
+		Builder analyzer = new Builder();
+		analyzer.setProperties(base);
+		analyzer.build();
+		assertTrue(analyzer.check());
+
+		Jar jar = analyzer.getJar();
+		assertTrue(jar.getResource("top.mf") != null);
+	}
+
+	/**
+	 * Check if we can use findpath to build the Bundle-Classpath.
+	 */
+
+	public static void testFindPathInBundleClasspath() throws Exception {
+		Properties base = new Properties();
+		base.put(Analyzer.INCLUDE_RESOURCE, "jar=jar");
+		base.put(Analyzer.BUNDLE_CLASSPATH, "${findpath;jar/.{1,4}\\.jar}");
+		Builder analyzer = new Builder();
+		analyzer.setProperties(base);
+		analyzer.build();
+		assertTrue(analyzer.check());
+
+		Manifest manifest = analyzer.getJar().getManifest();
+		String bcp = manifest.getMainAttributes().getValue("Bundle-Classpath");
+
+		assertTrue(bcp.indexOf("ds.jar") >= 0);
+		assertTrue(bcp.indexOf("asm.jar") >= 0);
+		assertTrue(bcp.indexOf("bcel.jar") >= 0);
+		assertTrue(bcp.indexOf("mina.jar") >= 0);
+		assertTrue(bcp.indexOf("rox.jar") >= 0);
+		assertTrue(bcp.indexOf("osgi.jar") >= 0);
+	}
+
+	/**
+	 * Check if we export META-INF when we export the complete classpath.
+	 */
+
+	public static void testVersionCleanupAll() throws Exception {
+		Properties base = new Properties();
+		base.put(Analyzer.EXPORT_PACKAGE, "*");
+		base.put(Analyzer.BUNDLE_VERSION, "0.9.0-incubator-SNAPSHOT");
+		Builder analyzer = new Builder();
+		analyzer.setClasspath(new File[] {
+			new File("jar/asm.jar")
+		});
+		analyzer.setProperties(base);
+		analyzer.build();
+
+		assertTrue(analyzer.check());
+		Manifest manifest = analyzer.getJar().getManifest();
+		String version = manifest.getMainAttributes().getValue(Analyzer.BUNDLE_VERSION);
+		assertEquals("0.9.0.incubator-SNAPSHOT", version);
+	}
+
+	/**
+	 * We are only adding privately the core equinox ds package. We then add
+	 * conditionally all packages that should belong to this as well as any OSGi
+	 * interfaces.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testConditional() throws Exception {
+		File cp[] = {
+				new File("jar/osgi.jar"), new File("jar/ds.jar")
+		};
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.put("Import-Package", "*");
+		p.put("Private-Package", "org.eclipse.equinox.ds");
+		p.put("Conditional-Package", "org.eclipse.equinox.ds.*, org.osgi.service.*");
+		bmaker.setProperties(p);
+		bmaker.setClasspath(cp);
+		bmaker.build();
+		assertTrue(bmaker.check());
+
+		assertTrue(bmaker.getContained().getByFQN("org.eclipse.equinox.ds.instance") != null);
+		assertTrue(bmaker.getContained().getByFQN("org.eclipse.equinox.ds.model") != null);
+		assertTrue(bmaker.getContained().getByFQN("org.eclipse.equinox.ds.parser") != null);
+		assertTrue(bmaker.getContained().getByFQN("org.osgi.service.cm") != null);
+		assertTrue(bmaker.getContained().getByFQN("org.osgi.service.component") != null);
+		assertFalse(bmaker.getContained().getByFQN("org.osgi.service.wireadmin") != null);
+	}
+
+	/**
+	 * Check if we export META-INF when we export the complete classpath.
+	 */
+
+	public static void testMetaInfExport() throws Exception {
+		Properties base = new Properties();
+		base.put(Analyzer.EXPORT_PACKAGE, "*");
+		Builder analyzer = new Builder();
+		analyzer.setClasspath(new File[] {
+			new File("jar/asm.jar")
+		});
+		analyzer.setProperties(base);
+		analyzer.build();
+		assertTrue(analyzer.check());
+		assertFalse(analyzer.getExports().getByFQN("META-INF") != null);
+		assertTrue(analyzer.getExports().getByFQN("org.objectweb.asm") != null);
+	}
+
+	/**
+	 * Check that the activator is found.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testFindActivator() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.put("Bundle-Activator", "test.activator.Activator");
+		p.put("build", "xyz"); // for @Version annotation
+		p.put("Private-Package", "test.*");
+		bmaker.setProperties(p);
+		bmaker.setClasspath(new File[] {
+			new File("bin")
+		});
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+		report("testFindActivator", bmaker, jar);
+		assertEquals(0, bmaker.getErrors().size());
+		assertEquals(0, bmaker.getWarnings().size());
+	}
+
+	public static void testImportVersionRange() throws Exception {
+		assertVersionEquals("[1.1,2.0)", "[1.1,2.0)");
+		assertVersionEquals("[${@},2.0)", "[1.3,2.0)");
+		assertVersionEquals("[${@},${@}]", "[1.3,1.3]");
+	}
+
+	static void assertVersionEquals(String input, String output) throws Exception {
+		File cp[] = {
+			new File("jar/osgi.jar")
+		};
+		Builder bmaker = new Builder();
+		bmaker.setClasspath(cp);
+		Properties p = new Properties();
+		p.put(Analyzer.EXPORT_PACKAGE, "test.activator");
+		p.put(Analyzer.IMPORT_PACKAGE, "org.osgi.framework;version=\"" + input + "\"");
+		bmaker.setProperties(p);
+		bmaker.build();
+		assertTrue(bmaker.check("The JAR is empty"));
+		Packages imports = bmaker.getImports();
+		Map<String,String> framework = imports.get(bmaker.getPackageRef("org.osgi.framework"));
+		assertEquals(output, framework.get("version"));
+	}
+
+	public static void testImportExportBadVersion() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/ds.jar"));
+		b.set(Analyzer.BUNDLE_VERSION, "0.9.5-@#SNAPSHOT");
+		b.set(Analyzer.EXPORT_PACKAGE, "*;version=0.9.5-@#SNAPSHOT");
+		b.set(Analyzer.IMPORT_PACKAGE, "*;version=0.9.5-@#SNAPSHOT");
+
+		Jar jar = b.build();
+		assertTrue(b.check());
+		Manifest m = jar.getManifest();
+		m.write(System.err);
+		assertEquals(m.getMainAttributes().getValue("Bundle-Version"), "0.9.5.SNAPSHOT");
+
+		assertNotNull(b.getExports().getByFQN("org.eclipse.equinox.ds.parser"));
+		assertEquals("0.9.5.SNAPSHOT", b.getExports().getByFQN("org.eclipse.equinox.ds.parser").getVersion());
+
+		assertNotNull(b.getImports().getByFQN("org.osgi.framework"));
+		assertEquals("0.9.5.SNAPSHOT", b.getImports().getByFQN("org.osgi.framework").getVersion());
+	}
+
+	/**
+	 * Check if can find an activator in the bundle while using a complex bundle
+	 * classpath.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testBundleClasspath3() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.put("Export-Package", "test.activator;-split-package:=merge-first");
+		p.put("Bundle-Activator", "test.activator.Activator");
+		p.put("Import-Package", "*");
+		p.put("Include-Resource", "ds.jar=jar/ds.jar");
+		p.put("Bundle-ClassPath", ".,ds.jar");
+		bmaker.setProperties(p);
+		bmaker.setClasspath(new File[] {
+				new File("bin"), new File("src")
+		});
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+
+		report("testBundleClasspath3", bmaker, jar);
+		assertEquals(0, bmaker.getErrors().size());
+		assertEquals(0, bmaker.getWarnings().size());
+	}
+
+	/**
+	 * Check if can find an activator in a embedded jar while using a complex
+	 * bundle classpath.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testBundleClasspath2() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.put("Bundle-Activator", "org.eclipse.equinox.ds.Activator");
+		p.put("Private-Package", "test.activator;-split-package:=merge-first");
+		p.put("Import-Package", "*");
+		p.put("Include-Resource", "ds.jar=jar/ds.jar");
+		p.put("Bundle-ClassPath", ".,ds.jar");
+		bmaker.setProperties(p);
+		bmaker.setClasspath(new File[] {
+				new File("bin"), new File("src")
+		});
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+
+		report("testBundleClasspath2", bmaker, jar);
+		assertEquals(bmaker.getErrors().size(), 0);
+		assertEquals(bmaker.getWarnings().size(), 0);
+	}
+
+	public static void testBundleClasspath() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.put("Export-Package", "test.activator;-split-package:=merge-first");
+		p.put("Bundle-Activator", "test.activator.Activator");
+		p.put("Import-Package", "*");
+		p.put("Bundle-ClassPath", ".");
+		bmaker.setProperties(p);
+		bmaker.setClasspath(new File[] {
+				new File("bin"), new File("src")
+		});
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+
+		report("testBundleClasspath", bmaker, jar);
+		jar.exists("test/activator/Activator.class");
+		assertEquals(bmaker.getErrors().size(), 0);
+		assertEquals(bmaker.getWarnings().size(), 0);
+	}
+
+	public static void testUnreferredImport() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+
+		p.put("-classpath", "jar/mina.jar");
+		p.put("Export-Package", "*");
+		p.put("Import-Package", "org.apache.commons.collections.map,*");
+		bmaker.setProperties(p);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+		report("testUnreferredImport", bmaker, jar);
+
+	}
+
+	public static void testUnreferredNegatedImport() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+
+		p.put("-classpath", "jar/mina.jar");
+		p.put("Export-Package", "*");
+		p.put("Import-Package", "!org.apache.commons.collections.map,*");
+		bmaker.setProperties(p);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+		report("testUnreferredImport", bmaker, jar);
+
+	}
+
+	public static void testIncludeResourceResourcesOnlyJar2() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+
+		p.put("-classpath", "jar/ro.jar");
+		p.put("Export-Package", "*");
+		p.put("Import-Package", "");
+		bmaker.setProperties(p);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+
+		report("testIncludeResourceResourcesOnlyJar2", bmaker, jar);
+		assertTrue(bmaker.getExports().getByFQN("ro") != null);
+		assertFalse(bmaker.getExports().getByFQN("META-INF") != null);
+
+		assertEquals(3, jar.getResources().size());
+
+	}
+
+	public static void testClasspathFileNotExist() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		String cwd = new File(".").getCanonicalPath();
+		File cp[] = new File[] {
+			IO.getFile("jar/idonotexist.jar")
+		};
+
+		bmaker.setProperties(p);
+		bmaker.setClasspath(cp);
+		bmaker.build();
+		assertTrue(bmaker.check("The JAR is empty", "Missing file on classpath: " + cwd + "/jar/idonotexist.jar"));
+	}
+
+	public static void testExpandWithNegate() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		File cp[] = new File[] {
+			new File("jar/asm.jar")
+		};
+
+		p.put("Export-Package", "!org.objectweb.asm,*");
+		bmaker.setProperties(p);
+		bmaker.setClasspath(cp);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+
+		assertNull(jar.getDirectories().get("org/objectweb/asm"));
+		assertNotNull(jar.getDirectories().get("org/objectweb/asm/signature"));
+		assertEquals(0, bmaker.getWarnings().size());
+		assertEquals(0, bmaker.getErrors().size());
+		assertEquals(3, jar.getResources().size());
+	}
+
+	public static void testIncludeResourceResourcesOnlyJar() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		File cp[] = new File[] {
+			new File("jar/ro.jar")
+		};
+
+		p.put("Export-Package", "*");
+		p.put("Import-Package", "");
+		bmaker.setProperties(p);
+		bmaker.setClasspath(cp);
+		Jar jar = bmaker.build();
+		assertEquals(0, bmaker.getWarnings().size());
+		assertEquals(0, bmaker.getErrors().size());
+		assertEquals(3, jar.getResources().size());
+
+	}
+
+	public static void testIncludeResourceResourcesOnly() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		File cp[] = new File[] {
+			new File("src")
+		};
+
+		p.put("Import-Package", "");
+		p.put("Private-Package", "test.resourcesonly");
+		bmaker.setProperties(p);
+		bmaker.setClasspath(cp);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+		assertEquals(0, bmaker.getWarnings().size());
+		assertEquals(0, bmaker.getErrors().size());
+		assertEquals(4, jar.getResources().size());
+
+	}
+
+	public static void testIncludeResourceFromZipDefault() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.put("Include-Resource", "@jar/easymock.jar");
+		bmaker.setProperties(p);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+		assertEquals(59, jar.getResources().size());
+
+	}
+
+	public static void testIncludeResourceFromZipDeep() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.put("Include-Resource", "@jar/easymock.jar!/**");
+		bmaker.setProperties(p);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+
+		assertEquals(59, jar.getResources().size());
+
+	}
+
+	public static void testIncludeResourceFromZipOneDirectory() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.put("Import-Package", "");
+		p.put("Include-Resource", "@jar/easymock.jar!/org/easymock/**");
+		bmaker.setProperties(p);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+
+		assertEquals(59, jar.getResources().size());
+		assertNotNull(jar.getResource("org/easymock/AbstractMatcher.class"));
+	}
+
+	public static void testIncludeResourceFromZipOneDirectoryOther() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.put(Constants.BUNDLE_CLASSPATH, "OPT-INF/test");
+		p.put("Import-Package", "!*");
+		p.put("-resourceonly", "true");
+		p.put("Include-Resource", "OPT-INF/test=@jar/osgi.jar!/org/osgi/service/event/**");
+		bmaker.setProperties(p);
+		Jar jar = bmaker.build();
+
+		assertTrue(bmaker.check());
+
+		assertEquals(7, jar.getResources().size());
+		assertNotNull(jar.getResource("OPT-INF/test/org/osgi/service/event/EventAdmin.class"));
+	}
+
+	public static void testIncludeResourceFromZipRecurseDirectory() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.put("Import-Package", "!*");
+		p.put("Include-Resource", "@jar/easymock.jar!/org/easymock/**");
+		bmaker.setProperties(p);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+		assertEquals(59, jar.getResources().size());
+	}
+
+	public static void testIncludeLicenseFromZip() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.put("Import-Package", "");
+		p.put("Include-Resource", "@jar/osgi.jar!/LICENSE");
+		bmaker.setProperties(p);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+		assertEquals(1, jar.getResources().size());
+		assertNotNull(jar.getResource("LICENSE"));
+	}
+
+	public static void testEasymock() throws Exception {
+		File cp[] = {
+			new File("jar/easymock.jar")
+		};
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.put("Import-Package", "*");
+		p.put("Export-Package", "*");
+		p.put("Bundle-SymbolicName", "easymock");
+		p.put("Bundle-Version", "2.2");
+		bmaker.setProperties(p);
+		bmaker.setClasspath(cp);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+		jar.getManifest().write(System.err);
+	}
+
+	public static void testSources() throws Exception {
+		Builder bmaker = new Builder();
+		bmaker.addClasspath(new File("bin"));
+		bmaker.setSourcepath(new File[] {
+			new File("src")
+		});
+		bmaker.setProperty("-sources", "true");
+		bmaker.setProperty("Export-Package", "test.activator");
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+		assertEquals(
+				"[test/activator/Activator.class, test/activator/Activator11.class, test/activator/Activator2.class, test/activator/Activator3.class, test/activator/ActivatorPackage.class, test/activator/ActivatorPrivate.class]",
+				new SortedList<String>(jar.getDirectories().get("test/activator").keySet()).toString());
+	}
+
+	public void testVerify() throws Exception {
+		System.err.println("Erroneous bundle: tb1.jar");
+		Jar jar = new Jar("test", getClass().getResourceAsStream("tb1.jar"));
+		Verifier verifier = new Verifier(jar);
+		verifier.verify();
+		assertTrue(verifier.check());
+	}
+
+	public static void report(String title, Analyzer builder, Jar jar) {
+		System.err.println("Directories " + jar.getDirectories().keySet());
+		System.err.println("Warnings    " + builder.getWarnings());
+		System.err.println("Errors      " + builder.getErrors());
+		System.err.println("Exports     " + builder.getExports());
+		System.err.println("Imports     " + builder.getImports());
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/CalltreeTest.java b/biz.aQute.bndlib.tests/src/test/CalltreeTest.java
new file mode 100644
index 0000000..e2b31f7
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/CalltreeTest.java
@@ -0,0 +1,168 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+
+import junit.framework.*;
+import aQute.bnd.make.calltree.*;
+import aQute.bnd.osgi.*;
+
+public class CalltreeTest extends TestCase {
+	public static void testCalltree() throws Exception {
+		StringWriter sw = new StringWriter();
+		PrintWriter pw = new PrintWriter(sw);
+		Builder b = new Builder();
+		b.addClasspath(new File("bin"));
+		b.setProperty("Private-Package", "test");
+		b.build();
+		Collection<Clazz> clazzes = b.getClassspace().values();
+		assertTrue(clazzes.size() > 10);
+
+		CalltreeResource.writeCalltree(pw, clazzes);
+		pw.close();
+		System.err.println(sw.toString());
+	}
+
+	static class Implements implements Resource {
+
+		@Override
+		public String getExtra() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public long lastModified() {
+			// TODO Auto-generated method stub
+			return 0;
+		}
+
+		@Override
+		public InputStream openInputStream() throws IOException {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public void setExtra(String extra) {
+			// TODO Auto-generated method stub
+
+		}
+
+		@Override
+		public void write(OutputStream out) throws IOException {
+			// TODO Auto-generated method stub
+
+		}
+
+		@Override
+		public long size() throws Exception {
+			// TODO Auto-generated method stub
+			return 0;
+		}
+	}
+
+	// public void testCoverage() throws Exception {
+	// Builder b = new Builder();
+	// b.addClasspath(new File("bin"));
+	// b.setProperty("Private-Package", "test");
+	// b.build();
+	// Collection<Clazz> testsuite = b.getClassspace().values();
+	//
+	// Builder c = new Builder();
+	// c.addClasspath(new File("bin"));
+	// c.setProperty("Private-Package", "aQute.bnd.osgi");
+	// c.build();
+	// Collection<Clazz> target = c.getClassspace().values();
+	//
+	// Map<Clazz.MethodDef, List<Clazz.MethodDef>> xref =
+	// Coverage.getCrossRef(testsuite, target);
+	// System.err.println(xref);
+	//
+	// List<Clazz.MethodDef> refs = xref.get(new Clazz.MethodDef(0,
+	// Resource.class.getName(),
+	// "write", "(Ljava/io/OutputStream;)V"));
+	//
+	// assertNotNull("The write(OutputStream) method is implemented by Resource",
+	// xref);
+	//
+	// assertTrue("We must have at least one reference", refs.size() > 0);
+	// // MethodDef md = refs.get(0);
+	// boolean found = false;
+	// for (MethodDef md : refs) {
+	// if (md.clazz.equals("test.CalltreeTest$Implements")) {
+	// found = true;
+	// assertEquals(md.name, "<implements>");
+	// assertEquals(md.descriptor, "()V");
+	// }
+	// }
+	// assertTrue( found);
+	//
+	// assertTrue(xref.containsKey(new Clazz.MethodDef(0,
+	// Analyzer.class.getName(), "analyze",
+	// "()V")));
+	// assertTrue(xref.containsKey(new Clazz.MethodDef(0,
+	// Builder.class.getName(), "build",
+	// "()LaQute/lib/osgi/Jar;")));
+	// assertTrue(xref
+	// .get(
+	// new Clazz.MethodDef(0, "aQute.bnd.osgi.Builder", "build",
+	// "()LaQute/lib/osgi/Jar;")).contains(
+	// new Clazz.MethodDef(0, "test.CalltreeTest", "testCoverage", "()V")));
+	//
+	// Tag tag = CoverageResource.toTag(xref);
+	// PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.err));
+	// tag.print(0, pw);
+	// pw.close();
+	// }
+	//
+	// public void testCatalog() throws Exception {
+	// Builder b = new Builder();
+	// b.addClasspath(new File("jar/osgi.jar"));
+	// b.setProperty("Private-Package", "org.osgi.framework");
+	// b.build();
+	// Collection<Clazz> target = b.getClassspace().values();
+	//
+	// Map<MethodDef, List<MethodDef>> xref = Coverage.getCrossRef(new
+	// ArrayList<Clazz>(), target);
+	//
+	// System.err.println(Processor.join(xref.keySet(), "\n"));
+	//
+	// assertTrue(xref.containsKey(new Clazz.MethodDef(0,
+	// "org.osgi.framework.AdminPermission",
+	// "<init>", "()V")));
+	// assertTrue(xref.containsKey(new Clazz.MethodDef(0,
+	// "org.osgi.framework.AdminPermission",
+	// "<init>", "(Lorg/osgi/framework/Bundle;Ljava/lang/String;)V")));
+	// assertTrue(xref.containsKey(new Clazz.MethodDef(0,
+	// "org.osgi.framework.AdminPermission",
+	// "<init>", "(Ljava/lang/String;Ljava/lang/String;)V")));
+	// assertFalse(xref.containsKey(new Clazz.MethodDef(0,
+	// "org.osgi.framework.AdminPermission$1",
+	// "run", "()Ljava/lang/Object;")));
+	// assertFalse(xref.containsKey(new Clazz.MethodDef(0,
+	// "org.osgi.framework.AdminPermission",
+	// "createName", "(Lorg/osgi/framework/Bundle;)Ljava/lang/String;")));
+	// }
+	//
+	// public void testResource() throws Exception {
+	// Builder b = new Builder();
+	// b.addClasspath(new File("jar/osgi.jar"));
+	// b.setProperty("Private-Package", "org.osgi.framework");
+	// b.build();
+	// Collection<Clazz> target = b.getClassspace().values();
+	//
+	// Resource r = new CoverageResource(target, target);
+	// InputStream in = r.openInputStream();
+	// ByteArrayOutputStream out = new ByteArrayOutputStream();
+	// byte[] buffer = new byte[1000];
+	// int size = in.read(buffer);
+	// while (size > 0) {
+	// out.write(buffer, 0, size);
+	// size = in.read(buffer);
+	// }
+	// out.close();
+	// assertTrue(out.toByteArray().length > 1000);
+	// }
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/ClassParserTest.java b/biz.aQute.bndlib.tests/src/test/ClassParserTest.java
new file mode 100755
index 0000000..5ecf76c
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/ClassParserTest.java
@@ -0,0 +1,355 @@
+package test;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.net.*;
+import java.util.*;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Descriptors.PackageRef;
+import aQute.bnd.service.*;
+import aQute.lib.io.*;
+import aQute.service.reporter.*;
+
+class ConstantValues {
+	public static final boolean	f		= false;
+	public static final boolean	t		= true;
+	public static final byte	bt		= Byte.MAX_VALUE;
+	public static final short	shrt	= Short.MAX_VALUE;
+	public static final char	chr		= Character.MAX_VALUE;
+	public static final int		intgr	= Integer.MAX_VALUE;
+	public static final long	lng		= Long.MAX_VALUE;
+	public static final float	flt		= Float.MAX_VALUE;
+	public static final double	dbl		= Double.MAX_VALUE;
+	public static final String	strng	= "blabla";
+	// Classes somehow are not treated as constants
+	// public static final Class clss = Object.class;
+}
+
+interface WithGenerics<VERYLONGTYPE, X extends Jar> {
+	List< ? super VERYLONGTYPE> baz2();
+
+	List< ? extends Jar>	field	= null;
+
+	WithGenerics<URL,Jar>	x		= null;
+}
+
+class Generics {
+	static Map<ClassParserTest, ? > baz() {
+		return null;
+	}
+
+	static Map<ClassParserTest, ? > baz1() {
+		return null;
+	}
+
+	static Map< ? extends String, ? > baz2() {
+		return null;
+	}
+
+	static List<ClassParserTest> foo() {
+		return null;
+	}
+
+	static Map<ClassParserTest,Clazz> bar() {
+		return null;
+	}
+
+	static WithGenerics<List<Jar>,Jar> xyz() {
+		return null;
+	}
+}
+
+class Implemented implements Plugin {
+	@Override
+	public void setProperties(Map<String,String> map) {}
+
+	@Override
+	public void setReporter(Reporter processor) {}
+}
+
+public class ClassParserTest extends TestCase {
+	static Analyzer	a	= new Analyzer();
+
+	/**
+	 * Test the constant values
+	 * 
+	 * @throws Exception
+	 */
+
+	public void testConstantValues() throws Exception {
+		final Map<String,Object> values = new HashMap<String,Object>();
+		Clazz c = new Clazz(a, "ConstantValues", new FileResource(IO.getFile(new File("").getAbsoluteFile(),
+				"bin/test/ConstantValues.class")));
+		c.parseClassFileWithCollector(new ClassDataCollector() {
+			Clazz.FieldDef	last;
+
+			@Override
+			public void field(Clazz.FieldDef referenced) {
+				last = referenced;
+			}
+
+			@Override
+			public void constant(Object value) {
+				values.put(last.getName(), value);
+			}
+
+		});
+
+		assertEquals(1, values.get("t"));
+		assertEquals(0, values.get("f"));
+		assertEquals((int) Byte.MAX_VALUE, values.get("bt"));
+		assertEquals((int) Short.MAX_VALUE, values.get("shrt"));
+		assertEquals((int) Character.MAX_VALUE, values.get("chr"));
+		assertEquals(Integer.MAX_VALUE, values.get("intgr"));
+		assertEquals(Long.MAX_VALUE, values.get("lng"));
+		assertEquals(Float.MAX_VALUE, values.get("flt"));
+		assertEquals(Double.MAX_VALUE, values.get("dbl"));
+		assertEquals("blabla", values.get("strng"));
+
+		// Classes are special
+		// assertEquals("java.lang.Object", ((Clazz.ClassConstant)
+		// values.get("clss")).getName());
+	}
+
+	public static void testGeneric() throws Exception {
+		print(System.err, WithGenerics.class.getField("field").getGenericType());
+		System.err.println();
+		print(System.err, Class.class);
+		System.err.println();
+		print(System.err, WithGenerics.class);
+		System.err.println();
+	}
+
+	public static void print(Appendable sb, Type t) throws Exception {
+		if (t instanceof ParameterizedType) {
+			ParameterizedType pt = (ParameterizedType) t;
+			Class< ? > c = (Class< ? >) pt.getRawType();
+			sb.append("L");
+			sb.append(c.getCanonicalName().replace('.', '/'));
+			sb.append("<");
+			for (Type arg : pt.getActualTypeArguments()) {
+				print(sb, arg);
+			}
+			sb.append(">");
+			sb.append(";");
+			return;
+		} else if (t instanceof WildcardType) {
+			sb.append("yyyy");
+		} else if (t instanceof GenericArrayType) {
+			sb.append("[" + ((GenericArrayType) t).getGenericComponentType());
+		} else if (t instanceof TypeVariable) {
+			TypeVariable< ? > tv = (TypeVariable< ? >) t;
+			sb.append("T");
+			sb.append(tv.getName());
+			for (Type upper : tv.getBounds()) {
+				if (upper != Object.class) {
+					sb.append(":");
+					print(sb, upper);
+				}
+			}
+			sb.append(";");
+		} else {
+			Class< ? > c = (Class< ? >) t;
+			sb.append("L");
+			sb.append(c.getCanonicalName().replace('.', '/'));
+			if (c instanceof GenericDeclaration) {
+				GenericDeclaration gd = c;
+				if (gd.getTypeParameters().length != 0) {
+					sb.append("<");
+					for (Type arg : gd.getTypeParameters()) {
+						print(sb, arg);
+					}
+					sb.append(">");
+				}
+			}
+			sb.append(";");
+		}
+	}
+
+	/**
+	 * Included an aop alliance class that is not directly referenced.
+	 */
+	public static void testUnacceptableReference() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/nl.fuji.general.jar"));
+		b.addClasspath(new File("jar/spring.jar"));
+		b.setProperty("Export-Package", "nl.fuji.log");
+		b.build();
+		assertFalse(b.getImports().getByFQN("org.aopalliance.aop") != null);
+	}
+
+	// public void testImplemented() throws Exception {
+	// Builder a = new Builder();
+	// a.addClasspath(new File("bin"));
+	// a.setProperty("Private-Package", "test");
+	// a.build();
+	// Clazz c = a.getClassspace().get("test/Implemented.class");
+	// Set<PackageRef> s = Create.set();
+	//
+	// Clazz.getImplementedPackages(s, a, c);
+	// assertTrue(s.contains( a.getPackageRef("aQute/bnd/service")));
+	// }
+
+	public void testWildcards() throws Exception {
+		Clazz c = new Clazz(a, "genericstest", null);
+		c.parseClassFile(getClass().getResourceAsStream("WithGenerics.class"));
+		System.err.println(c.getReferred());
+		assertEquals("size ", 5, c.getReferred().size());
+		assertTrue(c.getReferred().contains(a.getPackageRef("aQute/bnd/osgi")));
+		assertTrue(c.getReferred().contains(a.getPackageRef("java/util")));
+		assertTrue(c.getReferred().contains(a.getPackageRef("java/net")));
+		assertTrue(c.getReferred().contains(a.getPackageRef("java/lang")));
+	}
+
+	public void testGenericsSignature3() throws Exception {
+		Clazz c = new Clazz(a, "genericstest", null);
+		c.parseClassFile(getClass().getResourceAsStream("Generics.class"));
+		assertTrue(c.getReferred().contains(a.getPackageRef("test")));
+		assertTrue(c.getReferred().contains(a.getPackageRef("aQute/bnd/osgi")));
+	}
+
+	public static void testGenericsSignature2() throws Exception {
+		Clazz c = new Clazz(a, "genericstest", new FileResource(new File("src/test/generics.clazz")));
+		c.parseClassFile();
+		assertTrue(c.getReferred().contains(a.getPackageRef("javax/swing/table")));
+		assertTrue(c.getReferred().contains(a.getPackageRef("javax/swing")));
+	}
+
+	public static void testGenericsSignature() throws Exception {
+		Clazz c = new Clazz(a, "genericstest", new FileResource(new File("src/test/generics.clazz")));
+		c.parseClassFile();
+		assertTrue(c.getReferred().contains(a.getPackageRef("javax/swing/table")));
+		assertTrue(c.getReferred().contains(a.getPackageRef("javax/swing")));
+	}
+
+	/**
+	 * @Neil: I'm trying to use bnd to bundleize a library called JQuantLib, but
+	 *        it causes an ArrayIndexOutOfBoundsException while parsing a class.
+	 *        The problem is reproducible and I have even rebuilt the library
+	 *        from source and get the same problem. Here's the stack trace:
+	 *        java.lang.ArrayIndexOutOfBoundsException: -29373 at
+	 *        aQute.bnd.osgi.Clazz.parseClassFile(Clazz.java:262) at
+	 *        aQute.bnd.osgi.Clazz.<init>(Clazz.java:101) at
+	 *        aQute.bnd.osgi.Analyzer.analyzeJar(Analyzer.java:1647) at
+	 *        aQute.bnd.osgi.Analyzer.analyzeBundleClasspath(Analyzer.java:1563)
+	 *        at aQute.bnd.osgi.Analyzer.analyze(Analyzer.java:108) at
+	 *        aQute.bnd.osgi.Builder.analyze(Builder.java:192) at
+	 *        aQute.bnd.osgi.Builder.doConditional(Builder.java:158) at
+	 *        aQute.bnd.osgi.Builder.build(Builder.java:71) at
+	 *        aQute.bnd.main.bnd.doBuild(bnd.java:379) at
+	 *        aQute.bnd.main.bnd.run(bnd.java:130) at
+	 *        aQute.bnd.main.bnd.main(bnd.java:39)
+	 * @throws Exception
+	 */
+
+	public static void testJQuantlib() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("test/jquantlib-0.1.2.jar"));
+		b.setProperty("Export-Package", "*");
+		b.build();
+	}
+
+	public void testMissingPackage2() throws Exception {
+		InputStream in = getClass().getResourceAsStream("JobsService.clazz");
+		assertNotNull(in);
+		Clazz clazz = new Clazz(a, "test", null);
+		clazz.parseClassFile(in);
+		assertTrue(clazz.getReferred().contains(a.getPackageRef("com/linkedin/member2/pub/profile/core/view")));
+	}
+
+	public void testMissingPackage1() throws Exception {
+		InputStream in = getClass().getResourceAsStream("JobsService.clazz");
+		assertNotNull(in);
+		Clazz clazz = new Clazz(a, "test", null);
+		clazz.parseClassFile(in);
+
+		System.err.println(clazz.getReferred());
+		clazz.parseDescriptor("(IILcom/linkedin/member2/pub/profile/core/view/I18nPositionViews;)Lcom/linkedin/leo/cloud/overlap/api/OverlapQuery;", 0);
+		assertTrue(clazz.getReferred().contains(a.getPackageRef("com/linkedin/member2/pub/profile/core/view")));
+	}
+
+	public void testGeneratedClass() throws Exception {
+		InputStream in = getClass().getResourceAsStream("XDbCmpXView.clazz");
+		assertNotNull(in);
+		Clazz clazz = new Clazz(a, "test", null);
+		clazz.parseClassFile(in);
+		clazz.getReferred();
+	}
+
+	public void testParameterAnnotation() throws Exception {
+		InputStream in = getClass().getResourceAsStream("Test2.jclass");
+		assertNotNull(in);
+		Clazz clazz = new Clazz(a, "test", null);
+		clazz.parseClassFile(in);
+		Set<PackageRef> set = clazz.getReferred();
+		assertTrue(set.contains(a.getPackageRef("test")));
+		assertTrue(set.contains(a.getPackageRef("test/annotations")));
+	}
+
+	public static void testLargeClass2() throws IOException {
+		try {
+			URL url = new URL("jar:file:jar/ecj_3.2.2.jar!/org/eclipse/jdt/internal/compiler/parser/Parser.class");
+			InputStream in = url.openStream();
+			assertNotNull(in);
+			Clazz clazz = new Clazz(a, "test", null);
+			clazz.parseClassFile(in);
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+			fail();
+		}
+	}
+
+	/**
+	 * Still problems with the stuff in ecj
+	 */
+	public static void testEcj() throws Exception {
+		Builder builder = new Builder();
+		builder.setClasspath(new File[] {
+			new File("jar/ecj_3.2.2.jar")
+		});
+		builder.setProperty(Analyzer.EXPORT_PACKAGE, "org.eclipse.*");
+		builder.build();
+		System.err.println(builder.getErrors());
+		assertEquals(0, builder.getErrors().size());
+		assertEquals(0, builder.getWarnings().size());
+		System.err.println(builder.getErrors());
+		System.err.println(builder.getWarnings());
+	}
+
+	/**
+	 * This class threw an exception because we were using skip instead of
+	 * skipBytes. skip is not guaranteed to real skip the amount of bytes, not
+	 * even if there are still bytes left. It seems to be able to stop skipping
+	 * if it is at the end of a buffer or so :-( Idiots. The
+	 * DataInputStream.skipBytes works correctly.
+	 * 
+	 * @throws IOException
+	 */
+	public void testLargeClass() throws IOException {
+		InputStream in = getClass().getResourceAsStream("Parser.jclass");
+		assertNotNull(in);
+		try {
+			Clazz clazz = new Clazz(a, "test", null);
+			clazz.parseClassFile(in);
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+			fail();
+		}
+	}
+
+	public void testSimple() throws Exception {
+		InputStream in = getClass().getResourceAsStream("WithAnnotations.jclass");
+		assertNotNull(in);
+		Clazz clazz = new Clazz(a, "test", null);
+		clazz.parseClassFile(in);
+		Set<PackageRef> set = clazz.getReferred();
+		PackageRef test = a.getPackageRef("test");
+		PackageRef testAnnotations = a.getPackageRef("test/annotations");
+		assertTrue(set.contains(test));
+		assertTrue(set.contains(testAnnotations));
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/ClassReferenceTest.java b/biz.aQute.bndlib.tests/src/test/ClassReferenceTest.java
new file mode 100755
index 0000000..781c45e
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/ClassReferenceTest.java
@@ -0,0 +1,45 @@
+package test;
+
+import java.util.*;
+import java.util.jar.*;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+
+public class ClassReferenceTest extends TestCase {
+	class Inner {
+
+	}
+
+	static {
+		System.err.println(Inner.class);
+	}
+
+	/**
+	 * We create a JAR with the test.classreferenc.ClassReference class. This
+	 * class contains a javax.swing.Box.class reference Prior to Java 1.5, this
+	 * was done in a silly way that is handled specially. After 1.5 it is a
+	 * normal reference.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testReference() throws Exception {
+		Properties properties = new Properties();
+		properties.put("-classpath", "compilerversions/compilerversions.jar");
+		String[] packages = {
+				"sun_1_1", "sun_1_6", "eclipse_1_1", "sun_1_2", "sun_1_3", "sun_1_4", "sun_1_5", "sun_jsr14",
+				"eclipse_1_5", "eclipse_1_6", "eclipse_1_2", "eclipse_1_3", "eclipse_1_4", "eclipse_jsr14"
+		};
+		for (int i = 0; i < packages.length; i++) {
+			Builder builder = new Builder();
+			properties.put("Export-Package", packages[i]);
+			builder.setProperties(properties);
+			Jar jar = builder.build();
+			assertTrue(builder.check());
+			Manifest manifest = jar.getManifest();
+			String imports = manifest.getMainAttributes().getValue("Import-Package");
+			assertTrue("Package " + packages[i] + "contains swing ref", imports.indexOf("javax.swing") >= 0);
+			assertFalse("Package " + packages[i] + "should not contain ClassRef", imports.indexOf("ClassRef") >= 0);
+		}
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/ClasspathTest.java b/biz.aQute.bndlib.tests/src/test/ClasspathTest.java
new file mode 100755
index 0000000..b900234
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/ClasspathTest.java
@@ -0,0 +1,72 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+
+public class ClasspathTest extends TestCase {
+
+	/**
+	 * Test if we can refer to the jars on the classpath by their file name (
+	 * ignoring the path)
+	 * 
+	 * @throws Exception
+	 */
+	public static void testBundleClasspath() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("Include-Resource", "bin=bin");
+		b.setProperty("Bundle-Classpath", "bin");
+
+		Jar jar = b.build();
+		assertNotNull(jar.getResource("bin/test/activator/Activator.class")); // from
+		// test.jar
+	}
+
+	/**
+	 * Test if we can refer to the jars on the classpath by their file name (
+	 * ignoring the path)
+	 * 
+	 * @throws Exception
+	 */
+	public static void testFindJarOnClasspath() throws Exception {
+		Properties p = new Properties();
+		p.put("Include-Resource", "tb1.jar, @test.jar");
+
+		Builder b = new Builder();
+		b.setClasspath(new String[] {
+				"src", "src/test/test.jar", "src/test/tb1.jar"
+		});
+		b.setProperties(p);
+		Jar jar = b.build();
+		assertNotNull(jar.getResource("aQute/lib/aim/AIM.class")); // from
+																	// test.jar
+		assertNotNull(jar.getResource("tb1.jar"));
+	}
+
+	/**
+	 * Test if we can use URLs on the classpath
+	 * 
+	 * @throws Exception
+	 */
+	public static void testSimple() throws Exception {
+		Properties p = new Properties();
+		p.put("-classpath", new File("jar/osgi.jar").toURI().toURL().toString());
+		p.put("Export-Package", "org.osgi.service.event");
+		p.put("Private-Package", "test.refer");
+
+		Builder b = new Builder();
+		b.setClasspath(new String[] {
+			"bin"
+		});
+		b.setProperties(p);
+		Jar jar = b.build();
+		Manifest m = jar.getManifest();
+		String importPackage = m.getMainAttributes().getValue("Import-Package");
+		assertTrue(importPackage.contains("org.osgi.framework;version=\"[1.3,2)\""));
+		assertTrue(importPackage.contains("org.osgi.service.event;version=\"[1.0,2)\""));
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/ClazzTest.java b/biz.aQute.bndlib.tests/src/test/ClazzTest.java
new file mode 100644
index 0000000..be0f6fc
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/ClazzTest.java
@@ -0,0 +1,68 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Descriptors.PackageRef;
+
+public class ClazzTest extends TestCase {
+
+	/**
+	 * Complaint from Groovy that the dynamic instruction fails.
+	 * 
+	 * <pre>
+	 * [bndwrap] java.lang.ArrayIndexOutOfBoundsException: 15
+	 * [bndwrap]     at aQute.bnd.osgi.Clazz.parseClassFile(Clazz.java:387)
+	 * [bndwrap]     at aQute.bnd.osgi.Clazz.parseClassFile(Clazz.java:308)
+	 * [bndwrap]     at aQute.bnd.osgi.Clazz.parseClassFileWithCollector(Clazz.java:297)
+	 * [bndwrap]     at aQute.bnd.osgi.Clazz.parseClassFile(Clazz.java:286)
+	 * [bndwrap]     at aQute.bnd.osgi.Analyzer.analyzeJar(Analyzer.java:1489)
+	 * [bndwrap]     at aQute.bnd.osgi.Analyzer.analyzeBundleClasspath(Analyzer.java:1387)
+	 * [bndwrap] Invalid class file: groovy/inspect/swingui/AstNodeToScriptVisitor.class
+	 * [bndwrap] Exception: 15
+	 * </pre>
+	 */
+	public static void testDynamicInstr() throws Exception {
+		Analyzer a = new Analyzer();
+		Clazz c = new Clazz(a, "", null);
+		c.parseClassFile(new FileInputStream("jar/AstNodeToScriptVisitor.jclass"), new ClassDataCollector() {});
+		Set<PackageRef> referred = c.getReferred();
+		Descriptors d = new Descriptors();
+		assertFalse(referred.contains(d.getPackageRef("")));
+		System.out.println(referred);
+	}
+
+	/**
+	 * Check if the class is not picking up false references when the
+	 * CLass.forName name is constructed. The DeploymentAdminPermission.1.jclass
+	 * turned out to use Class.forName with a name that was prefixed with a
+	 * package from a property. bnd discovered the suffix
+	 * (.DeploymentAdminPermission) but this ended up in the default package. So
+	 * now the clazz parser tests that the name guessed for Class.forName must
+	 * actually resemble a class name.
+	 */
+
+	public static void testClassForNameFalsePickup() throws Exception {
+		Analyzer a = new Analyzer();
+		Clazz c = new Clazz(a, "", null);
+		c.parseClassFile(new FileInputStream("jar/DeploymentAdminPermission.1.jclass"), new ClassDataCollector() {});
+		Set<PackageRef> referred = c.getReferred();
+		Descriptors d = new Descriptors();
+		assertFalse(referred.contains(d.getPackageRef("")));
+		System.out.println(referred);
+	}
+
+	/**
+	 * Test the uncamel
+	 */
+
+	public static void testUncamel() throws Exception {
+		assertEquals("New", Clazz.unCamel("_new"));
+		assertEquals("An XMLMessage", Clazz.unCamel("anXMLMessage"));
+		assertEquals("A message", Clazz.unCamel("aMessage"));
+		assertEquals("URL", Clazz.unCamel("URL"));
+		assertEquals("A nice party", Clazz.unCamel("aNiceParty"));
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/CompareTest.java b/biz.aQute.bndlib.tests/src/test/CompareTest.java
new file mode 100644
index 0000000..5c50e85
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/CompareTest.java
@@ -0,0 +1,128 @@
+package test;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import junit.framework.*;
+
+public class CompareTest<O extends Serializable> extends TestCase {
+
+	interface I<T> {}
+
+	class B {
+		class C<X extends O> {}
+	}
+
+	class A0 {}
+
+	// Declarations
+	class A1<T> { //
+	}
+
+	class A2<T extends Serializable> { //
+	}
+
+	class A3<T extends Exception & Serializable> { //
+	}
+
+	public static String foo0() {
+		return null;
+	}
+
+	public static <T> T foo1() {
+		return null;
+	}
+
+	public static <T extends Serializable> T foo2() {
+		return null;
+	}
+
+	public static <T extends Exception & I<String>> T foo3() {
+		return null;
+	}
+
+	@SuppressWarnings("static-method")
+	public <T extends O> T foo4() {
+		return null;
+	}
+
+	public void testGenericDeclaration() throws Exception {
+		assertTrue(A0.class.getTypeParameters().length == 0);
+
+		assertTrue(A1.class.getTypeParameters().length == 1);
+		assertEquals("T", A1.class.getTypeParameters()[0].getName());
+		assertEquals(1, A1.class.getTypeParameters()[0].getBounds().length);
+		assertEquals(Object.class, A1.class.getTypeParameters()[0].getBounds()[0]);
+
+		assertTrue(A2.class.getTypeParameters().length == 1);
+		assertEquals("T", A2.class.getTypeParameters()[0].getName());
+		assertEquals(1, A2.class.getTypeParameters()[0].getBounds().length);
+		assertEquals(Serializable.class, A2.class.getTypeParameters()[0].getBounds()[0]);
+
+		assertTrue(A3.class.getTypeParameters().length == 1);
+		assertEquals("T", A3.class.getTypeParameters()[0].getName());
+		assertEquals(2, A3.class.getTypeParameters()[0].getBounds().length);
+		assertEquals(Exception.class, A3.class.getTypeParameters()[0].getBounds()[0]);
+		assertEquals(Serializable.class, A3.class.getTypeParameters()[0].getBounds()[1]);
+
+		Method m = getClass().getMethod("foo0");
+		assertEquals(0, m.getTypeParameters().length);
+
+		m = getClass().getMethod("foo1");
+		assertEquals(1, m.getTypeParameters().length);
+		assertEquals("T", m.getTypeParameters()[0].getName());
+		assertEquals(1, m.getTypeParameters()[0].getBounds().length);
+		assertEquals(Object.class, m.getTypeParameters()[0].getBounds()[0]);
+
+		m = getClass().getMethod("foo3");
+		assertEquals(1, m.getTypeParameters().length);
+		assertEquals("T", m.getTypeParameters()[0].getName());
+		assertEquals(2, m.getTypeParameters()[0].getBounds().length);
+		assertEquals(Exception.class, m.getTypeParameters()[0].getBounds()[0]);
+
+		m = getClass().getMethod("foo4");
+		assertEquals(1, m.getTypeParameters().length);
+		assertEquals("T", m.getTypeParameters()[0].getName());
+		assertEquals(1, m.getTypeParameters()[0].getBounds().length);
+		assertTrue(m.getTypeParameters()[0].getBounds()[0] instanceof TypeVariable);
+		assertEquals(getClass(), ((TypeVariable< ? >) m.getTypeParameters()[0].getBounds()[0]).getGenericDeclaration());
+
+	}
+
+	public A1<Collection<String>[]>	a1;
+
+	@SuppressWarnings("static-method")
+	<Y, X extends A1<Y>> A1< ? extends X> bar() {
+		return null;
+	}
+
+	public static void testSimple() throws IOException {
+
+		// Scope root = new Scope(Access.PUBLIC, Kind.ROOT, ".");
+		// RuntimeSignatureBuilder pc = new RuntimeSignatureBuilder(root);
+		// pc.add(CompareTest.class);
+		// pc.add(A.class);
+		// pc.add(A.B.class);
+		//
+		// A a = new A<String, String, String, String, String>();
+		//
+		// pc.add(a.bar().getClass());
+		// pc.add(a.bar().foo().getClass());
+		//
+		// // ParseSignatureBuilder pb = new ParseSignatureBuilder(root);
+		// // pb.parse(new FileInputStream("bin/test/CompareTest$A$B$1.class"));
+		// // pb.parse(new FileInputStream("bin/test/CompareTest$A$1.class"));
+		// // pb.parse(new FileInputStream("bin/test/CompareTest$Z.class"));
+		//
+		// root.cleanRoot();
+		// PrintWriter pw = new PrintWriter(System.err);
+		// root.report(pw, 0);
+		// pw.flush();
+		//
+		// root.prune(EnumSet.of(Access.PUBLIC, Access.PROTECTED));
+		// root.report(pw, 0);
+		// pw.flush();
+
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/ComponentTests.java b/biz.aQute.bndlib.tests/src/test/ComponentTests.java
new file mode 100644
index 0000000..2921390
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/ComponentTests.java
@@ -0,0 +1,18 @@
+package test;
+
+import junit.framework.*;
+import test.component.*;
+
+public class ComponentTests {
+
+	public static Test suite() {
+		TestSuite suite = new TestSuite(ComponentTests.class.getName());
+		// $JUnit-BEGIN$
+		suite.addTestSuite(DSAnnotationTest.class);
+		suite.addTestSuite(BNDAnnotationTest.class);
+		suite.addTestSuite(ComponentTest.class);
+		// $JUnit-END$
+		return suite;
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/CorruptManifest.java b/biz.aQute.bndlib.tests/src/test/CorruptManifest.java
new file mode 100755
index 0000000..1044683
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/CorruptManifest.java
@@ -0,0 +1,49 @@
+package test;
+
+import java.io.*;
+import java.util.jar.*;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+
+public class CorruptManifest extends TestCase {
+	static String	ltext	= "bla bla \nbla bla bla bla \nbla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla  [...]
+
+	public static void testCorruptJar() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("NL1", "\n");
+		b.setProperty("NL2", "\r\n");
+		b.setProperty("NL3", ".");
+		b.setProperty("NL4", ".\n.\n");
+		b.setProperty("NL5", ltext);
+		b.setProperty("Export-Package", "*");
+		b.setClasspath(new File[] {
+			new File("jar/asm.jar")
+		});
+		Jar jar = b.build();
+		Manifest manifest = jar.getManifest();
+		jar.writeManifest(System.err);
+
+		Attributes main = manifest.getMainAttributes();
+		assertNull(main.getValue("NL1"));
+		assertNull(main.getValue("NL2"));
+		assertEquals(".", main.getValue("NL3"));
+		assertEquals(".\n.\n", main.getValue("NL4"));
+		assertEquals(ltext, main.getValue("NL5"));
+
+		ByteArrayOutputStream bout = new ByteArrayOutputStream();
+		jar.writeManifest(bout);
+		bout.flush();
+		System.err.println("-----");
+		System.err.write(bout.toByteArray());
+		System.err.println("-----");
+		ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+		manifest = new Manifest(bin);
+
+		main = manifest.getMainAttributes();
+		assertNull(main.getValue("NL1"));
+		assertNull(main.getValue("NL2"));
+		assertEquals(".", main.getValue("NL3"));
+		assertEquals("..", main.getValue("NL4"));
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/DescriptorsTest.java b/biz.aQute.bndlib.tests/src/test/DescriptorsTest.java
new file mode 100644
index 0000000..4743889
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/DescriptorsTest.java
@@ -0,0 +1,23 @@
+package test;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Descriptors.PackageRef;
+import aQute.bnd.osgi.Descriptors.TypeRef;
+
+public class DescriptorsTest extends TestCase {
+
+	public static void testReferences() {
+		Descriptors d = new Descriptors();
+		TypeRef r = d.getTypeRef("[B");
+		assertNotNull(r);
+		assertEquals("byte[]", r.getFQN());
+		assertNotNull(r.getPackageRef());
+		assertEquals(".", r.getPackageRef().getFQN());
+
+		PackageRef a = d.getPackageRef("a.b.c");
+		PackageRef b = d.getPackageRef("a/b/c");
+		assertTrue(a == b);
+
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/DownloadBlockerTest.java b/biz.aQute.bndlib.tests/src/test/DownloadBlockerTest.java
new file mode 100644
index 0000000..f417f77
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/DownloadBlockerTest.java
@@ -0,0 +1,63 @@
+package test;
+
+import java.io.*;
+
+import junit.framework.*;
+import aQute.bnd.build.*;
+
+public class DownloadBlockerTest extends TestCase {
+
+	public void testSimple() throws Exception {
+		{
+			DownloadBlocker db = new DownloadBlocker(null);
+			assertEquals(DownloadBlocker.Stage.INIT, db.getStage());
+			db.failure(new File(""), "ouch");
+			assertEquals(DownloadBlocker.Stage.FAILURE, db.getStage());
+		}
+		{
+			DownloadBlocker db = new DownloadBlocker(null);
+			db.success(new File(""));
+			assertEquals(DownloadBlocker.Stage.SUCCESS, db.getStage());
+		}
+		{
+			final DownloadBlocker dbb = new DownloadBlocker(null);
+
+			Thread t = new Thread() {
+				@Override
+				public void run() {
+					try {
+						Thread.sleep(1000);
+						dbb.failure(new File(""), "Ouch");
+					}
+					catch (Exception e) {
+						e.printStackTrace();
+					}
+				}
+			};
+			t.start();
+			assertEquals(DownloadBlocker.Stage.INIT, dbb.getStage());
+			assertEquals("Ouch", dbb.getReason());
+			assertEquals(DownloadBlocker.Stage.FAILURE, dbb.getStage());
+		}
+		{
+			final DownloadBlocker dbb = new DownloadBlocker(null);
+
+			Thread t = new Thread() {
+				@Override
+				public void run() {
+					try {
+						Thread.sleep(1000);
+						dbb.success(new File(""));
+					}
+					catch (Exception e) {
+						e.printStackTrace();
+					}
+				}
+			};
+			t.start();
+			assertEquals(DownloadBlocker.Stage.INIT, dbb.getStage());
+			assertNull(dbb.getReason());
+			assertEquals(DownloadBlocker.Stage.SUCCESS, dbb.getStage());
+		}
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/ExportHeaderTest.java b/biz.aQute.bndlib.tests/src/test/ExportHeaderTest.java
new file mode 100644
index 0000000..7fd5f7b
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/ExportHeaderTest.java
@@ -0,0 +1,71 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+
+import junit.framework.*;
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
+
+public class ExportHeaderTest extends TestCase {
+
+	/**
+	 * If you import a range then the maven guys can have the silly -SNAPSHOT in
+	 * the version. This tests if ranges are correcly cleaned up.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testImportHeaderWithMessedUpRange() throws Exception {
+		Builder builder = new Builder();
+		Jar bin = new Jar(new File("bin"));
+		builder.setClasspath(new Jar[] {
+			bin
+		});
+		Properties p = new Properties();
+		p.setProperty("Private-Package", "test.packageinfo.ref");
+		p.setProperty("Import-Package", "test.packageinfo;version=\"[1.1.1-SNAPSHOT,1.1.1-SNAPSHOT]");
+		builder.setProperties(p);
+		Jar jar = builder.build();
+		Manifest manifest = jar.getManifest();
+
+		String imph = manifest.getMainAttributes().getValue("Import-Package");
+		assertEquals("test.packageinfo;version=\"[1.1.1.SNAPSHOT,1.1.1.SNAPSHOT]\"", imph);
+	}
+
+	public static void testPickupExportVersion() throws Exception {
+		Builder builder = new Builder();
+		Jar bin = new Jar(new File("bin"));
+		builder.setClasspath(new Jar[] {
+			bin
+		});
+		Properties p = new Properties();
+		p.setProperty("Private-Package", "test.packageinfo.ref");
+		builder.setProperties(p);
+		Jar jar = builder.build();
+		Manifest manifest = jar.getManifest();
+
+		String imph = manifest.getMainAttributes().getValue("Import-Package");
+		assertEquals("test.packageinfo;version=\"[1.0,2)\"", imph);
+	}
+
+	public static void testExportVersionWithPackageInfo() throws Exception {
+		Builder builder = new Builder();
+		Jar bin = new Jar(new File("bin"));
+		builder.setClasspath(new Jar[] {
+			bin
+		});
+		Properties p = new Properties();
+		p.setProperty("Export-Package", "test.packageinfo");
+		builder.setProperties(p);
+
+		Jar jar = builder.build();
+		Manifest manifest = jar.getManifest();
+
+		String exph = manifest.getMainAttributes().getValue("Export-Package");
+		Map<String,String> exports = OSGiHeader.parseHeader(exph).get("test.packageinfo");
+		assertEquals("1.0.0.SNAPSHOT", exports.get(Constants.VERSION_ATTRIBUTE));
+		assertEquals("1.2.3", exports.get("Implementation-Version"));
+		assertEquals("", exports.get("Implementation-Title"));
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/FileRepoTests.java b/biz.aQute.bndlib.tests/src/test/FileRepoTests.java
new file mode 100644
index 0000000..436d7da
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/FileRepoTests.java
@@ -0,0 +1,14 @@
+package test;
+
+import junit.framework.*;
+
+public class FileRepoTests {
+
+	public static Test suite() {
+		TestSuite suite = new TestSuite(FileRepoTests.class.getName());
+		// $JUnit-BEGIN$
+		suite.addTestSuite(test.deployer.FileRepoTest.class);
+		// $JUnit-END$
+		return suite;
+	}
+}
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/src/test/FilterTest.java b/biz.aQute.bndlib.tests/src/test/FilterTest.java
new file mode 100644
index 0000000..4ec9c67
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/FilterTest.java
@@ -0,0 +1,12 @@
+package test;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+
+public class FilterTest extends TestCase {
+
+	public static void testFilter() throws Exception {
+		String s = Verifier.validateFilter("(org.osgi.framework.windowing.system=xyz)");
+		assertNull(s);
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/IncludeHeaderTest.java b/biz.aQute.bndlib.tests/src/test/IncludeHeaderTest.java
new file mode 100755
index 0000000..a2d77b7
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/IncludeHeaderTest.java
@@ -0,0 +1,142 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+
+public class IncludeHeaderTest extends TestCase {
+
+	// public void testMavenInclude() throws Exception {
+	// String b = "pom.modelVersion=b\n";
+	// File bb = new File("b.props");
+	// write(bb, b );
+	// bb.deleteOnExit();
+	//
+	// Analyzer analyzer = new Analyzer();
+	// Properties x = new Properties();
+	// x.put("pom.modelVersion", "set");
+	// x.put("pom.scope.test", "set");
+	// x.put("-include", "~maven/pom.xml,b.props");
+	// analyzer.setProperties(x);
+	// System.err.println(analyzer.getErrors());
+	// System.err.println(analyzer.getWarnings());
+	// assertEquals("b", analyzer.getProperty("pom.modelVersion")); // from b
+	// assertEquals("org.apache.felix.metatype",
+	// analyzer.getProperty("pom.artifactId")); // from pom
+	// assertEquals("org.apache.felix", analyzer.getProperty("pom.groupId")); //
+	// from parent pom
+	// assertEquals("set", analyzer.getProperty("pom.scope.test")); // Set
+	// }
+
+	public static void testTopBottom() throws Exception {
+		Analyzer analyzer = new Analyzer();
+		analyzer.setProperties(new File("src/test/include.bnd/top.bnd"));
+		assertEquals("0.0.257", analyzer.getProperty("Bundle-Version"));
+	}
+
+	public static void testPrecedence() throws Exception {
+		File base = new File("src/test");
+		String a = "a=a.props\n";
+		String b = "a=b.props\n";
+		File aa = new File(base, "a.props");
+		File bb = new File(base, "b.props");
+		write(aa, a);
+		write(bb, b);
+
+		Analyzer analyzer = new Analyzer();
+		analyzer.setBase(base);
+		Properties x = new Properties();
+		x.put("a", "x");
+		x.put("-include", "a.props, b.props");
+		analyzer.setProperties(x);
+		assertEquals("b.props", analyzer.getProperty("a")); // from org
+
+		analyzer = new Analyzer();
+		analyzer.setBase(base);
+		x = new Properties();
+		x.put("a", "x");
+		x.put("-include", "~a.props, b.props");
+		analyzer.setProperties(x);
+		assertEquals("b.props", analyzer.getProperty("a")); // from org
+
+		analyzer = new Analyzer();
+		analyzer.setBase(base);
+		x = new Properties();
+		x.put("a", "x");
+		x.put("-include", "a.props, ~b.props");
+		analyzer.setProperties(x);
+		assertEquals("a.props", analyzer.getProperty("a")); // from org
+
+		analyzer = new Analyzer();
+		analyzer.setBase(base);
+		x = new Properties();
+		x.put("a", "x");
+		x.put("-include", "~a.props, ~b.props");
+		analyzer.setProperties(x);
+		assertEquals("x", analyzer.getProperty("a")); // from org
+
+		aa.delete();
+		bb.delete();
+	}
+
+	private static void write(File file, String b) throws Exception {
+		FileOutputStream out = new FileOutputStream(file);
+		out.write(b.getBytes());
+		out.close();
+	}
+
+	public static void testAbsentIncludes() throws IOException {
+		Analyzer analyzer = new Analyzer();
+		analyzer.setBase(new File("src/test"));
+		Properties p = new Properties();
+		p.put("-include", "-iamnotthere.txt");
+		analyzer.setProperties(p);
+		System.err.println(analyzer.getErrors());
+		assertEquals(0, analyzer.getErrors().size());
+	}
+
+	public static void testIncludeWithProperty() throws IOException {
+		File home = new File(System.getProperty("user.home"));
+		File include = new File(home, "includeheadertest.txt");
+		try {
+			FileOutputStream fw = new FileOutputStream(include);
+			fw.write("IncludeHeaderTest: yes\n\r".getBytes());
+			fw.write("a: 2\n\r".getBytes());
+			fw.write("b: ${a}\n\r".getBytes());
+			fw.close();
+			Analyzer analyzer = new Analyzer();
+			analyzer.setBase(new File("src/test"));
+			Properties p = new Properties();
+			p.put("a", "1");
+			p.put("-include", "-iamnotthere.txt, ${user.home}/includeheadertest.txt");
+			analyzer.setProperties(p);
+			String value = analyzer.getProperty("IncludeHeaderTest");
+			assertEquals("yes", value);
+			assertEquals("2", analyzer.getProperty("a"));
+			assertEquals("2", analyzer.getProperty("b"));
+			assertEquals(0, analyzer.getErrors().size());
+		}
+		finally {
+			include.delete();
+		}
+	}
+
+	public static void testIncludeHeader() throws IOException {
+		Analyzer analyzer = new Analyzer();
+		analyzer.setBase(new File("src/test"));
+		Properties p = new Properties();
+		p.put("a", "1");
+		p.put("-include", "includeheadertest.mf, includeheadertest.prop");
+		analyzer.setProperties(p);
+		System.err.println(analyzer.getProperties());
+		assertEquals("1", analyzer.getProperty("a"));
+		assertEquals("end", analyzer.getProperty("last-props"));
+		assertEquals("end", analyzer.getProperty("last-manifest"));
+		assertEquals("abcd", analyzer.getProperty("manifest"));
+		assertEquals("abcd", analyzer.getProperty("props"));
+		assertEquals("1", analyzer.getProperty("test"));
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/InlineTest.java b/biz.aQute.bndlib.tests/src/test/InlineTest.java
new file mode 100644
index 0000000..6b438d2
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/InlineTest.java
@@ -0,0 +1,24 @@
+package test;
+
+import java.util.jar.*;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+
+public class InlineTest extends TestCase {
+	public static void testSimple() throws Exception {
+		Builder builder = new Builder();
+		builder.setProperty("Include-Resource", "@jar/osgi.jar");
+		Jar jar = builder.build();
+		Manifest manifest = jar.getManifest();
+
+		// See if the version is the default and not copied from the inline
+		// bundle.
+		String version = manifest.getMainAttributes().getValue("Bundle-Version");
+		assertEquals("0", version);
+
+		// Check if we got some relevant directories
+		assertTrue(jar.getDirectories().containsKey("org/osgi/framework"));
+		assertTrue(jar.getDirectories().containsKey("org/osgi/util/tracker"));
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/InstructionTest.java b/biz.aQute.bndlib.tests/src/test/InstructionTest.java
new file mode 100644
index 0000000..a141b19
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/InstructionTest.java
@@ -0,0 +1,58 @@
+package test;
+
+import java.util.*;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+
+public class InstructionTest extends TestCase {
+
+	public static void testSelect() {
+		assertEquals(Arrays.asList("a", "c"), new Instructions("b").reject(Arrays.asList("a", "b", "c")));
+		assertEquals(Arrays.asList("a", "c"), new Instructions("a,c").select(Arrays.asList("a", "b", "c"), false));
+		assertEquals(Arrays.asList("a", "c"), new Instructions("!b,*").select(Arrays.asList("a", "b", "c"), false));
+	}
+
+	public static void testWildcard() {
+		assertTrue(new Instruction("a|b").matches("a"));
+		assertTrue(new Instruction("a|b").matches("b"));
+		assertTrue(new Instruction("com.foo.*").matches("com.foo"));
+		assertTrue(new Instruction("com.foo.*").matches("com.foo.bar"));
+		assertTrue(new Instruction("com.foo.*").matches("com.foo.bar.baz"));
+
+		assertTrue(new Instruction("!com.foo.*").matches("com.foo"));
+		assertTrue(new Instruction("!com.foo.*").matches("com.foo.bar"));
+		assertTrue(new Instruction("!com.foo.*").matches("com.foo.bar.baz"));
+
+		assertTrue(new Instruction("com.foo.*~").matches("com.foo"));
+		assertTrue(new Instruction("com.foo.*~").matches("com.foo.bar"));
+		assertTrue(new Instruction("com.foo.*~").matches("com.foo.bar.baz"));
+
+		assertTrue(new Instruction("!com.foo.*~").matches("com.foo"));
+		assertTrue(new Instruction("!com.foo.*~").matches("com.foo.bar"));
+		assertTrue(new Instruction("!com.foo.*~").matches("com.foo.bar.baz"));
+
+		assertTrue(new Instruction("com.foo.*~").isDuplicate());
+		assertTrue(new Instruction("!com.foo.*~").isDuplicate());
+		assertTrue(new Instruction("!com.foo.*~").isNegated());
+
+	}
+
+	public static void testLiteral() {
+		assertTrue(new Instruction("literal").isLiteral());
+		assertTrue(new Instruction("literal").matches("literal"));
+		assertTrue(new Instruction("!literal").matches("literal"));
+		assertTrue(new Instruction("=literal").matches("literal"));
+		assertTrue(new Instruction("literal~").matches("literal"));
+		assertTrue(new Instruction("!literal~").matches("literal"));
+		assertTrue(new Instruction("=literal~").matches("literal"));
+		assertFalse(new Instruction("=literal").matches(""));
+		assertFalse(new Instruction("!literal").matches(""));
+		assertFalse(new Instruction("literal").matches(""));
+		assertTrue(new Instruction("literal").isLiteral());
+		assertTrue(new Instruction("=literal").isLiteral());
+		assertTrue(new Instruction("!literal").isNegated());
+		assertTrue(new Instruction("!=literal").isNegated());
+		assertTrue(new Instruction("=*********").isLiteral());
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/JarSignerTest.java b/biz.aQute.bndlib.tests/src/test/JarSignerTest.java
new file mode 100644
index 0000000..2f9884a
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/JarSignerTest.java
@@ -0,0 +1,90 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.signing.*;
+import aQute.libg.generics.*;
+
+public class JarSignerTest extends TestCase {
+
+	public static void testNoManifest() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("-sign", "test");
+		b.setProperty(Constants.PLUGIN, JartoolSigner.class.getName()
+				+ ";keystore=test/keystore;keypass=testtest;storepass=testtest;sigfile=test");
+		b.setProperty("-nomanifest", "true");
+		b.setProperty("-resourceonly", "true");
+		b.setProperty("Include-Resource", "WEB-INF/classes=@jar/osgi.jar");
+
+		Jar jar = b.build();
+		File tmp = new File("xyztmp.jar");
+		tmp.deleteOnExit();
+
+		jar.write(tmp);
+
+		Jar jar2 = new Jar(tmp);
+		Manifest manifest = jar2.getManifest();
+		assertEquals("1.0", manifest.getMainAttributes().getValue("Manifest-Version"));
+		assertNotNull(manifest.getAttributes("WEB-INF/classes/org/osgi/framework/BundleContext.class"));
+	}
+
+	public static void testError() throws Exception {
+		JartoolSigner signer = new JartoolSigner();
+		Map<String,String> properties = Create.map();
+		properties.put("keystore", "test/keystore");
+		properties.put("keypass", "testtest");
+		properties.put("storepass", "notvalid");
+		signer.setProperties(properties);
+
+		Jar jar = new Jar(new File("test/test.jar"));
+		Builder b = new Builder();
+		b.setTrace(true);
+		b.setJar(jar);
+		signer.sign(b, "test");
+		System.err.printf(Processor.join(b.getErrors(), "%n") + "%n");
+		assertEquals(1, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+	}
+
+	public static void testSimple() throws Exception {
+		JartoolSigner signer = new JartoolSigner();
+		Map<String,String> properties = Create.map();
+		properties.put("keystore", "test/keystore");
+		properties.put("keypass", "testtest");
+		properties.put("storepass", "testtest");
+		properties.put("sigFile", "test");
+		properties.put("digestalg", "SHA1");
+		signer.setProperties(properties);
+
+		Jar jar = new Jar(new File("test/test.jar"));
+		Set<String> names = new HashSet<String>(jar.getResources().keySet());
+		names.remove("META-INF/MANIFEST.MF");
+		Builder b = new Builder();
+		b.setJar(jar);
+		signer.sign(b, "test");
+		System.err.printf(Processor.join(b.getErrors(), "%n") + "%n");
+		System.err.printf(Processor.join(b.getWarnings(), "%n") + "%n");
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+		assertNotNull(jar.getResource("META-INF/TEST.SF"));
+		Manifest m = jar.getManifest();
+
+		// Should have added 2 new resources: TEST.SF and TEST.DSA/RSA
+		assertEquals(names.size(), b.getJar().getResources().size() - 3);
+
+		Attributes a = m.getAttributes("aQute/rendezvous/DNS.class");
+		assertNotNull(a);
+		assertEquals("G0/1CIZlB4eIVyY8tU/ZfMCqZm4=", a.getValue("SHA1-Digest"));
+
+		// Check if all resources are named
+		for (String name : names) {
+			System.err.println("name: " + name);
+			assertNotNull(m.getAttributes(name));
+		}
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/JarTest.java b/biz.aQute.bndlib.tests/src/test/JarTest.java
new file mode 100755
index 0000000..e74a8d9
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/JarTest.java
@@ -0,0 +1,68 @@
+package test;
+
+import java.io.*;
+import java.util.jar.*;
+import java.util.zip.*;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+
+public class JarTest extends TestCase {
+
+	public static void testNoManifest() throws Exception {
+		Jar jar = new Jar("dot");
+		jar.setManifest(new Manifest());
+		jar.setDoNotTouchManifest();
+		jar.putResource("a/b", new FileResource(new File("test/bnd.jar")));
+
+		ByteArrayOutputStream bout = new ByteArrayOutputStream();
+		jar.write(bout);
+
+		Jar jin = new Jar("dotin", new ByteArrayInputStream(bout.toByteArray()));
+		Resource m = jin.getResource("META-INF/MANIFEST.MF");
+		assertNull(m);
+		Resource r = jin.getResource("a/b");
+		assertNotNull(r);
+	}
+
+	public static void testManualManifest() throws Exception {
+		Jar jar = new Jar("dot");
+		jar.setManifest(new Manifest());
+		jar.setDoNotTouchManifest();
+		jar.putResource("a/b", new FileResource(new File("test/bnd.jar")));
+		jar.putResource("META-INF/MANIFEST.MF", new EmbeddedResource("Manifest-Version: 1\r\nX: 1\r\n\r\n".getBytes(),
+				0));
+
+		ByteArrayOutputStream bout = new ByteArrayOutputStream();
+		jar.write(bout);
+
+		JarInputStream jin = new JarInputStream(new ByteArrayInputStream(bout.toByteArray()));
+		Manifest m = jin.getManifest();
+		assertNotNull(m);
+		assertEquals("1", m.getMainAttributes().getValue("X"));
+		jin.close();
+	}
+
+	public static void testSimple() throws ZipException, IOException {
+		File file = new File("jar/asm.jar");
+		Jar jar = new Jar("asm.jar", file);
+		long jarTime = jar.lastModified();
+		long fileTime = file.lastModified();
+		long now = System.currentTimeMillis();
+
+		// Sanity check
+		assertTrue(jarTime < fileTime);
+		assertTrue(fileTime <= now);
+
+		// TODO see if we can improve this test case
+		// // We should use the highest modification time
+		// // of the files in the JAR not the JAR (though
+		// // this is a backup if time is not set in the jar)
+		// assertEquals(1144412850000L, jarTime);
+
+		// Now add the file and check that
+		// the modification time has changed
+		jar.putResource("asm", new FileResource(file));
+		assertEquals(file.lastModified(), jar.lastModified());
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/JobsService.clazz b/biz.aQute.bndlib.tests/src/test/JobsService.clazz
new file mode 100644
index 0000000..af9096e
Binary files /dev/null and b/biz.aQute.bndlib.tests/src/test/JobsService.clazz differ
diff --git a/biz.aQute.bndlib.tests/src/test/LauncherTest.java b/biz.aQute.bndlib.tests/src/test/LauncherTest.java
new file mode 100644
index 0000000..07d500e
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/LauncherTest.java
@@ -0,0 +1,168 @@
+package test;
+
+import java.io.*;
+import java.util.concurrent.*;
+
+import junit.framework.*;
+import aQute.bnd.build.*;
+import aQute.lib.io.*;
+
+public class LauncherTest extends TestCase {
+
+	/**
+	 * Tests if the properties are cleaned up. This requires some knowledge of
+	 * the launcher unfortunately. It is also not sure if the file is not just
+	 * deleted by the onExit ...
+	 * 
+	 * @throws Exception
+	 */
+	public static void testCleanup() throws Exception {
+		Project project = getProject();
+		File target = project.getTarget();
+		IO.deleteWithException(target);
+		project.clear();
+		assertNoProperties(target);
+		final ProjectLauncher l = project.getProjectLauncher();
+		l.setTrace(true);
+
+		Thread t = new Thread() {
+			@Override
+			public void run() {
+				try {
+					Thread.sleep(1000);
+					l.cancel();
+				}
+				catch (Exception e) {
+					// Ignore
+				}
+			}
+		};
+
+		t.start();
+		l.getRunProperties().put("test.cmd", "timeout");
+		l.launch();
+		assertNoProperties(target);
+	}
+
+	/**
+	 * The properties file is an implementation detail ... so this is white box
+	 * testing.
+	 * 
+	 * @param project
+	 * @throws Exception
+	 */
+	private static void assertNoProperties(File target) throws Exception {
+		if (!target.exists())
+			return;
+
+		for (File file : target.listFiles()) {
+			if (file.getAbsolutePath().startsWith("launch")) {
+				fail("There is a launch file in the target directory: " + file);
+			}
+		}
+	}
+
+	public static void testSimple() throws Exception {
+		Project project = getProject();
+		project.clear();
+
+		ProjectLauncher l = project.getProjectLauncher();
+		l.setTrace(true);
+		l.getRunProperties().put("test.cmd", "exit");
+		assertEquals(42, l.launch());
+	}
+
+
+	/**
+	 * This needs to be adapted because the previous left lots of files after
+	 * testing. This current one does not work since the demo project
+	 * uses the snapshots of the launcher and tester, and when copied
+	 * they are not there in that workspace. So we need another demo project
+	 * that does not use OSGi and has not special deps. Then the following code
+	 * can be used.
+	 * @throws Exception
+	 */
+	public static void testWorkspaceWithSpace() throws Exception {
+//		// reuse built .class files from the demo project.
+//		String base = new File("").getAbsoluteFile().getParentFile().getAbsolutePath();
+//		File ws = IO.getFile("tmp/ space ");
+//		try {
+//			IO.delete(ws);
+//			ws.mkdirs();
+//			IO.copy( IO.getFile("../demo"), IO.getFile(ws, "demo"));
+//			IO.getFile(ws, "cnf").mkdirs();
+//			IO.copy( IO.getFile("../cnf"), IO.getFile(ws, "cnf"));
+//			Workspace wp = new Workspace(ws);
+//			
+//			Project p = wp.getProject("demo");
+//			p.clear();
+//			ProjectLauncher l = p.getProjectLauncher();
+//			l.setTrace(true);
+//			l.getRunProperties().put("test.cmd", "exit");
+//			assertEquals(42, l.launch());			
+//		}
+//		finally {
+//			IO.delete(ws);
+//		}
+	}
+
+	/**
+	 * @return
+	 * @throws Exception
+	 */
+	static Project getProject() throws Exception {
+		Workspace workspace = Workspace.getWorkspace(new File("").getAbsoluteFile().getParentFile());
+		Project project = workspace.getProject("demo");
+		return project;
+	}
+
+	static Project getProjectFromWorkspaceWithSpace() throws Exception {
+		Workspace workspace = Workspace.getWorkspace(new File("test/a space"));
+		Project project = workspace.getProject("test");
+		return project;
+	}
+
+	public static void testTester() throws Exception {
+		Project project = getProject();
+		project.clear();
+		project.build();
+
+		ProjectTester pt = project.getProjectTester();
+		pt.addTest("test.TestCase1");
+
+		assertEquals(2, pt.test());
+	}
+
+	public static void testTimeoutActivator() throws Exception {
+		Project project = getProject();
+		project.clear();
+
+		ProjectLauncher l = project.getProjectLauncher();
+		l.setTimeout(100, TimeUnit.MILLISECONDS);
+		l.setTrace(false);
+		assertEquals(ProjectLauncher.TIMEDOUT, l.launch());
+
+	}
+
+	public static void testTimeout() throws Exception {
+		Project project = getProject();
+		project.clear();
+
+		ProjectLauncher l = project.getProjectLauncher();
+		l.setTimeout(100, TimeUnit.MILLISECONDS);
+		l.setTrace(false);
+		l.getRunProperties().put("test.cmd", "timeout");
+		assertEquals(ProjectLauncher.TIMEDOUT, l.launch());
+	}
+
+	public static void testMainThread() throws Exception {
+		Project project = getProject();
+		project.clear();
+
+		ProjectLauncher l = project.getProjectLauncher();
+		l.setTimeout(10000, TimeUnit.MILLISECONDS);
+		l.setTrace(false);
+		l.getRunProperties().put("test.cmd", "main.thread");
+		assertEquals(ProjectLauncher.OK, l.launch());
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/MacroTest.java b/biz.aQute.bndlib.tests/src/test/MacroTest.java
new file mode 100755
index 0000000..6316076
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/MacroTest.java
@@ -0,0 +1,609 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+
+public class MacroTest extends TestCase {
+
+	/**
+	 * Test replacement of ./ with cwd
+	 */
+
+	public static void testCurrentWorkingDirectory() {
+		Processor top = new Processor();
+		top.setProperty("cwd.1", "./"); // empty
+		top.setProperty("cwd.2", " ./"); // empty
+		top.setProperty("cwd.3", "./ "); // empty
+		top.setProperty("cwd.4", " ./ "); // empty
+		top.setProperty("cwd.5", "|./|"); // empty
+		top.setProperty("cwd.6", "/.//"); // empty
+		top.setProperty("cwd.7", "."); // empty
+		top.setProperty("cwd.8", " . "); // empty
+		top.setProperty("cwd.9", " . /"); // empty
+		top.setProperty("cwd.10", " ."); // empty
+		top.setProperty("cwd.11", "| ./|"); // empty
+		top.setProperty("cwd.12", "|\t./|"); // empty
+		top.setProperty("cwd.13", "|\r./|"); // empty
+		top.setProperty("cwd.14", "|\n./|"); // empty
+
+		String cwd = top.getBase().getAbsolutePath() + "/";
+
+		assertEquals(" . ", top.getProperty("cwd.8"));
+		assertEquals(cwd, top.getProperty("cwd.1"));
+		assertEquals(" " + cwd, top.getProperty("cwd.2"));
+		assertEquals(cwd + " ", top.getProperty("cwd.3"));
+		assertEquals(" " + cwd + " ", top.getProperty("cwd.4"));
+		assertEquals("|./|", top.getProperty("cwd.5"));
+		assertEquals("/.//", top.getProperty("cwd.6"));
+		assertEquals(".", top.getProperty("cwd.7"));
+		assertEquals(" . /", top.getProperty("cwd.9"));
+		assertEquals(" .", top.getProperty("cwd.10"));
+		assertEquals("| " + cwd + "|", top.getProperty("cwd.11"));
+		assertEquals("|\t" + cwd + "|", top.getProperty("cwd.12"));
+		assertEquals("|\r" + cwd + "|", top.getProperty("cwd.13"));
+		assertEquals("|\n" + cwd + "|", top.getProperty("cwd.14"));
+	}
+
+	/**
+	 * Test if $if accepts isdir
+	 */
+
+	public static void testifDir() {
+		Processor top = new Processor();
+		top.setProperty("presentd", "${if;${isdir;jar};YES;NO}");
+		top.setProperty("absentd", "${if;${isdir;xxx};YES;NO}");
+		top.setProperty("wrongd", "${if;${isdir;bnd.bnd};YES;NO}");
+		assertEquals("YES", top.getProperty("presentd"));
+		assertEquals("NO", top.getProperty("wrongd"));
+		assertEquals("NO", top.getProperty("absentd"));
+		top.setProperty("presentf", "${if;${isfile;bnd.bnd};YES;NO}");
+		top.setProperty("absentf", "${if;${isfile;xxx};YES;NO}");
+		top.setProperty("wrongf", "${if;${isfile;jar};YES;NO}");
+		assertEquals("YES", top.getProperty("presentf"));
+		assertEquals("NO", top.getProperty("absentf"));
+		assertEquals("NO", top.getProperty("wrongf"));
+	}
+
+	/**
+	 * Test the combine macro that groups properties
+	 */
+
+	public static void testWildcardKeys() {
+		Processor top = new Processor();
+		top.setProperty("a.3", "a.3");
+		top.setProperty("a.1", "a.1");
+		top.setProperty("a.2", "a.2");
+		top.setProperty("a.4", "a.4");
+		top.setProperty("aa", "${a.*}");
+		assertEquals("a.1,a.2,a.3,a.4", top.getProperty("a.*"));
+		assertEquals("a.1,a.2,a.3,a.4", top.getProperty("aa"));
+
+	}
+
+	public static void testEnv() {
+		Processor proc = new Processor();
+		String s = proc.getReplacer().process("${env;USER}");
+		assertNotNull(s);
+	}
+
+	/**
+	 * Test the random macro
+	 */
+	public static void testRandom() {
+		Processor top = new Processor();
+		top.setProperty("a", "${random}");
+		top.setProperty("a12", "${random;12}");
+		String a = top.getProperty("a");
+		System.err.println(a);
+		assertEquals(8, a.length());
+		String a12 = top.getProperty("a12");
+		System.err.println(a12);
+		assertEquals(12, a12.length());
+		assertNotSame(a, a12);
+	}
+	
+	/**
+	 * Test the native macro
+	 */
+	public static void testNativeCapabilityMacro() {
+		Processor p = new Processor();
+		p.setProperty("a", "${native_capability}");
+		
+		String origOsName = System.getProperty("os.name");
+		String origOsVersion = System.getProperty("os.version");
+		String origOsArch = System.getProperty("os.arch");
+		try {
+			System.setProperty("os.name", "Mac OS X");
+			System.setProperty("os.version", "10.8.2");
+			System.setProperty("os.arch", "x86_64");
+			assertEquals("osgi.native;osgi.native.osname:List<String>=\"MacOSX,Mac OS X\";osgi.native.osversion:Version=10.8.2;osgi.native.processor:List<String>=\"x86-64,amd64,em64t,x86_64\"", p.getProperty("a"));
+			
+			System.setProperty("os.name", "Windows 7");
+			System.setProperty("os.version", "6.1.7601.17514");
+			System.setProperty("os.arch", "x86");
+			assertEquals("osgi.native;osgi.native.osname:List<String>=\"Windows7,Windows 7,Win32\";osgi.native.osversion:Version=6.1.0;osgi.native.processor:List<String>=\"x86,pentium,i386,i486,i586,i686\"", p.getProperty("a"));
+		} finally {
+			System.setProperty("os.name", origOsName);
+			System.setProperty("os.version", origOsVersion);
+			System.setProperty("os.arch", origOsArch);
+		}
+	}
+
+	/**
+	 * Testing an example with nesting that was supposd not to work
+	 */
+
+	public static void testSuper() {
+		Processor top = new Processor();
+		Processor middle = new Processor(top);
+		Processor bottom = new Processor(middle);
+
+		top.setProperty("a", "top.a");
+		top.setProperty("b", "top.b");
+		top.setProperty("c", "top.c");
+		top.setProperty("Bundle-Version", "0.0.0");
+		middle.setProperty("a", "middle.a");
+		middle.setProperty("b", "${^a}");
+		middle.setProperty("c", "-${^c}-");
+		middle.setProperty("Bundle-Version", "${^Bundle-Version}");
+		assertEquals("middle.a", bottom.getProperty("a"));
+		assertEquals("top.a", bottom.getProperty("b"));
+		assertEquals("-top.c-", bottom.getProperty("c"));
+		assertEquals("0.0.0", bottom.getProperty("Bundle-Version"));
+	}
+
+	/**
+	 * Testing an example with nesting that was supposd not to work
+	 */
+
+	public static void testNesting2() {
+		Processor p = new Processor();
+		p.setProperty("groupId", "com.trivadis.tomas");
+		p.setProperty("artifactId", "common");
+		p.setProperty("bsn", "${if;${symbolicName};${symbolicName};${groupId}.${artifactId}}");
+		p.setProperty("Bundle-SymbolicName", "${bsn}");
+		p.setProperty("symbolicName", "");
+
+		// Not set, so get the maven name
+		assertEquals("com.trivadis.tomas.common", p.getProperty("Bundle-SymbolicName"));
+
+		// Set it
+		p.setProperty("symbolicName", "testing");
+		assertEquals("testing", p.getProperty("Bundle-SymbolicName"));
+
+		// And remove it
+		p.setProperty("symbolicName", "");
+		assertEquals("com.trivadis.tomas.common", p.getProperty("Bundle-SymbolicName"));
+	}
+
+	/**
+	 * Verify system command
+	 */
+
+	public static void testSystem() throws Exception {
+		// disable this test on windows
+		if (!"/".equals(File.separator)) return;
+		
+		Processor p = new Processor();
+		Macro macro = new Macro(p);
+		assertEquals("Hello World", macro.process("${system;echo Hello World}"));
+		assertTrue(macro.process("${system;wc;Hello World}").matches("\\s*[0-9]+\\s+[0-9]+\\s+[0-9]+\\s*"));
+	}
+
+	public static void testSystemFail() throws Exception {
+		Processor p = new Processor();
+		Macro macro = new Macro(p);
+		String cmd = "${system;mostidioticcommandthatwillsurelyfail}";
+		assertTrue(macro.process(cmd).startsWith("${system;"));
+	}
+
+	/**
+	 * Verify system-allow-fail command
+	 */
+
+	public static void testSystemAllowFail() throws Exception {
+		Processor p = new Processor();
+		Macro macro = new Macro(p);
+		assertEquals("", macro.process("${system-allow-fail;mostidioticcommandthatwillsurelyfail}"));
+	}
+
+	/**
+	 * Check that variables override macros.
+	 */
+	public static void testPriority() {
+		Processor p = new Processor();
+		p.setProperty("now", "not set");
+		Macro macro = new Macro(p);
+		assertEquals("not set", macro.process("${now}"));
+
+	}
+
+	public static void testNames() {
+		Processor p = new Processor();
+		p.setProperty("a", "a");
+		p.setProperty("aa", "aa");
+		Macro macro = new Macro(p);
+
+		assertEquals("aa", macro.process("${${a}${a}}"));
+	}
+
+	public static void testVersion() throws Exception {
+		Processor proc = new Processor();
+		Macro macro = new Macro(proc);
+		assertEquals("1.0.0", macro.process("${version;===;1.0.0}"));
+		assertEquals("1.0.1", macro.process("${version;==+;1.0.0}"));
+		assertEquals("1.1.1", macro.process("${version;=++;1.0.0}"));
+		assertEquals("2.1.1", macro.process("${version;+++;1.0.0}"));
+		assertEquals("0.1.1", macro.process("${version;-++;1.0.0}"));
+		assertEquals("0.1.1", macro.process("${version;-++;1.0.0}"));
+		assertEquals("0.0.0", macro.process("${version;---;1.1.1}"));
+		assertEquals("0.0", macro.process("${version;--;1.1.1}"));
+		assertEquals("1", macro.process("${version;=;1.1.1}"));
+		assertEquals("[1.1,1.2)", macro.process("[${version;==;1.1.1},${version;=+;1.1.1})"));
+		assertEquals("1.1", macro.process("${version;==;1.1.1}"));
+		assertEquals("0.1.0", macro.process("${version;=+0;0.0.1}"));
+		assertEquals("1.0.0", macro.process("${version;+00;0.1.1}"));
+
+		// Test implicit version
+		proc.setProperty("@", "1.2.3");
+		assertEquals("[1.2,1.3)", macro.process("[${version;==},${version;=+})"));
+		assertEquals("1.2", macro.process("${version;==}"));
+		assertEquals("1.3.0", macro.process("${version;=+0}"));
+		assertEquals("2.0.0", macro.process("${version;+00}"));
+
+		assertEquals(0, proc.getErrors().size());
+		assertEquals(0, proc.getWarnings().size());
+
+	}
+
+	public static void testRange() throws Exception {
+		Processor proc = new Processor();
+		Macro macro = new Macro(proc);
+		assertEquals("[1.0,1.0]", macro.process("${range;[==,==];1.0.0}"));
+		assertEquals("[1.0.0,1.0.1]", macro.process("${range;[===,==+];1.0.0}"));
+		assertEquals("[0.1.0,0.1.2)", macro.process("${range;[=+0,=++);0.0.1}"));
+		assertEquals("[0.0.9,0.1.2)", macro.process("${range;[==9,=++);0.0.1}"));
+
+		assertEquals(0, proc.getErrors().size());
+		assertEquals(0, proc.getWarnings().size());
+
+		proc.setProperty("@", "1.2.3");
+		assertEquals("[1.0.0,2)", macro.process("${range;[=00,+)}"));
+
+		proc.clear();
+		macro.process("${range;=+0,=++;0.0.1}");
+		assertEquals(1, proc.getErrors().size());
+		assertEquals(1, proc.getWarnings().size());
+
+		proc.clear();
+		macro.process("${range;[+,=)}");
+		assertEquals(1, proc.getErrors().size());
+		assertEquals(1, proc.getWarnings().size());
+	}
+
+	/**
+	 * Test the wc function
+	 */
+
+	public static void testWc() {
+		Processor p = new Processor();
+		Macro macro = new Macro(p);
+		String a = macro.process("${lsr;" + new File("src" + File.separator + "test").getAbsolutePath() + ";*.java}");
+		assertTrue(a.contains("MacroTest.java"));
+		assertTrue(a.contains("ManifestTest.java"));
+		assertFalse(a.contains("bnd.info"));
+		assertFalse(a.contains("com.acme"));
+		assertFalse(a.contains("src" + File.separator + "test" + File.separator + "MacroTest.java"));
+		assertFalse(a.contains("src" + File.separator + "test" + File.separator + "ManifestTest.java"));
+
+		String b = macro.process("${lsa;" + new File("src" + File.separator + "test").getAbsolutePath() + ";*.java}");
+		assertTrue(b.contains("src" + File.separator + "test" + File.separator + "MacroTest.java"));
+		assertTrue(b.contains("src" + File.separator + "test" + File.separator + "ManifestTest.java"));
+	}
+
+	/**
+	 * Check the uniq command
+	 */
+
+	public static void testUniq() {
+		Builder builder = new Builder();
+		Properties p = new Properties();
+		p.setProperty("a", "${uniq;1}");
+		p.setProperty("b", "${uniq;1,2}");
+		p.setProperty("c", "${uniq;1;2}");
+		p.setProperty("d", "${uniq;1; 1,  2 , 3}");
+		p.setProperty("e", "${uniq;1; 1 , 2 ;      3;3,4,5,6}");
+		builder.setProperties(p);
+		assertEquals("1,2,3", builder.getProperty("d"));
+		assertEquals("1,2", builder.getProperty("b"));
+		assertEquals("1", builder.getProperty("a"));
+		assertEquals("1,2", builder.getProperty("c"));
+		assertEquals("1,2,3", builder.getProperty("d"));
+		assertEquals("1,2,3,4,5,6", builder.getProperty("e"));
+
+	}
+
+	/**
+	 * Test arguments with difficult characters like ;
+	 */
+
+	public static void testEscapedArgs() {
+		Builder builder = new Builder();
+		Properties p = new Properties();
+		p.setProperty("x", "${replace;1,2,3;.+;$0\\;version=1}");
+		builder.setProperties(p);
+		assertEquals("1;version=1, 2;version=1, 3;version=1", builder.getProperty("x"));
+
+	}
+
+	/**
+	 * Check if variables that contain variables, ad nauseum, really wrk
+	 */
+	public static void testNested() {
+		Builder builder = new Builder();
+		Properties p = new Properties();
+		p.setProperty("a", ".");
+		p.setProperty("b", "${a}");
+		p.setProperty("c", "${b}");
+
+		p.setProperty("d", "${tstamp;${format};UTC;${aug152008}}");
+		p.setProperty("format", "yyyy");
+		p.setProperty("aug152008", "1218810097322");
+
+		p.setProperty("f", "${d}");
+		p.setProperty("aug152008", "1218810097322");
+
+		builder.setProperties(p);
+		assertEquals(".", builder.getProperty("c"));
+		assertEquals("2008", builder.getProperty("d"));
+		assertEquals(builder.getProperty("f"), builder.getProperty("d"));
+	}
+
+	public static void testLoop() {
+		Builder builder = new Builder();
+		Properties p = new Properties();
+		p.setProperty("a", "${b}");
+		p.setProperty("b", "${a}");
+
+		p.setProperty("d", "${e}");
+		p.setProperty("e", "${f}");
+		p.setProperty("f", "${g}");
+		p.setProperty("g", "${h}");
+		p.setProperty("h", "${d}");
+
+		builder.setProperties(p);
+		assertEquals("${infinite:[a,b,${b}]}", builder.getProperty("a"));
+		assertEquals("${infinite:[d,h,g,f,e,${e}]}", builder.getProperty("d"));
+	}
+
+	public static void testTstamp() {
+		String aug152008 = "1218810097322";
+		Processor p = new Processor();
+		Macro m = new Macro(p);
+		assertEquals("200808151421", m.process("${tstamp;yyyyMMddHHmm;UTC;" + aug152008 + "}"));
+		assertEquals("200808151521", m.process("${tstamp;yyyyMMddHHmm;GMT+01;" + aug152008 + "}"));
+		assertEquals("2008", m.process("${tstamp;yyyy;UTC;" + aug152008 + "}"));
+		
+		// Why Tokyo? Japan doesn't use daylight savings, so the test shouldn't break when clocks change.
+		assertEquals("200808152321", m.process("${tstamp;yyyyMMddHHmm;Asia/Tokyo;" + aug152008 + "}"));
+	}
+
+	public static void testIsfile() {
+		Processor p = new Processor();
+		Macro m = new Macro(p);
+		assertEquals("true", m.process("${isfile;.project}"));
+		assertEquals("false", m.process("${isfile;thisfiledoesnotexist}"));
+	}
+
+	public static void testParentFile() {
+		Processor p = new Processor();
+		Macro m = new Macro(p);
+		assertTrue(m.process("${dir;.project}").endsWith("biz.aQute.bndlib.tests"));
+	}
+
+	public static void testBasename() {
+		Processor p = new Processor();
+		Macro m = new Macro(p);
+		assertEquals("biz.aQute.bndlib.tests", m.process("${basename;${dir;.project}}"));
+	}
+
+	public static void testMavenVersionMacro() throws Exception {
+		Builder builder = new Builder();
+		Properties p = new Properties();
+		p.setProperty("Export-Package", "org.objectweb.*;version=1.5-SNAPSHOT");
+		builder.setProperties(p);
+		builder.setClasspath(new File[] {
+			new File("jar/asm.jar")
+		});
+		Jar jar = builder.build();
+		Manifest manifest = jar.getManifest();
+		String export = manifest.getMainAttributes().getValue("Export-Package");
+		assertNotNull(export);
+		assertTrue("Test snapshot version", export.contains("1.5.0.SNAPSHOT"));
+	}
+
+	/**
+	 * Check if we can check for the defintion of a variable
+	 */
+
+	public static void testDef() {
+		Processor p = new Processor();
+		p.setProperty("set.1", "1");
+		p.setProperty("set.2", "2");
+		Macro m = new Macro(p);
+		assertEquals("NO", m.process("${if;${def;set.3};YES;NO}"));
+		assertEquals("YES", m.process("${if;${def;set.1};YES;NO}"));
+		assertEquals("YES", m.process("${if;${def;set.2};YES;NO}"));
+	}
+
+	/**
+	 * NEW
+	 */
+	public static void testReplace() {
+		Processor p = new Processor();
+		p.setProperty("specs", "a,b, c,    d");
+		Macro m = new Macro(p);
+		assertEquals("xay, xby, xcy, xdy", m.process("${replace;${specs};([^\\s]+);x$1y}"));
+	}
+
+	public static void testToClassName() {
+		Processor p = new Processor();
+		Macro m = new Macro(p);
+		assertEquals("com.acme.test.Test", m.process("${toclassname;com/acme/test/Test.class}"));
+		assertEquals("Test", m.process("$<toclassname;Test.class>"));
+		assertEquals("Test,com.acme.test.Test", m.process("${toclassname;Test.class, com/acme/test/Test.class}"));
+		assertEquals("", m.process("$(toclassname;Test)"));
+		assertEquals("com/acme/test/Test.class", m.process("$[toclasspath;com.acme.test.Test]"));
+		assertEquals("Test.class", m.process("${toclasspath;Test}"));
+		assertEquals("Test.class,com/acme/test/Test.class", m.process("${toclasspath;Test,com.acme.test.Test}"));
+	}
+
+	public static void testFindPath() throws IOException {
+		Analyzer analyzer = new Analyzer();
+		analyzer.setJar(new File("jar/asm.jar"));
+		Macro m = new Macro(analyzer);
+
+		assertTrue(m.process("${findname;(.*)\\.class;$1.xyz}").indexOf("FieldVisitor.xyz,") >= 0);
+		assertTrue(m.process("${findname;(.*)\\.class;$1.xyz}").indexOf("MethodVisitor.xyz,") >= 0);
+		assertTrue(m.process("${findpath;(.*)\\.class}").indexOf("org/objectweb/asm/AnnotationVisitor.class,") >= 0);
+		assertTrue(m.process("${findpath;(.*)\\.class}").indexOf(
+				"org/objectweb/asm/ByteVector.class, org/objectweb/asm/ClassAdapter.class,") >= 0);
+		assertEquals("META-INF/MANIFEST.MF", m.process("${findpath;META-INF/MANIFEST.MF}"));
+		assertEquals("Label.class", m.process("${findname;Label\\..*}"));
+		assertEquals("Adapter, Visitor, Writer", m.process("${findname;Method(.*)\\.class;$1}"));
+	}
+
+	public static void testWarning() {
+		Processor p = new Processor();
+		p.setProperty("three", "333");
+		p.setProperty("empty", "");
+		p.setProperty("real", "true");
+		Macro m = new Macro(p);
+
+		m.process("    ${warning;xw;1;2;3 ${three}}");
+		m.process("    ${error;xe;1;2;3 ${three}}");
+		m.process("    ${if;1;$<a>}");
+		assertEquals("xw", p.getWarnings().get(0));
+		assertEquals("1", p.getWarnings().get(1));
+		assertEquals("2", p.getWarnings().get(2));
+		assertEquals("3 333", p.getWarnings().get(3));
+
+		assertEquals("xe", p.getErrors().get(0));
+		assertEquals("1", p.getErrors().get(1));
+		assertEquals("2", p.getErrors().get(2));
+		assertEquals("3 333", p.getErrors().get(3));
+	}
+
+	public static void testNestedReplace() {
+		Processor p = new Processor();
+		Macro m = new Macro(p);
+		String value = m.process("xx$(replace;1.2.3-SNAPSHOT;(\\d(\\.\\d)+).*;$1)xx");
+		System.err.println(p.getWarnings());
+		assertEquals("xx1.2.3xx", value);
+
+		assertEquals("xx1.222.3xx", m.process("xx$(replace;1.222.3-SNAPSHOT;(\\d+(\\.\\d+)+).*;$1)xx"));
+
+		p.setProperty("a", "aaaa");
+		assertEquals("[cac]", m.process("$[replace;acaca;a(.*)a;[$1]]"));
+		assertEquals("xxx", m.process("$(replace;yxxxy;[^x]*(x+)[^x]*;$1)"));
+		assertEquals("xxx", m.process("$(replace;yxxxy;([^x]*(x+)[^x]*);$2)"));
+
+	}
+
+	public static void testParentheses() {
+		Processor p = new Processor();
+		Macro m = new Macro(p);
+		String value = m.process("$(replace;();(\\(\\));$1)");
+		assertEquals("()", value);
+	}
+
+	public static void testSimple() {
+		Processor p = new Processor();
+		p.setProperty("a", "aaaa");
+		Macro m = new Macro(p);
+		assertEquals("aaaa", m.process("${a}"));
+		assertEquals("aaaa", m.process("$<a>"));
+		assertEquals("aaaa", m.process("$(a)"));
+		assertEquals("aaaa", m.process("$[a]"));
+
+		assertEquals("xaaaax", m.process("x${a}x"));
+		assertEquals("xaaaaxaaaax", m.process("x${a}x${a}x"));
+	}
+
+	public static void testFilter() {
+		Processor p = new Processor();
+		p.setProperty("a", "aaaa");
+		Macro m = new Macro(p);
+		assertEquals("aa,cc,ee", m.process("${filter;aa,bb,cc,dd,ee,ff;[ace]+}"));
+		assertEquals("aaaa,cc,ee", m.process("${filter;${a},bb,cc,dd,ee,ff;[ace]+}"));
+		assertEquals("bb,dd,ff", m.process("${filter;${a},bb,cc,dd,ee,ff;[^ace]+}"));
+	}
+
+	public static void testFilterOut() {
+		Processor p = new Processor();
+		p.setProperty("a", "aaaa");
+		Macro m = new Macro(p);
+		assertEquals("bb,dd,ff", m.process("${filterout;aa,bb,cc,dd,ee,ff;[ace]+}"));
+		assertEquals("bb,dd,ff", m.process("${filterout;${a},bb,cc,dd,ee,ff;[ace]+}"));
+		assertEquals("aaaa,cc,ee", m.process("${filterout;${a},bb,cc,dd,ee,ff;[^ace]+}"));
+	}
+
+	public static void testSort() {
+		Processor p = new Processor();
+		p.setProperty("a", "aaaa");
+		Macro m = new Macro(p);
+		assertEquals("aa,bb,cc,dd,ee,ff", m.process("${sort;aa,bb,cc,dd,ee,ff}"));
+		assertEquals("aa,bb,cc,dd,ee,ff", m.process("${sort;ff,ee,cc,bb,dd,aa}"));
+		assertEquals("aaaa,bb,cc,dd,ee,ff", m.process("${sort;ff,ee,cc,bb,dd,$<a>}"));
+	}
+
+	public static void testJoin() {
+		Processor p = new Processor();
+		p.setProperty("a", "aaaa");
+		Macro m = new Macro(p);
+		assertEquals("aa,bb,cc,dd,ee,ff", m.process("${join;aa,bb,cc,dd,ee,ff}"));
+		assertEquals("aa,bb,cc,dd,ee,ff", m.process("${join;aa,bb,cc;dd,ee,ff}"));
+		assertEquals("aa,bb,cc,dd,ee,ff", m.process("${join;aa;bb;cc;dd;ee,ff}"));
+	}
+
+	public static void testIf() {
+		Processor p = new Processor();
+		p.setProperty("a", "aaaa");
+		Macro m = new Macro(p);
+		assertEquals("aaaa", m.process("${if;1;$<a>}"));
+		assertEquals("", m.process("${if;;$<a>}"));
+		assertEquals("yes", m.process("${if;;$<a>;yes}"));
+		assertEquals("yes", m.process("${if;false;$<a>;yes}"));
+	}
+
+	public static void testLiteral() {
+		Processor p = new Processor();
+		p.setProperty("a", "aaaa");
+		Macro m = new Macro(p);
+		assertEquals("${aaaa}", m.process("${literal;$<a>}"));
+	}
+
+	public static void testFilterout() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.addClasspath(new File("jar/ds.jar"));
+		b.setProperty("Export-Package", "org.eclipse.*, org.osgi.*");
+		b.setProperty("fwusers", "${classes;importing;org.osgi.framework}");
+		b.setProperty("foo", "${filterout;${fwusers};org\\.osgi\\..*}");
+		b.build();
+		String fwusers = b.getProperty("fwusers");
+		String foo = b.getProperty("foo");
+		assertTrue(fwusers.length() > foo.length());
+		assertTrue(fwusers.indexOf("org.osgi.framework.ServicePermission") >= 0);
+		assertTrue(fwusers.indexOf("org.eclipse.equinox.ds.instance.BuildDispose") >= 0);
+		assertFalse(foo.indexOf("org.osgi.framework.ServicePermission") >= 0);
+		assertTrue(foo.indexOf("org.eclipse.equinox.ds.instance.BuildDispose") >= 0);
+		System.err.println(b.getProperty("fwusers"));
+		System.err.println(b.getProperty("foo"));
+
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/MakeTest.java b/biz.aQute.bndlib.tests/src/test/MakeTest.java
new file mode 100644
index 0000000..4a6a9fc
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/MakeTest.java
@@ -0,0 +1,117 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+
+/**
+ * Tests the make functionality.
+ * 
+ * @author aqute
+ */
+public class MakeTest extends TestCase {
+
+	/**
+	 * Test a make plugin
+	 */
+
+	public static void testMakePlugin() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("Export-Package", "*");
+		b.setProperty("Include-Resource", "jar/asm.jar.md5");
+		b.setProperty("-make", "(*).md5;type=md5;file=$1");
+		b.setProperty("-plugin", "test.make.MD5");
+		b.addClasspath(new File("jar/osgi.jar"));
+		Jar jar = b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+		assertNotNull(jar.getResource("asm.jar.md5"));
+	}
+
+	/**
+	 * Check if we can get a resource through the make copy facility.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testCopy() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.setProperty("-resourceonly", "true");
+		p.setProperty("-plugin", "aQute.bnd.make.MakeBnd, aQute.bnd.make.MakeCopy");
+		p.setProperty("-make", "(*).jar;type=bnd;recipe=bnd/$1.bnd, (*).jar;type=copy;from=jar/$1.jar");
+		p.setProperty("Include-Resource", "asm.jar,xyz=asm.jar");
+		bmaker.setProperties(p);
+		Jar jar = bmaker.build();
+		assertNotNull(jar.getResource("asm.jar"));
+		assertNotNull(jar.getResource("xyz"));
+		report(bmaker);
+
+	}
+
+	/**
+	 * Check if we can create a JAR recursively
+	 * 
+	 * @throws Exception
+	 */
+	public static void testJarInJarInJar() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.setProperty("-plugin", "aQute.bnd.make.MakeBnd, aQute.bnd.make.MakeCopy");
+		p.setProperty("-resourceonly", "true");
+		p.setProperty("-make", "(*).jar;type=bnd;recipe=bnd/$1.bnd");
+		p.setProperty("Include-Resource", "makesondemand.jar");
+		bmaker.setProperties(p);
+		bmaker.setClasspath(new String[] {
+			"bin"
+		});
+		Jar jar = bmaker.build();
+		JarResource resource = (JarResource) jar.getResource("makesondemand.jar");
+		assertNotNull(resource);
+
+		jar = resource.getJar();
+		resource = (JarResource) jar.getResource("ondemand.jar");
+		assertNotNull(resource);
+
+		report(bmaker);
+	}
+
+	/**
+	 * Check if we can create a jar on demand through the make facility with a
+	 * new name.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testComplexOnDemand() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.setProperty("-resourceonly", "true");
+		p.setProperty("-plugin", "aQute.bnd.make.MakeBnd, aQute.bnd.make.MakeCopy");
+		p.setProperty("-make", "(*).jar;type=bnd;recipe=bnd/$1.bnd");
+		p.setProperty("Include-Resource", "www/xyz.jar=ondemand.jar");
+		bmaker.setProperties(p);
+		bmaker.setClasspath(new String[] {
+			"bin"
+		});
+		Jar jar = bmaker.build();
+		Resource resource = jar.getResource("www/xyz.jar");
+		assertNotNull(resource);
+		assertTrue(resource instanceof JarResource);
+		report(bmaker);
+
+	}
+
+	static void report(Processor processor) {
+		System.err.println();
+		for (int i = 0; i < processor.getErrors().size(); i++)
+			System.err.println(processor.getErrors().get(i));
+		for (int i = 0; i < processor.getWarnings().size(); i++)
+			System.err.println(processor.getWarnings().get(i));
+		assertEquals(0, processor.getErrors().size());
+		assertEquals(0, processor.getWarnings().size());
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/ManifestTest.java b/biz.aQute.bndlib.tests/src/test/ManifestTest.java
new file mode 100755
index 0000000..c5678c9
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/ManifestTest.java
@@ -0,0 +1,190 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+import java.util.regex.*;
+import java.util.zip.*;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+import aQute.lib.io.*;
+
+public class ManifestTest extends TestCase {
+
+	public static void testNameSection() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("Export-Package", "org.osgi.framework");
+		b.addClasspath(new File("jar/osgi.jar"));
+
+		Jar jar = b.build();
+		jar.calcChecksums(null);
+		File f = File.createTempFile("abc", ".jar");
+		f.deleteOnExit();
+		jar.write(f);
+
+		jar = new Jar(f);
+		f.delete();
+		assertTrue(b.check());
+
+		Resource r = jar.getResource("META-INF/MANIFEST.MF");
+		assertNotNull(r);
+
+		// String ms = IO.collect( r.openInputStream());
+
+		Manifest m = new Manifest(r.openInputStream());
+
+		assertEquals(31, m.getEntries().size());
+
+		Attributes ba = m.getAttributes("org/osgi/framework/BundleActivator.class");
+		assertNotNull(ba);
+		assertEquals("RTRhr3kadnulINegRhpmog==", ba.getValue("MD5-Digest"));
+
+		Attributes bundle = m.getAttributes("org/osgi/framework/Bundle.class");
+		assertNotNull(bundle);
+		assertEquals("fpQdL60w3CQK+7xlXtM6oA==", bundle.getValue("MD5-Digest"));
+
+		Attributes sl = m.getAttributes("org/osgi/framework/ServiceListener.class");
+		assertNotNull(sl);
+		assertEquals("nzDRN19MrTJG+LP8ayKZITZ653g=", sl.getValue("SHA-Digest"));
+
+	}
+
+	public static void testUnicode() throws Exception {
+		Builder b = new Builder();
+		String longSentence = "\u1401\u1402\u1403\u1404\u1405\u1406\u1407\u1408\u1409\u140A\u140B\u140C\u140D\u140E\u140F\u1410\u1411\u1412\u1413\u1414\u1415\u1416\u1417\u1418\u1419\u141A\u141B\u141C\u141D\u141E\u141F\u1420\u1421\u1422\u1422\u1423\u1424\u1425\u1426\u1427\u1428\u1429\u1429\u142A\u142B\u142C\u142D\u142E\u142F\u1430\u1431\u1432\u1433\u1434\u1435\u1436\u1437\u1438\u1439\u143A\u143B\u143C\u143D\u143E\u143F\u1440\u1441\u1442\u1443\u1444\u1444\u1445\u1446\u1447\u1448\u1449\u144A\u144 [...]
+		String shortSentence = "\u1401\u1402\u1403\u1404\u1405\u1406\u1407\u1408\u1409\u140A\u140B\u140C\u140D\u140E\u140F\u1410\u1411\u1412\u1413\u1414\u1415\u1416";
+		assertEquals(66, shortSentence.getBytes("UTF8").length);
+		assertEquals(22, shortSentence.length());
+
+		b.setProperty("A1", shortSentence);
+		b.setProperty("A11", shortSentence);
+		b.setProperty("A111", shortSentence);
+		b.setProperty("A1111", shortSentence);
+		b.setProperty("Long", longSentence);
+
+		b.setProperty("-resourceonly", "true");
+		b.setProperty("Include-Resource", "jar/osgi.jar");
+		Jar jar = b.build();
+		File f = File.createTempFile("abc", ".jar");
+		f.deleteOnExit();
+		jar.write(f);
+
+		jar = new Jar(f);
+		f.delete();
+
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+		Resource r = jar.getResource("META-INF/MANIFEST.MF");
+		assertNotNull(r);
+
+		Manifest m = new Manifest(r.openInputStream());
+		// String ms = IO.collect(r.openInputStream());
+
+		assertEquals(shortSentence, m.getMainAttributes().getValue("A1"));
+		assertEquals(shortSentence, m.getMainAttributes().getValue("A11"));
+		assertEquals(shortSentence, m.getMainAttributes().getValue("A111"));
+		assertEquals(shortSentence, m.getMainAttributes().getValue("A1111"));
+		assertEquals(longSentence, m.getMainAttributes().getValue("Long"));
+
+	}
+
+	public static void test72() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("H65", "01234567890123456789012345678901234567890123456789012345678901234");
+		b.setProperty("H66", "012345678901234567890123456789012345678901234567890123456789012345");
+		b.setProperty("H67", "0123456789012345678901234567890123456789012345678901234567890123456");
+		b.setProperty("H68", "01234567890123456789012345678901234567890123456789012345678901234567");
+		b.setProperty("H69", "012345678901234567890123456789012345678901234567890123456789012345678");
+		b.setProperty("-resourceonly", "true");
+		b.setProperty("Include-Resource", "jar/osgi.jar");
+		Jar jar = b.build();
+		File f = File.createTempFile("abc", ".jar");
+		f.deleteOnExit();
+		jar.write(f);
+
+		jar = new Jar(f);
+		f.delete();
+
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+		Resource r = jar.getResource("META-INF/MANIFEST.MF");
+		assertNotNull(r);
+
+		Manifest m = new Manifest(r.openInputStream());
+		String ms = IO.collect(r.openInputStream());
+
+		assertEquals(65, m.getMainAttributes().getValue("H65").length());
+		assertEquals(66, m.getMainAttributes().getValue("H66").length());
+		assertEquals(67, m.getMainAttributes().getValue("H67").length());
+		assertEquals(68, m.getMainAttributes().getValue("H68").length());
+		assertEquals(69, m.getMainAttributes().getValue("H69").length());
+
+		assertTrue(Pattern.compile("H65: \\d{65}\r\n").matcher(ms).find());
+		assertTrue(Pattern.compile("H66: \\d{66}\r\n").matcher(ms).find());
+		assertTrue(Pattern.compile("H67: \\d{67}\r\n").matcher(ms).find());
+		assertTrue(Pattern.compile("H68: \\d{67}\r\n 7\r\n").matcher(ms).find());
+		assertTrue(Pattern.compile("H69: \\d{67}\r\n 78\r\n").matcher(ms).find());
+	}
+
+	public static void testNoManifest() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("-nomanifest", "true");
+		b.setProperty("Export-Package", "org.osgi.service.event.*");
+		b.addClasspath(new File("jar/osgi.jar"));
+		Jar jar = b.build();
+		assertNull(jar.getResource("META-INF/MANIFEST.MF"));
+		ByteArrayOutputStream bout = new ByteArrayOutputStream();
+		jar.write(bout);
+		ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+		JarInputStream in = new JarInputStream(bin);
+		ZipEntry entry = in.getNextEntry();
+		assertNotNull(entry);
+		assertNull(entry.getExtra());
+	}
+
+	public static void testNames() throws Exception {
+		Manifest m = new Manifest();
+		m.getMainAttributes().putValue("Manifest-Version", "1.0");
+		m.getMainAttributes().putValue("x", "Loïc Cotonéa");
+		m.getMainAttributes().putValue("y", "Loïc Cotonéa");
+		m.getMainAttributes().putValue("z", "Loïc Cotonéa");
+
+		ByteArrayOutputStream bout = new ByteArrayOutputStream();
+		Jar.writeManifest(m, bout);
+		byte[] result = bout.toByteArray();
+
+		System.err.println(new String(result));
+	}
+
+	public static void testUTF8() throws Exception {
+		Manifest m = new Manifest();
+		m.getMainAttributes().putValue("Manifest-Version", "1.0");
+		m.getMainAttributes().putValue("x", "Loïc Cotonéa");
+		m.getMainAttributes().putValue("y", "Loïc Cotonéa");
+		m.getMainAttributes().putValue("z", "Loïc Cotonéa");
+
+		ByteArrayOutputStream bout = new ByteArrayOutputStream();
+		Jar.writeManifest(m, bout);
+		byte[] result = bout.toByteArray();
+
+		System.err.println(new String(result));
+	}
+
+	public static void testQuotes() throws IOException {
+		Map<String,Map<String,String>> map = new HashMap<String,Map<String,String>>();
+		Map<String,String> clause = new HashMap<String,String>();
+		clause.put("version1", "0");
+		clause.put("version2", "0.0");
+		clause.put("version3", "\"0.0\"");
+		clause.put("version4", "   \"0.0\"    ");
+		clause.put("version5", "   0.0    ");
+		map.put("alpha", clause);
+		String s = Processor.printClauses(map);
+		assertTrue(s.indexOf("version1=0") >= 0);
+		assertTrue(s.indexOf("version2=\"0.0\"") >= 0);
+		assertTrue(s.indexOf("version3=\"0.0\"") >= 0);
+		assertTrue(s.indexOf("version4=\"0.0\"") >= 0);
+		assertTrue(s.indexOf("version5=\"0.0\"") >= 0);
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/MavenTest.java b/biz.aQute.bndlib.tests/src/test/MavenTest.java
new file mode 100644
index 0000000..3b2fb60
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/MavenTest.java
@@ -0,0 +1,335 @@
+package test;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import junit.framework.*;
+import aQute.bnd.build.*;
+import aQute.bnd.header.*;
+import aQute.bnd.maven.*;
+import aQute.bnd.maven.support.*;
+import aQute.bnd.maven.support.Pom.Dependency;
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.*;
+import aQute.lib.io.*;
+import aQute.libg.map.*;
+
+public class MavenTest extends TestCase {
+	Processor				processor	= new Processor();
+	final static File		cwd			= new File("").getAbsoluteFile();
+	static ExecutorService	executor	= Executors.newCachedThreadPool();
+	Maven					maven		= new Maven(executor);
+
+	/**
+	 * A test against maven 2
+	 * 
+	 * @throws Exception
+	 * @throws URISyntaxException
+	 */
+	public void testRemote() throws URISyntaxException, Exception {
+		// URI repo = new URI("http://repo1.maven.org/maven2");
+		// MavenEntry entry = maven.getEntry("org.springframework",
+		// "spring-aspects" , "3.0.5.RELEASE");
+		// entry.remove();
+		// CachedPom pom = maven.getPom("org.springframework", "spring-aspects"
+		// , "3.0.5.RELEASE", repo);
+		// Set<Pom> dependencies = pom.getDependencies(Scope.compile, repo);
+		// for ( Pom dep : dependencies ) {
+		// System.err.printf( "%20s %-20s %10s%n", dep.getGroupId(),
+		// dep.getArtifactId(), dep.getVersion());
+		// }
+
+	}
+
+	/**
+	 * Check if we get the correct bundles for a project
+	 * 
+	 * @throws Exception
+	 */
+
+	public void testProjectBundles() throws Exception {
+		// Project project = getProject("maven1");
+		//
+		// Collection<Container> containers = project.getBuildpath();
+		// List<String> files = new ArrayList<String>();
+		// for ( Container c : containers ) {
+		// files.add( c.getFile().getName());
+		// }
+		// assertTrue(files.remove("bin"));
+		// System.err.println(files);
+		// assertTrue(
+		// files.contains("com.springsource.org.apache.commons.beanutils-1.6.1.jar"));
+	}
+
+	/**
+	 * @return
+	 * @throws Exception
+	 */
+	protected static Project getProject(String name) throws Exception {
+		File wsf = IO.getFile(cwd, "test/ws");
+		Workspace ws = Workspace.getWorkspace(wsf);
+
+		assertNotNull(ws);
+
+		Project project = ws.getProject(name);
+		assertNotNull(project);
+		return project;
+	}
+
+	/**
+	 * See if we can create a maven repostory as a plugin
+	 * 
+	 * @throws Exception
+	 */
+
+	public static void testMavenRepo() throws Exception {
+		Workspace ws = Workspace.getWorkspace(cwd.getParentFile());
+		Maven maven = ws.getMaven();
+
+		Processor processor = new Processor(ws);
+		processor.setProperty(Constants.PLUGIN,
+				"aQute.bnd.maven.support.MavenRemoteRepository;repositories=test/ws/maven1/m2");
+
+		MavenRemoteRepository mr = processor.getPlugin(MavenRemoteRepository.class);
+		assertNotNull(mr);
+		assertEquals(maven, mr.getMaven());
+
+		// Cleanup the maven cache so we do not get random results
+		MavenEntry me = maven.getEntry("org.apache.commons", "com.springsource.org.apache.commons.beanutils", "1.6.1");
+		assertNotNull(me);
+		me.remove();
+
+		Map<String,String> map = MAP.$("groupId", "org.apache.commons");
+		File file = mr.get("com.springsource.org.apache.commons.beanutils", "1.6.1", Strategy.LOWEST, map);
+
+		assertNotNull(file);
+		assertEquals("com.springsource.org.apache.commons.beanutils-1.6.1.jar", file.getName());
+		assertTrue(file.isFile());
+
+		Map<String,String> map2 = MAP.$("groupId", "org.apache.commons").$("scope", "compile");
+
+		file = mr.get("com.springsource.org.apache.commons.beanutils", "1.6.1", Strategy.LOWEST, map2);
+		assertNotNull(file);
+		assertTrue(file.isFile());
+		assertEquals("compile.lib", file.getName());
+		String lib = IO.collect(file);
+		System.err.println(lib);
+		lib = lib.replaceAll("org.apache.commons\\+com.springsource.org.apache.commons.beanutils;version=\"1.6.1\"",
+				"1");
+		lib = lib.replaceAll("org.apache.commons\\+com.springsource.org.apache.commons.collections;version=\"2.1.1\"",
+				"2");
+		lib = lib.replaceAll("org.apache.commons\\+com.springsource.org.apache.commons.logging;version=\"1.0.4\"", "3");
+		assertEquals("1\n2\n3\n", lib);
+	}
+
+	/**
+	 * Test parsing a project pom
+	 * 
+	 * @throws Exception
+	 */
+
+	public static void testProjectPom() throws Exception {
+		Maven maven = new Maven(null);
+		ProjectPom pom = maven.createProjectModel(IO.getFile(cwd, "test/ws/maven1/testpom.xml"));
+		assertEquals("artifact", pom.getArtifactId());
+		assertEquals("group-parent", pom.getGroupId());
+		assertEquals("1.0.0", pom.getVersion());
+		assertEquals("Artifact", pom.getName());
+		assertEquals("Parent Description\n\nDescription artifact", pom.getDescription());
+
+		List<Dependency> dependencies = pom.getDependencies();
+		boolean dep1 = false; // dep1
+		boolean dep2 = false; // artifact (after macro)
+		boolean dep3 = false; // junit
+		boolean dep4 = false; // easymock
+
+		for (Dependency dep : dependencies) {
+			String artifactId = dep.getArtifactId();
+			if ("dep1".equals(artifactId)) {
+				assertFalse(dep1);
+				dep1 = true;
+				assertEquals("xyz", dep.getGroupId());
+				assertEquals("1.0.1", dep.getVersion());
+				assertEquals(Pom.Scope.valueOf("compile"), dep.getScope());
+
+			} else if ("artifact".equals(artifactId)) {
+				assertFalse(dep2);
+				dep2 = true;
+				assertEquals("group-parent", dep.getGroupId());
+				assertEquals("1.0.2", dep.getVersion());
+				assertEquals(Pom.Scope.valueOf("compile"), dep.getScope());
+			} else if ("junit".equals(artifactId)) {
+				assertFalse(dep3);
+				dep3 = true;
+				assertEquals("junit", dep.getGroupId());
+				assertEquals("4.0", dep.getVersion());
+				assertEquals(Pom.Scope.valueOf("test"), dep.getScope());
+			} else if ("easymock".equals(artifactId)) {
+				assertFalse(dep4);
+				dep4 = true;
+				assertEquals("org.easymock", dep.getGroupId());
+				assertEquals("2.4", dep.getVersion());
+				assertEquals(Pom.Scope.valueOf("compile"), dep.getScope());
+			} else
+				fail("'" + artifactId + "'");
+		}
+		assertTrue(dep1 && dep2 && dep3 && dep4);
+
+		assertEquals("aa", pom.getProperty("a"));
+		assertEquals("b from parent", pom.getProperty("b"));
+		assertEquals("aab from parentartifact", pom.getProperty("c"));
+	}
+
+	/**
+	 * Test the maven remote repository
+	 */
+
+	public static void testMavenRepo1() throws Exception {
+		Maven maven = new Maven(null);
+		MavenRemoteRepository mr = new MavenRemoteRepository();
+		mr.setMaven(maven);
+
+		MavenEntry me = maven.getEntry("org.apache.commons", "com.springsource.org.apache.commons.beanutils", "1.6.1");
+		me.remove();
+
+		me = maven.getEntry("org.apache.commons", "com.springsource.org.apache.commons.collections", "2.1.1");
+		me.remove();
+
+		me = maven.getEntry("org.apache.commons", "com.springsource.org.apache.commons.logging", "1.0.4");
+		me.remove();
+
+		mr.setRepositories(new URI[] {
+			IO.getFile(new File("").getAbsoluteFile(), "test/ws/maven1/m2").toURI()
+		});
+
+		Map<String,String> map = new HashMap<String,String>();
+		map.put("scope", "compile");
+		File file = mr.get("org.apache.commons+com.springsource.org.apache.commons.beanutils", "1.6.1",
+				Strategy.LOWEST, map);
+
+		assertNotNull(file);
+		assertTrue(file.isFile());
+
+		assertEquals("org.apache.commons+com.springsource.org.apache.commons.beanutils;version=\"1.6.1\"\n"
+				+ "org.apache.commons+com.springsource.org.apache.commons.collections;version=\"2.1.1\"\n"
+				+ "org.apache.commons+com.springsource.org.apache.commons.logging;version=\"1.0.4\"\n",
+				IO.collect(file));
+
+		file = mr.get("org.apache.commons+com.springsource.org.apache.commons.beanutils", "1.6.1", Strategy.LOWEST,
+				null);
+		assertEquals("com.springsource.org.apache.commons.beanutils-1.6.1.jar", file.getName());
+	}
+
+	public static void testMavenx() throws Exception {
+		Maven maven = new Maven(null);
+		CachedPom pom = maven.getPom("javax.xml.bind", "com.springsource.javax.xml.bind", "2.2.0", new URI(
+				"http://repository.springsource.com/maven/bundles/release"), new URI(
+				"http://repository.springsource.com/maven/bundles/external"));
+		// Pom pom = maven.getPom("javax.xml.ws",
+		// "com.springsource.javax.xml.ws", "2.1.1", new
+		// URL("http://repository.springsource.com/maven/bundles/release"), new
+		// URL("http://repository.springsource.com/maven/bundles/external"));
+		System.err.println(pom.getGroupId() + " + " + pom.getArtifactId() + "-" + pom.getVersion());
+
+		System.err.println(pom.getDependencies(Pom.Scope.compile));
+
+		File artifact = pom.getArtifact();
+		System.err.println(artifact);
+	}
+
+	/**
+	 * Test the pom parser which will turn the pom into a set of properties,
+	 * which will make it actually readable according to some.
+	 * 
+	 * @throws Exception
+	 */
+
+	public static void testPomParser() throws Exception {
+		PomParser parser = new PomParser();
+		Properties p = parser.getProperties(new File("test/ws/maven1/pom.xml"));
+		p.store(System.err, "testing");
+		assertEquals("Apache Felix Metatype Service", p.get("pom.name"));
+		assertEquals("org.apache.felix", p.get("pom.groupId")); // is from
+																// parent
+		assertEquals("org.apache.felix.metatype", p.get("pom.artifactId"));
+		assertEquals("bundle", p.get("pom.packaging"));
+
+		Parameters map = parser.parseHeader(p.getProperty("pom.scope.test"));
+		Map<String,String> junit = map.get("junit.junit");
+		assertNotNull(junit);
+		assertEquals("4.0", junit.get("version"));
+		Map<String,String> easymock = map.get("org.easymock.easymock");
+		assertNotNull(easymock);
+		assertEquals("2.4", easymock.get("version"));
+	}
+
+	// public void testDependencies() throws Exception {
+	// MavenDependencyGraph graph;
+	//
+	// graph = new MavenDependencyGraph();
+	// File home = new File( System.getProperty("user.home"));
+	// File m2 = new File( home, ".m2");
+	// File m2Repo = new File( m2, "repository");
+	// if ( m2Repo.isDirectory())
+	// graph.addRepository( m2Repo.toURI().toURL());
+	//
+	// graph.addRepository( new URL("http://repo1.maven.org/maven2/"));
+	// graph.addRepository( new
+	// URL("http://repository.springsource.com/maven/bundles/external"));
+	// // graph.root.add( new File("test/poms/pom-1.xml").toURI().toURL());
+	//
+	// }
+
+	// public void testMaven() throws Exception {
+	// MavenRepository maven = new MavenRepository();
+	// maven.setReporter(processor);
+	// maven.setProperties(new HashMap<String, String>());
+	// maven.setRoot(processor.getFile("test/maven-repo"));
+	//
+	// File files[] = maven.get("activation.activation", null);
+	// assertNotNull(files);
+	// assertEquals("activation-1.0.2.jar", files[0].getName());
+	//
+	// files = maven.get("biz.aQute.bndlib", null);
+	// assertNotNull(files);
+	// assertEquals(5, files.length);
+	// assertEquals("bndlib-0.0.145.jar", files[0].getName());
+	// assertEquals("bndlib-0.0.255.jar", files[4].getName());
+	//
+	// List<String> names = maven.list(null);
+	// System.err.println(names);
+	// assertEquals(13, names.size());
+	// assertTrue(names.contains("biz.aQute.bndlib"));
+	// assertTrue(names.contains("org.apache.felix.javax.servlet"));
+	// assertTrue(names.contains("org.apache.felix.org.osgi.core"));
+	//
+	// List<Version> versions =
+	// maven.versions("org.apache.felix.javax.servlet");
+	// assertEquals(1, versions.size());
+	// versions.contains(new Version("1.0.0"));
+	//
+	// versions = maven.versions("biz.aQute.bndlib");
+	// assertEquals(5, versions.size());
+	// versions.contains(new Version("0.0.148"));
+	// versions.contains(new Version("0.0.255"));
+	// }
+
+	// public void testMavenBsnMapping() throws Exception {
+	// Processor processor = new Processor();
+	// processor
+	// .setProperty("-plugin",
+	// "aQute.bnd.maven.MavenGroup; groupId=org.apache.felix, aQute.bnd.maven.MavenRepository");
+	// MavenRepository maven = new MavenRepository();
+	// maven.setReporter(processor);
+	// Map<String, String> map = new HashMap<String, String>();
+	// map.put("root", IO.getFile(cwd,"test/maven-repo").getAbsolutePath());
+	// maven.setProperties(map);
+	//
+	// File files[] = maven.get("org.apache.felix.framework", null);
+	// assertNotNull(files);
+	// ;
+	// assertEquals(1, files.length);
+	// }
+}
diff --git a/biz.aQute.bndlib.tests/src/test/MergeTest.java b/biz.aQute.bndlib.tests/src/test/MergeTest.java
new file mode 100644
index 0000000..37867dd
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/MergeTest.java
@@ -0,0 +1,78 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+
+public class MergeTest extends TestCase {
+
+	public static void testFirst() throws Exception {
+		testMerge("first", new String[] {
+				"A", "C"
+		}, new String[] {
+			"B"
+		}, "first", 0, 0);
+	}
+
+	public static void testMergeFirst() throws Exception {
+		testMerge("merge-first", new String[] {
+				"A", "B", "C"
+		}, new String[] {
+			""
+		}, "first", 0, 0);
+	}
+
+	public static void testDefault() throws Exception {
+		testMerge(null, new String[] {
+				"A", "B", "C"
+		}, new String[] {}, "first", 0, 1);
+	}
+
+	public static void testMergeLast() throws Exception {
+		testMerge("merge-last", new String[] {
+				"A", "B", "C"
+		}, new String[] {
+			""
+		}, "last", 0, 0);
+	}
+
+	public static void testError() throws Exception {
+		testMerge("error", null, null, null, 1, 1);
+	}
+
+	static void testMerge(String type, String[] in, String[] out, String c, int errors, int warnings) throws Exception {
+		Builder b = new Builder();
+		b.setClasspath(new File[] {
+				new File("src/test/split/split-a.jar"), new File("src/test/split/split-b.jar")
+		});
+		Properties p = new Properties();
+		if (type != null)
+			p.put("Export-Package", "test.split;-split-package:=" + type);
+		else
+			p.put("Export-Package", "test.split");
+		p.put("Import-Package", "");
+		b.setProperties(p);
+		Jar jar = b.build();
+
+		System.err.println("Errors     :" + b.getErrors());
+		System.err.println("Warnings   :" + b.getWarnings());
+		assertEquals(errors, b.getErrors().size());
+		assertEquals(warnings, b.getWarnings().size());
+		if (errors != 0)
+			return;
+
+		for (int i = 0; in != null && i < in.length; i++)
+			assertNotNull("Contains " + in[i], jar.getResource("test/split/" + in[i]));
+		for (int i = 0; out != null && i < out.length; i++)
+			assertNull("Does not contain " + out[i], jar.getResource("test/split/" + out[i]));
+
+		Resource r = jar.getResource("test/split/C");
+		InputStream is = r.openInputStream();
+		BufferedReader dis = new BufferedReader(new InputStreamReader(is));
+		String s = dis.readLine();
+		assertEquals(s, c);
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/MetatypeTests.java b/biz.aQute.bndlib.tests/src/test/MetatypeTests.java
new file mode 100644
index 0000000..80d8149
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/MetatypeTests.java
@@ -0,0 +1,15 @@
+package test;
+
+import junit.framework.*;
+
+public class MetatypeTests {
+
+	public static Test suite() {
+		TestSuite suite = new TestSuite(MetatypeTests.class.getName());
+		// $JUnit-BEGIN$
+		suite.addTestSuite(test.metatype.MetatypeTest.class);
+		// $JUnit-END$
+		return suite;
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/NativeHeader.java b/biz.aQute.bndlib.tests/src/test/NativeHeader.java
new file mode 100755
index 0000000..4c2cdac
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/NativeHeader.java
@@ -0,0 +1,67 @@
+package test;
+
+import java.util.*;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+
+public class NativeHeader extends TestCase {
+	static Builder	b	= new Builder();
+	static {
+		try {
+
+			b.setProperty(
+					"Include-Resource",
+					"x.so;literal='x',y.so;literal='y',native/libclib_jiio.so;literal='',native/libmlib_jai.so;literal='', org/osgi/test/cases/framework/fragments/tb8/linux_x86/libNative.so;literal=''");
+			b.build();
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	public static void testFunnyHeader() throws Exception {
+		Verifier v = new Verifier(b);
+		v.doNative("org/osgi/test/cases/framework/fragments/tb8/linux_x86/libNative.so; osname=Linux; processor=x86; osversion=\"(1000,10000]\",");
+		assertBad(v, "name");
+	}
+
+	public static void testWildcardNotAtEnd() throws Exception {
+		Verifier v = new Verifier(b);
+		v.doNative("x.so;osname=win32,*,x.dll");
+		assertBad(v, "may only END in wildcard");
+	}
+
+	public static void testWildcard() throws Exception {
+		Verifier v = new Verifier(b);
+		v.doNative("x.so ;y.so;osname=Linux;processor=amd64,*");
+		assertOk(v);
+	}
+
+	public static void testSimple() throws Exception {
+		Verifier v = new Verifier(b);
+		v.doNative("\rnative/libclib_jiio.so ;\r" + "native/libmlib_jai.so;\r" + "osname=Linux ;\r"
+				+ "processor=amd64\r");
+		assertOk(v);
+	}
+
+	static void assertOk(Processor v) {
+		System.err.println(v.getWarnings());
+		System.err.println(v.getErrors());
+		assertEquals(0, v.getErrors().size());
+		assertEquals(0, v.getWarnings().size());
+	}
+
+	static void assertBad(Processor v, String ok) {
+		assertEmptyAfterRemove(v.getErrors(), ok);
+		assertEmptyAfterRemove(v.getWarnings(), ok);
+	}
+
+	private static void assertEmptyAfterRemove(List<String> errors, String ok) {
+		for (String s : errors) {
+			if (s.indexOf(ok) < 0)
+				fail("Found error/warning that can not be removed: " + s + " : " + ok);
+		}
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/NoUsesTest.java b/biz.aQute.bndlib.tests/src/test/NoUsesTest.java
new file mode 100644
index 0000000..f1448df
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/NoUsesTest.java
@@ -0,0 +1,122 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+
+import junit.framework.*;
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
+
+public class NoUsesTest extends TestCase {
+
+	/*
+	 * Check if we explicitly set a uses directive, prepend the calculated but
+	 * the calculated is empty. This should remove the extraneuous comma
+	 */
+	public static void testExplicitUsesWithPrependZeroUses() throws Exception {
+		Builder bmaker = new Builder();
+		bmaker.setProperty("Private-Package", "org.osgi.framework");
+		bmaker.setProperty("Export-Package", "org.osgi.util.tracker;uses:=\"<<USES>>,not.used\"");
+		String uses = findUses(bmaker, "org.osgi.util.tracker", "has 1,  private");
+		assertEquals("not.used", uses);
+	}
+
+	/*
+	 * Check if we explicitly set a uses directive, but append it with the
+	 * calculated directive
+	 */
+	public static void testExplicitUsesWithAppend() throws Exception {
+		Builder bmaker = new Builder();
+		bmaker.setProperty("Export-Package", "org.osgi.util.tracker;uses:=\"not.used,<<USES>>\"");
+		String uses = findUses(bmaker, "org.osgi.util.tracker");
+		assertTrue("not.used", uses.indexOf("not.used") >= 0);
+		assertTrue("org.osgi.framework", uses.indexOf("org.osgi.framework") >= 0);
+	}
+
+	/*
+	 * Check if we explicitly set a uses directive, append the calculated but
+	 * the calculated is empty. This should remove the extraneuous comma
+	 */
+	public static void testExplicitUsesWithAppendZeroUses() throws Exception {
+		Builder bmaker = new Builder();
+		bmaker.setProperty("Private-Package", "org.osgi.framework");
+		bmaker.setProperty("Export-Package", "org.osgi.util.tracker;uses:=\"not.used,<<USES>>\"");
+		String uses = findUses(bmaker, "org.osgi.util.tracker", "has 1,  private");
+		assertEquals("not.used", uses);
+	}
+
+	/*
+	 * Check if we explicitly set a uses directive, but append it with the
+	 * calculated directive
+	 */
+	public static void testExplicitUsesWithPrepend() throws Exception {
+		Builder bmaker = new Builder();
+		bmaker.setProperty("Export-Package", "org.osgi.util.tracker;uses:=\"<<USES>>,not.used\"");
+		String uses = findUses(bmaker, "org.osgi.util.tracker");
+		assertTrue("not.used", uses.indexOf("not.used") >= 0);
+		assertTrue("org.osgi.framework", uses.indexOf("org.osgi.framework") >= 0);
+	}
+
+	/*
+	 * Check if we explicitly set a uses directive
+	 */
+	public static void testExplicitUses() throws Exception {
+		Builder bmaker = new Builder();
+		bmaker.setProperty("Export-Package", "org.osgi.util.tracker;uses:=\"not.used\"");
+		String uses = findUses(bmaker, "org.osgi.util.tracker");
+		assertEquals("not.used", uses);
+	}
+
+	public static void testExportedUses() throws Exception {
+		Builder bmaker = new Builder();
+		bmaker.setProperty("Export-Package", "org.osgi.util.tracker, org.osgi.framework");
+		String uses = findUses(bmaker, "org.osgi.util.tracker");
+		assertEquals("org.osgi.framework", uses);
+	}
+
+	public static void testPrivateUses() throws Exception {
+		Builder bmaker = new Builder();
+		bmaker.setProperty("Private-Package", "org.osgi.framework");
+		bmaker.setProperty("Export-Package", "org.osgi.util.tracker");
+		String uses = findUses(bmaker, "org.osgi.util.tracker", "has 1,  private");
+		assertNull("org.osgi.framework", uses);
+	}
+
+	public static void testHasUses() throws Exception {
+		Builder bmaker = new Builder();
+		bmaker.setProperty("Export-Package", "test.activator");
+		String uses = findUses(bmaker, "test.activator");
+		Set<String> usesSet = new HashSet<String>(Arrays.asList(uses.split(",")));
+		assertTrue(usesSet.contains("org.osgi.service.component"));
+		assertTrue(usesSet.contains("org.osgi.framework"));
+	}
+
+	public static void testNoUses() throws Exception {
+		Builder bmaker = new Builder();
+		bmaker.setProperty("Export-Package", "test.activator");
+		bmaker.setProperty("-nouses", "true");
+		String uses = findUses(bmaker, "test.activator");
+		assertNull("org.osgi.framework", uses);
+	}
+
+	static String findUses(Builder bmaker, String pack, String ... ignore) throws Exception {
+		File cp[] = {
+				new File("bin"), new File("jar/osgi.jar")
+		};
+		bmaker.setClasspath(cp);
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check(ignore));
+		String exports = jar.getManifest().getMainAttributes().getValue("Export-Package");
+		assertNotNull("exports", exports);
+		Parameters map = Processor.parseHeader(exports, null);
+		if (map == null)
+			return null;
+
+		Map<String,String> clause = map.get(pack);
+		if (clause == null)
+			return null;
+
+		return clause.get("uses:");
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/PackTest.java b/biz.aQute.bndlib.tests/src/test/PackTest.java
new file mode 100644
index 0000000..f238770
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/PackTest.java
@@ -0,0 +1,18 @@
+package test;
+
+import junit.framework.*;
+
+public class PackTest extends TestCase {
+
+	public void testNot() {}
+
+	// public void testSimple() throws Exception {
+	// Workspace ws= Workspace.getWorkspace("/Ws/aQute");
+	// Project p = ws.getProject("aQute.metatype");
+	// ProjectLauncher pl = p.getProjectLauncher();
+	//
+	// Jar jar = pl.executable();
+	//
+	// }
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/ParseHeaderTest.java b/biz.aQute.bndlib.tests/src/test/ParseHeaderTest.java
new file mode 100755
index 0000000..7e4a7de
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/ParseHeaderTest.java
@@ -0,0 +1,128 @@
+package test;
+
+import java.util.*;
+
+import junit.framework.*;
+import aQute.bnd.header.*;
+import aQute.bnd.header.Attrs.Type;
+import aQute.bnd.osgi.*;
+import aQute.bnd.version.*;
+
+public class ParseHeaderTest extends TestCase {
+
+	public static void testPropertiesSimple() {
+		Map<String,String> p = OSGiHeader.parseProperties("a=1, b=\"3   3\", c=c");
+		assertEquals("1", p.get("a"));
+		assertEquals("3   3", p.get("b"));
+		assertEquals("c", p.get("c"));
+	}
+
+	public static void testClauseName() {
+		assertNames("a,b,c;", new String[] {
+				"a", "b", "c"
+		});
+		assertNames("a,b,c", new String[] {
+				"a", "b", "c"
+		});
+		assertNames("a;x=0,b;x=0,c;x=0", new String[] {
+				"a", "b", "c"
+		});
+		assertNames("a;b;c;x=0", new String[] {
+				"a", "b", "c"
+		});
+		assertNames(",", new String[] {}, null, "Empty clause, usually caused");
+		assertNames("a;a,b", new String[] {
+				"a", "a~", "b"
+		}, null, "Duplicate name a used in header");
+		assertNames("a;x=0;b", new String[] {
+				"a", "b"
+		}, "Header contains name field after attribute or directive", null);
+		assertNames("a;x=0;x=0,b", new String[] {
+				"a", "b"
+		}, null, "Duplicate attribute/directive name");
+		assertNames("a;;;,b", new String[] {
+				"a", "b"
+		});
+		assertNames(",,a,,", new String[] {
+			"a"
+		}, null, "Empty clause, usually caused by repeating");
+		assertNames(",a", new String[] {
+			"a"
+		}, null, "Empty clause, usually caused");
+		assertNames(",a,b,c,", new String[] {
+				"a", "b", "c"
+		}, null, "Empty clause, usually caused");
+		assertNames("a,b,c,", new String[] {
+				"a", "b", "c"
+		}, null, "Empty clause, usually caused");
+		assertNames("a,b,,c", new String[] {
+				"a", "b", "c"
+		}, null, "Empty clause, usually caused");
+	}
+
+	static void assertNames(String header, String[] keys) {
+		assertNames(header, keys, null, null);
+	}
+
+	static void assertNames(String header, String[] keys, String expectedError, String expectedWarning) {
+		Processor p = new Processor();
+		p.setPedantic(true);
+		Parameters map = Processor.parseHeader(header, p);
+		for (String key : keys)
+			assertTrue(map.containsKey(key));
+
+		assertEquals(keys.length, map.size());
+		if (expectedError != null) {
+			System.err.println(p.getErrors());
+			assertTrue(p.getErrors().size() > 0);
+			assertTrue(p.getErrors().get(0).indexOf(expectedError) >= 0);
+		} else
+			assertEquals(0, p.getErrors().size());
+		if (expectedWarning != null) {
+			System.err.println(p.getWarnings());
+			assertTrue(p.getWarnings().size() > 0);
+			String w = p.getWarnings().get(0);
+			assertTrue(w.startsWith(expectedWarning));
+		} else
+			assertEquals(0, p.getWarnings().size());
+	}
+
+	public static void testSimple() {
+		String s = "a;a=a1;b=a2;c=a3, b;a=b1;b=b2;c=b3, c;d;e;a=x1";
+		Parameters map = Processor.parseHeader(s, null);
+		assertEquals(5, map.size());
+
+		Map<String,String> a = map.get("a");
+		assertEquals("a1", a.get("a"));
+		assertEquals("a2", a.get("b"));
+		assertEquals("a3", a.get("c"));
+
+		Map<String,String> d = map.get("d");
+		assertEquals("x1", d.get("a"));
+
+		Map<String,String> e = map.get("e");
+		assertEquals(e, d);
+
+		System.err.println(map);
+	}
+	
+	public static void testParseMultiValueAttribute() {
+		String s = "capability;foo:List<String>=\"MacOSX,Mac OS X\";version:List<Version>=\"1.0, 2.0, 2.1\"";
+		Parameters map = Processor.parseHeader(s, null);
+		
+		Attrs attrs = map.get("capability");
+		
+		assertEquals(Type.STRINGS, attrs.getType("foo"));
+		List<String> foo = (List<String>) attrs.getTyped("foo");
+		assertEquals(2, foo.size());
+		assertEquals("MacOSX", foo.get(0));
+		assertEquals("Mac OS X", foo.get(1));
+		
+		assertEquals(Type.VERSIONS, attrs.getType("version"));
+		List<Version> version = (List<Version>) attrs.getTyped("version");
+		assertEquals(3, version.size());
+		assertEquals(new Version(1), version.get(0));
+		assertEquals(new Version(2), version.get(1));
+		assertEquals(new Version(2, 1), version.get(2));
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/Parser.jclass b/biz.aQute.bndlib.tests/src/test/Parser.jclass
new file mode 100755
index 0000000..5d37be0
Binary files /dev/null and b/biz.aQute.bndlib.tests/src/test/Parser.jclass differ
diff --git a/biz.aQute.bndlib.tests/src/test/PluginTest.java b/biz.aQute.bndlib.tests/src/test/PluginTest.java
new file mode 100644
index 0000000..6978121
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/PluginTest.java
@@ -0,0 +1,89 @@
+package test;
+
+import java.applet.*;
+import java.awt.*;
+import java.util.*;
+import java.util.List;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.*;
+import aQute.service.reporter.*;
+
+public class PluginTest extends TestCase {
+	static Processor	main	= new Processor();
+
+	public static void testMissingPluginNotUsed() throws Exception {
+		Builder p = new Builder();
+		p.setProperty("-plugin", "missing;command:=\"-abc,-def\"");
+		/* List<?> plugins = */p.getPlugins(Object.class);
+		assertEquals(0, p.getErrors().size());
+
+		p.setProperty("-abc", "whatever");
+		p.setProperty("-resourceonly", "true");
+		p.setProperty("Include-Resource", "jar/osgi.jar");
+		p.build();
+		assertEquals(1, p.getErrors().size());
+		assertTrue(p.getErrors().get(0).contains("Missing plugin"));
+	}
+
+	static class TPlugin implements Plugin {
+		Map<String,String>	properties;
+
+		@Override
+		public void setProperties(Map<String,String> map) {
+			properties = map;
+		}
+
+		@Override
+		public void setReporter(Reporter processor) {
+			assertEquals(main, processor);
+		}
+	}
+
+	public static void testPlugin() {
+		main.setProperty(Constants.PLUGIN, "test.PluginTest.TPlugin;a=1;b=2");
+
+		for (TPlugin plugin : main.getPlugins(TPlugin.class)) {
+			assertEquals(test.PluginTest.TPlugin.class, plugin.getClass());
+			assertEquals("1", plugin.properties.get("a"));
+			assertEquals("2", plugin.properties.get("b"));
+		}
+	}
+
+	public static void testLoadPlugin() {
+		main.setProperty(Constants.PLUGIN, "thinlet.Thinlet;path:=jar/thinlet.jar");
+		for (Applet applet : main.getPlugins(Applet.class)) {
+			assertEquals("thinlet.Thinlet", applet.getClass().getName());
+		}
+	}
+
+	public static void testLoadPluginFailsWithMissingPath() throws Exception {
+		Builder p = new Builder();
+		p.setProperty(Constants.PLUGIN, "thinlet.Thinlet");
+
+		p.getPlugins(Object.class);
+		assertEquals(1, p.getErrors().size());
+	}
+
+	public static void testLoadPluginWithPath() {
+		Builder p = new Builder();
+		p.setProperty(Constants.PLUGIN, "thinlet.Thinlet;path:=jar/thinlet.jar");
+
+		List<MenuContainer> plugins = p.getPlugins(MenuContainer.class);
+		assertEquals(0, p.getErrors().size());
+		assertEquals(1, plugins.size());
+		assertEquals("thinlet.Thinlet", plugins.get(0).getClass().getName());
+	}
+
+	public static void testLoadPluginWithGlobalPluginPath() {
+		Builder p = new Builder();
+		p.setProperty(Constants.PLUGIN, "thinlet.Thinlet");
+		p.setProperty(Constants.PLUGINPATH, "jar/thinlet.jar");
+
+		List<MenuContainer> plugins = p.getPlugins(MenuContainer.class);
+		assertEquals(0, p.getErrors().size());
+		assertEquals(1, plugins.size());
+		assertEquals("thinlet.Thinlet", plugins.get(0).getClass().getName());
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/ProcessorTest.java b/biz.aQute.bndlib.tests/src/test/ProcessorTest.java
new file mode 100644
index 0000000..8469eb5
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/ProcessorTest.java
@@ -0,0 +1,43 @@
+package test;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+
+public class ProcessorTest extends TestCase {
+
+	public static void testPlugins() {
+
+	}
+
+	public static void testDuplicates() {
+		assertEquals("", Processor.removeDuplicateMarker("~"));
+
+		assertTrue(Processor.isDuplicate("abc~"));
+		assertTrue(Processor.isDuplicate("abc~~~~~~~~~"));
+		assertTrue(Processor.isDuplicate("~"));
+		assertFalse(Processor.isDuplicate(""));
+		assertFalse(Processor.isDuplicate("abc"));
+		assertFalse(Processor.isDuplicate("ab~c"));
+		assertFalse(Processor.isDuplicate("~abc"));
+
+		assertEquals("abc", Processor.removeDuplicateMarker("abc~"));
+		assertEquals("abc", Processor.removeDuplicateMarker("abc~~~~~~~"));
+		assertEquals("abc", Processor.removeDuplicateMarker("abc"));
+		assertEquals("ab~c", Processor.removeDuplicateMarker("ab~c"));
+		assertEquals("~abc", Processor.removeDuplicateMarker("~abc"));
+		assertEquals("", Processor.removeDuplicateMarker(""));
+		assertEquals("", Processor.removeDuplicateMarker("~~~~~~~~~~~~~~"));
+	}
+
+	public static void appendPathTest() throws Exception {
+		assertEquals("a/b/c", Processor.appendPath("", "a/b/c/"));
+		assertEquals("a/b/c", Processor.appendPath("", "/a/b/c"));
+		assertEquals("a/b/c", Processor.appendPath("/", "/a/b/c/"));
+		assertEquals("a/b/c", Processor.appendPath("a", "b/c/"));
+		assertEquals("a/b/c", Processor.appendPath("a", "b", "c"));
+		assertEquals("a/b/c", Processor.appendPath("a", "b", "/c/"));
+		assertEquals("a/b/c", Processor.appendPath("/", "a", "b", "/c/"));
+		assertEquals("a/b/c", Processor.appendPath("////////", "////a////b///c//"));
+
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/ProjectTest.java b/biz.aQute.bndlib.tests/src/test/ProjectTest.java
new file mode 100755
index 0000000..3be1a9a
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/ProjectTest.java
@@ -0,0 +1,479 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+
+import junit.framework.*;
+import aQute.bnd.build.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.eclipse.*;
+import aQute.bnd.service.*;
+import aQute.bnd.version.*;
+import aQute.lib.deployer.*;
+import aQute.lib.io.*;
+
+public class ProjectTest extends TestCase {
+	
+	/**
+	 * #194 StackOverflowError when -runbundles in bnd.bnd refers to itself
+	 */
+	
+	public static void testProjectReferringToItself() throws Exception {
+		Workspace ws = new Workspace(new File("test/ws"));
+		Project top = ws.getProject("bug194");
+		top.addClasspath(top.getOutput());
+		assertTrue(top.check("Circular dependency context"));
+	}
+	/**
+	 * Test if you can add directories and files to the
+	 * classpath. Originally checked only for files
+	 */
+	
+	public static void testAddDirToClasspath() throws Exception {
+		Workspace ws = new Workspace(new File("test/ws"));
+		Project top = ws.getProject("p1");
+		top.addClasspath(top.getOutput());
+		assertTrue(top.check());
+	}
+	/**
+	 * Test bnd.bnd of project `foo`: `-runbundles: foo;version=latest`
+	 */
+	public static void testRunBundlesContainsSelf() throws Exception {
+		Workspace ws = new Workspace(new File("test/ws"));
+		Project top = ws.getProject("p1");
+		top.setProperty("-runbundles", "p1;version=latest");
+		top.setChanged();
+		top.isStale();
+		Collection<Container> runbundles = top.getRunbundles();
+		assertTrue(top.check("Circular dependency"));
+		assertNotNull(runbundles);
+		assertEquals(0, runbundles.size());
+	}
+
+	/**
+	 * Test 2 equal bsns but diff. versions
+	 */
+
+	public static void testSameBsnRunBundles() throws Exception {
+		Workspace ws = new Workspace(new File("test/ws"));
+		Project top = ws.getProject("p1");
+		top.setProperty("-runbundles",
+				"org.apache.felix.configadmin;version='[1.0.1,1.0.1]',org.apache.felix.configadmin;version='[1.1.0,1.1.0]'");
+		Collection<Container> runbundles = top.getRunbundles();
+		assertTrue(top.check());
+		assertNotNull(runbundles);
+		assertEquals(2, runbundles.size());
+	}
+
+	/**
+	 * Duplicates in runbundles gave a bad error, should be ignored
+	 */
+
+	public static void testRunbundleDuplicates() throws Exception {
+		Workspace ws = new Workspace(new File("test/ws"));
+		Project top = ws.getProject("p1");
+		top.clear();
+		top.setProperty("-runbundles", "org.apache.felix.configadmin,org.apache.felix.configadmin");
+		Collection<Container> runbundles = top.getRunbundles();
+		assertTrue(top.check("Multiple bundles with the same final URL"));
+		assertNotNull(runbundles);
+		assertEquals(1, runbundles.size());
+	}
+
+	/**
+	 * Check isStale
+	 */
+
+	public static void testIsStale() throws Exception {
+		Workspace ws = Workspace.getWorkspace(new File("test/ws"));
+		ws.setOffline(false);
+		Project top = ws.getProject("p-stale");
+		assertNotNull(top);
+		top.build();
+		Project bottom = ws.getProject("p-stale-dep");
+		assertNotNull(bottom);
+		bottom.build();
+
+		long lastModified = bottom.lastModified();
+		top.getPropertiesFile().setLastModified(lastModified + 1000);
+
+		stale(top, true);
+		stale(bottom, true);
+		assertTrue(top.isStale());
+		assertTrue(bottom.isStale());
+
+		stale(top, false);
+		stale(bottom, true);
+		assertTrue(top.isStale());
+		assertTrue(bottom.isStale());
+
+		stale(top, true);
+		stale(bottom, false);
+		assertTrue(top.isStale());
+		assertFalse(bottom.isStale());
+
+		// Thread.sleep(1000);
+		// stale(top, false);
+		// stale(bottom, false);
+		// assertFalse(top.isStale());
+		// assertFalse(bottom.isStale());
+	}
+
+	private static void stale(Project project, boolean b) throws Exception {
+		File file = project.getBuildFiles(false)[0];
+		if (b)
+			file.setLastModified(project.lastModified() - 10000);
+		else
+			file.setLastModified(project.lastModified() + 10000);
+	}
+
+	/**
+	 * Check multiple repos
+	 * 
+	 * @throws Exception
+	 */
+	public static void testMultipleRepos() throws Exception {
+		Workspace ws = Workspace.getWorkspace(new File("test/ws"));
+		Project project = ws.getProject("p1");
+		System.err.println(project.getBundle("org.apache.felix.configadmin", "1.1.0", Strategy.EXACT, null));
+		System.err.println(project.getBundle("org.apache.felix.configadmin", "1.1.0", Strategy.HIGHEST, null));
+		System.err.println(project.getBundle("org.apache.felix.configadmin", "1.1.0", Strategy.LOWEST, null));
+	}
+
+	/**
+	 * Check if the getSubBuilders properly predicts the output.
+	 */
+
+	public static void testSubBuilders() throws Exception {
+		Workspace ws = Workspace.getWorkspace(new File("test/ws"));
+		Project project = ws.getProject("p4-sub");
+
+		Collection< ? extends Builder> bs = project.getSubBuilders();
+		assertNotNull(bs);
+		assertEquals(3, bs.size());
+		Set<String> names = new HashSet<String>();
+		for (Builder b : bs) {
+			names.add(b.getBsn());
+		}
+		assertTrue(names.contains("p4-sub.a"));
+		assertTrue(names.contains("p4-sub.b"));
+		assertTrue(names.contains("p4-sub.c"));
+
+		File[] files = project.build();
+		assertTrue(project.check());
+
+		System.err.println(Processor.join(project.getErrors(), "\n"));
+		System.err.println(Processor.join(project.getWarnings(), "\n"));
+		assertEquals(0, project.getErrors().size());
+		assertEquals(0, project.getWarnings().size());
+		assertNotNull(files);
+		assertEquals(3, files.length);
+		for (File file : files) {
+			Jar jar = new Jar(file);
+			Manifest m = jar.getManifest();
+			assertTrue(names.contains(m.getMainAttributes().getValue("Bundle-SymbolicName")));
+		}
+	}
+
+	/**
+	 * Tests the handling of the -sub facility
+	 * 
+	 * @throws Exception
+	 */
+
+	public static void testSub() throws Exception {
+		Workspace ws = Workspace.getWorkspace(new File("test/ws"));
+		Project project = ws.getProject("p4-sub");
+		File[] files = project.build();
+		Arrays.sort(files);
+
+		System.err.println(Processor.join(project.getErrors(), "\n"));
+		System.err.println(Processor.join(project.getWarnings(), "\n"));
+
+		assertEquals(0, project.getErrors().size());
+		assertEquals(0, project.getWarnings().size());
+		assertNotNull(files);
+		assertEquals(3, files.length);
+
+		Jar a = new Jar(files[0]);
+		Jar b = new Jar(files[1]);
+		Manifest ma = a.getManifest();
+		Manifest mb = b.getManifest();
+
+		assertEquals("base", ma.getMainAttributes().getValue("Base-Header"));
+		assertEquals("base", mb.getMainAttributes().getValue("Base-Header"));
+		assertEquals("a", ma.getMainAttributes().getValue("Sub-Header"));
+		assertEquals("b", mb.getMainAttributes().getValue("Sub-Header"));
+	}
+
+	public static void testOutofDate() throws Exception {
+		Workspace ws = Workspace.getWorkspace(new File("test/ws"));
+		Project project = ws.getProject("p3");
+		File bnd = new File("test/ws/p3/bnd.bnd");
+		assertTrue(bnd.exists());
+
+		project.clean();
+		File pt = project.getTarget();
+		if (!pt.exists() && !pt.mkdirs()) {
+			throw new IOException("Could not create directory " + pt);
+		}
+		try {
+			// Now we build it.
+			File[] files = project.build();
+			System.err.println(project.getErrors());
+			System.err.println(project.getWarnings());
+			assertTrue(project.isOk());
+			assertNotNull(files);
+			assertEquals(1, files.length);
+
+			// Now we should not rebuild it
+			long lastTime = files[0].lastModified();
+			files = project.build();
+			assertEquals(1, files.length);
+			assertTrue(files[0].lastModified() == lastTime);
+
+			Thread.sleep(2000);
+
+			project.updateModified(System.currentTimeMillis(), "Testing");
+			files = project.build();
+			assertEquals(1, files.length);
+			assertTrue("Must have newer files now", files[0].lastModified() > lastTime);
+		}
+		finally {
+			project.clean();
+		}
+	}
+
+	public static void testRepoMacro() throws Exception {
+		Workspace ws = Workspace.getWorkspace(new File("test/ws"));
+		Project project = ws.getProject("p2");
+		System.err.println(project.getPlugins(FileRepo.class));
+		String s = project.getReplacer().process(("${repo;libtest}"));
+		System.err.println(s);
+		assertTrue(s.contains("org.apache.felix.configadmin" + File.separator + "org.apache.felix.configadmin-1.2.0"));
+		assertTrue(s.contains("org.apache.felix.ipojo" + File.separator + "org.apache.felix.ipojo-1.0.0.jar"));
+
+		s = project.getReplacer().process(("${repo;libtestxyz}"));
+		assertTrue(s.matches("<<[^>]+>>"));
+
+		s = project.getReplacer().process("${repo;org.apache.felix.configadmin;1.0.0;highest}");
+		assertTrue(s.endsWith("org.apache.felix.configadmin-1.2.0.jar"));
+		s = project.getReplacer().process("${repo;org.apache.felix.configadmin;1.0.0;lowest}");
+		assertTrue(s.endsWith("org.apache.felix.configadmin-1.0.1.jar"));
+	}
+
+	public static void testClasspath() throws Exception {
+		File project = new File("").getAbsoluteFile();
+		File workspace = project.getParentFile();
+		Processor processor = new Processor();
+		EclipseClasspath p = new EclipseClasspath(processor, workspace, project);
+		System.err.println(p.getDependents());
+		System.err.println(p.getClasspath());
+		System.err.println(p.getSourcepath());
+		System.err.println(p.getOutput());
+	}
+
+	public static void testBump() throws Exception {
+		File tmp = new File("tmp-ws");
+		if (tmp.exists())
+			IO.deleteWithException(tmp);
+		tmp.mkdir();
+		assertTrue(tmp.isDirectory());
+
+		try {
+			IO.copy(new File("test/ws"), tmp);
+			Workspace ws = Workspace.getWorkspace(tmp);
+			Project project = ws.getProject("p1");
+			int size = project.getProperties().size();
+			Version old = new Version(project.getProperty("Bundle-Version"));
+			System.err.println("Old version " + old);
+			project.bump("=+0");
+			Version newv = new Version(project.getProperty("Bundle-Version"));
+			System.err.println("New version " + newv);
+			assertEquals(old.getMajor(), newv.getMajor());
+			assertEquals(old.getMinor() + 1, newv.getMinor());
+			assertEquals(0, newv.getMicro());
+			assertEquals(size, project.getProperties().size());
+			assertEquals("sometime", newv.getQualifier());
+		}
+		finally {
+			IO.deleteWithException(tmp);
+		}
+	}
+
+	public static void testBumpIncludeFile() throws Exception {
+		File tmp = new File("tmp-ws");
+		if (tmp.exists())
+			IO.deleteWithException(tmp);
+		tmp.mkdir();
+		assertTrue(tmp.isDirectory());
+
+		try {
+			IO.copy(new File("test/ws"), tmp);
+			Workspace ws = Workspace.getWorkspace(tmp);
+			Project project = ws.getProject("bump-included");
+			project.setTrace(true);
+			Version old = new Version(project.getProperty("Bundle-Version"));
+			assertEquals(new Version(1, 0, 0), old);
+			project.bump("=+0");
+
+			Processor processor = new Processor();
+			processor.setProperties(project.getFile("include.txt"));
+
+			Version newv = new Version(processor.getProperty("Bundle-Version"));
+			System.err.println("New version " + newv);
+			assertEquals(1, newv.getMajor());
+			assertEquals(1, newv.getMinor());
+			assertEquals(0, newv.getMicro());
+		}
+		finally {
+			IO.deleteWithException(tmp);
+		}
+	}
+
+	public static void testBumpSubBuilders() throws Exception {
+		File tmp = new File("tmp-ws");
+		if (tmp.exists())
+			IO.deleteWithException(tmp);
+		tmp.mkdir();
+		assertTrue(tmp.isDirectory());
+
+		try {
+			IO.copy(new File("test/ws"), tmp);
+			Workspace ws = Workspace.getWorkspace(tmp);
+			Project project = ws.getProject("bump-sub");
+			project.setTrace(true);
+
+			assertNull(project.getProperty("Bundle-Version"));
+
+			project.bump("=+0");
+
+			assertNull(project.getProperty("Bundle-Version"));
+
+			for (Builder b : project.getSubBuilders()) {
+				assertEquals(new Version(1, 1, 0), new Version(b.getVersion()));
+			}
+		}
+		finally {
+			IO.deleteWithException(tmp);
+		}
+	}
+
+	public static void testRunBuilds() throws Exception {
+		Workspace ws = Workspace.getWorkspace(new File("test/ws"));
+
+		// Running a .bnd includes built bundles by default
+		Project p1 = ws.getProject("p1");
+		assertTrue(p1.getRunBuilds());
+
+		// Can override the default by specifying -runbuilds: false
+		Project p2 = ws.getProject("p2");
+		assertFalse(p2.getRunBuilds());
+
+		// Running a .bndrun DOES NOT include built bundles by default
+		Project p1a = new Project(ws, new File("test/ws/p1"), new File("test/ws/p1/p1a.bndrun"));
+		assertFalse(p1a.getRunBuilds());
+
+		// ... unless we override the default by specifying -runbuilds: true
+		Project p1b = new Project(ws, new File("test/ws/p1"), new File("test/ws/p1/p1b.bndrun"));
+		assertTrue(p1b.getRunBuilds());
+	}
+
+	public static void testSetPackageVersion() throws Exception {
+		File tmp = new File("tmp-ws");
+		if (tmp.exists())
+			IO.deleteWithException(tmp);
+		tmp.mkdir();
+		assertTrue(tmp.isDirectory());
+
+		try {
+			IO.copy(new File("test/ws"), tmp);
+			Workspace ws = Workspace.getWorkspace(tmp);
+			Project project = ws.getProject("p5");
+			project.setTrace(true);
+
+			Version newVersion = new Version(2,0,0);
+
+			// Package with no package info
+			project.setPackageInfo("pkg1", newVersion);
+			Version version = project.getPackageInfo("pkg1");
+			assertEquals(newVersion, version);
+			checkPackageInfoFiles(project, "pkg1", true, false);
+
+			// Package with package-info.java containing @Version("1.0.0")
+			project.setPackageInfo("pkg2", newVersion);
+			version = project.getPackageInfo("pkg2");
+			assertEquals(newVersion, version);
+			checkPackageInfoFiles(project, "pkg2", false, true);
+
+			// Package with package-info.java containing @aQute.bnd.annotations.Version("1.0.0")
+			project.setPackageInfo("pkg3", newVersion);
+			version = project.getPackageInfo("pkg3");
+			assertEquals(newVersion, version);
+			checkPackageInfoFiles(project, "pkg3", false, true);
+
+			// Package with package-info.java containing @aQute.bnd.annotations.Version(value="1.0.0")
+			project.setPackageInfo("pkg4", newVersion);
+			version = project.getPackageInfo("pkg4");
+			assertEquals(newVersion, version);
+			checkPackageInfoFiles(project, "pkg4", false, true);
+
+			// Package with package-info.java containing version + packageinfo
+			project.setPackageInfo("pkg5", newVersion);
+			version = project.getPackageInfo("pkg5");
+			assertEquals(newVersion, version);
+			checkPackageInfoFiles(project, "pkg5", true, true);
+
+			// Package with package-info.java NOT containing version + packageinfo
+			project.setPackageInfo("pkg6", newVersion);
+			version = project.getPackageInfo("pkg6");
+			assertEquals(newVersion, version);
+			checkPackageInfoFiles(project, "pkg6", true, true);
+
+			// Package with package-info.java NOT containing version
+			project.setPackageInfo("pkg7", newVersion);
+			version = project.getPackageInfo("pkg7");
+			assertEquals(newVersion, version);
+			checkPackageInfoFiles(project, "pkg7", true, true);
+
+			newVersion = new Version(2,2,0);
+
+			// Update packageinfo file
+			project.setPackageInfo("pkg1", newVersion);
+			version = project.getPackageInfo("pkg1");
+			assertEquals(newVersion, version);
+			checkPackageInfoFiles(project, "pkg1", true, false);
+
+		}
+		finally {
+			IO.deleteWithException(tmp);
+		}
+	}
+
+	private static void checkPackageInfoFiles(Project project, String packageName, boolean expectPackageInfo, boolean expectPackageInfoJava) throws Exception {
+		File pkgInfo = IO.getFile(project.getSrc(), packageName + "/packageinfo");
+		File pkgInfoJava = IO.getFile(project.getSrc(), packageName + "/package-info.java");
+		assertEquals(expectPackageInfo, pkgInfo.exists());
+		assertEquals(expectPackageInfoJava, pkgInfoJava.exists());
+	}
+	
+	public static void testBuildAll() throws Exception {
+		assertTrue(testBuildAll("*", 14).check()); //there are 14 projects
+		assertTrue(testBuildAll("p*", 8).check()); //7 begin with p, plus build-all
+		assertTrue(testBuildAll("!p*, *", 6).check()); // negation: 6 don't begin with p, including build-all
+		assertTrue(testBuildAll("*-*", 7).check()); //more than one wildcard: 7 have a dash
+		assertTrue(testBuildAll("!p*, p1, *", 6).check("Missing dependson p1")); //check that an unused instruction is an error
+		assertTrue(testBuildAll("p*, !*-*, *", 11).check()); // check that negation works after some projects have been selected.
+	}
+	
+	private static Project testBuildAll(String dependsOn, int count) throws Exception {
+		Workspace ws = new Workspace(new File("test/ws"));
+		Project all = ws.getProject("build-all");
+		all.setProperty("-dependson", dependsOn);
+		all.prepare();
+		Collection<Project> dependson = all.getDependson();
+		assertEquals(count, dependson.size());
+		return all;
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/PropertiesTest.java b/biz.aQute.bndlib.tests/src/test/PropertiesTest.java
new file mode 100755
index 0000000..b959571
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/PropertiesTest.java
@@ -0,0 +1,124 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+
+import junit.framework.*;
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
+
+public class PropertiesTest extends TestCase {
+	static <T> T notNull(T t) {
+		assertNotNull(t);
+		return t;
+	}
+
+	public static void testFlattening() throws Exception {
+		Processor p = new Processor();
+		p.setProperty("-versionpolicy", "${version;===;${@}}");
+		p.setProperty("x", "x");
+		p.setProperty("_x", "_x");
+
+		Properties flattened = notNull(p.getFlattenedProperties());
+		String x = notNull(flattened.getProperty("-versionpolicy"));
+		assertTrue(x.contains("@"));
+		notNull(flattened.getProperty("x"));
+		assertNull(flattened.getProperty("_x"));
+		assertEquals(2, flattened.size());
+	}
+
+	public static void testFilter() {
+		Processor p1 = new Processor();
+		p1.setProperty("dan", "bandera");
+		p1.setProperty("susan", "sarandon");
+		p1.setProperty("jon", "bostrom");
+
+		Processor p2 = new Processor(p1);
+		p2.setForceLocal(Arrays.asList("dan"));
+		p2.setProperty("susan", "schwarze");
+
+		assertNull(p2.getProperty("dan"));
+		assertEquals("schwarze", p2.getProperty("susan"));
+		assertEquals("bostrom", p2.getProperty("jon"));
+	}
+	
+	public static void testUnicode() {
+		StringBuilder sb = new StringBuilder();
+		String s = "Loïc Cotonéa";
+		for (int i = 0; i < s.length(); i++) {
+			char c = s.charAt(i);
+			if (c < 0x20 || c > 0x7F) {
+				sb.append("\\u");
+				sb.append(String.format("%04x", (int) c));
+			} else {
+				sb.append(c);
+			}
+		}
+		System.err.println(sb);
+	}
+
+	public static void testSpacesAround() throws Exception {
+		String test = "#comment\n" + "   abc    =   abc\r\n" + "def = def\n\r" + " ghi =               ghi\r"
+				+ " jkl =               jkl";
+
+		byte[] bytes = test.getBytes("ISO8859-1");
+		ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
+		Properties p = new Properties();
+		p.load(bin);
+
+		assertEquals("abc", p.get("abc"));
+		assertEquals("def", p.get("def"));
+		assertEquals("ghi", p.get("ghi"));
+		assertEquals("jkl", p.get("jkl"));
+	}
+
+	public static void testInternationalCharacters() throws Exception {
+		String test = "#comment\n" + "Namex=Lo\u00EFc Coton\u00E9a\n" + "Export-Package: *\n" + "Unicode=\\u0040\n"
+				+ "NameAgain=Loïc Cotonéa";
+
+		byte[] bytes = test.getBytes("ISO8859-1");
+		ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
+		Properties p = new Properties();
+		p.load(bin);
+		assertEquals("@", p.get("Unicode"));
+		assertEquals("Lo\u00EFc Coton\u00E9a", p.get("Namex"));
+
+		// Now test if we can make the round trip
+		Builder b = new Builder();
+		b.setProperties(p);
+		b.addClasspath(new File("jar/asm.jar"));
+		Jar jar = b.build();
+
+		ByteArrayOutputStream bout = new ByteArrayOutputStream();
+		jar.getManifest().write(bout);
+
+		bin = new ByteArrayInputStream(bout.toByteArray());
+		Manifest m = new Manifest(bin);
+
+		assertEquals("Lo\u00EFc Coton\u00E9a", m.getMainAttributes().getValue("Namex"));
+	}
+
+	public static void testBadProperties() throws Exception {
+		Analyzer analyzer = new Analyzer();
+		analyzer.setPedantic(true);
+		analyzer.setProperties(new File("src/test/badproperties.prop"));
+		String s = analyzer.getProperty(Analyzer.IMPORT_PACKAGE);
+		Parameters map = analyzer.parseHeader(s);
+		assertEquals(2, map.size());
+		assertTrue(map.containsKey("org.osgi.service.cm"));
+		assertTrue(map.containsKey("org.osgi.util.tracker"));
+		assertEquals(1, analyzer.getWarnings().size());
+		System.err.println(analyzer.getWarnings());
+		assertTrue(analyzer.getWarnings().get(0).indexOf("Empty clause, usually caused by repeating a comma without") >= 0);
+		System.err.println(analyzer.getWarnings());
+	}
+
+	public static void testProperties() throws Exception {
+		Analyzer analyzer = new Analyzer();
+		analyzer.setProperties(new File("src/test/variables.mf"));
+
+		assertEquals("aQute.test", analyzer.getProperty("Header"));
+		System.err.println("property " + analyzer.getProperty("Header"));
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/RepoBuilderTest.java b/biz.aQute.bndlib.tests/src/test/RepoBuilderTest.java
new file mode 100644
index 0000000..07d0357
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/RepoBuilderTest.java
@@ -0,0 +1,60 @@
+package test;
+
+import junit.framework.*;
+
+public class RepoBuilderTest extends TestCase {
+
+	public static void testA() {}
+
+	// public void testSimple() {
+	// assertBundles("osgi", RepoBuilder.STRATEGY_LOWEST, new
+	// String[]{"osgi-3.0.0.jar"});
+	// assertBundles("osgi", RepoBuilder.STRATEGY_HIGHEST, new
+	// String[]{"osgi-4.2.0.jar"});
+	// assertBundles("osgi;version=4.1", RepoBuilder.STRATEGY_HIGHEST, new
+	// String[]{"osgi-4.2.0.jar"});
+	// assertBundles("osgi;version=4.1", RepoBuilder.STRATEGY_LOWEST, new
+	// String[]{"osgi-4.1.0.jar"});
+	// assertBundles("osgi;version=4.1.1", RepoBuilder.STRATEGY_LOWEST, new
+	// String[]{"osgi-4.2.0.jar"});
+	// assertBundles("osgi;version=\"(4.1,5)\"", RepoBuilder.STRATEGY_LOWEST,
+	// new String[]{"osgi-4.2.0.jar"});
+	// assertBundles("osgi;version=\"[4.1,5)\"", RepoBuilder.STRATEGY_LOWEST,
+	// new String[]{"osgi-4.1.0.jar"});
+	// assertBundles("osgi;version=\"[4.1,5)\"", RepoBuilder.STRATEGY_HIGHEST,
+	// new String[]{"osgi-4.2.0.jar"});
+	// assertBundles("osgi;version=\"[3,4)\"", RepoBuilder.STRATEGY_HIGHEST, new
+	// String[]{"osgi-3.0.0.jar"});
+	// //assertBundles("osgi,org.osgi.impl.service.log,org.osgi.impl.service.cm",
+	// RepoBuilder.STRATEGY_LOWEST, new String[]{"osgi-3.0.0.jar",
+	// "org.osgi.impl.service.cm-2.1.1.jar"});
+	// }
+	//
+	//
+	// void assertBundles(String bundles, int strategy, String endsWith[]) {
+	// RepoBuilder r = new RepoBuilder();
+	// Properties p = new Properties();
+	// p.setProperty("-plugin",
+	// "aQute.lib.deployer.FileRepo;location=src/test/repo");
+	// p.setProperty("-bundles", bundles );
+	// r.setProperties(p);
+	// List<Container> b = r.getBundles(strategy, r.getProperty("-bundles"));
+	// List<File> l = new ArrayList<File>();
+	// for ( Container c : b )
+	// l.add(c.getFile());
+	// check(r);
+	// assertEquals( endsWith.length, b.size());
+	// for ( int i =0; i<endsWith.length; i++ ) {
+	// assertTrue(endsWith[i] + " : " + l.get(i),
+	// l.get(i).toString().endsWith(endsWith[i]));
+	// }
+	// System.err.println(b);
+	// }
+	//
+	// void check(Analyzer r) {
+	// System.err.println(r.getErrors());
+	// System.err.println(r.getWarnings());
+	// assertEquals(0, r.getWarnings().size());
+	// assertEquals(0, r.getErrors().size());
+	// }
+}
diff --git a/biz.aQute.bndlib.tests/src/test/RepoTreeTest.java b/biz.aQute.bndlib.tests/src/test/RepoTreeTest.java
new file mode 100644
index 0000000..82e3c40
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/RepoTreeTest.java
@@ -0,0 +1,59 @@
+
+package test;
+
+import static org.mockito.Mockito.*;
+
+import java.util.*;
+
+import junit.framework.*;
+import aQute.bnd.differ.*;
+import aQute.bnd.service.*;
+import aQute.bnd.service.diff.*;
+import aQute.bnd.version.*;
+import aQute.lib.collections.*;
+
+public class RepoTreeTest extends TestCase {
+	public static void testSimple() throws Exception {
+		RepositoryPlugin a = mock(RepositoryPlugin.class);
+		RepositoryPlugin b = mock(RepositoryPlugin.class);
+		
+		when(a.getName()).thenReturn("a");
+		when(a.list(null)).thenReturn(Arrays.asList("a","b"));
+		when(a.versions("a")).thenReturn(new SortedList<Version>(new Version("1"), new Version("2")));
+		when(a.versions("b")).thenReturn(new SortedList<Version>(new Version("2"), new Version("3")));
+
+		when(b.getName()).thenReturn("b");
+		when(b.list(null)).thenReturn(Arrays.asList("b","c"));
+		when(b.versions("b")).thenReturn(new SortedList<Version>(new Version("1"), new Version("2")));
+		when(b.versions("c")).thenReturn(new SortedList<Version>(new Version("2"), new Version("3")));
+		
+		Tree ta = RepositoryElement.getTree(a);
+		Tree tb = RepositoryElement.getTree(b);
+		
+		Diff diff = new DiffImpl(ta, tb);
+		print(diff,0);
+		
+		assertEquals(Delta.MAJOR, diff.getDelta());
+		assertEquals(Type.PROGRAM, diff.get("a").getType());
+		assertEquals(Type.VERSION, diff.get("a").get("1.0.0").getType());
+		assertEquals(Delta.ADDED, diff.get("a").get("1.0.0").getDelta());
+		assertEquals(Delta.ADDED, diff.get("a").get("2.0.0").getDelta());
+		
+		assertEquals(Delta.REMOVED, diff.get("b").get("1.0.0").getDelta());
+		assertEquals(Delta.UNCHANGED, diff.get("b").get("2.0.0").getDelta());
+		assertEquals(Delta.ADDED, diff.get("b").get("3.0.0").getDelta());
+		
+		assertEquals(Delta.REMOVED, diff.get("c").getDelta());
+		assertEquals(Delta.REMOVED, diff.get("c").get("2.0.0").getDelta());
+		assertEquals(Delta.REMOVED, diff.get("c").get("3.0.0").getDelta());
+		
+	}
+	
+	static void print(Diff diff , int n) {
+		System.out.println("                            ".substring(0,n) + diff.getName() + " " + diff.getType() + "  " + diff.getDelta());
+		for ( Diff c : diff.getChildren()) {
+			print(c, n+1);
+		}
+		
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/ResourcesTest.java b/biz.aQute.bndlib.tests/src/test/ResourcesTest.java
new file mode 100644
index 0000000..77c7e6e
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/ResourcesTest.java
@@ -0,0 +1,325 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+
+public class ResourcesTest extends TestCase {
+
+	/**
+	 * If a name starts with a - sign then it is ok if it does not exist. The -
+	 * sign must be skipped obviously.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testAbsentIsOk() throws Exception {
+		{
+			Builder b = new Builder();
+			b.setProperty("Include-Resource", "TargetFolder=-test/ws/p2/Resources");
+			b.setProperty("-resourceonly", "true");
+			Jar jar = b.build();
+			assertTrue(b.check());
+			Resource r = jar.getResource("TargetFolder/resource1.res");
+			assertNotNull(r);
+			r = jar.getResource("TargetFolder/resource2.res");
+			assertNotNull(r);
+			r = jar.getResource("TargetFolder/resource5.asc");
+			assertNotNull(r);
+		}
+
+		{
+			Builder b = new Builder();
+			b.setProperty("Include-Resource", "TargetFolder=-doesnotexist, text;literal='Hello'");
+			b.setProperty("-resourceonly", "true");
+			b.build();
+			assertTrue(b.check());
+		}
+
+		{
+			Builder b = new Builder();
+			b.setProperty("Include-Resource", "-doesnotexist, text;literal='Hello'");
+			b.setProperty("-resourceonly", "true");
+			b.build();
+			assertTrue(b.check());
+		}
+
+		{
+			Builder b = new Builder();
+			b.setProperty("Include-Resource", "-test/ws/p2/Resources");
+			b.setProperty("-resourceonly", "true");
+			Jar jar = b.build();
+			assertTrue(b.check());
+			Resource r = jar.getResource("resource1.res");
+			assertNotNull(r);
+		}
+
+	}
+
+	public static void testNegativeFilter() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("Include-Resource", "TargetFolder=test/ws/p2/Resources;filter:=!*.txt");
+		b.setProperty("-resourceonly", "true");
+		Jar jar = b.build();
+		Resource r = jar.getResource("TargetFolder/resource1.res");
+		assertNotNull(r);
+		r = jar.getResource("TargetFolder/resource2.res");
+		assertNotNull(r);
+		r = jar.getResource("TargetFolder/resource5.asc");
+		assertNotNull(r);
+	}
+
+	public static void testCopyToRoot() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.setProperty("-resourceonly", "true");
+		p.setProperty("Include-Resource", "/=src/test/activator");
+		bmaker.setProperties(p);
+		Jar jar = bmaker.build();
+		for (String s : jar.getResources().keySet())
+			System.err.println(s);
+		assertNotNull(jar.getResource("Activator.java"));
+		assertEquals(0, bmaker.getErrors().size());
+		assertEquals(0, bmaker.getWarnings().size());
+	}
+
+	public static void testIncludeResourceDirectivesDefault() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("Include-Resource", "TargetFolder=test/ws/p2/Resources");
+		b.setProperty("-resourceonly", "true");
+		Jar jar = b.build();
+		Resource r = jar.getResource("TargetFolder/resource3.txt");
+		assertNotNull(r);
+		r = jar.getResource("TargetFolder/resource4.txt");
+		assertNotNull(r);
+		r = jar.getResource("TargetFolder/more/resource6.txt");
+		assertNotNull(r);
+		r = jar.getResource("TargetFolder/more/resource7.txt");
+		assertNotNull(r);
+		r = jar.getResource("TargetFolder/stuff/resource9.res");
+		assertNotNull(r);
+		r = jar.getResource("TargetFolder/text.txt");
+		assertNotNull(r);
+
+	}
+
+	public static void testIncludeResourceDoNotCopy() throws Exception {
+		Builder b = new Builder();
+
+		// Use Properties file otherwise -donotcopy is not picked up
+		Properties p = new Properties();
+		p.put("-donotcopy", "CVS|.svn|stuff");
+		p.put("Include-Resource", "TargetFolder=test/ws/p2/Resources");
+		p.put("-resourceonly", "true");
+		b.setProperties(p);
+
+		Jar jar = b.build();
+		Resource r = jar.getResource("TargetFolder/resource3.txt");
+		assertNotNull(r);
+		r = jar.getResource("TargetFolder/resource4.txt");
+		assertNotNull(r);
+		r = jar.getResource("TargetFolder/more/resource6.txt");
+		assertNotNull(r);
+		r = jar.getResource("TargetFolder/more/resource7.txt");
+		assertNotNull(r);
+		r = jar.getResource("TargetFolder/stuff/resource9.res");
+		assertNull(r);
+		r = jar.getResource("TargetFolder/text.txt");
+		assertNotNull(r);
+
+	}
+
+	public static void testIncludeResourceDirectivesFilterRecursive() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("Include-Resource", "TargetFolder=test/ws/p2/Resources;filter:=re*.txt");
+		b.setProperty("-resourceonly", "true");
+		Jar jar = b.build();
+		Resource r = jar.getResource("TargetFolder/resource3.txt");
+		assertNotNull(r);
+		r = jar.getResource("TargetFolder/resource4.txt");
+		assertNotNull(r);
+		r = jar.getResource("TargetFolder/more/resource6.txt");
+		assertNotNull(r);
+		r = jar.getResource("TargetFolder/more/resource7.txt");
+		assertNotNull(r);
+		r = jar.getResource("TargetFolder/text.txt");
+		assertNull(r);
+
+	}
+
+	public static void testIncludeResourceDirectivesFilterRecursive2() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("Include-Resource", "test/ws/p2/Resources;filter:=re*.txt");
+		b.setProperty("-resourceonly", "true");
+		Jar jar = b.build();
+		Resource r = jar.getResource("resource3.txt");
+		assertNotNull(r);
+		r = jar.getResource("resource4.txt");
+		assertNotNull(r);
+		r = jar.getResource("more/resource6.txt");
+		assertNotNull(r);
+		r = jar.getResource("more/resource7.txt");
+		assertNotNull(r);
+		r = jar.getResource("text.txt");
+		assertNull(r);
+
+	}
+
+	public static void testIncludeResourceDirectivesFilterNonRecursive() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("Include-Resource", "TargetFolder=test/ws/p2/Resources;filter:=re*.txt;recursive:=false");
+		b.setProperty("-resourceonly", "true");
+		Jar jar = b.build();
+		Resource r = jar.getResource("TargetFolder/resource3.txt");
+		assertNotNull(r);
+		r = jar.getResource("TargetFolder/resource4.txt");
+		assertNotNull(r);
+		r = jar.getResource("TargetFolder/more/resource6.txt");
+		assertNull(r);
+		r = jar.getResource("TargetFolder/more/resource7.txt");
+		assertNull(r);
+	}
+
+	public static void testIncludeResourceDirectivesFilterRecursiveFlatten() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("Include-Resource", "TargetFolder=test/ws/p2/Resources;filter:=re*.txt;flatten:=true");
+		b.setProperty("-resourceonly", "true");
+		Jar jar = b.build();
+
+		Resource r = jar.getResource("TargetFolder/resource3.txt");
+		assertNotNull(r);
+		r = jar.getResource("TargetFolder/resource4.txt");
+		assertNotNull(r);
+		r = jar.getResource("TargetFolder/resource6.txt");
+		assertNotNull(r);
+		r = jar.getResource("TargetFolder/resource7.txt");
+		assertNotNull(r);
+		r = jar.getResource("TargetFolder/resource1.res");
+		assertNull(r);
+
+	}
+
+	public static void testEmpty() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.setProperty("-resourceonly", "true");
+		p.setProperty("Include-Resource", "  ");
+		bmaker.setProperties(p);
+		Jar jar = bmaker.build();
+		assertEquals(0, jar.getResources().size());
+		assertTrue(bmaker.check("The JAR is empty"));
+	}
+
+	public static void testLiteral() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.setProperty("-resourceonly", "true");
+		p.setProperty("Include-Resource", "text;literal=TEXT;extra='hello/world;charset=UTF-8'");
+		bmaker.setProperties(p);
+		bmaker.setClasspath(new String[] {
+			"src"
+		});
+		Jar jar = bmaker.build();
+		Resource resource = jar.getResource("text");
+		assertNotNull(resource);
+		byte buffer[] = new byte[1000];
+		int size = resource.openInputStream().read(buffer);
+		String s = new String(buffer, 0, size);
+		assertEquals("TEXT", s);
+		assertEquals("hello/world;charset=UTF-8", resource.getExtra());
+		report(bmaker);
+
+	}
+
+	/**
+	 * Check if we can create a jar on demand through the make facility.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testOnDemandResource() throws Exception {
+		Builder bmaker = new Builder();
+		Properties p = new Properties();
+		p.setProperty("-resourceonly", "true");
+		p.setProperty("-plugin", "aQute.bnd.make.MakeBnd, aQute.bnd.make.MakeCopy");
+		p.setProperty("-make", "(*).jar;type=bnd;recipe=bnd/$1.bnd");
+		p.setProperty("Include-Resource", "ondemand.jar");
+		bmaker.setProperties(p);
+		bmaker.setClasspath(new String[] {
+			"bin"
+		});
+		Jar jar = bmaker.build();
+		Resource resource = jar.getResource("ondemand.jar");
+		assertNotNull(resource);
+		assertTrue(bmaker.check());
+		assertTrue(resource instanceof JarResource);
+		report(bmaker);
+
+	}
+
+	public void testEmptyDirs() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("-resourceonly", "true");
+		b.setProperty("Include-Resource", "hello/world/<<EMPTY>>;literal=''");
+		Jar jar = b.build();
+		Map<String, Map<String, Resource>> directories = jar.getDirectories();
+		assertTrue(directories.containsKey("hello/world"));
+//		report(b); //error due to empty literal
+		ByteArrayOutputStream baos = new ByteArrayOutputStream();
+		jar.write(baos);
+		byte[] contents = baos.toByteArray();
+		ByteArrayInputStream bais = new ByteArrayInputStream(contents);
+		ZipInputStream zis = new ZipInputStream(bais);
+		boolean hasDir = false;
+		boolean hasContent = false;
+		ZipEntry ze = zis.getNextEntry();
+		while (null != ze) {
+			if (ze.getName().equals("hello/world/") && ze.isDirectory())
+				hasDir = true;
+			if (ze.getName().startsWith("hello/world/") && ze.getName().length() > "hello/world/".length())
+				hasContent = true;
+			ze = zis.getNextEntry();
+		}
+		assertTrue(hasDir);
+		assertFalse(hasContent);
+	}
+
+	public void testEmptyDirs2() throws Exception {
+		new File("test/ws/p2/Resources/empty").mkdirs();
+		Builder b = new Builder();
+		b.setProperty("Include-Resource", "TargetFolder=test/ws/p2/Resources");
+		b.setProperty("-resourceonly", "true");
+		Jar jar = b.build();
+		Resource r = jar.getResource("TargetFolder/empty/<<EMPTY>>");
+		assertNotNull(r);
+		ByteArrayOutputStream baos = new ByteArrayOutputStream();
+		jar.write(baos);
+		byte[] contents = baos.toByteArray();
+		ByteArrayInputStream bais = new ByteArrayInputStream(contents);
+		ZipInputStream zis = new ZipInputStream(bais);
+		boolean hasDir = false;
+		boolean hasContent = false;
+		ZipEntry ze = zis.getNextEntry();
+		while (null != ze) {
+			if (ze.getName().equals("TargetFolder/empty/") && ze.isDirectory())
+				hasDir = true;
+			if (ze.getName().startsWith("TargetFolder/empty/") && ze.getName().length() > "TargetFolder/empty/".length())
+				hasContent = true;
+			ze = zis.getNextEntry();
+		}
+		assertTrue(hasDir);
+		assertFalse(hasContent);
+	}
+
+
+static void report(Processor processor) {
+		System.err.println();
+		for (int i = 0; i < processor.getErrors().size(); i++)
+			System.err.println(processor.getErrors().get(i));
+		for (int i = 0; i < processor.getWarnings().size(); i++)
+			System.err.println(processor.getWarnings().get(i));
+		assertEquals(0, processor.getErrors().size());
+		assertEquals(0, processor.getWarnings().size());
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/SemanticVersioningTests.java b/biz.aQute.bndlib.tests/src/test/SemanticVersioningTests.java
new file mode 100644
index 0000000..94e0375
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/SemanticVersioningTests.java
@@ -0,0 +1,15 @@
+package test;
+
+import junit.framework.*;
+
+public class SemanticVersioningTests {
+
+	public static Test suite() {
+		TestSuite suite = new TestSuite(SemanticVersioningTests.class.getName());
+		// $JUnit-BEGIN$
+		suite.addTestSuite(test.diff.DiffTest.class);
+		// $JUnit-END$
+		return suite;
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/Simple.jclass b/biz.aQute.bndlib.tests/src/test/Simple.jclass
new file mode 100644
index 0000000..0ccd005
Binary files /dev/null and b/biz.aQute.bndlib.tests/src/test/Simple.jclass differ
diff --git a/biz.aQute.bndlib.tests/src/test/SpringTest.java b/biz.aQute.bndlib.tests/src/test/SpringTest.java
new file mode 100644
index 0000000..ae6f6f3
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/SpringTest.java
@@ -0,0 +1,87 @@
+package test;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+
+public class SpringTest extends TestCase {
+
+	/**
+	 * Basic test to see if the analzyer works. We read the sprint-test1.xml and
+	 * see if we can detect all the different packages.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testSimple() throws Exception {
+
+		// InputStream in = getClass().getResourceAsStream("spring-test1.xml");
+		// Set set = SpringComponent.analyze(in);
+		// System.err.println(set);
+		// assertTrue(set.contains("com.foo.one"));
+		// assertTrue(set.contains("com.foo.one.one"));
+		// assertTrue(set.contains("com.foo.one.two"));
+		// assertTrue(set.contains("value_type"));
+		// assertTrue(set.contains("a.b"));
+		// assertTrue(set.contains("c.d"));
+		// assertTrue(set.contains("e.f"));
+		// assertTrue(set.contains("interfaces_1"));
+		// assertTrue(set.contains("interfaces_2"));
+		// assertFalse(set.contains("interfaces_3"));
+		// assertFalse(set.contains("I-am-not-here"));
+	}
+
+	/**
+	 * Now check if the plugin works, we create a dummy bundle and put the
+	 * spring-test1.xml in the appropriate place. This means that the
+	 * import-header contains all the the packages.
+	 * 
+	 * @throws Exception
+	 *             public void testPlugin() throws Exception { Builder b = new
+	 *             Builder(); b.setProperty(Analyzer.INCLUDE_RESOURCE,
+	 *             "META-INF/spring/one.xml=src/test/spring-test1.xml");
+	 *             b.setProperty(Analyzer.IMPORT_PACKAGE, "*");
+	 *             b.setProperty(Analyzer.EXPORT_PACKAGE, "*");
+	 *             b.setClasspath(new File[] { new File("jar/asm.jar") }); Jar
+	 *             jar = b.build(); checkMessages(b,0,0); test(jar); }
+	 */
+
+	/**
+	 * See what happens if we put the spring file in the wrong place. We should
+	 * have no import packages.
+	 * 
+	 * @throws Exception
+	 */
+	// public void testPluginWrongPlace() throws Exception {
+	// Builder b = new Builder();
+	// b.setProperty(Analyzer.INCLUDE_RESOURCE,
+	// "META-INF/not-spring/one.xml=src/test/spring-test1.xml");
+	// Jar jar = b.build();
+	// checkMessages(b,0,2);
+	// Manifest m = jar.getManifest();
+	// assertNull(m.getMainAttributes().getValue(Analyzer.IMPORT_PACKAGE));
+	// }
+	//
+	// void test(Jar jar) throws Exception {
+	// Manifest m = jar.getManifest();
+	// String header = m.getMainAttributes().getValue("Import-Package");
+	// assertTrue(header.indexOf("com.foo.one") >= 0);
+	// assertTrue(header.indexOf("com.foo.one.one") >= 0);
+	// assertTrue(header.indexOf("com.foo.one.two") >= 0);
+	// assertTrue(header.indexOf("value_type") >= 0);
+	// assertTrue(header.indexOf("a.b") >= 0);
+	// assertTrue(header.indexOf("c.d") >= 0);
+	// assertTrue(header.indexOf("e.f") >= 0);
+	// assertTrue(header.indexOf("interfaces_1") >= 0);
+	// assertTrue(header.indexOf("interfaces_2") >= 0);
+	// assertFalse(header.indexOf("interfaces_3") >= 0);
+	// assertFalse(header.indexOf("I-am-not-here") >= 0);
+	//
+	// }
+
+	public static void checkMessages(Processor processor, int errors, int warnings) {
+		System.err.println("Errors:    " + processor.getErrors());
+		System.err.println("Warnings:  " + processor.getWarnings());
+		assertEquals(errors, processor.getErrors().size());
+		assertEquals(warnings, processor.getWarnings().size());
+
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/Test.jclass b/biz.aQute.bndlib.tests/src/test/Test.jclass
new file mode 100755
index 0000000..833a815
Binary files /dev/null and b/biz.aQute.bndlib.tests/src/test/Test.jclass differ
diff --git a/biz.aQute.bndlib.tests/src/test/Test2.jclass b/biz.aQute.bndlib.tests/src/test/Test2.jclass
new file mode 100755
index 0000000..12ddba6
Binary files /dev/null and b/biz.aQute.bndlib.tests/src/test/Test2.jclass differ
diff --git a/biz.aQute.bndlib.tests/src/test/TestAttrs.java b/biz.aQute.bndlib.tests/src/test/TestAttrs.java
new file mode 100644
index 0000000..e8b152a
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/TestAttrs.java
@@ -0,0 +1,20 @@
+package test;
+
+import junit.framework.*;
+import aQute.bnd.header.*;
+
+public class TestAttrs extends TestCase {
+
+	public static void testAttrs() {
+		Attrs attrs = new Attrs();
+		attrs.put("a", "aa");
+		attrs.put("a:", "ab");
+		attrs.put("along:Long", "123");
+		attrs.put("aversion:Version", "1.2.3");
+
+		assertEquals("aa", attrs.get("a"));
+		assertEquals("ab", attrs.get("a:"));
+		assertEquals("123", attrs.get("along"));
+		assertEquals("1.2.3", attrs.get("aversion"));
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/TestBndBook.java b/biz.aQute.bndlib.tests/src/test/TestBndBook.java
new file mode 100644
index 0000000..8d2dacb
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/TestBndBook.java
@@ -0,0 +1,29 @@
+package test;
+
+import java.io.*;
+
+import junit.framework.*;
+import aQute.bnd.osgi.*;
+
+public class TestBndBook extends TestCase {
+
+	public static void testFilterout() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.addClasspath(new File("jar/ds.jar"));
+		b.setProperty("Export-Package", "org.eclipse.*, org.osgi.*");
+		b.setProperty("fwusers", "${classes;importing;org.osgi.framework}");
+		b.setProperty("foo", "${filterout;${fwusers};org\\.osgi\\..*}");
+		b.build();
+		String fwusers = b.getProperty("fwusers");
+		String foo = b.getProperty("foo");
+		assertTrue(fwusers.length() > foo.length());
+		assertTrue(fwusers.indexOf("org.osgi.framework.ServicePermission") >= 0);
+		assertTrue(fwusers.indexOf("org.eclipse.equinox.ds.instance.BuildDispose") >= 0);
+		assertFalse(foo.indexOf("org.osgi.framework.ServicePermission") >= 0);
+		assertTrue(foo.indexOf("org.eclipse.equinox.ds.instance.BuildDispose") >= 0);
+		System.err.println(b.getProperty("fwusers"));
+		System.err.println(b.getProperty("foo"));
+
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/TestQuotedTokenizer.java b/biz.aQute.bndlib.tests/src/test/TestQuotedTokenizer.java
new file mode 100755
index 0000000..eaf78fd
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/TestQuotedTokenizer.java
@@ -0,0 +1,72 @@
+package test;
+
+import junit.framework.*;
+import aQute.libg.qtokens.*;
+
+public class TestQuotedTokenizer extends TestCase {
+
+	public static void testNativeSeps() {
+		String s[] = new QuotedTokenizer("x;c;d=4", ";,=", true).getTokens();
+		assertEquals("Length", 7, s.length);
+		assertEquals("x", s[0]);
+		assertEquals(";", s[1]);
+		assertEquals("c", s[2]);
+		assertEquals(";", s[3]);
+		assertEquals("d", s[4]);
+		assertEquals("=", s[5]);
+		assertEquals("4", s[6]);
+	}
+
+	public static void testSimple() {
+		String s[] = new QuotedTokenizer("1.jar, 2.jar,    \t   3.jar", ",").getTokens();
+		assertEquals("Length", 3, s.length);
+		assertEquals("1.jar", s[0]);
+		assertEquals("2.jar", s[1]);
+		assertEquals("3.jar", s[2]);
+	}
+
+	public static void testQuoted() {
+		String s[] = new QuotedTokenizer("'1 ,\t.jar'", ",").getTokens();
+		assertEquals("Length", 1, s.length);
+		assertEquals("1 ,\t.jar", s[0]);
+	}
+
+	public static void testWhiteSpace() {
+		String s[] = new QuotedTokenizer("               1.jar,               2.jar         ", ",").getTokens();
+		assertEquals("Length", 2, s.length);
+		assertEquals("1.jar", s[0]);
+		assertEquals("2.jar", s[1]);
+	}
+
+	public static void testMultipleSeps() {
+		String s[] = new QuotedTokenizer("1.jar,,,,,,,,,,,    , ,2.jar", ",").getTokens();
+		assertEquals("Length", 14, s.length);
+		assertEquals("1.jar", s[0]);
+		assertEquals("2.jar", s[13]);
+	}
+
+	public static void testNative() {
+		String s[] = new QuotedTokenizer("x.dll;y.dll;abc=3;def=5;version=\"1.2.34,123\"", ";,=").getTokens();
+		assertEquals("Length", 8, s.length);
+		assertEquals("x.dll", s[0]);
+		assertEquals("y.dll", s[1]);
+		assertEquals("abc", s[2]);
+		assertEquals("3", s[3]);
+		assertEquals("def", s[4]);
+		assertEquals("5", s[5]);
+		assertEquals("version", s[6]);
+		assertEquals("1.2.34,123", s[7]);
+	}
+	
+	public static void testEscapedQuote() {
+		QuotedTokenizer qt = new QuotedTokenizer("'\\'y'", ",");
+		String s = qt.nextToken();
+		assertEquals("'y", s);
+	}
+	
+	public static void testExplicitEmptyStringTurnedToNull() {
+		QuotedTokenizer qt = new QuotedTokenizer("literal=''", ";=,");
+		qt.nextToken();
+		assertNull(qt.nextToken());
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/TestSelfBuild.java b/biz.aQute.bndlib.tests/src/test/TestSelfBuild.java
new file mode 100644
index 0000000..bae32ed
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/TestSelfBuild.java
@@ -0,0 +1,21 @@
+package test;
+
+import java.io.*;
+
+import junit.framework.*;
+import aQute.bnd.build.*;
+
+public class TestSelfBuild extends TestCase {
+
+	public static void testSelfBuild() throws Throwable {
+		Project project = Workspace.getWorkspace(new File("").getAbsoluteFile().getParentFile()).getProject(
+				"biz.aQute.bndlib");
+		project.setPedantic(true);
+		project.action("build");
+
+		File files[] = project.build();
+		assertTrue(project.check("Imports that lack version ranges"));
+		assertNotNull(files);
+		assertEquals(1, files.length);
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/TestSignatures.java b/biz.aQute.bndlib.tests/src/test/TestSignatures.java
new file mode 100644
index 0000000..2d2cb16
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/TestSignatures.java
@@ -0,0 +1,94 @@
+package test;
+
+import java.io.*;
+import java.lang.reflect.*;
+
+import junit.framework.*;
+import test.signatures.*;
+import aQute.bnd.compatibility.*;
+
+public class TestSignatures extends TestCase {
+	static Signatures	s	= new Signatures();
+
+	public static void testScopes() throws Exception {
+		assertEquals("<E:Ljava/lang/Object;>(TE;TC;TD;)V",
+				s.getSignature(Z.V.class.getMethod("fooLCO", Object.class, Object.class, Object.class)));
+	}
+
+	public static void testClass() throws Exception {
+		assertEquals(
+				"<C:Ljava/lang/Object;>Ltest/signatures/X<Ljava/lang/String;>;Ltest/signatures/Y<Ljava/lang/Integer;>;",
+				s.getSignature(Z.class));
+		assertEquals("<D:Ljava/lang/Object;>Ljava/lang/Object;", s.getSignature(Z.V.class));
+	}
+
+	public static void testMethodDeclarations() throws Exception {
+		assertEquals("<E:Ljava/lang/Object;>(TE;)V", s.getSignature(Z.class.getMethod("foo", Object.class)));
+		assertEquals("<E:Ljava/io/InputStream;>(TE;)V", s.getSignature(Z.class.getMethod("fooC", InputStream.class)));
+		assertEquals("<E:Ljava/io/InputStream;:Ljava/lang/Cloneable;>(TE;)V",
+				s.getSignature(Z.class.getMethod("fooCI", InputStream.class)));
+		assertEquals("<E:Ljava/io/InputStream;:Ljava/lang/Cloneable;:Ljava/io/Serializable;>(TE;)V",
+				s.getSignature(Z.class.getMethod("fooCII", InputStream.class)));
+		assertEquals("<E::Ljava/io/Serializable;:Ljava/lang/Cloneable;>(TE;)V",
+				s.getSignature(Z.class.getMethod("fooII", Serializable.class)));
+		assertEquals("<E::Ljava/lang/Cloneable;>(TE;)V", s.getSignature(Z.class.getMethod("fooI", Cloneable.class)));
+		assertEquals("<E:TC;>(TE;)V", s.getSignature(Z.class.getMethod("fooP", Object.class)));
+		assertEquals("<E:Ljava/lang/Object;F:Ljava/lang/Object;>(TE;TF;)V",
+				s.getSignature(Z.class.getMethod("foo", Object.class, Object.class)));
+	}
+
+	public static void testFields() throws Exception {
+		// Z<Long>.V<Integer>
+		assertEquals("Ltest/signatures/Z<Ljava/lang/Long;>.V<Ljava/lang/Integer;>;",
+				s.getSignature(Z.class.getField("referenceToNestedClass")));
+
+		//
+		assertEquals("Ltest/signatures/Z<TC;>.V<TC;>;", s.getSignature(Z.class.getField("vc")));
+		assertEquals(
+				"<C:Ljava/lang/Object;>Ltest/signatures/X<Ljava/lang/String;>;Ltest/signatures/Y<Ljava/lang/Integer;>;",
+				s.getSignature(Z.class));
+		assertEquals("<D:Ljava/lang/Object;>Ljava/lang/Object;", s.getSignature(Z.V.class));
+		assertEquals("Ltest/signatures/X<Ltest/signatures/Y<TC;>;>;", s.getSignature(Z.class.getField("field")));
+	}
+
+	public static void testWildcards() throws Exception {
+		assertEquals("Ljava/util/Collection<*>;", s.getSignature(Z.class.getField("wildcard_001")));
+		assertEquals("Ljava/util/Collection<+Ljava/lang/Cloneable;>;", s.getSignature(Z.class.getField("wildcard_002")));
+		assertEquals("Ljava/util/Collection<-Ljava/lang/Cloneable;>;", s.getSignature(Z.class.getField("wildcard_003")));
+		assertEquals("Ljava/util/Collection<+TC;>;", s.getSignature(Z.class.getField("wildcard_004")));
+		assertEquals("Ljava/util/Collection<-TC;>;", s.getSignature(Z.class.getField("wildcard_005")));
+		assertEquals("Ljava/util/Collection<+Ltest/signatures/Z<TC;>.V<Ljava/lang/Integer;>;>;",
+				s.getSignature(Z.class.getField("wildcard_006")));
+		assertEquals("Ljava/util/Collection<-Ltest/signatures/Z<TC;>.V<Ljava/lang/Integer;>;>;",
+				s.getSignature(Z.class.getField("wildcard_007")));
+	}
+
+	public static void testNormalize() {
+		assertEquals("Ltest/signatures/Z<Ljava/lang/Long;>.V<Ljava/lang/Integer;>;",
+				s.normalize("Ltest/signatures/Z<Ljava/lang/Long;>.V<Ljava/lang/Integer;>;"));
+		assertEquals(s.normalize("<A:Ljava/lang/Object;>(TA;)V"), s.normalize("<E:Ljava/lang/Object;>(TE;)V"));
+		assertEquals(s.normalize("<A:Ljava/lang/Object;>(TA;TB;)V"), s.normalize("<E:Ljava/lang/Object;>(TE;TC;)V"));
+
+		// we use (A,A) and test against (A,B)
+		assertFalse(s.normalize("<A:Ljava/lang/Object;>(TA;TA;)V").equals(
+				s.normalize("<E:Ljava/lang/Object;>(TE;TC;)V")));
+		assertEquals("<_0:Ljava/lang/Object;>(T_0;)V", s.normalize("<E:Ljava/lang/Object;>(TE;)V"));
+		assertEquals("<_0:Ljava/lang/Object;>(T_0;T_1;T_2;)V", s.normalize("<E:Ljava/lang/Object;>(TE;TC;TD;)V"));
+		assertEquals("<_0:Ljava/lang/Object;>Ljava/lang/Object;",
+				s.normalize("<_0:Ljava/lang/Object;>Ljava/lang/Object;"));
+	}
+
+	public static void testCompatibility() throws Exception {
+		String _001 = ns(Z.class.getMethod("compatibility_001"));
+		String _002 = ns(Z.class.getMethod("compatibility_002"));
+		String _003 = ns(Z.class.getMethod("compatibility_003"));
+		assertEquals(_001, _002);
+		assertTrue(_001.equals(_002));
+		assertFalse(_001.equals(_003));
+	}
+
+	private static String ns(Method method) throws Exception {
+		String sig = s.getSignature(method);
+		return s.normalize(sig);
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/UsesTest.java b/biz.aQute.bndlib.tests/src/test/UsesTest.java
new file mode 100644
index 0000000..e3386b4
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/UsesTest.java
@@ -0,0 +1,88 @@
+package test;
+
+import java.io.*;
+import java.util.jar.*;
+
+import junit.framework.*;
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
+
+public class UsesTest extends TestCase {
+
+	public static void testUsesExtend() throws Exception {
+		checkUses("test.uses.extend");
+	}
+
+	public static void testUsesGenericExtend() throws Exception {
+		checkUses("test.uses.generic.extend");
+	}
+
+	public static void testUsesConstructor() throws Exception {
+		checkUses("test.uses.constructor");
+	}
+
+	public static void testUsesImplement() throws Exception {
+		checkUses("test.uses.implement");
+	}
+
+	public static void testUsesGenericImplement() throws Exception {
+		checkUses("test.uses.generic.implement");
+	}
+
+	public static void testUsesParam() throws Exception {
+		checkUses("test.uses.param");
+	}
+
+	public static void testUsesGenericParam() throws Exception {
+		checkUses("test.uses.generic.param");
+	}
+
+	public static void testUsesRValue() throws Exception {
+		checkUses("test.uses.rvalue");
+	}
+
+	public static void testUsesGenericRValue() throws Exception {
+		checkUses("test.uses.generic.rvalue");
+	}
+
+	public static void testUsesException() throws Exception {
+		checkUses("test.uses.exception");
+	}
+
+	public static void testUsesField() throws Exception {
+		checkUses("test.uses.field");
+	}
+
+	public static void testUsesAnnotation() throws Exception {
+		checkUses("test.uses.annotation", "test.uses.annotation.annotation");
+	}
+	
+	public static void testUsesMulti() throws Exception {
+		// Check for consistent ordering
+		for (int i = 0; i < 10; i++)
+			checkUses("test.uses.multi", "javax.security.auth.callback,javax.sql");
+	}
+
+	private static void checkUses(String export) throws IOException, Exception {
+		String uses = "javax.security.auth.callback";
+		checkUses(export, uses);
+	}
+
+	private static void checkUses(String export, String uses) throws IOException, Exception {
+		Builder a = new Builder();
+		a.addClasspath(new File("bin"));
+		a.setExportPackage(export);
+		a.setProperty("build", "123");
+		Jar jar = a.build();
+		assertTrue(a.check());
+		Manifest m = jar.getManifest();
+		m.write(System.err);
+		Domain d = Domain.domain(m);
+
+		Parameters parameters = d.getExportPackage();
+		Attrs attrs = parameters.get(export);
+		assertNotNull(attrs);
+		assertEquals(uses, attrs.get("uses:"));
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/VerifierTest.java b/biz.aQute.bndlib.tests/src/test/VerifierTest.java
new file mode 100755
index 0000000..3eac06e
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/VerifierTest.java
@@ -0,0 +1,242 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+
+import junit.framework.*;
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
+
+public class VerifierTest extends TestCase {
+
+	public static void testCapability() throws Exception {
+
+		Parameters h = OSGiHeader
+				.parseHeader("test; version.list:List < Version > = \"1.0, 1.1, 1.2\"; effective:=\"resolve\"; test =\"aName\";version : Version=\"1.0\"; long :Long=\"100\"; "
+						+ "double: Double=\"1.001\"; string:String =\"aString\";   "
+						+ "long.list : List <Long >=\"1, 2, 3, 4\";double.list: List< Double>= \"1.001, 1.002, 1.003\"; "
+						+ "string.list :List<String >= \"aString,bString,cString\"");
+
+		assertEquals(Attrs.Type.VERSION, h.get("test").getType("version"));
+		assertEquals(Attrs.Type.LONG, h.get("test").getType("long"));
+		assertEquals(Attrs.Type.DOUBLE, h.get("test").getType("double"));
+		assertEquals(Attrs.Type.STRING, h.get("test").getType("string"));
+		assertEquals(Attrs.Type.STRING, h.get("test").getType("test"));
+		assertEquals(Attrs.Type.LONGS, h.get("test").getType("long.list"));
+		assertEquals(Attrs.Type.DOUBLES, h.get("test").getType("double.list"));
+		assertEquals(Attrs.Type.STRINGS, h.get("test").getType("string.list"));
+		assertEquals(Attrs.Type.VERSIONS, h.get("test").getType("version.list"));
+	}
+
+	public static void testFailedOSGiJar() throws Exception {
+		Jar jar = new Jar("jar/osgi.residential-4.3.0.jar");
+		Verifier v = new Verifier(jar);
+		assertTrue(v.check());
+	}
+
+	public static void testnativeCode() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("bin"));
+		b.setProperty("-resourceonly", "true");
+		b.setProperty("Include-Resource", "native/win32/NTEventLogAppender-1.2.dll;literal='abc'");
+		b.setProperty("Bundle-NativeCode", "native/win32/NTEventLogAppender-1.2.dll; osname=Win32; processor=x86");
+		b.build();
+		Verifier v = new Verifier(b);
+
+		v.verifyNative();
+		System.err.println(v.getErrors());
+		assertEquals(0, v.getErrors().size());
+		v.close();
+		b.close();
+	}
+
+	public static void testFilter() {
+
+		testFilter("(&(a=b)(c=1))");
+		testFilter("(&(a=b)(!(c=1))(&(c=1))(c=1)(c=1)(c=1)(c=1)(c=1)(c=1)(c=1)(c=1))");
+		testFilter("(!(a=b))");
+		testInvalidFilter("(!(a=b)(c=2))");
+		testInvalidFilter("(axb)");
+		testInvalidFilter("(a=3 ");
+		testFilter("(room=*)");
+		testFilter("(room=bedroom)");
+		testFilter("(room~= B E D R O O M )");
+		testFilter("(room=abc)");
+		testFilter(" ( room >=aaaa)");
+		testFilter("(room <=aaaa)");
+		testFilter("  ( room =b*) ");
+		testFilter("  ( room =*m) ");
+		testFilter("(room=bed*room)");
+		testFilter("  ( room =b*oo*m) ");
+		testFilter("  ( room =*b*oo*m*) ");
+		testFilter("  ( room =b*b*  *m*) ");
+		testFilter("  (& (room =bedroom) (channel ~=34))");
+		testFilter("  (&  (room =b*)  (room =*x) (channel=34))");
+		testFilter("(| (room =bed*)(channel=222)) ");
+		testFilter("(| (room =boom*)(channel=101)) ");
+		testFilter("  (! (room =ab*b*oo*m*) ) ");
+		testFilter("  (status =\\(o*\\\\\\)\\*) ");
+		testFilter("  (canRecord =true\\(x\\)) ");
+		testFilter("(max Record Time <=140) ");
+		testFilter("(shortValue >=100) ");
+		testFilter("(intValue <=100001) ");
+		testFilter("(longValue >=10000000000) ");
+		testFilter("  (  &  (  byteValue <=100)  (  byteValue >=10)  )  ");
+		testFilter("(weirdValue =100) ");
+		testFilter("(bigIntValue =4123456) ");
+		testFilter("(bigDecValue =4.123456) ");
+		testFilter("(floatValue >=1.0) ");
+		testFilter("(doubleValue <=2.011) ");
+		testFilter("(charValue ~=a) ");
+		testFilter("(booleanValue =true) ");
+		testFilter("(primIntArrayValue =1) ");
+		testFilter("(primLongArrayValue =2) ");
+		testFilter("(primByteArrayValue =3) ");
+		testFilter("(primShortArrayValue =1) ");
+		testFilter("(primFloatArrayValue =1.1) ");
+		testFilter("(primDoubleArrayValue =2.2) ");
+		testFilter("(primCharArrayValue ~=D) ");
+		testFilter("(primBooleanArrayValue =false) ");
+		testFilter("(& (| (room =d*m) (room =bed*) (room=abc)) (! (channel=999)))");
+		testFilter("(room=bedroom)");
+		testFilter("(*=foo)");
+		testInvalidFilter("(!  ab=b)");
+		testInvalidFilter("(|   ab=b)");
+		testInvalidFilter("(&=c)");
+		testInvalidFilter("(!=c)");
+		testInvalidFilter("(|=c)");
+		testInvalidFilter("(&    ab=b)");
+		testInvalidFilter("(!ab=*)");
+		testInvalidFilter("(|ab=*)");
+		testInvalidFilter("(&ab=*)");
+		testFilter("(empty=)");
+		testFilter("(empty=*)");
+		testFilter("(space= )");
+		testFilter("(space=*)");
+		testFilter("(intvalue=*)");
+		testFilter("(intvalue=b)");
+		testFilter("(intvalue=)");
+		testFilter("(longvalue=*)");
+		testFilter("(longvalue=b)");
+		testFilter("(longvalue=)");
+		testFilter("(shortvalue=*)");
+		testFilter("(shortvalue=b)");
+		testFilter("(shortvalue=)");
+		testFilter("(bytevalue=*)");
+		testFilter("(bytevalue=b)");
+		testFilter("(bytevalue=)");
+		testFilter("(charvalue=*)");
+		testFilter("(charvalue=)");
+		testFilter("(floatvalue=*)");
+		testFilter("(floatvalue=b)");
+		testFilter("(floatvalue=)");
+		testFilter("(doublevalue=*)");
+		testFilter("(doublevalue=b)");
+		testFilter("(doublevalue=)");
+		testFilter("(booleanvalue=*)");
+		testFilter("(booleanvalue=b)");
+		testFilter("(booleanvalue=)");
+
+		testInvalidFilter("");
+		testInvalidFilter("()");
+		testInvalidFilter("(=foo)");
+		testInvalidFilter("(");
+		testInvalidFilter("(abc = ))");
+		testInvalidFilter("(& (abc = xyz) (& (345))");
+		testInvalidFilter("  (room = b**oo!*m*) ) ");
+		testInvalidFilter("  (room = b**oo)*m*) ) ");
+		testInvalidFilter("  (room = *=b**oo*m*) ) ");
+		testInvalidFilter("  (room = =b**oo*m*) ) ");
+		testFilter("(shortValue =100*) ");
+		testFilter("(intValue =100*) ");
+		testFilter("(longValue =100*) ");
+		testFilter("(  byteValue =1*00  )");
+		testFilter("(bigIntValue =4*23456) ");
+		testFilter("(bigDecValue =4*123456) ");
+		testFilter("(floatValue =1*0) ");
+		testFilter("(doubleValue =2*011) ");
+		testFilter("(charValue =a*) ");
+		testFilter("(booleanValue =t*ue) ");
+	}
+
+	private static void testFilter(String string) {
+		int index = Verifier.verifyFilter(string, 0);
+		while (index < string.length() && Character.isWhitespace(string.charAt(index)))
+			index++;
+
+		if (index != string.length())
+			throw new IllegalArgumentException("Characters after filter");
+	}
+
+	private static void testInvalidFilter(String string) {
+		try {
+			testFilter(string);
+			fail("Invalid filter");
+		}
+		catch (Exception e) {}
+	}
+
+	public static void testBundleActivationPolicyNone() throws Exception {
+		Builder v = new Builder();
+		v.setProperty("Private-Package", "test.activator");
+		v.addClasspath(new File("bin"));
+		v.build();
+		assertTrue(v.check());
+	}
+
+	public static void testBundleActivationPolicyBad() throws Exception {
+		Builder v = new Builder();
+		v.setProperty("Private-Package", "test.activator");
+		v.addClasspath(new File("bin"));
+		v.setProperty(Constants.BUNDLE_ACTIVATIONPOLICY, "eager");
+		v.build();
+		assertTrue(v.check("Bundle-ActivationPolicy set but is not set to lazy: eager"));
+	}
+
+	public static void testBundleActivationPolicyGood() throws Exception {
+		Builder v = new Builder();
+		v.setProperty("Private-Package", "test.activator");
+		v.addClasspath(new File("bin"));
+		v.setProperty(Constants.BUNDLE_ACTIVATIONPOLICY, "lazy   ;   hello:=1");
+		v.build();
+		assertTrue(v.check());
+	}
+
+	public static void testBundleActivationPolicyMultiple() throws Exception {
+		Builder v = new Builder();
+		v.setProperty("Private-Package", "test.activator");
+		v.addClasspath(new File("bin"));
+		v.setProperty(Constants.BUNDLE_ACTIVATIONPOLICY, "lazy;hello:=1,2");
+		v.build();
+		assertTrue(v.check("Bundle-ActivationPolicy has too many arguments lazy;hello:=1,2"));
+	}
+
+	public static void testInvalidCaseForHeader() throws Exception {
+		Properties p = new Properties();
+		p.put("Export-package", "org.apache.mina.*");
+		p.put("Bundle-Classpath", ".");
+		Analyzer analyzer = new Analyzer();
+		analyzer.setProperties(p);
+		analyzer.getProperties();
+		System.err.println("Errors   " + analyzer.getErrors());
+		System.err.println("Warnings " + analyzer.getWarnings());
+		assertEquals(0, analyzer.getErrors().size());
+		assertEquals(2, analyzer.getWarnings().size());
+	}
+
+	public static void testSimple() throws Exception {
+		Builder bmaker = new Builder();
+		bmaker.addClasspath(new File("jar/mina.jar"));
+		bmaker.set("Export-Package", "org.apache.mina.*;version=1");
+		bmaker.set("DynamicImport-Package", "org.slf4j");
+		Jar jar = bmaker.build();
+		assertTrue(bmaker.check());
+
+		Manifest m = jar.getManifest();
+		m.write(System.err);
+		assertTrue(m.getMainAttributes().getValue("Import-Package").indexOf("org.slf4j") >= 0);
+		assertTrue(m.getMainAttributes().getValue("DynamicImport-Package").indexOf("org.slf4j") >= 0);
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/VersionPolicyTest.java b/biz.aQute.bndlib.tests/src/test/VersionPolicyTest.java
new file mode 100644
index 0000000..0ad93c0
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/VersionPolicyTest.java
@@ -0,0 +1,278 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+
+import junit.framework.*;
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
+
+public class VersionPolicyTest extends TestCase {
+
+	/**
+	 * Test disable default package versions.
+	 */
+	public static void testDisableDefaultPackageVersion() throws Exception {
+		Builder a = new Builder();
+		a.addClasspath(new File("bin"));
+		a.setProperty("Bundle-Version", "1.2.3");
+		a.setProperty("Export-Package", "test.refer");
+		a.setProperty("-nodefaultversion", "true");
+		Jar jar = a.build();
+
+		Manifest m = jar.getManifest();
+		Parameters exports = Processor.parseHeader(m.getMainAttributes().getValue(Constants.EXPORT_PACKAGE), null);
+		Map<String,String> attrs = exports.get("test.refer");
+		assertNotNull(attrs);
+		assertNull(attrs.get("version"));
+	}
+
+	/**
+	 * Test default package versions.
+	 */
+	public static void testDefaultPackageVersion() throws Exception {
+		Builder a = new Builder();
+		a.addClasspath(new File("bin"));
+		a.setProperty("Bundle-Version", "1.2.3");
+		a.setProperty("Export-Package", "test.refer");
+		Jar jar = a.build();
+
+		Manifest m = jar.getManifest();
+		Parameters exports = Processor.parseHeader(m.getMainAttributes().getValue(Constants.EXPORT_PACKAGE), null);
+		Map<String,String> attrs = exports.get("test.refer");
+		assertNotNull(attrs);
+		assertEquals("1.2.3", attrs.get("version"));
+	}
+
+	/**
+	 * Test import provide:.
+	 */
+	public static void testImportProvided() throws Exception {
+		Builder a = new Builder();
+		a.addClasspath(new File("jar/osgi.jar"));
+		a.addClasspath(new File("bin"));
+		a.setProperty("Private-Package", "test.refer");
+		a.setProperty("Import-Package", "org.osgi.service.event;provide:=true,*");
+		Jar jar = a.build();
+		Map<String,String> event = a.getImports().getByFQN("org.osgi.service.event");
+		assertEquals("[1.0,1.1)", event.get("version"));
+		Map<String,String> http = a.getImports().getByFQN("org.osgi.service.http");
+		assertEquals("[1.2,2)", http.get("version"));
+
+		Manifest m = jar.getManifest();
+		String imports = m.getMainAttributes().getValue(Constants.IMPORT_PACKAGE);
+		assertFalse(imports.contains(Constants.PROVIDE_DIRECTIVE));
+	}
+
+	/**
+	 * Test import provide:.
+	 */
+	public static void testExportProvided() throws Exception {
+		Builder a = new Builder();
+		a.addClasspath(new File("jar/osgi.jar"));
+		a.addClasspath(new File("bin"));
+		a.setProperty("Private-Package", "test.refer");
+		a.setProperty("Export-Package", "org.osgi.service.http;provide:=true");
+		Jar jar = a.build();
+		Map<String,String> event = a.getImports().getByFQN("org.osgi.service.event");
+		assertEquals("[1.0,2)", event.get("version"));
+		Map<String,String> http = a.getImports().getByFQN("org.osgi.service.http");
+		assertEquals("[1.2,1.3)", http.get("version"));
+
+		Manifest m = jar.getManifest();
+		String imports = m.getMainAttributes().getValue(Constants.IMPORT_PACKAGE);
+		assertFalse(imports.contains(Constants.PROVIDE_DIRECTIVE));
+	}
+
+	/**
+	 * Test export annotation.
+	 */
+	public static void testExportAnnotation() throws Exception {
+		Builder a = new Builder();
+		a.addClasspath(new File("bin"));
+		a.setProperty("build", "xyz");
+		a.setProperty("Export-Package", "test.versionpolicy.api");
+		a.build();
+		Map<String,String> attrs = a.getExports().getByFQN("test.versionpolicy.api");
+		assertEquals("1.2.0.xyz", attrs.get("version"));
+		assertEquals("PrivateImpl", attrs.get("exclude:"));
+		assertEquals("a", attrs.get("mandatory:"));
+	}
+
+	/**
+	 * Tests if the implementation of the EventAdmin (which is marked as a
+	 * ProviderType) causes the import of the api package to use the provider
+	 * version policy.
+	 */
+	public static void testProviderType() throws Exception {
+		Builder a = new Builder();
+		a.addClasspath(new File("bin"));
+		a.setPrivatePackage("test.versionpolicy.implemented");
+		a.setExportPackage("test.versionpolicy.api");
+		a.setImportPackage("test.versionpolicy.api"); //what changed so this is not automatically added?
+		a.setProperty("build", "123");
+		Jar jar = a.build();
+		assertTrue(a.check());
+		Manifest m = jar.getManifest();
+		m.write(System.err);
+		Domain d = Domain.domain(m);
+
+		Parameters parameters = d.getImportPackage();
+		Attrs attrs = parameters.get("test.versionpolicy.api");
+		assertNotNull(attrs);
+		assertEquals("[1.2,1.3)", attrs.get("version"));
+
+	}
+
+	/**
+	 * Tests if the implementation of the EventHandler (which is marked as a
+	 * ConsumerType) causes the import of the api package to use the consumer
+	 * version policy.
+	 */
+	public static void testConsumerType() throws Exception {
+		Builder a = new Builder();
+		a.addClasspath(new File("bin"));
+		a.setPrivatePackage("test.versionpolicy.uses");
+		a.setExportPackage("test.versionpolicy.api");
+		a.setProperty("build", "123");
+		Jar jar = a.build();
+		assertTrue(a.check());
+		Manifest m = jar.getManifest();
+		m.write(System.err);
+		Domain d = Domain.domain(m);
+
+		Parameters parameters = d.getImportPackage();
+		Attrs attrs = parameters.get("test.versionpolicy.api");
+		assertNotNull(attrs);
+		assertEquals("[1.2,2)", attrs.get("version"));
+
+	}
+
+	/**
+	 * Check implementation version policy. Uses the package
+	 * test.versionpolicy.(uses|implemented)
+	 */
+	static void assertPolicy(String pack, String type) throws Exception {
+		Builder a = new Builder();
+		a.addClasspath(new File("bin"));
+		a.setProperty("Export-Package", "test.versionpolicy.api");
+		Jar jar = a.build();
+
+		Builder b = new Builder();
+		b.addClasspath(jar);
+		b.addClasspath(new File("bin"));
+
+		b.setProperty("-versionpolicy-impl", "IMPL");
+		b.setProperty("-versionpolicy-uses", "USES");
+		b.setProperty("Private-Package", pack);
+		b.build();
+		Manifest m = b.getJar().getManifest();
+		m.write(System.err);
+		Map<String,String> map = b.getImports().getByFQN("test.versionpolicy.api");
+		assertNotNull(map);
+		// String s = map.get(Constants.IMPLEMENTED_DIRECTIVE);
+		// assertEquals("true", s);
+		Parameters mp = Processor.parseHeader(m.getMainAttributes().getValue("Import-Package"), null);
+		assertEquals(type, mp.get("test.versionpolicy.api").get("version"));
+	}
+
+	/**
+	 * hardcoded imports
+	 */
+	public static void testHardcodedImports() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.setProperty("-versionpolicy", "${range;[==,+)}");
+		b.setProperty("Private-Package", "org.objectweb.asm");
+		b.setProperty("Import-Package", "org.osgi.framework,org.objectweb.asm,abc;version=2.0.0,*");
+		b.build();
+		Manifest m = b.getJar().getManifest();
+		m.write(System.err);
+		String s = b.getImports().getByFQN("org.objectweb.asm").get("version");
+		assertNull(s);
+		s = b.getImports().getByFQN("abc").get("version");
+		assertEquals("2.0.0", s);
+
+		s = b.getImports().getByFQN("org.osgi.framework").get("version");
+		assertEquals("[1.3,2)", s);
+
+	}
+
+	/**
+	 * Specify the version on the export and verify that the policy is applied
+	 * on the matching import.
+	 */
+	public static void testExportsSpecifiesVersion() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.addClasspath(new File("bin"));
+		b.setProperty("Export-Package", "org.osgi.service.event");
+		b.setProperty("Private-Package", "test.refer");
+		b.build();
+		String s = b.getImports().getByFQN("org.osgi.service.event").get("version");
+		assertEquals("[1.0,2)", s);
+
+	}
+
+	/**
+	 * See if we a can override the version from the export statement and the
+	 * version from the source.
+	 */
+	public static void testImportOverridesDiscoveredVersion() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.addClasspath(new File("bin"));
+		b.setProperty("Export-Package", "org.osgi.service.event");
+		b.setProperty("Private-Package", "test.refer");
+		b.setProperty("Import-Package", "org.osgi.service.event;version=2.1.3.q");
+		b.build();
+		String s = b.getImports().getByFQN("org.osgi.service.event").get("version");
+		assertEquals("2.1.3.q", s);
+	}
+
+	/**
+	 * Test if we can get the version from the source and apply the default
+	 * policy.
+	 */
+	public static void testVersionPolicyImportedExportsDefaultPolicy() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.addClasspath(new File("bin"));
+		b.setProperty("Export-Package", "org.osgi.service.event");
+		b.setProperty("Private-Package", "test.refer");
+		b.build();
+		String s = b.getImports().getByFQN("org.osgi.service.event").get("version");
+		assertEquals("[1.0,2)", s);
+	}
+
+	/**
+	 * The default policy is truncate micro. Check if this is applied to the
+	 * import.
+	 */
+	public static void testImportMicroTruncated() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.setProperty("Import-Package", "org.osgi.service.event");
+		b.build();
+		String s = b.getImports().getByFQN("org.osgi.service.event").get("version");
+		assertEquals("[1.0,2)", s);
+	}
+
+	/**
+	 * Check if we can set a specific version on the import that does not use a
+	 * version policy.
+	 */
+	public static void testImportMicroNotTruncated() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.setProperty("Import-Package",
+				"org.osgi.service.event;version=${@}, org.osgi.service.log;version=\"${range;[==,=+)}\"");
+		b.build();
+		String s = b.getImports().getByFQN("org.osgi.service.event").get("version");
+		String l = b.getImports().getByFQN("org.osgi.service.log").get("version");
+		assertEquals("1.0.1", s);
+		assertEquals("[1.3,1.4)", l);
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/WithAnnotations.jclass b/biz.aQute.bndlib.tests/src/test/WithAnnotations.jclass
new file mode 100755
index 0000000..db11a06
Binary files /dev/null and b/biz.aQute.bndlib.tests/src/test/WithAnnotations.jclass differ
diff --git a/biz.aQute.bndlib.tests/src/test/WorkspaceRepositoryTest.java b/biz.aQute.bndlib.tests/src/test/WorkspaceRepositoryTest.java
new file mode 100644
index 0000000..135ef61
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/WorkspaceRepositoryTest.java
@@ -0,0 +1,85 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+
+import junit.framework.*;
+import aQute.bnd.build.*;
+import aQute.bnd.version.*;
+import aQute.lib.io.*;
+
+public class WorkspaceRepositoryTest extends TestCase {
+	static Workspace			workspace;
+	static WorkspaceRepository	repo;
+
+	public static void testIMustBeUpdated() {
+		
+	}
+	public void setUp() throws Exception {
+		workspace = new Workspace(new File("test/ws-repo-test"));
+		repo = new WorkspaceRepository(workspace);
+	}
+
+	public void tearDown() throws Exception {
+		IO.deleteWithException(new File("tmp-ws"));
+	}
+
+	public void testListNoFilter() throws Exception {
+		List<String> files = repo.list(null);
+		assertNotNull(files);
+		assertTrue(files.size() > 0);
+	}
+
+	public void testListBsn() throws Exception {
+		List<String> files = repo.list("p1");
+		assertTrue(workspace.check());
+		assertNotNull(files);
+		assertTrue(files.size() > 0);
+	}
+
+	public void testListBsnForSubProject() throws Exception {
+		List<String> files = repo.list("p4-sub.a");
+		assertTrue(workspace.check());
+		assertNotNull(files);
+		assertTrue(files.size() > 0);
+	}
+
+	public void testListNotExisting() throws Exception {
+		List<String> files = repo.list("somenotexistingproject");
+		assertTrue(workspace.check());
+		assertNotNull(files);
+		assertEquals(0, files.size());
+	}
+
+	public void testVersionsSingle() throws Exception {
+		SortedSet<Version> versions = repo.versions("p2");
+		assertTrue(workspace.check());
+		assertNotNull(versions);
+		assertEquals(1, versions.size());
+	}
+
+	public void testVersionsNotExistingBsn() throws Exception {
+		SortedSet<Version> versions = repo.versions("somenotexistingproject");
+		assertTrue(workspace.check());
+		assertNotNull(versions);
+		assertEquals(0, versions.size());
+	}
+	
+	public void testVersionsTranslateFromMavenStyle() throws Exception {
+		SortedSet<Version> versions = repo.versions("p5");
+		assertTrue(workspace.check());
+		assertNotNull(versions);
+		assertEquals(1, versions.size());
+		assertEquals("1.0.0.FOOBAR", versions.iterator().next().toString());
+	}
+
+	public void testGetName() {
+		assertEquals("Workspace ws-repo-test", repo.getName());
+	}
+
+	public void testGetExact() throws Exception {
+		File file = repo.get("p2", new Version("1.2.3"), new HashMap<String,String>());
+		assertTrue(workspace.check());
+		assertNotNull(file);
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/WorkspaceTest.java b/biz.aQute.bndlib.tests/src/test/WorkspaceTest.java
new file mode 100644
index 0000000..a4eabbe
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/WorkspaceTest.java
@@ -0,0 +1,26 @@
+package test;
+
+import java.io.*;
+
+import junit.framework.*;
+import aQute.bnd.build.*;
+
+public class WorkspaceTest extends TestCase {
+
+	public static void testWorkspace() throws Exception {
+		Workspace ws = Workspace.getWorkspace(new File("test/w o r k s p a c e"));
+
+		assertEquals("parent", ws.getProperty("override"));
+		assertEquals("ExtPlugin,ParentPlugin", ws.getProperty("-plugin"));
+		assertEquals("true", ws.getProperty("ext"));
+		assertEquals("abcdef", ws.getProperty("test"));
+	}
+
+	public static void testNestedWorkspace() throws Exception {
+		Workspace ws = Workspace.getWorkspace(new File("test/redirectws/wss/ws"));
+
+		assertEquals("true", ws.getProperty("testcnf"));
+		assertEquals("true", ws.getProperty("ext"));
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/XDbCmpXView.clazz b/biz.aQute.bndlib.tests/src/test/XDbCmpXView.clazz
new file mode 100644
index 0000000..7d3a6e3
Binary files /dev/null and b/biz.aQute.bndlib.tests/src/test/XDbCmpXView.clazz differ
diff --git a/biz.aQute.bndlib.tests/src/test/activator/Activator.java b/biz.aQute.bndlib.tests/src/test/activator/Activator.java
new file mode 100755
index 0000000..895c738
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/activator/Activator.java
@@ -0,0 +1,13 @@
+package test.activator;
+
+import org.osgi.framework.*;
+
+public class Activator implements BundleActivator {
+
+	@Override
+	public void start(BundleContext context) throws Exception {/**/}
+
+	@Override
+	public void stop(BundleContext context) throws Exception {/**/}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/activator/Activator11.java b/biz.aQute.bndlib.tests/src/test/activator/Activator11.java
new file mode 100644
index 0000000..3ece184
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/activator/Activator11.java
@@ -0,0 +1,14 @@
+package test.activator;
+
+import org.osgi.framework.*;
+
+public class Activator11 implements BundleActivator {
+
+	@Override
+	public void start(BundleContext context) throws Exception {/**/}
+
+	@Override
+	public void stop(BundleContext context) throws Exception {/**/}
+
+	public void modded(BundleContext context) throws Exception {/**/}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/activator/Activator2.java b/biz.aQute.bndlib.tests/src/test/activator/Activator2.java
new file mode 100644
index 0000000..3540a02
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/activator/Activator2.java
@@ -0,0 +1,11 @@
+package test.activator;
+
+import org.osgi.framework.*;
+
+public class Activator2 extends Activator {
+
+	public void activate(BundleContext context) throws Exception {/**/}
+
+	public void deactivate(BundleContext context) throws Exception {/**/}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/activator/Activator3.java b/biz.aQute.bndlib.tests/src/test/activator/Activator3.java
new file mode 100644
index 0000000..52ce1aa
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/activator/Activator3.java
@@ -0,0 +1,11 @@
+package test.activator;
+
+import org.osgi.service.component.ComponentContext;
+
+public class Activator3 extends Activator {
+
+	public void activate(ComponentContext context) throws Exception {/**/}
+
+	public void deactivate(ComponentContext context, int reason) throws Exception {/**/}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/activator/ActivatorPackage.java b/biz.aQute.bndlib.tests/src/test/activator/ActivatorPackage.java
new file mode 100644
index 0000000..c4b33f9
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/activator/ActivatorPackage.java
@@ -0,0 +1,11 @@
+package test.activator;
+
+import org.osgi.service.component.ComponentContext;
+
+public class ActivatorPackage extends Activator {
+
+	void activate(ComponentContext context) throws Exception {/**/}
+
+	void deactivate(ComponentContext context) throws Exception {/**/}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/activator/ActivatorPrivate.java b/biz.aQute.bndlib.tests/src/test/activator/ActivatorPrivate.java
new file mode 100644
index 0000000..d5ed88c
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/activator/ActivatorPrivate.java
@@ -0,0 +1,13 @@
+package test.activator;
+
+import org.osgi.service.component.ComponentContext;
+
+public class ActivatorPrivate extends Activator {
+
+	@SuppressWarnings("unused")
+	private void activate(ComponentContext context) throws Exception {/**/}
+
+	@SuppressWarnings("unused")
+	private void deactivate(ComponentContext context) throws Exception {/**/}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/activator/inherits/InheritedActivator.java b/biz.aQute.bndlib.tests/src/test/activator/inherits/InheritedActivator.java
new file mode 100644
index 0000000..a392be9
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/activator/inherits/InheritedActivator.java
@@ -0,0 +1,11 @@
+package test.activator.inherits;
+
+import org.osgi.framework.*;
+
+import test.activator.*;
+import aQute.bnd.annotation.component.*;
+
+ at Component(name = "inheritedactivator", provide = BundleActivator.class)
+public class InheritedActivator extends Activator {
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/annotation/AnnotationWithRefToAny.java b/biz.aQute.bndlib.tests/src/test/annotation/AnnotationWithRefToAny.java
new file mode 100644
index 0000000..2c9baa3
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/annotation/AnnotationWithRefToAny.java
@@ -0,0 +1,10 @@
+package test.annotation;
+
+import java.lang.annotation.*;
+
+import test.annotation.any.*;
+
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface AnnotationWithRefToAny {
+	Class<?> c() default Any.class;
+}
diff --git a/biz.aQute.bndlib.tests/src/test/annotation/any/Any.java b/biz.aQute.bndlib.tests/src/test/annotation/any/Any.java
new file mode 100644
index 0000000..4332ef6
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/annotation/any/Any.java
@@ -0,0 +1,5 @@
+package test.annotation.any;
+
+public class Any {
+
+}
diff --git a/biz.aQute.bndlib/src/test/badproperties.prop b/biz.aQute.bndlib.tests/src/test/badproperties.prop
similarity index 100%
rename from biz.aQute.bndlib/src/test/badproperties.prop
rename to biz.aQute.bndlib.tests/src/test/badproperties.prop
diff --git a/biz.aQute.bndlib.tests/src/test/baseline/BaselineTest.java b/biz.aQute.bndlib.tests/src/test/baseline/BaselineTest.java
new file mode 100644
index 0000000..8b35d68
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/baseline/BaselineTest.java
@@ -0,0 +1,100 @@
+package test.baseline;
+
+import java.io.*;
+import java.util.*;
+
+import junit.framework.*;
+import aQute.bnd.build.*;
+import aQute.bnd.differ.*;
+import aQute.bnd.differ.Baseline.Info;
+import aQute.bnd.osgi.*;
+import aQute.service.reporter.*;
+
+public class BaselineTest extends TestCase {
+
+	public static void testBaslineJar() throws Exception {
+		Workspace ws = new Workspace(new File("test/ws"));
+
+		Project p3 = ws.getProject("p3");
+
+		ProjectBuilder builder = (ProjectBuilder) p3.getBuilder(null).getSubBuilder();
+		builder.setBundleSymbolicName("p3");
+
+		// Nothing specified
+		Jar jar = builder.getBaselineJar(false);
+		assertNull(jar);
+
+		jar = builder.getBaselineJar(true);
+		assertEquals(".", jar.getName());
+
+		// Fallback to release repo
+		builder.set("-releaserepo", "Repo");
+		jar = builder.getBaselineJar(false);
+		assertNull(jar);
+
+		jar = builder.getBaselineJar(true);
+		assertEquals("p3", jar.getBsn());
+		assertEquals("1.0.1", jar.getVersion());
+
+		// -baselinerepo specified
+		builder.set("-baselinerepo", "Release");
+		jar = builder.getBaselineJar(false);
+		assertEquals("p3", jar.getBsn());
+		assertEquals("1.2.0", jar.getVersion());
+
+		jar = builder.getBaselineJar(true);
+		assertEquals("p3", jar.getBsn());
+		assertEquals("1.2.0", jar.getVersion());
+
+		// -baseline specified
+		builder.set("-baseline", "p3;version=1.1.0");
+		jar = builder.getBaselineJar(false);
+		assertEquals("p3", jar.getBsn());
+		assertEquals("1.1.0", jar.getVersion());
+
+		jar = builder.getBaselineJar(true);
+		assertEquals("p3", jar.getBsn());
+		assertEquals("1.1.0", jar.getVersion());
+
+	}
+	
+	// Adding a method to a ProviderType produces a MINOR bump (1.0.0 -> 1.1.0)
+	public static void testProviderTypeBump() throws Exception {
+		Processor processor = new Processor();
+		
+		DiffPluginImpl differ = new DiffPluginImpl();
+		Baseline baseline = new Baseline(processor, differ);
+
+		Jar older = new Jar(new File("test/api-orig.jar"));
+		Jar newer = new Jar(new File("test/api-providerbump.jar"));
+
+		Set<Info> infoSet = baseline.baseline(newer, older, null);
+		
+		assertEquals(1, infoSet.size());
+		Info info = infoSet.iterator().next();
+		
+		assertTrue(info.mismatch);
+		assertEquals("dummy.api", info.packageName);
+		assertEquals("1.1.0", info.suggestedVersion.toString());
+	}
+	
+	// Adding a method to a ConsumerType produces a MINOR bump (1.0.0 -> 2.0.0)
+	public static void testConsumerTypeBump() throws Exception {
+		Processor processor = new Processor();
+		
+		DiffPluginImpl differ = new DiffPluginImpl();
+		Baseline baseline = new Baseline(processor, differ);
+
+		Jar older = new Jar(new File("test/api-orig.jar"));
+		Jar newer = new Jar(new File("test/api-consumerbump.jar"));
+
+		Set<Info> infoSet = baseline.baseline(newer, older, null);
+		
+		assertEquals(1, infoSet.size());
+		Info info = infoSet.iterator().next();
+		
+		assertTrue(info.mismatch);
+		assertEquals("dummy.api", info.packageName);
+		assertEquals("2.0.0", info.suggestedVersion.toString());
+	}
+}
diff --git a/biz.aQute.bndlib/src/test/beasymock.bnd b/biz.aQute.bndlib.tests/src/test/beasymock.bnd
similarity index 100%
rename from biz.aQute.bndlib/src/test/beasymock.bnd
rename to biz.aQute.bndlib.tests/src/test/beasymock.bnd
diff --git a/biz.aQute.bndlib/src/test/bnd.info b/biz.aQute.bndlib.tests/src/test/bnd.info
similarity index 100%
rename from biz.aQute.bndlib/src/test/bnd.info
rename to biz.aQute.bndlib.tests/src/test/bnd.info
diff --git a/biz.aQute.bndlib.tests/src/test/classreference/ClassReference.java b/biz.aQute.bndlib.tests/src/test/classreference/ClassReference.java
new file mode 100755
index 0000000..c902370
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/classreference/ClassReference.java
@@ -0,0 +1,8 @@
+package test.classreference;
+
+public class ClassReference {
+
+	public static void testClassReference() {
+		System.err.println(javax.swing.Box.class);
+	}
+}
diff --git a/biz.aQute.bndlib/src/test/com.acme/bnd.bnd b/biz.aQute.bndlib.tests/src/test/com.acme/bnd.bnd
similarity index 100%
rename from biz.aQute.bndlib/src/test/com.acme/bnd.bnd
rename to biz.aQute.bndlib.tests/src/test/com.acme/bnd.bnd
diff --git a/biz.aQute.bndlib/src/test/com.acme/defaultbsn.bnd b/biz.aQute.bndlib.tests/src/test/com.acme/defaultbsn.bnd
similarity index 100%
rename from biz.aQute.bndlib/src/test/com.acme/defaultbsn.bnd
rename to biz.aQute.bndlib.tests/src/test/com.acme/defaultbsn.bnd
diff --git a/biz.aQute.bndlib/src/test/com.acme/setsbsn.bnd b/biz.aQute.bndlib.tests/src/test/com.acme/setsbsn.bnd
similarity index 100%
rename from biz.aQute.bndlib/src/test/com.acme/setsbsn.bnd
rename to biz.aQute.bndlib.tests/src/test/com.acme/setsbsn.bnd
diff --git a/biz.aQute.bndlib.tests/src/test/component/BNDAnnotationTest.java b/biz.aQute.bndlib.tests/src/test/component/BNDAnnotationTest.java
new file mode 100644
index 0000000..ed695a1
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/component/BNDAnnotationTest.java
@@ -0,0 +1,882 @@
+package test.component;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+
+import javax.xml.namespace.*;
+import javax.xml.parsers.*;
+import javax.xml.xpath.*;
+
+import junit.framework.*;
+
+import org.osgi.framework.*;
+import org.osgi.service.component.*;
+import org.osgi.service.event.*;
+import org.osgi.service.log.*;
+import org.w3c.dom.*;
+
+import aQute.bnd.annotation.component.*;
+import aQute.bnd.annotation.metatype.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Constants;
+
+public class BNDAnnotationTest extends TestCase {
+	static final DocumentBuilderFactory	dbf		= DocumentBuilderFactory.newInstance();
+	static final XPathFactory				xpathf	= XPathFactory.newInstance();
+	static final XPath						xpath	= xpathf.newXPath();
+	static DocumentBuilder					db;
+
+	static {
+		try {
+			dbf.setNamespaceAware(true);
+			db = dbf.newDocumentBuilder();
+			xpath.setNamespaceContext(new NamespaceContext() {
+
+				@Override
+				public Iterator<String> getPrefixes(String namespaceURI) {
+					return Arrays.asList("md", "scr").iterator();
+				}
+
+				@Override
+				public String getPrefix(String namespaceURI) {
+					if (namespaceURI.equals("http://www.osgi.org/xmlns/metatype/v1.1.0"))
+						return "md";
+					if (namespaceURI.equals("http://www.osgi.org/xmlns/scr/v1.1.0"))
+						return "scr";
+
+					return null;
+				}
+
+				@Override
+				public String getNamespaceURI(String prefix) {
+					if (prefix.equals("md"))
+						return "http://www.osgi.org/xmlns/metatype/v1.1.0";
+					else if (prefix.equals("scr"))
+						return "http://www.osgi.org/xmlns/scr/v1.1.0";
+					else
+						return null;
+				}
+			});
+		}
+		catch (ParserConfigurationException e) {
+			e.printStackTrace();
+			throw new ExceptionInInitializerError(e);
+		}
+	}
+
+	/**
+	 * Can we order the references? References are ordered by their name as Java
+	 * does not define the order of the methods.
+	 * 
+	 * @throws Exception
+	 */
+
+	@Component
+	static class TestReferenceOrdering {
+
+		@Reference(service = LogService.class)
+		void setA(@SuppressWarnings("unused") ServiceReference ref) {}
+
+		@Reference
+		void setC(@SuppressWarnings("unused") LogService log) {}
+
+		@Reference(service = LogService.class)
+		void setB(@SuppressWarnings("unused") Map<String,Object> map) {}
+	}
+
+	public static void testAnnotationReferenceOrdering() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("bin"));
+		b.setProperty("Service-Component", "*TestReferenceOrdering");
+		b.setProperty("Private-Package", "test.component");
+		b.build();
+		Document doc = doc(b, "test.component.BNDAnnotationTest$TestReferenceOrdering");
+		NodeList nodes = (NodeList) xpath.evaluate("//reference", doc, XPathConstants.NODESET);
+		assertEquals("a", nodes.item(0).getAttributes().getNamedItem("name").getTextContent());
+		assertEquals("b", nodes.item(1).getAttributes().getNamedItem("name").getTextContent());
+		assertEquals("c", nodes.item(2).getAttributes().getNamedItem("name").getTextContent());
+	}
+
+	/**
+	 * Test config with metatype
+	 */
+
+	@Component(name = "config", designateFactory = Config.class, configurationPolicy = ConfigurationPolicy.require)
+	static class MetatypeConfig {
+		interface Config {
+			String name();
+		}
+	}
+
+	@Component(designate = Config.class)
+	static class MetatypeConfig2 {
+		interface Config {
+			String name();
+		}
+	}
+
+	public static void testConfig() throws Exception {
+		Builder b = new Builder();
+		b.setExceptions(true);
+		b.setClasspath(new File[] {
+			new File("bin")
+		});
+		b.setProperty("Service-Component", "*MetatypeConfig*");
+		b.setProperty("Private-Package", "test.component");
+		b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+		System.err.println(b.getJar().getResources().keySet());
+
+		// Check component name
+		{
+			Resource cr = b.getJar().getResource("OSGI-INF/config.xml");
+			cr.write(System.err);
+			Document d = db.parse(cr.openInputStream());
+			assertEquals("config", xpath.evaluate("/scr:component/@name", d, XPathConstants.STRING));
+		}
+
+		// Check if config properly linked
+		{
+			Resource mr = b.getJar().getResource("OSGI-INF/metatype/config.xml");
+			mr.write(System.err);
+			Document d = db.parse(mr.openInputStream());
+			assertEquals("config", xpath.evaluate("//Designate/@factoryPid", d, XPathConstants.STRING));
+			assertEquals("config", xpath.evaluate("//Object/@ocdref", d, XPathConstants.STRING));
+		}
+
+		// Now with default name
+		{
+			Resource cr2 = b.getJar().getResource("OSGI-INF/test.component.BNDAnnotationTest$MetatypeConfig2.xml");
+			cr2.write(System.err);
+			Document d = db.parse(cr2.openInputStream());
+			assertEquals("test.component.BNDAnnotationTest$MetatypeConfig2",
+					xpath.evaluate("//scr:component/@name", d, XPathConstants.STRING));
+		}
+		{
+			Resource mr2 = b.getJar().getResource("OSGI-INF/metatype/test.component.BNDAnnotationTest$MetatypeConfig2.xml");
+			mr2.write(System.err);
+			Document d = db.parse(mr2.openInputStream());
+			assertEquals("test.component.BNDAnnotationTest$MetatypeConfig2",
+					xpath.evaluate("//Designate/@pid", d, XPathConstants.STRING));
+			assertEquals("test.component.BNDAnnotationTest$MetatypeConfig2",
+					xpath.evaluate("//Object/@ocdref", d, XPathConstants.STRING));
+		}
+	}
+
+	/**
+	 * Test properties
+	 */
+	@Meta.OCD
+	static interface Config {
+		String name();
+	}
+
+	@Component(name = "props", properties = {
+			" a =1", "b=3", "c=1|2|3"
+	}, designate = Config.class, designateFactory = Config.class)
+	static class PropertiesAndConfig {
+		@Activate
+		protected void activate(@SuppressWarnings("unused") ComponentContext c) {}
+	}
+
+	public static void testPropertiesAndConfig() throws Exception {
+		Builder b = new Builder();
+		b.setExceptions(true);
+		b.setClasspath(new File[] {
+			new File("bin")
+		});
+		b.setProperty("Service-Component", "*PropertiesAndConfig");
+		b.setProperty("Private-Package", "test.component");
+		b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+
+		Resource cr = b.getJar().getResource("OSGI-INF/props.xml");
+		cr.write(System.err);
+		{
+			Document doc = doc(b, "props");
+			assertEquals("1", xpath.evaluate("scr:component/property[@name='a']/@value", doc));
+			assertEquals("3", xpath.evaluate("scr:component/property[@name='b']/@value", doc));
+			assertEquals("1\n2\n3", xpath.evaluate("scr:component/property[@name='c']", doc).trim());
+		}
+
+	}
+
+	/**
+	 * Test if a package private method gives us 1.1 + namespace in the XML using bnd annotations
+	 */
+
+	@Component(name = "protected")
+	static class PackageProtectedActivateMethod {
+		@Activate
+		protected void activatex(@SuppressWarnings("unused") ComponentContext c) {}
+	}
+
+	@Component(name = "packageprivate")
+	static class PackagePrivateActivateMethod {
+		@Activate
+		void activatex(@SuppressWarnings("unused") ComponentContext c) {}
+	}
+
+	@Component(name = "private")
+	static class PrivateActivateMethod {
+		@SuppressWarnings("unused")
+		@Activate
+		private void activatex(ComponentContext c) {}
+	}
+
+	@Component(name = "default-private")
+	static class DefaultPrivateActivateMethod {
+		@SuppressWarnings("unused")
+		@Activate
+		private void activate(ComponentContext c) {}
+	}
+
+	@Component(name = "default-protected")
+	static class DefaultProtectedActivateMethod {
+		@Activate
+		protected void activate(@SuppressWarnings("unused") ComponentContext c) {}
+	}
+
+	@Component(name = "public")
+	static class PublicActivateMethod {
+		@Activate
+		public void activatex(@SuppressWarnings("unused") ComponentContext c) {}
+	}
+
+	public static void testPackagePrivateActivateMethodBndAnnos() throws Exception {
+		Builder b = new Builder();
+		b.setClasspath(new File[] {
+			new File("bin")
+		});
+		b.setProperty("Service-Component", "*ActivateMethod");
+		b.setProperty("Private-Package", "test.component");
+		b.build();
+		assertTrue(b.check());
+
+		{
+			Document doc = doc(b, "default-private");
+			Object o = xpath.evaluate("scr:component", doc, XPathConstants.NODE);
+			assertNotNull(o);
+			assertEquals("", xpath.evaluate("component/@activate", doc));
+		}
+		{
+			Document doc = doc(b, "default-protected");
+			Object o = xpath.evaluate("component", doc, XPathConstants.NODE);
+			assertNotNull(o);
+			assertEquals("", xpath.evaluate("component/@activate", doc));
+		}
+		{
+			Document doc = doc(b, "public");
+			Object o = xpath.evaluate("//scr:component", doc, XPathConstants.NODE);
+			assertNotNull(o);
+			assertEquals("activatex", xpath.evaluate("scr:component/@activate", doc));
+		}
+		{
+			Document doc = doc(b, "private");
+			Object o = xpath.evaluate("//scr:component", doc, XPathConstants.NODE);
+			assertNotNull(o);
+			assertEquals("activatex", xpath.evaluate("scr:component/@activate", doc));
+		}
+		{
+			Document doc = doc(b, "protected");
+			Object o = xpath.evaluate("//scr:component", doc, XPathConstants.NODE);
+			assertNotNull(o);
+			assertEquals("activatex", xpath.evaluate("scr:component/@activate", doc));
+		}
+		{
+			Document doc = doc(b, "packageprivate");
+			Object o = xpath.evaluate("//scr:component", doc, XPathConstants.NODE);
+			assertNotNull(o);
+			assertEquals("activatex", xpath.evaluate("scr:component/@activate", doc));
+		}
+
+	}
+	
+	/**
+	 * Test an attribute on an annotation
+	 */
+
+	@Component(name = "annotated")
+	static class Annotated {
+
+		@Reference
+		protected void setLog(@SuppressWarnings("unused") LogService log) {}
+
+	}
+
+	public static void testAnnotatedWithAttribute() throws Exception {
+		Builder b = new Builder();
+		b.setClasspath(new File[] {
+			new File("bin")
+		});
+		b.setProperty("Service-Component", "*NoUnbind;log=org.osgi.service.log.LogService");
+		b.setProperty("Private-Package", "test.component");
+		Jar jar = b.build();
+		Manifest manifest = jar.getManifest();
+		String sc = manifest.getMainAttributes().getValue(Constants.SERVICE_COMPONENT);
+		assertFalse(sc.contains(";"));
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+
+	}
+
+	/**
+	 * Imported default package because JSR14 seems to do something weird with
+	 * annotations.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testJSR14ComponentAnnotations() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("Include-Resource",
+				"org/osgi/impl/service/coordinator/AnnotationWithJSR14.class=jar/AnnotationWithJSR14.jclass");
+		b.setProperty("Service-Component", "*");
+		b.setProperty("-resourceonly", "true");
+		Jar jar = b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(0, b.getErrors().size());
+		assertEquals(1, b.getWarnings().size());
+
+		Manifest manifest = jar.getManifest();
+		String component = manifest.getMainAttributes().getValue("Service-Component");
+		System.err.println(component);
+		assertNull(component);
+	}
+
+	@Component(name = "nounbind")
+	static class NoUnbind {
+
+		@Reference
+		protected void setLog(@SuppressWarnings("unused") LogService log) {}
+
+	}
+	
+	public static void testNoUnbind() throws Exception {
+		Builder b = new Builder();
+		b.setClasspath(new File[] {
+			new File("bin")
+		});
+		b.setProperty("Service-Component", "*NoUnbind");
+		b.setProperty("Private-Package", "test.component");
+		b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+
+		Document doc = doc(b, "nounbind");
+		assertEquals("setLog", xpath.evaluate("component/reference/@bind", doc));
+		assertEquals("", xpath.evaluate("component/reference/@unbind", doc));
+	}
+
+	@Component(name = "nounbind_dynamic")
+	static class NoUnbindDynamic {
+		
+		@Reference(dynamic = true)
+		protected void setLog(@SuppressWarnings("unused") LogService log) {}
+	}
+	
+	public static void testNoUnbindDynamic() throws Exception {
+		Builder b = new Builder();
+		b.setClasspath(new File[] {
+			new File("bin")
+		});
+		b.setProperty("Service-Component", "*NoUnbindDynamic");
+		b.setProperty("Private-Package", "test.component");
+		b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(1, b.getErrors().size());
+		assertTrue(b.getErrors().get(0).endsWith("dynamic but has no unbind method."));
+		assertEquals(0, b.getWarnings().size());
+	}
+	
+	//this is a bnd annotation not a DS annotation
+	@Component(name = "explicitunbind")
+	static class ExplicitUnbind {
+
+		@Reference(unbind = "killLog")
+		protected void setLog(@SuppressWarnings("unused") LogService log) {}
+
+	}
+
+	public static void testExplicitUnbind() throws Exception {
+		Builder b = new Builder();
+		b.setClasspath(new File[] {
+			new File("bin")
+		});
+		b.setProperty("Service-Component", "*ExplicitUnbind");
+		b.setProperty("Private-Package", "test.component");
+		b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(1, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+
+		Document doc = doc(b, "explicitunbind");
+		assertEquals("setLog", xpath.evaluate("component/reference/@bind", doc));
+		assertEquals("killLog", xpath.evaluate("component/reference/@unbind", doc));
+	}
+
+	/**
+	 * Test to see if we get a namespace when we use 1.1 semantics on the
+	 * activate and deactivate
+	 */
+
+	@Component(name = "ncomp", provide = {})
+	static class NewActivateVersion {
+
+		@Activate
+		protected void activate(@SuppressWarnings("unused") ComponentContext context) {}
+
+	}
+
+	@Component(name = "ndcomp", provide = {})
+	static class NewDeActivateVersion {
+		@Deactivate
+		protected void deactivate() {}
+
+	}
+
+	@Component(name = "nbcomp", provide = {})
+	static class NewBindVersion {
+
+		@Reference
+		protected void bind(@SuppressWarnings("unused") ServiceReference ref, @SuppressWarnings("unused") Map<String,Object> map) {}
+
+	}
+
+	public static void testNewVersion() throws Exception {
+		Builder b = new Builder();
+		b.setClasspath(new File[] {
+			new File("bin")
+		});
+		b.setProperty("Service-Component", "*Version");
+		b.setProperty("Private-Package", "test.component");
+		b.build();
+		assertTrue(b.check());
+
+		{
+			Document doc = doc(b, "ncomp");
+			Node o = (Node) xpath.evaluate("scr:component", doc, XPathConstants.NODE);
+			assertNull("Expected ncomp to have old namespace", o);
+			o = (Node) xpath.evaluate("component", doc, XPathConstants.NODE);
+			assertNotNull("Expected ncomp to have old namespace", o);
+		}
+
+	}
+
+	/**
+	 * Test the same bind method names
+	 */
+
+	@Component(name = "cpcomp")
+	static class SameRefName {
+
+		@Reference
+		protected void bind(@SuppressWarnings("unused") LogService log) {
+
+		}
+
+		@Reference
+		protected void bind(@SuppressWarnings("unused") EventAdmin event) {
+
+		}
+	}
+
+	public static void testSameRefName() throws Exception {
+		Builder b = new Builder();
+		b.setClasspath(new File[] {
+			new File("bin")
+		});
+		b.setProperty("Service-Component", "*.SameRefName");
+		b.setProperty("Private-Package", "test.component");
+		b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(1, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+
+		// Document doc = doc(b, "cpcomp");
+	}
+
+	/**
+	 * Test the configuration policy
+	 */
+
+	@Component(name = "cpcomp", configurationPolicy = ConfigurationPolicy.require, provide = {
+			Serializable.class, EventAdmin.class
+	})
+	static class ConfigurationPolicyTest {
+
+	}
+
+	public static void testConfigurationPolicy() throws Exception {
+		Builder b = new Builder();
+		b.setClasspath(new File[] {
+			new File("bin")
+		});
+		b.setProperty("Service-Component", "*.ConfigurationPolicyTest");
+		b.setProperty("Private-Package", "test.component");
+		b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+
+		Document doc = doc(b, "cpcomp");
+		assertEquals("java.io.Serializable",
+				doc.getElementsByTagName("provide").item(0).getAttributes().getNamedItem("interface").getTextContent());
+		assertEquals("org.osgi.service.event.EventAdmin", doc.getElementsByTagName("provide").item(1).getAttributes()
+				.getNamedItem("interface").getTextContent());
+
+	}
+
+	/**
+	 * Test to see if we use defaults we get the old version of the namespace
+	 */
+
+	@Component(name = "vcomp", provide = {})
+	static class OldVersion {
+
+		@Activate
+		protected void activate(@SuppressWarnings("unused") ComponentContext cc) {}
+
+		@Deactivate
+		protected void deactivate(@SuppressWarnings("unused") ComponentContext cc) {}
+
+		@Reference
+		protected void bindLog(@SuppressWarnings("unused") LogService log) {
+
+		}
+	}
+
+	/**
+	 * Test if an activate/deactivate method that has wrong prototype
+	 */
+
+	@Component(name = "wacomp", provide = {})
+	static class ActivateWithWrongArguments {
+
+		@Activate
+		// Is not allowed, must give an error
+		protected void whatever(@SuppressWarnings("unused") String x) {}
+
+	}
+
+	public static void testActivateWithActivateWithWrongArguments() throws Exception {
+		Builder b = new Builder();
+		b.setClasspath(new File[] {
+			new File("bin")
+		});
+		b.setProperty("Service-Component", "*.ActivateWithWrongArguments");
+		b.setProperty("Private-Package", "test.component");
+		b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(2, b.getErrors().size()); //same error detected twice
+		assertEquals(0, b.getWarnings().size());
+
+		Document doc = doc(b, "wacomp");
+		assertAttribute(doc, "", "scr:component/@activate"); //validation removes the non-existent method.
+	}
+
+	/**
+	 * Test if an activate/deactivate method can have multiple args
+	 */
+
+	@Component(name = "amcomp", provide = {})
+	static class ActivateWithMultipleArguments {
+
+		@Activate
+		protected void whatever(@SuppressWarnings("unused") Map< ? , ? > map, @SuppressWarnings("unused") ComponentContext cc, @SuppressWarnings("unused") BundleContext bc, @SuppressWarnings("unused") Map< ? , ? > x) {}
+
+	}
+
+	public static void testActivateWithMultipleArguments() throws Exception {
+		Builder b = new Builder();
+		b.setClasspath(new File[] {
+			new File("bin")
+		});
+		b.setProperty("Service-Component", "*.ActivateWithMultipleArguments");
+		b.setProperty("Private-Package", "test.component");
+		b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+
+		Document doc = doc(b, "amcomp");
+		assertAttribute(doc, "whatever", "scr:component/@activate");
+	}
+
+	/**
+	 * Test components with references that have multiple arguments.
+	 */
+	@Component(name = "mcomp", provide = {})
+	static class MultipleArguments {
+
+		@Reference
+		protected void bindWithMap(@SuppressWarnings("unused") LogService log, @SuppressWarnings("unused") Map< ? , ? > map) {}
+
+	}
+
+	@Component(name = "rcomp", provide = {})
+	static class ReferenceArgument {
+
+		@Reference(service = LogService.class)
+		protected void bindReference(@SuppressWarnings("unused") ServiceReference ref) {}
+
+	}
+
+	public static void testMultipleArguments() throws Exception {
+		Builder b = new Builder();
+		b.setClasspath(new File[] {
+			new File("bin")
+		});
+		b.setProperty("Service-Component", "*.(MultipleArguments|ReferenceArgument)");
+		b.setProperty("Private-Package", "test.component");
+		b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+
+		Document doc = doc(b, "mcomp");
+		assertAttribute(doc, "bindWithMap", "scr:component/reference/@bind");
+		assertAttribute(doc, "org.osgi.service.log.LogService", "scr:component/reference/@interface");
+
+		doc = doc(b, "rcomp");
+		assertAttribute(doc, "bindReference", "scr:component/reference/@bind");
+		assertAttribute(doc, "org.osgi.service.log.LogService", "scr:component/reference/@interface");
+	}
+
+	/**
+	 * Test components with weird bind methods.
+	 */
+	@Component(name = "xcomp", provide = {})
+	static class TypeVersusDetailed {
+
+		@Reference(type = '*')
+		protected void bind(@SuppressWarnings("unused") LogService log) {}
+		protected void unbind(@SuppressWarnings("unused") LogService log) {}
+
+		@Reference(multiple = true, optional = true, dynamic = true)
+		protected void bind2(@SuppressWarnings("unused") LogService log) {}
+		protected void unbind2(@SuppressWarnings("unused") LogService log) {}
+	}
+
+	public static void testTypeVersusDetailed() throws Exception {
+		Builder b = new Builder();
+		b.setClasspath(new File[] {
+			new File("bin")
+		});
+		b.setProperty("Service-Component", "*.TypeVersusDetailed");
+		b.setProperty("Private-Package", "test.component");
+		b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+
+		Document doc = doc(b, "xcomp");
+		print(doc, "");
+		assertAttribute(doc, "bind2", "component/reference[1]/@bind");
+		assertAttribute(doc, "dynamic", "component/reference[1]/@policy");
+		assertAttribute(doc, "0..n", "component/reference[1]/@cardinality");
+		assertAttribute(doc, "bind", "component/reference[2]/@bind");
+		assertAttribute(doc, "dynamic", "component/reference[2]/@policy");
+		assertAttribute(doc, "0..n", "component/reference[2]/@cardinality");
+	}
+
+	/**
+	 * Test components with weird bind methods.
+	 */
+	@Component(name = "acomp", provide = {})
+	static class MyComponent4 {
+		@Activate
+		protected void xyz() {}
+	}
+
+	public static void testAnnotationsNamespaceVersion() throws Exception {
+		Builder b = new Builder();
+		b.setClasspath(new File[] {
+			new File("bin")
+		});
+		b.setProperty("Service-Component", "*.MyComponent4");
+		b.setProperty("Private-Package", "test.component");
+		b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+
+		Document doc = doc(b, "acomp");
+		System.err.println(doc.getDocumentElement().getNamespaceURI());
+	}
+
+	/**
+	 * Test components with weird bind methods.
+	 */
+	@Component(name = "acomp", configurationPolicy = ConfigurationPolicy.require)
+	static class MyComponent2 {
+		@Reference
+		protected void addLogMultiple(@SuppressWarnings("unused") LogService log) {
+
+		}
+	}
+
+	public static void testAnnotationsStrangeBindMethods() throws Exception {
+		Builder b = new Builder();
+		b.setClasspath(new File[] {
+			new File("bin")
+		});
+		b.setProperty("Service-Component", "*.MyComponent2");
+		b.setProperty("Private-Package", "test.component");
+		b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+
+		Document doc = doc(b, "acomp");
+		assertEquals("addLogMultiple", xpath.evaluate("//@bind", doc));
+		assertEquals("", xpath.evaluate("//@unbind", doc));
+
+		assertAttribute(doc, "logMultiple", "scr:component/reference[1]/@name");
+		assertAttribute(doc, "addLogMultiple", "scr:component/reference[1]/@bind");
+
+	}
+
+	/**
+	 * Test setting the unbind method
+	 */
+	@Component(name = "acomp", configurationPolicy = ConfigurationPolicy.ignore)
+	static class MyComponent3 {
+		@Reference(unbind = "destroyX")
+		protected void putX(@SuppressWarnings("unused") LogService log) {
+
+		}
+	}
+
+	public static void testAnnotationsSettingUnbind() throws Exception {
+		Builder b = new Builder();
+		b.setClasspath(new File[] {
+			new File("bin")
+		});
+		b.setProperty("Service-Component", "*.MyComponent3");
+		b.setProperty("Private-Package", "test.component");
+		b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(1, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+
+		Document doc = doc(b, "acomp");
+		assertAttribute(doc, "putx", "scr:component/reference[1]/@name");
+		assertAttribute(doc, "putX", "scr:component/reference[1]/@bind");
+		assertAttribute(doc, "destroyX", "scr:component/reference[1]/@unbind");
+	}
+
+	/**
+	 * Test some more components
+	 * 
+	 * @author aqute
+	 */
+	@Component(name = "acomp", enabled = true, factory = "abc", immediate = false, provide = LogService.class, servicefactory = true, configurationPolicy = ConfigurationPolicy.optional)
+	static class MyComponent implements Serializable {
+		private static final long	serialVersionUID	= 1L;
+		LogService					log;
+
+		@Activate
+		protected void activatex() {}
+
+		@Deactivate
+		protected void deactivatex() {}
+
+		@Modified
+		protected void modifiedx() {}
+
+		@Reference(type = '~', target = "(abc=3)")
+		protected void setLog(LogService log) {
+			this.log = log;
+		}
+
+		protected void unsetLog(@SuppressWarnings("unused") LogService log) {
+			this.log = null;
+		}
+
+	}
+
+	public static void testAnnotations() throws Exception {
+		Builder b = new Builder();
+		b.setClasspath(new File[] {
+			new File("bin")
+		});
+		b.setProperty("Service-Component", "*.MyComponent");
+		b.setProperty("Private-Package", "test.component");
+		b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+
+		Document doc = doc(b, "acomp");
+		print(doc, "");
+		assertAttribute(doc, "test.component.BNDAnnotationTest$MyComponent", "scr:component/implementation/@class");
+		assertAttribute(doc, "acomp", "scr:component/@name");
+		assertAttribute(doc, "abc", "scr:component/@factory");
+		assertAttribute(doc, "true", "scr:component/service/@servicefactory");
+		assertAttribute(doc, "activatex", "scr:component/@activate");
+		assertAttribute(doc, "modifiedx", "scr:component/@modified");
+		assertAttribute(doc, "deactivatex", "scr:component/@deactivate");
+		assertAttribute(doc, "org.osgi.service.log.LogService", "scr:component/service/provide/@interface");
+		assertAttribute(doc, "(abc=3)", "scr:component/reference/@target");
+		assertAttribute(doc, "setLog", "scr:component/reference/@bind");
+		assertAttribute(doc, "unsetLog", "scr:component/reference/@unbind");
+		assertAttribute(doc, "0..1", "scr:component/reference/@cardinality");
+	}
+
+	public static void assertAttribute(Document doc, String value, String expr) throws XPathExpressionException {
+		System.err.println(expr);
+		String o = (String) xpath.evaluate(expr, doc, XPathConstants.STRING);
+		if (o == null) {
+
+		}
+		assertNotNull(o);
+		assertEquals(value, o);
+	}
+
+	static Document doc(Builder b, String name) throws Exception {
+		Jar jar = b.getJar();
+		Resource r = jar.getResource("OSGI-INF/" + name + ".xml");
+		assertNotNull(r);
+		Document doc = db.parse(r.openInputStream());
+		r.write(System.err);
+		return doc;
+	}
+
+	private static void print(Node doc, String indent) {
+		System.err.println(indent + doc);
+		NamedNodeMap attributes = doc.getAttributes();
+		if (attributes != null)
+			for (int i = 0; i < attributes.getLength(); i++) {
+				print(attributes.item(i), indent + "  ");
+			}
+		NodeList nl = doc.getChildNodes();
+		for (int i = 0; i < nl.getLength(); i++) {
+			print(nl.item(i), indent + "  ");
+		}
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/component/ComponentOrderingTest.java b/biz.aQute.bndlib.tests/src/test/component/ComponentOrderingTest.java
new file mode 100644
index 0000000..daa9fd3
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/component/ComponentOrderingTest.java
@@ -0,0 +1,36 @@
+package test.component;
+
+import java.io.*;
+
+import junit.framework.*;
+import aQute.bnd.differ.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.diff.*;
+
+public class ComponentOrderingTest extends TestCase {
+
+	static DiffPluginImpl	differ	= new DiffPluginImpl();
+
+	public static void testOrdering() throws Exception {
+		Builder builder = new Builder();
+		builder.addClasspath(new File("bin"));
+		builder.setProperty("Service-Component", "OSGI-INF/a.xml,OSGI-INF/b.xml,OSGI-INF/c.xml,OSGI-INF/d.xml");
+		Jar a = builder.build();
+
+		String exa = (String) a.getManifest().getMainAttributes().getValue(Constants.EXPORT_PACKAGE);
+		
+		builder = new Builder();
+		builder.addClasspath(new File("bin"));
+		builder.setProperty("Service-Component", "OSGI-INF/d.xml,OSGI-INF/b.xml,OSGI-INF/a.xml,OSGI-INF/c.xml");
+		Jar b = builder.build();
+
+		String exb = (String) b.getManifest().getMainAttributes().getValue("Service-Component");
+
+		Tree newer = differ.tree(b);
+		Tree older = differ.tree(a);
+
+		Diff diff = newer.diff(older);
+
+		assertEquals(Delta.UNCHANGED, diff.getDelta());
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/component/ComponentTest.java b/biz.aQute.bndlib.tests/src/test/component/ComponentTest.java
new file mode 100755
index 0000000..315320f
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/component/ComponentTest.java
@@ -0,0 +1,493 @@
+package test.component;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+
+import javax.xml.namespace.*;
+import javax.xml.parsers.*;
+import javax.xml.xpath.*;
+
+import junit.framework.*;
+
+import org.osgi.framework.*;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Constants;
+import aQute.lib.io.*;
+
+public class ComponentTest extends TestCase {
+	static final DocumentBuilderFactory	dbf		= DocumentBuilderFactory.newInstance();
+	static final XPathFactory				xpathf	= XPathFactory.newInstance();
+	static final XPath						xpath	= xpathf.newXPath();
+	static DocumentBuilder					db;
+
+	static {
+		try {
+			dbf.setNamespaceAware(true);
+			db = dbf.newDocumentBuilder();
+			xpath.setNamespaceContext(new NamespaceContext() {
+
+				@Override
+				public Iterator<String> getPrefixes(String namespaceURI) {
+					return Arrays.asList("md", "scr").iterator();
+				}
+
+				@Override
+				public String getPrefix(String namespaceURI) {
+					if (namespaceURI.equals("http://www.osgi.org/xmlns/metatype/v1.1.0"))
+						return "md";
+					if (namespaceURI.equals("http://www.osgi.org/xmlns/scr/v1.1.0"))
+						return "scr";
+
+					return null;
+				}
+
+				@Override
+				public String getNamespaceURI(String prefix) {
+					if (prefix.equals("md"))
+						return "http://www.osgi.org/xmlns/metatype/v1.1.0";
+					else if (prefix.equals("scr"))
+						return "http://www.osgi.org/xmlns/scr/v1.1.0";
+					else
+						return null;
+				}
+			});
+		}
+		catch (ParserConfigurationException e) {
+			e.printStackTrace();
+			throw new ExceptionInInitializerError(e);
+		}
+	}
+
+
+	public static class ReferenceOrder {
+		
+		void setA(ServiceReference sr) {}
+		void unsetA(ServiceReference sr) {}
+		
+		void setZ(ServiceReference sr) {}
+		void unsetZ(ServiceReference sr) {}
+	}
+
+	/**
+	 * 112.5.7 says refeence order is used to order binding services, so from headers we preserve order.
+	 * @throws Exception
+	 */
+	public static void testHeaderReferenceOrder() throws Exception {
+		Document doc = setup(ReferenceOrder.class.getName() + ";version:=1.1;z=org.osgi.service.http.HttpService?;a=org.osgi.service.http.HttpService?", ReferenceOrder.class.getName());
+		assertAttribute(doc, "z", "scr:component/reference[1]/@name");
+		assertAttribute(doc, "a", "scr:component/reference[2]/@name");
+	}
+	
+	/**
+	 * Test to see if we ignore scala.ScalaObject as interface
+	 * 
+	 * @throws Exception
+	 */
+	public static void testScalaObject() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("jar/com.test.scala.jar"));
+		b.setProperty("Service-Component", "*");
+		b.setProperty("Export-Package", "com.test.scala.*");
+		Jar jar = b.build();
+		Manifest m = jar.getManifest();
+		System.err.println(Processor.join(b.getErrors()));
+		System.err.println(Processor.join(b.getWarnings()));
+		System.err.println(m.getMainAttributes().getValue("Service-Component"));
+		IO.copy(jar.getResource("OSGI-INF/com.test.scala.Service.xml").openInputStream(), System.err);
+		Document doc = doc(b, "com.test.scala.Service");
+		assertEquals("com.test.scala.Service", xpath.evaluate("component/implementation/@class", doc));
+		assertEquals("", xpath.evaluate("component/service/provide/@interface", doc));
+
+	}
+
+	/**
+	 * Test if a reference is made to an interface implemented on a superclass.
+	 * This is from https://github.com/bndtools/bnd/issues#issue/23
+	 */
+
+	public static void testProvideFromSuperClass() throws Exception {
+		Builder b = new Builder();
+		b.setClasspath(new File[] {
+			new File("bin")
+		});
+		b.setProperty("Service-Component", "*InheritedActivator");
+		b.setProperty("Private-Package", "test.activator.inherits");
+		b.addClasspath(new File("jar/osgi.jar"));
+		b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+
+		Manifest m = b.getJar().getManifest();
+		String imports = m.getMainAttributes().getValue("Import-Package");
+		assertTrue(imports.contains("org.osgi.framework"));
+	}
+
+	
+	/**
+	 * A non-FQN entry but we demand no annotations, should generate an error
+	 * and no component
+	 */
+
+	public static void testNonFQNAndNoAnnotations() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("Include-Resource",
+				"org/osgi/impl/service/coordinator/AnnotationWithJSR14.class=jar/AnnotationWithJSR14.jclass");
+		b.setProperty("Service-Component", "*;" + Constants.NOANNOTATIONS + "=true");
+		b.setProperty("-resourceonly", "true");
+		Jar jar = b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(1, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+
+		Manifest manifest = jar.getManifest();
+		String component = manifest.getMainAttributes().getValue("Service-Component");
+		System.err.println(component);
+		assertNull(component);
+	}
+
+
+	public static void assertAttribute(Document doc, String value, String expr) throws XPathExpressionException {
+		System.err.println(expr);
+		String o = (String) xpath.evaluate(expr, doc, XPathConstants.STRING);
+		if (o == null) {
+
+		}
+		assertNotNull(o);
+		assertEquals(value, o);
+	}
+
+	static Document doc(Builder b, String name) throws Exception {
+		Jar jar = b.getJar();
+		Resource r = jar.getResource("OSGI-INF/" + name + ".xml");
+		assertNotNull(r);
+		Document doc = db.parse(r.openInputStream());
+		r.write(System.err);
+		return doc;
+	}
+
+	public static void testV1_1Directives() throws Exception {
+		Element component = setup("test.activator.Activator11;factory:=blabla;immediate:=true;enabled:=false;configuration-policy:=optional;activate:=start;deactivate:=stop;modified:=modded",
+				"test.activator.Activator11").getDocumentElement();
+		assertEquals("http://www.osgi.org/xmlns/scr/v1.1.0", component.getNamespaceURI());
+		assertEquals("blabla", component.getAttribute("factory"));
+		assertEquals("false", component.getAttribute("enabled"));
+		assertEquals("optional", component.getAttribute("configuration-policy"));
+		assertEquals("start", component.getAttribute("activate"));
+		assertEquals("stop", component.getAttribute("deactivate"));
+		assertEquals("modded", component.getAttribute("modified"));
+
+	}
+
+	public static void testNoNamespace() throws Exception {
+		Element component = setup("test.activator.Activator");
+		assertEquals(null, component.getNamespaceURI());
+	}
+
+	public static void testAutoNamespace() throws Exception {
+		Element component = setup("test.activator.Activator;activate:='start';deactivate:='stop'");
+		assertEquals("http://www.osgi.org/xmlns/scr/v1.1.0", component.getNamespaceURI());
+
+		//activate/deactivate with  BundleContext args
+		component = setup("test.activator.Activator2", "test.activator.Activator2").getDocumentElement();
+		assertEquals("http://www.osgi.org/xmlns/scr/v1.1.0", component.getNamespaceURI());
+
+		//deactivate with a int reason
+		component = setup("test.activator.Activator3", "test.activator.Activator3").getDocumentElement();
+		assertEquals("http://www.osgi.org/xmlns/scr/v1.1.0", component.getNamespaceURI());
+
+		//package access activate/deactivate with ComponentContext args
+		component = setup("test.activator.ActivatorPackage", "test.activator.ActivatorPackage").getDocumentElement();
+		assertEquals("http://www.osgi.org/xmlns/scr/v1.1.0", component.getNamespaceURI());
+
+		//private access activate/deactivate with ComponentContext args
+		component = setup("test.activator.ActivatorPrivate", "test.activator.ActivatorPrivate").getDocumentElement();
+		assertEquals("http://www.osgi.org/xmlns/scr/v1.1.0", component.getNamespaceURI());
+
+	}
+
+	public static void testCustomVersion() throws Exception {
+		Element component = setup("test.activator.Activator;version:=2");
+		assertEquals("http://www.osgi.org/xmlns/scr/v2.0.0", component.getNamespaceURI());
+	}
+
+	public static void testCustomNamespace() throws Exception {
+		Element component = setup("test.activator.Activator;xmlns:='http://www.osgi.org/xmlns/xscr/v2.0.0'");
+		assertEquals("http://www.osgi.org/xmlns/xscr/v2.0.0", component.getNamespaceURI());
+	}
+
+	static Document setup(String header, String className) throws Exception {
+		Builder b = new Builder();
+		b.setProperty(Analyzer.SERVICE_COMPONENT, header);
+		b.setClasspath(new File[] {
+				new File("bin"), new File("jar/osgi.jar")
+		});
+		b.setProperty("Private-Package", "test.activator, org.osgi.service.http.*");
+		b.build();
+
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		List<String> errors = b.getErrors();
+		// ignore the dynamic-without-unbind error here
+		if (!errors.isEmpty()) {
+			assertEquals(1, errors.size());
+			assertTrue(errors.get(0).endsWith("dynamic but has no unbind method."));
+		}
+		assertEquals(0, b.getWarnings().size());
+
+		String path = "OSGI-INF/" + className + ".xml";
+		print(b.getJar().getResource(path), System.err);
+		Document doc = db.parse(new InputSource(b.getJar().getResource(path)
+				.openInputStream()));
+
+		return doc;
+	}
+	
+	static Element setup(String header) throws Exception {
+		return setup(header, "test.activator.Activator").getDocumentElement();
+	}
+
+	private static void print(Resource resource, OutputStream out) throws Exception {
+		InputStream in = resource.openInputStream();
+		try {
+			byte[] buffer = new byte[1024];
+			int size = in.read(buffer);
+			while (size > 0) {
+				out.write(buffer, 0, size);
+				size = in.read(buffer);
+			}
+			out.flush();
+		}
+		finally {
+			in.close();
+		}
+	}
+
+	/*
+	 * public void testWildcards() throws Exception { Builder b = new Builder();
+	 * b .setProperty(Analyzer.SERVICE_COMPONENT, "test/component/*.xml");
+	 * b.setProperty("-resourceonly", "true"); b.setProperty("Include-Resource",
+	 * "test/component=test/component"); Jar jar = b.build();
+	 * System.err.println(b.getErrors()); System.err.println(b.getWarnings());
+	 * assertEquals(0, b.getErrors().size()); assertEquals(0,
+	 * b.getWarnings().size()); }
+	 */
+	public static void testImplementation() throws Exception {
+		Builder b = new Builder();
+		b.setProperty(Analyzer.SERVICE_COMPONENT,
+				"silly.name;implementation:=test.activator.Activator;provide:=java.io.Serialization;servicefactory:=true");
+		b.setClasspath(new File[] {
+				new File("bin"), new File("jar/osgi.jar")
+		});
+		b.setProperty("Private-Package", "test.activator");
+		b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+
+		Jar jar = b.getJar();
+
+		Document doc = db.parse(new InputSource(jar.getResource("OSGI-INF/silly.name.xml").openInputStream()));
+
+		assertEquals("test.activator.Activator", doc.getElementsByTagName("implementation").item(0).getAttributes()
+				.getNamedItem("class").getNodeValue());
+		assertEquals("true", doc.getElementsByTagName("service").item(0).getAttributes().getNamedItem("servicefactory")
+				.getNodeValue());
+	}
+
+	/**
+	 * Standard activator with reference to http.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testProperties() throws Exception {
+		java.util.Properties p = new Properties();
+		p.put(Analyzer.EXPORT_PACKAGE, "test.activator,org.osgi.service.http");
+		p.put(Analyzer.IMPORT_PACKAGE, "*");
+		p.put(Analyzer.SERVICE_COMPONENT, "test.activator.Activator;properties:=\"a=3|4,b=1|2|3\"");
+		Builder b = new Builder();
+		b.setClasspath(new File[] {
+				new File("bin"), new File("jar/osgi.jar")
+		});
+		b.setProperties(p);
+		b.build();
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+
+		Jar jar = b.getJar();
+
+		Document doc = db.parse(new InputSource(jar.getResource("OSGI-INF/test.activator.Activator.xml")
+				.openInputStream()));
+
+		NodeList l = doc.getElementsByTagName("property");
+		assertEquals(2, l.getLength());
+		Node n = l.item(0);
+		System.err.println(n.getFirstChild().getNodeValue());
+		assertEquals("3\n4", l.item(1).getFirstChild().getNodeValue().trim());
+		assertEquals("1\n2\n3", l.item(0).getFirstChild().getNodeValue().trim());
+
+		assertEquals("test.activator.Activator", doc.getElementsByTagName("implementation").item(0).getAttributes()
+				.getNamedItem("class").getNodeValue());
+		// assertEquals("test.activator.Activator", xp.evaluate(
+		// "/component/implementation/@class", doc));
+		// assertEquals("org.osgi.service.http.HttpService", xp.evaluate(
+		// "/component/reference[@name='http']/@interface", doc));
+		// assertEquals("setHttp", xp.evaluate(
+		// "/component/reference[@name='http']/@bind", doc));
+		// assertEquals("unsetHttp", xp.evaluate(
+		// "/component/reference[@name='http']/@unbind", doc));
+		// assertEquals("", xp.evaluate(
+		// "/component/reference[@name='http']/@target", doc));
+	}
+
+	/**
+	 * Check if all the directives work
+	 * 
+	 * @throws Exception
+	 */
+	public static void testUnknownDirective() throws Exception {
+		java.util.Properties p = new Properties();
+		p.put(Analyzer.EXPORT_PACKAGE, "test.activator,org.osgi.service.http");
+		p.put(Analyzer.IMPORT_PACKAGE, "*");
+		p.put(Analyzer.SERVICE_COMPONENT, "test.activator.Activator;provides:=true");
+		Builder b = new Builder();
+		b.setClasspath(new File[] {
+				new File("bin"), new File("jar/osgi.jar")
+		});
+		b.setProperties(p);
+		b.build();
+		doc(b, "test.activator.Activator");
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(1, b.getErrors().size());
+		assertTrue(b.getErrors().get(0).indexOf("Unrecognized directive") >= 0);
+		assertEquals(0, b.getWarnings().size());
+	}
+
+	/**
+	 * Check if all the directives work
+	 * 
+	 * @throws Exception
+	 */
+	public static void testDirectives() throws Exception {
+		Document doc =
+			setup("test.activator.Activator;http=org.osgi.service.http.HttpService;dynamic:=http;optional:=http;provide:=test.activator.Activator; multiple:=http", "test.activator.Activator");
+
+		assertEquals("test.activator.Activator", xpath.evaluate(
+				"/component/implementation/@class", doc));
+		assertEquals("org.osgi.service.http.HttpService", xpath.evaluate(
+				"/component/reference[@name='http']/@interface", doc));
+		// there are no bind/unbind methods...
+		assertEquals("", xpath.evaluate(
+				 "/component/reference[@name='http']/@bind", doc));
+		assertEquals("", xpath.evaluate(
+				 "/component/reference[@name='http']/@unbind", doc));
+		assertEquals("0..n", xpath.evaluate(
+				"/component/reference[@name='http']/@cardinality", doc));
+		assertEquals("dynamic", xpath.evaluate(
+				"/component/reference[@name='http']/@policy", doc));
+		assertEquals("test.activator.Activator", xpath.evaluate(
+				"/component/service/provide/@interface", doc));
+	}
+
+	/**
+	 * Check if a bad filter on a service component causes an error.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testBadFilter() throws Exception {
+		java.util.Properties p = new Properties();
+		p.put(Analyzer.EXPORT_PACKAGE, "test.activator,org.osgi.service.http");
+		p.put(Analyzer.IMPORT_PACKAGE, "*");
+		p.put(Analyzer.SERVICE_COMPONENT, "test.activator.Activator;http=\"org.osgi.service.http.HttpService(|p=1)(p=2))\"");
+		Builder b = new Builder();
+		b.setClasspath(new File[] { new File("bin"), new File("jar/osgi.jar") });
+		b.setProperties(p);
+		b.build();
+		System.err.println(b.getErrors());
+		System.err.println(b.getWarnings());
+		assertEquals(1, b.getErrors().size());
+		assertTrue(b.getErrors().get(0).indexOf("Invalid target filter") >= 0);
+		assertEquals(0, b.getWarnings().size());
+	}
+
+	/**
+	 * Check if we can set a target filter
+	 * 
+	 * @throws Exception
+	 */
+	public static void testFilter() throws Exception {
+		Element component = setup("test.activator.Activator;http=\"org.osgi.service.http.HttpService(|(p=1)(p=2))\"");
+		Element implementation = (Element) component.getElementsByTagName("implementation").item(0);
+		assertEquals(null, implementation.getNamespaceURI());
+		assertEquals("test.activator.Activator", implementation.getAttribute("class"));
+
+		Element reference = (Element) component.getElementsByTagName("reference").item(0);
+		assertEquals("org.osgi.service.http.HttpService", reference.getAttribute("interface"));
+		//we actually check for the methods and don't add them blindly
+		assertEquals("", reference.getAttribute("bind"));
+		assertEquals("", reference.getAttribute("unbind"));
+		assertEquals("(|(p=1)(p=2))", reference.getAttribute("target"));
+	}
+
+	/**
+	 * Standard activator with reference to http.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testSimple() throws Exception {
+		Element component = setup("test.activator.Activator;http=org.osgi.service.http.HttpService?");
+		Element implementation = (Element) component.getElementsByTagName("implementation").item(0);
+		assertEquals(null, implementation.getNamespaceURI());
+		assertEquals("test.activator.Activator", implementation.getAttribute("class"));
+
+		Element reference = (Element) component.getElementsByTagName("reference").item(0);
+		assertEquals("org.osgi.service.http.HttpService", reference.getAttribute("interface"));
+		assertEquals("", reference.getAttribute("bind"));
+		assertEquals("", reference.getAttribute("unbind"));
+		assertEquals("", reference.getAttribute("target"));
+		assertEquals("0..1", reference.getAttribute("cardinality"));
+		assertEquals("dynamic", reference.getAttribute("policy"));
+	}
+
+	/**
+	 * Standard activator with reference to http.
+	 * 
+	 * @throws Exception
+	 */
+	public static void testQuestion() throws Exception {
+		Element component = setup("test.activator.Activator;http=org.osgi.service.http.HttpService?");
+		Element reference = (Element) component.getElementsByTagName("reference").item(0);
+		assertEquals("0..1", reference.getAttribute("cardinality"));
+		assertEquals("dynamic", reference.getAttribute("policy"));
+	}
+
+	public static void testStar() throws Exception {
+		Element component = setup("test.activator.Activator;http=org.osgi.service.http.HttpService*");
+		Element reference = (Element) component.getElementsByTagName("reference").item(0);
+		assertEquals("0..n", reference.getAttribute("cardinality"));
+		assertEquals("dynamic", reference.getAttribute("policy"));
+	}
+
+	public static void testPlus() throws Exception {
+		Element component = setup("test.activator.Activator;http=org.osgi.service.http.HttpService+");
+		Element reference = (Element) component.getElementsByTagName("reference").item(0);
+		assertEquals("1..n", reference.getAttribute("cardinality"));
+		assertEquals("dynamic", reference.getAttribute("policy"));
+	}
+
+	public static void testTilde() throws Exception {
+		Element component = setup("test.activator.Activator;http=org.osgi.service.http.HttpService~");
+		Element reference = (Element) component.getElementsByTagName("reference").item(0);
+		assertEquals("0..1", reference.getAttribute("cardinality"));
+		assertEquals("", reference.getAttribute("policy"));
+	}
+	
+}
diff --git a/biz.aQute.bndlib.tests/src/test/component/DSAnnotationTest.java b/biz.aQute.bndlib.tests/src/test/component/DSAnnotationTest.java
new file mode 100644
index 0000000..bf64c28
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/component/DSAnnotationTest.java
@@ -0,0 +1,1133 @@
+package test.component;
+
+import java.io.*;
+import java.util.*;
+
+import javax.xml.xpath.*;
+
+import org.osgi.framework.*;
+import org.osgi.service.component.*;
+import org.osgi.service.component.annotations.*;
+import org.osgi.service.log.*;
+
+import aQute.bnd.component.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.test.*;
+
+/**
+ * #118
+ */
+public class DSAnnotationTest extends BndTestCase {
+
+	/**
+	 * Property test
+	 */
+
+	@Component(xmlns= "http://www.osgi.org/xmlns/scr/v1.1.0", 
+			property = {
+			"x:Integer=3.0", "a=1", "a=2", "b=1", "boolean:Boolean=true", "byte:Byte=1", "char:Character=1",
+			"short:Short=3", "integer:Integer=3", "long:Long=3", "float:Float=3.0", "double:Double=3e7",
+			"string:String=%", "wrongInteger:Integer=blabla", "\n\r\t \u0343\u0344\u0345\u0346\n:Integer=3"
+	})
+	public static class PropertiesTestx {
+
+	}
+
+	public static void testProperties() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("-dsannotations", "test.component.*x");
+		b.setProperty("Private-Package", "test.component");
+		b.addClasspath(new File("bin"));
+
+		Jar jar = b.build();
+		if (!b.check("Cannot convert data blabla to type Integer", "Cannot convert data 3.0 to type Integer"))
+			fail();
+
+		//
+		// Test all the defaults
+		//
+
+		Resource r = jar.getResource("OSGI-INF/test.component.DSAnnotationTest$PropertiesTestx.xml");
+		System.err.println(Processor.join(jar.getResources().keySet(), "\n"));
+		assertNotNull(r);
+		r.write(System.err);
+		XmlTester xt = new XmlTester(r.openInputStream(), "scr", "http://www.osgi.org/xmlns/scr/v1.1.0");
+		xt.assertAttribute("1", "scr:component/property[@name='b']/@value");
+		xt.assertAttribute("", "scr:component/property[@name='a']/@value");
+		xt.assertAttribute("Byte", "scr:component/property[@name='byte']/@type");
+		xt.assertAttribute("Boolean", "scr:component/property[@name='boolean']/@type");
+		xt.assertAttribute("Character", "scr:component/property[@name='char']/@type");
+		xt.assertAttribute("Short", "scr:component/property[@name='short']/@type");
+		xt.assertAttribute("Integer", "scr:component/property[@name='integer']/@type");
+		xt.assertAttribute("Long", "scr:component/property[@name='long']/@type");
+		xt.assertAttribute("Float", "scr:component/property[@name='float']/@type");
+		xt.assertAttribute("Double", "scr:component/property[@name='double']/@type");
+		xt.assertAttribute("Integer", "scr:component/property[@name='\u0343\u0344\u0345\u0346']/@type");
+	}
+
+	/**
+	 * Check that a DS 1.0 compotible class with annotations ends up with the DS 1.0 (no) namespace
+	 *
+	 */
+	@Component()
+	public static class DS10_basic implements Serializable, Runnable {
+		private static final long	serialVersionUID	= 1L;
+
+		@Activate
+		void activate(@SuppressWarnings("unused")ComponentContext cc) {}
+
+		@Deactivate
+		void deactivate(@SuppressWarnings("unused")ComponentContext cc) {}
+
+		@Reference
+		void xsetLogService(@SuppressWarnings("unused") LogService log) {
+
+		}
+
+		void unxsetLogService(@SuppressWarnings("unused") LogService log) {
+
+		}
+
+		@Override
+		public void run() {
+			// TODO Auto-generated method stub
+
+		}
+	}
+
+	/**
+	 * Check that a DS 1.1 compotible class ends up with the DS 1.1 namespace and appropriate activate/deactivate attributes
+	 *
+	 */
+	@Component()
+	public static class DS11_basic implements Serializable, Runnable {
+		private static final long	serialVersionUID	= 1L;
+
+		@Activate
+		void activate(@SuppressWarnings("unused")ComponentContext cc, @SuppressWarnings("unused")BundleContext ctx) {}
+
+		@Deactivate
+		void deactivate(@SuppressWarnings("unused")ComponentContext cc, @SuppressWarnings("unused")int cause) {}
+
+		@Reference
+		void xsetLogService(@SuppressWarnings("unused") LogService log) {
+
+		}
+
+		void unxsetLogService(@SuppressWarnings("unused") LogService log) {
+
+		}
+
+		@Override
+		public void run() {
+			// TODO Auto-generated method stub
+
+		}
+	}
+
+	/**
+	 * Check that a DS 1.1 bind method causes a DS 1.1 namespace
+	 *
+	 */
+	@Component()
+	public static class DS11_ref1_basic implements Serializable, Runnable {
+		private static final long	serialVersionUID	= 1L;
+
+		@Activate
+		void activate(@SuppressWarnings("unused")ComponentContext cc) {}
+
+		@Deactivate
+		void deactivate(@SuppressWarnings("unused")ComponentContext cc) {}
+
+		@Reference
+		void xsetLogService(@SuppressWarnings("unused") LogService log, @SuppressWarnings("unused")  Map map) {
+
+		}
+
+		void unxsetLogService(@SuppressWarnings("unused") LogService log) {
+
+		}
+
+		@Override
+		public void run() {
+			// TODO Auto-generated method stub
+
+		}
+	}
+
+	/**
+	 * Check that a DS 1.1 unbind method causes a DS 1.1 namespace
+	 *
+	 */
+	@Component()
+	public static class DS11_ref2_basic implements Serializable, Runnable {
+		private static final long	serialVersionUID	= 1L;
+
+		@Activate
+		void activate(@SuppressWarnings("unused")ComponentContext cc) {}
+
+		@Deactivate
+		void deactivate(@SuppressWarnings("unused")ComponentContext cc) {}
+
+		@Reference
+		void xsetLogService(@SuppressWarnings("unused") LogService log) {
+
+		}
+
+		void unxsetLogService(@SuppressWarnings("unused") LogService log, @SuppressWarnings("unused")  Map map) {
+
+		}
+
+		@Override
+		public void run() {
+			// TODO Auto-generated method stub
+
+		}
+	}
+
+	/**
+	 * The basic test. This test will take an all default component and a
+	 * component that has all values set.  Since the activate/deactivate methods have non-default names
+	 * and there is a modified methods, this is a DS 1.1 component.
+	 */
+	@Component()
+	public static class Defaults_basic implements Serializable, Runnable {
+		private static final long	serialVersionUID	= 1L;
+
+		@Activate
+		void open() {}
+
+		@Deactivate
+		void close() {}
+
+		@Modified
+		void modified() {}
+
+		@Reference
+		void xsetLogService(@SuppressWarnings("unused") LogService log) {
+
+		}
+
+		void unxsetLogService(@SuppressWarnings("unused") LogService log) {
+
+		}
+
+		// void modifiedLogService(LogService log) {
+		//
+		// }
+
+		@Override
+		public void run() {
+			// TODO Auto-generated method stub
+
+		}
+	}
+
+	@Component(service = Object.class, configurationPolicy = ConfigurationPolicy.IGNORE, enabled = false, factory = "factory", immediate = false, name = "name", property = {
+			"a=1", "a=2", "b=3"
+	}, properties = "resource.props", servicefactory = false, configurationPid = "configuration-pid", xmlns = "xmlns")
+	public static class Explicit_basic implements Serializable, Runnable {
+		private static final long	serialVersionUID	= 1L;
+
+		@Activate
+		void open() {}
+
+		@Deactivate
+		void close() {}
+
+		@Modified
+		void changed() {}
+
+		@Reference(cardinality = ReferenceCardinality.AT_LEAST_ONE, name = "foo", policy = ReferencePolicy.DYNAMIC, service = Object.class, target = "(objectclass=*)", unbind = "unset", updated = "updatedLogService", policyOption = ReferencePolicyOption.GREEDY)
+		void setLogService(@SuppressWarnings("unused") LogService log) {
+
+		}
+
+		void unset(@SuppressWarnings("unused") Object log) {
+
+		}
+
+		void unset() {
+
+		}
+
+		void unsetLogService(@SuppressWarnings("unused") LogService log) {
+
+		}
+
+		void updatedLogService(@SuppressWarnings("unused") Object log) {
+
+		}
+
+		@Override
+		public void run() {
+			// TODO Auto-generated method stub
+
+		}
+	}
+
+	public static void testBasic() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("-dsannotations", "test.component.*_basic");
+		b.setProperty("Private-Package", "test.component");
+		b.addClasspath(new File("bin"));
+
+		Jar jar = b.build();
+		assertOk(b);
+
+		{
+			//
+			// Test all the DS 1.0 defaults
+			//
+
+			Resource r = jar.getResource("OSGI-INF/test.component.DSAnnotationTest$DS10_basic.xml");
+			System.err.println(Processor.join(jar.getResources().keySet(), "\n"));
+			assertNotNull(r);
+			r.write(System.err);
+			XmlTester xt = new XmlTester(r.openInputStream()); 
+
+			// Test the defaults
+			xt.assertAttribute("test.component.DSAnnotationTest$DS10_basic", "component/implementation/@class");
+
+			// Default must be the implementation class
+			xt.assertAttribute("test.component.DSAnnotationTest$DS10_basic", "component/@name");
+
+			xt.assertAttribute("", "component/@configuration-policy");
+			xt.assertAttribute("", "component/@immediate");
+			xt.assertAttribute("", "component/@enabled");
+			xt.assertAttribute("", "component/@factory");
+			xt.assertAttribute("", "component/@servicefactory");
+			xt.assertAttribute("", "component/@configuration-pid");
+			xt.assertAttribute("", "component/@activate");
+			xt.assertAttribute("", "component/@deactivate");
+			xt.assertAttribute("", "component/@modified");
+			xt.assertAttribute("java.io.Serializable", "component/service/provide[1]/@interface");
+			xt.assertAttribute("java.lang.Runnable", "component/service/provide[2]/@interface");
+
+			xt.assertAttribute("0", "count(component/properties)");
+			xt.assertAttribute("0", "count(component/property)");
+
+			xt.assertAttribute("xsetLogService", "component/reference[1]/@name");
+			xt.assertAttribute("", "component/reference[1]/@target");
+			xt.assertAttribute("xsetLogService", "component/reference[1]/@bind");
+			xt.assertAttribute("unxsetLogService", "component/reference[1]/@unbind");
+			xt.assertAttribute("", "component/reference[1]/@cardinality");
+			xt.assertAttribute("", "component/reference[1]/@policy");
+			xt.assertAttribute("", "component/reference[1]/@target");
+			xt.assertAttribute("", "component/reference[1]/@policy-option");
+	}
+	{
+			//
+			// Test the DS 1.1 defaults 
+			//
+
+			Resource r = jar.getResource("OSGI-INF/test.component.DSAnnotationTest$DS11_basic.xml");
+			System.err.println(Processor.join(jar.getResources().keySet(), "\n"));
+			assertNotNull(r);
+			r.write(System.err);
+			XmlTester xt = new XmlTester(r.openInputStream(), "scr", "http://www.osgi.org/xmlns/scr/v1.1.0"); // #136
+																												// was
+																												// http://www.osgi.org/xmlns/scr/1.1.0
+
+			// Test the defaults
+			xt.assertAttribute("test.component.DSAnnotationTest$DS11_basic", "scr:component/implementation/@class");
+
+			// Default must be the implementation class
+			xt.assertAttribute("test.component.DSAnnotationTest$DS11_basic", "scr:component/@name");
+
+			xt.assertAttribute("", "scr:component/@configuration-policy");
+			xt.assertAttribute("", "scr:component/@immediate");
+			xt.assertAttribute("", "scr:component/@enabled");
+			xt.assertAttribute("", "scr:component/@factory");
+			xt.assertAttribute("", "scr:component/@servicefactory");
+			xt.assertAttribute("", "scr:component/@configuration-pid");
+			xt.assertAttribute("activate", "scr:component/@activate");
+			xt.assertAttribute("deactivate", "scr:component/@deactivate");
+			xt.assertAttribute("", "scr:component/@modified");
+			xt.assertAttribute("java.io.Serializable", "scr:component/service/provide[1]/@interface");
+			xt.assertAttribute("java.lang.Runnable", "scr:component/service/provide[2]/@interface");
+
+			xt.assertAttribute("0", "count(scr:component/properties)");
+			xt.assertAttribute("0", "count(scr:component/property)");
+
+			xt.assertAttribute("xsetLogService", "scr:component/reference[1]/@name");
+			xt.assertAttribute("", "scr:component/reference[1]/@target");
+			xt.assertAttribute("xsetLogService", "scr:component/reference[1]/@bind");
+			xt.assertAttribute("unxsetLogService", "scr:component/reference[1]/@unbind");
+			xt.assertAttribute("", "scr:component/reference[1]/@cardinality");
+			xt.assertAttribute("", "scr:component/reference[1]/@policy");
+			xt.assertAttribute("", "scr:component/reference[1]/@target");
+			xt.assertAttribute("", "scr:component/reference[1]/@policy-option");
+	}
+	{
+		//
+		// Test a DS 1.1 bind method results in the DS 1.1 namespace
+		//
+
+		Resource r = jar.getResource("OSGI-INF/test.component.DSAnnotationTest$DS11_ref1_basic.xml");
+		System.err.println(Processor.join(jar.getResources().keySet(), "\n"));
+		assertNotNull(r);
+		r.write(System.err);
+		XmlTester xt = new XmlTester(r.openInputStream(), "scr", "http://www.osgi.org/xmlns/scr/v1.1.0"); // #136
+																											// was
+																											// http://www.osgi.org/xmlns/scr/1.1.0
+
+		// Test the defaults
+		xt.assertAttribute("test.component.DSAnnotationTest$DS11_ref1_basic", "scr:component/implementation/@class");
+
+		// Default must be the implementation class
+		xt.assertAttribute("test.component.DSAnnotationTest$DS11_ref1_basic", "scr:component/@name");
+
+		xt.assertAttribute("", "scr:component/@configuration-policy");
+		xt.assertAttribute("", "scr:component/@immediate");
+		xt.assertAttribute("", "scr:component/@enabled");
+		xt.assertAttribute("", "scr:component/@factory");
+		xt.assertAttribute("", "scr:component/@servicefactory");
+		xt.assertAttribute("", "scr:component/@configuration-pid");
+		xt.assertAttribute("activate", "scr:component/@activate");
+		xt.assertAttribute("deactivate", "scr:component/@deactivate");
+		xt.assertAttribute("", "scr:component/@modified");
+		xt.assertAttribute("java.io.Serializable", "scr:component/service/provide[1]/@interface");
+		xt.assertAttribute("java.lang.Runnable", "scr:component/service/provide[2]/@interface");
+
+		xt.assertAttribute("0", "count(scr:component/properties)");
+		xt.assertAttribute("0", "count(scr:component/property)");
+
+		xt.assertAttribute("xsetLogService", "scr:component/reference[1]/@name");
+		xt.assertAttribute("", "scr:component/reference[1]/@target");
+		xt.assertAttribute("xsetLogService", "scr:component/reference[1]/@bind");
+		xt.assertAttribute("unxsetLogService", "scr:component/reference[1]/@unbind");
+		xt.assertAttribute("", "scr:component/reference[1]/@cardinality");
+		xt.assertAttribute("", "scr:component/reference[1]/@policy");
+		xt.assertAttribute("", "scr:component/reference[1]/@target");
+		xt.assertAttribute("", "scr:component/reference[1]/@policy-option");
+	}
+	{
+		//
+		// Test a DS 1.1 unbind method results in the DS 1.1 namespace
+		//
+
+		Resource r = jar.getResource("OSGI-INF/test.component.DSAnnotationTest$DS11_ref2_basic.xml");
+		System.err.println(Processor.join(jar.getResources().keySet(), "\n"));
+		assertNotNull(r);
+		r.write(System.err);
+		XmlTester xt = new XmlTester(r.openInputStream(), "scr", "http://www.osgi.org/xmlns/scr/v1.1.0"); // #136
+																											// was
+																											// http://www.osgi.org/xmlns/scr/1.1.0
+
+		// Test the defaults
+		xt.assertAttribute("test.component.DSAnnotationTest$DS11_ref2_basic", "scr:component/implementation/@class");
+
+		// Default must be the implementation class
+		xt.assertAttribute("test.component.DSAnnotationTest$DS11_ref2_basic", "scr:component/@name");
+
+		xt.assertAttribute("", "scr:component/@configuration-policy");
+		xt.assertAttribute("", "scr:component/@immediate");
+		xt.assertAttribute("", "scr:component/@enabled");
+		xt.assertAttribute("", "scr:component/@factory");
+		xt.assertAttribute("", "scr:component/@servicefactory");
+		xt.assertAttribute("", "scr:component/@configuration-pid");
+		xt.assertAttribute("activate", "scr:component/@activate");
+		xt.assertAttribute("deactivate", "scr:component/@deactivate");
+		xt.assertAttribute("", "scr:component/@modified");
+		xt.assertAttribute("java.io.Serializable", "scr:component/service/provide[1]/@interface");
+		xt.assertAttribute("java.lang.Runnable", "scr:component/service/provide[2]/@interface");
+
+		xt.assertAttribute("0", "count(scr:component/properties)");
+		xt.assertAttribute("0", "count(scr:component/property)");
+
+		xt.assertAttribute("xsetLogService", "scr:component/reference[1]/@name");
+		xt.assertAttribute("", "scr:component/reference[1]/@target");
+		xt.assertAttribute("xsetLogService", "scr:component/reference[1]/@bind");
+		xt.assertAttribute("unxsetLogService", "scr:component/reference[1]/@unbind");
+		xt.assertAttribute("", "scr:component/reference[1]/@cardinality");
+		xt.assertAttribute("", "scr:component/reference[1]/@policy");
+		xt.assertAttribute("", "scr:component/reference[1]/@target");
+		xt.assertAttribute("", "scr:component/reference[1]/@policy-option");
+	}
+	{
+			//
+			// Test all the defaults
+			//
+
+			Resource r = jar.getResource("OSGI-INF/test.component.DSAnnotationTest$Defaults_basic.xml");
+			System.err.println(Processor.join(jar.getResources().keySet(), "\n"));
+			assertNotNull(r);
+			r.write(System.err);
+			XmlTester xt = new XmlTester(r.openInputStream(), "scr", "http://www.osgi.org/xmlns/scr/v1.1.0"); // #136
+																												// was
+																												// http://www.osgi.org/xmlns/scr/1.1.0
+
+			// Test the defaults
+			xt.assertAttribute("test.component.DSAnnotationTest$Defaults_basic", "scr:component/implementation/@class");
+
+			// Default must be the implementation class
+			xt.assertAttribute("test.component.DSAnnotationTest$Defaults_basic", "scr:component/@name");
+
+			xt.assertAttribute("", "scr:component/@configuration-policy");
+			xt.assertAttribute("", "scr:component/@immediate");
+			xt.assertAttribute("", "scr:component/@enabled");
+			xt.assertAttribute("", "scr:component/@factory");
+			xt.assertAttribute("", "scr:component/@servicefactory");
+			xt.assertAttribute("", "scr:component/@configuration-pid");
+			xt.assertAttribute("open", "scr:component/@activate");
+			xt.assertAttribute("close", "scr:component/@deactivate");
+			xt.assertAttribute("modified", "scr:component/@modified");
+			xt.assertAttribute("java.io.Serializable", "scr:component/service/provide[1]/@interface");
+			xt.assertAttribute("java.lang.Runnable", "scr:component/service/provide[2]/@interface");
+
+			xt.assertAttribute("0", "count(scr:component/properties)");
+			xt.assertAttribute("0", "count(scr:component/property)");
+
+			xt.assertAttribute("xsetLogService", "scr:component/reference[1]/@name");
+			xt.assertAttribute("", "scr:component/reference[1]/@target");
+			xt.assertAttribute("xsetLogService", "scr:component/reference[1]/@bind");
+			xt.assertAttribute("unxsetLogService", "scr:component/reference[1]/@unbind");
+			xt.assertAttribute("", "scr:component/reference[1]/@cardinality");
+			xt.assertAttribute("", "scr:component/reference[1]/@policy");
+			xt.assertAttribute("", "scr:component/reference[1]/@target");
+			xt.assertAttribute("", "scr:component/reference[1]/@policy-option");
+		}
+		{
+			//
+			// Test explicit
+			//
+
+			Resource r = jar.getResource("OSGI-INF/name.xml");
+			assertNotNull(r);
+			r.write(System.err);
+			XmlTester xt = new XmlTester(r.openInputStream(), "scr", "xmlns");
+
+			// Test the defaults
+			xt.assertAttribute("test.component.DSAnnotationTest$Explicit_basic", "scr:component/implementation/@class");
+
+			// Default must be the implementation class
+			xt.assertAttribute("name", "scr:component/@name");
+
+			xt.assertAttribute("ignore", "scr:component/@configuration-policy");
+			xt.assertAttribute("configuration-pid", "scr:component/@configuration-pid");
+			xt.assertAttribute("false", "scr:component/@immediate");
+			xt.assertAttribute("false", "scr:component/@enabled");
+			xt.assertAttribute("factory", "scr:component/@factory");
+			xt.assertAttribute("false", "scr:component/@servicefactory");
+			xt.assertAttribute("open", "scr:component/@activate");
+			xt.assertAttribute("close", "scr:component/@deactivate");
+			xt.assertAttribute("changed", "scr:component/@modified");
+			xt.assertAttribute("java.lang.Object", "scr:component/service/provide[1]/@interface");
+			xt.assertAttribute("1", "count(scr:component/service/provide)");
+
+			xt.assertAttribute("1", "count(scr:component/properties)");
+			xt.assertAttribute("2", "count(scr:component/property)");
+
+			xt.assertAttribute("(objectclass=*)", "scr:component/reference[1]/@target");
+			xt.assertAttribute("setLogService", "scr:component/reference[1]/@bind");
+			xt.assertAttribute("unset", "scr:component/reference[1]/@unbind");
+			xt.assertAttribute("updatedLogService", "scr:component/reference[1]/@updated");
+			xt.assertAttribute("1..n", "scr:component/reference[1]/@cardinality");
+			xt.assertAttribute("dynamic", "scr:component/reference[1]/@policy");
+			xt.assertAttribute("(objectclass=*)", "scr:component/reference[1]/@target");
+
+			xt.assertAttribute("2", "count(scr:component/property)");
+			xt.assertAttribute("1", "count(scr:component/properties)");
+			xt.assertAttribute("resource.props", "scr:component/properties[1]/@entry");
+			xt.assertAttribute("greedy", "scr:component/reference[1]/@policy-option");
+		}
+	}
+	
+	/**
+	 * Check that a Felix 1.2 compotible class ends up with the Felix 1.2 namespace and appropriate activate/deactivate attributes
+	 *
+	 */
+	@Component()
+	public static class activate_basicFelix12 implements Serializable, Runnable {
+		private static final long	serialVersionUID	= 1L;
+
+		@Activate
+		Map<String, Object> activate(@SuppressWarnings("unused")ComponentContext cc, @SuppressWarnings("unused")BundleContext ctx) {
+			return null;
+		}
+
+		@Deactivate
+		void deactivate(@SuppressWarnings("unused")ComponentContext cc, @SuppressWarnings("unused")int cause) {}
+
+		@Modified
+		void modified(@SuppressWarnings("unused")ComponentContext cc) {}
+
+		@Reference
+		void setLogService(@SuppressWarnings("unused") LogService log) {}
+
+		void unsetLogService(@SuppressWarnings("unused") LogService log) {}
+
+		void updatedLogService(@SuppressWarnings("unused") LogService log) {}
+
+		@Override
+		public void run() {
+			// TODO Auto-generated method stub
+
+		}
+	}
+
+	@Component()
+	public static class deactivate_basicFelix12 implements Serializable, Runnable {
+		private static final long	serialVersionUID	= 1L;
+
+		@Activate
+		void activate(@SuppressWarnings("unused")ComponentContext cc, @SuppressWarnings("unused")BundleContext ctx) {}
+
+		@Deactivate
+		Map<String, Object> deactivate(@SuppressWarnings("unused")ComponentContext cc, @SuppressWarnings("unused")int cause) {
+			return null;
+		}
+		
+		@Modified
+		void modified(@SuppressWarnings("unused")ComponentContext cc) {}
+
+		@Reference
+		void setLogService(@SuppressWarnings("unused") LogService log) {}
+
+		void unsetLogService(@SuppressWarnings("unused") LogService log) {}
+
+		void updatedLogService(@SuppressWarnings("unused") LogService log) {}
+
+		@Override
+		public void run() {
+			// TODO Auto-generated method stub
+
+		}
+	}
+
+	@Component()
+	public static class modified_basicFelix12 implements Serializable, Runnable {
+		private static final long	serialVersionUID	= 1L;
+
+		@Activate
+		void activate(@SuppressWarnings("unused")ComponentContext cc, @SuppressWarnings("unused")BundleContext ctx) {}
+
+		@Deactivate
+		void deactivate(@SuppressWarnings("unused")ComponentContext cc, @SuppressWarnings("unused")int cause) {}
+		
+		@Modified
+		Map<String, Object> modified(@SuppressWarnings("unused")ComponentContext cc) {
+			return null;
+		}
+
+		@Reference
+		void setLogService(@SuppressWarnings("unused") LogService log) {}
+
+		void unsetLogService(@SuppressWarnings("unused") LogService log) {}
+
+		void updatedLogService(@SuppressWarnings("unused") LogService log) {}
+
+		@Override
+		public void run() {
+			// TODO Auto-generated method stub
+
+		}
+	}
+
+	@Component()
+	public static class bind_basicFelix12 implements Serializable, Runnable {
+		private static final long	serialVersionUID	= 1L;
+
+		@Activate
+		void activate(@SuppressWarnings("unused")ComponentContext cc, @SuppressWarnings("unused")BundleContext ctx) {}
+
+		@Deactivate
+		void deactivate(@SuppressWarnings("unused")ComponentContext cc, @SuppressWarnings("unused")int cause) {}
+		
+		@Modified
+		void modified(@SuppressWarnings("unused")ComponentContext cc) {}
+
+		@Reference
+		Map<String, Object> setLogService(@SuppressWarnings("unused") LogService log) {
+			return null;
+		}
+
+		void unsetLogService(@SuppressWarnings("unused") LogService log) {}
+
+		void updatedLogService(@SuppressWarnings("unused") LogService log) {}
+
+		@Override
+		public void run() {
+			// TODO Auto-generated method stub
+
+		}
+	}
+
+	@Component()
+	public static class unbind_basicFelix12 implements Serializable, Runnable {
+		private static final long	serialVersionUID	= 1L;
+
+		@Activate
+		void activate(@SuppressWarnings("unused")ComponentContext cc, @SuppressWarnings("unused")BundleContext ctx) {}
+
+		@Deactivate
+		void deactivate(@SuppressWarnings("unused")ComponentContext cc, @SuppressWarnings("unused")int cause) {}
+		
+		@Modified
+		void modified(@SuppressWarnings("unused")ComponentContext cc) {}
+
+		@Reference
+		void setLogService(@SuppressWarnings("unused") LogService log) {}
+
+		Map<String, Object> unsetLogService(@SuppressWarnings("unused") LogService log) {
+			return null;
+		}
+		
+		void updatedLogService(@SuppressWarnings("unused") LogService log) {}
+
+		@Override
+		public void run() {
+			// TODO Auto-generated method stub
+
+		}
+	}
+
+	@Component()
+	public static class updated_basicFelix12 implements Serializable, Runnable {
+		private static final long	serialVersionUID	= 1L;
+
+		@Activate
+		void activate(@SuppressWarnings("unused")ComponentContext cc, @SuppressWarnings("unused")BundleContext ctx) {}
+
+		@Deactivate
+		void deactivate(@SuppressWarnings("unused")ComponentContext cc, @SuppressWarnings("unused")int cause) {}
+		
+		@Modified
+		void modified(@SuppressWarnings("unused")ComponentContext cc) {}
+
+		@Reference
+		void setLogService(@SuppressWarnings("unused") LogService log) {}
+
+		void unsetLogService(@SuppressWarnings("unused") LogService log) {}
+
+		Map<String, Object> updatedLogService(@SuppressWarnings("unused") LogService log) {
+			return null;
+		}
+
+		@Override
+		public void run() {
+			// TODO Auto-generated method stub
+
+		}
+	}
+
+	public static void testBasicFelix12() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("-dsannotations", "test.component.*_basicFelix12");
+		b.setProperty("-ds-felix-extensions", "");
+		b.setProperty("Private-Package", "test.component");
+		b.addClasspath(new File("bin"));
+
+		Jar jar = b.build();
+		assertOk(b);
+
+		// Test Felix12 activate gives Felix 1.2 namespace 
+		checkDSFelix12(jar, "test.component.DSAnnotationTest$activate_basicFelix12");
+		// Test Felix12 deactivate gives Felix 1.2 namespace 
+		checkDSFelix12(jar, "test.component.DSAnnotationTest$deactivate_basicFelix12");
+		// Test Felix12 modified gives Felix 1.2 namespace 
+		checkDSFelix12(jar, "test.component.DSAnnotationTest$modified_basicFelix12");
+		// Test Felix12 bind gives Felix 1.2 namespace 
+		checkDSFelix12(jar, "test.component.DSAnnotationTest$bind_basicFelix12");
+		// Test Felix12 bind gives Felix 1.2 namespace 
+		checkDSFelix12(jar, "test.component.DSAnnotationTest$unbind_basicFelix12");
+	}
+
+	private static void checkDSFelix12(Jar jar, String name) throws Exception, XPathExpressionException {
+		Resource r = jar.getResource("OSGI-INF/" + name + ".xml");
+		System.err.println(Processor.join(jar.getResources().keySet(), "\n"));
+		assertNotNull(r);
+		r.write(System.err);
+		XmlTester xt = new XmlTester(r.openInputStream(), "scr", AnnotationReader.FELIX_1_2); 
+		// Test the defaults
+		xt.assertAttribute(name, "scr:component/implementation/@class");
+
+		// Default must be the implementation class
+		xt.assertAttribute(name, "scr:component/@name");
+
+		xt.assertAttribute("", "scr:component/@configuration-policy");
+		xt.assertAttribute("", "scr:component/@immediate");
+		xt.assertAttribute("", "scr:component/@enabled");
+		xt.assertAttribute("", "scr:component/@factory");
+		xt.assertAttribute("", "scr:component/@servicefactory");
+		xt.assertAttribute("", "scr:component/@configuration-pid");
+		xt.assertAttribute("activate", "scr:component/@activate");
+		xt.assertAttribute("deactivate", "scr:component/@deactivate");
+		xt.assertAttribute("modified", "scr:component/@modified");
+		xt.assertAttribute("java.io.Serializable", "scr:component/service/provide[1]/@interface");
+		xt.assertAttribute("java.lang.Runnable", "scr:component/service/provide[2]/@interface");
+
+		xt.assertAttribute("0", "count(scr:component/properties)");
+		xt.assertAttribute("0", "count(scr:component/property)");
+
+		xt.assertAttribute("LogService", "scr:component/reference[1]/@name");
+		xt.assertAttribute("", "scr:component/reference[1]/@target");
+		xt.assertAttribute("setLogService", "scr:component/reference[1]/@bind");
+		xt.assertAttribute("unsetLogService", "scr:component/reference[1]/@unbind");
+		xt.assertAttribute("updatedLogService", "scr:component/reference[1]/@updated");
+		xt.assertAttribute("", "scr:component/reference[1]/@cardinality");
+		xt.assertAttribute("", "scr:component/reference[1]/@policy");
+		xt.assertAttribute("", "scr:component/reference[1]/@target");
+		xt.assertAttribute("", "scr:component/reference[1]/@policy-option");
+	}
+
+	/**
+	 * Tests all the different enum values. This also tests the ordering.
+	 */
+	@Component(name = "enums")
+	public static class Enums {
+
+		@Reference
+		void setA(@SuppressWarnings("unused") LogService l) {}
+
+		@Reference(cardinality = ReferenceCardinality.AT_LEAST_ONE, policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY)
+		void setB(@SuppressWarnings("unused") LogService l) {}
+		void unsetB(@SuppressWarnings("unused") LogService l) {}
+
+		@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.RELUCTANT)
+		void setE(@SuppressWarnings("unused") LogService l) {}
+		void unsetE(@SuppressWarnings("unused") LogService l) {}
+
+		@Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.STATIC, policyOption = ReferencePolicyOption.RELUCTANT)
+		void setC(@SuppressWarnings("unused") LogService l) {}
+
+		@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY)
+		void setD(@SuppressWarnings("unused") LogService l) {}
+		void unsetD(@SuppressWarnings("unused") LogService l) {}
+
+	}
+
+	public static void testEnums() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("-dsannotations", "test.component.DSAnnotationTest*Enums");
+		b.setProperty("Private-Package", "test.component");
+		b.addClasspath(new File("bin"));
+
+		Jar jar = b.build();
+		assertOk(b);
+
+		Resource r = jar.getResource("OSGI-INF/enums.xml");
+		assertNotNull(r);
+		r.write(System.err);
+		XmlTester xt = new XmlTester(r.openInputStream(), "scr", "http://www.osgi.org/xmlns/scr/v1.2.0");
+
+		xt.assertAttribute("A", "scr:component/reference[1]/@name");
+		xt.assertAttribute("", "scr:component/reference[1]/@cardinality");
+		xt.assertAttribute("", "scr:component/reference[1]/@policy");
+		xt.assertAttribute("", "scr:component/reference[1]/@policy-option");
+
+		xt.assertAttribute("B", "scr:component/reference[2]/@name");
+		xt.assertAttribute("1..n", "scr:component/reference[2]/@cardinality");
+		xt.assertAttribute("dynamic", "scr:component/reference[2]/@policy");
+		xt.assertAttribute("greedy", "scr:component/reference[2]/@policy-option");
+
+		xt.assertAttribute("C", "scr:component/reference[3]/@name");
+		xt.assertAttribute("1..1", "scr:component/reference[3]/@cardinality");
+		xt.assertAttribute("static", "scr:component/reference[3]/@policy");
+		xt.assertAttribute("reluctant", "scr:component/reference[3]/@policy-option");
+
+		xt.assertAttribute("D", "scr:component/reference[4]/@name");
+		xt.assertAttribute("0..n", "scr:component/reference[4]/@cardinality");
+		xt.assertAttribute("dynamic", "scr:component/reference[4]/@policy");
+		xt.assertAttribute("greedy", "scr:component/reference[4]/@policy-option");
+
+		xt.assertAttribute("E", "scr:component/reference[5]/@name");
+		xt.assertAttribute("0..1", "scr:component/reference[5]/@cardinality");
+		xt.assertAttribute("dynamic", "scr:component/reference[5]/@policy");
+		xt.assertAttribute("reluctant", "scr:component/reference[5]/@policy-option");
+	}
+
+	/**
+	 * Test the - for the unbind and updated parameter.
+	 */
+	@Component(name = "methods")
+	public static class Methods {
+
+		@Reference(unbind = "-", updated = "-")
+		void setA(@SuppressWarnings("unused") LogService l) {}
+
+		void updatedA(@SuppressWarnings("unused") LogService l) {}
+
+		void unsetA(@SuppressWarnings("unused") LogService l) {}
+
+		@Reference(unbind = "_B", updated = "__B")
+		void setB(@SuppressWarnings("unused") LogService l) {}
+
+		void _B(@SuppressWarnings("unused") LogService l) {}
+
+		void __B(@SuppressWarnings("unused") LogService l) {}
+
+		void updatedB(@SuppressWarnings("unused") LogService l) {}
+
+		void unsetB(@SuppressWarnings("unused") LogService l) {}
+
+		@Reference
+		void setC(@SuppressWarnings("unused") LogService l) {}
+
+		void updatedC(@SuppressWarnings("unused") LogService l) {}
+
+		void unsetC(@SuppressWarnings("unused") LogService l) {}
+
+		@Reference
+		void setD(@SuppressWarnings("unused") LogService l) {}
+
+	}
+
+	public static void testMethods() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("-dsannotations", "test.component.DSAnnotationTest*Methods");
+		b.setProperty("Private-Package", "test.component");
+		b.addClasspath(new File("bin"));
+
+		Jar jar = b.build();
+		assertOk(b);
+
+		Resource r = jar.getResource("OSGI-INF/methods.xml");
+		assertNotNull(r);
+		r.write(System.err);
+		XmlTester xt = new XmlTester(r.openInputStream(), "scr", "http://www.osgi.org/xmlns/scr/v1.2.0");
+
+		// use - to make sure no unbind and updated method is set
+		xt.assertAttribute("A", "scr:component/reference[1]/@name");
+		xt.assertAttribute("setA", "scr:component/reference[1]/@bind");
+		xt.assertAttribute("", "scr:component/reference[1]/@unbind");
+		xt.assertAttribute("", "scr:component/reference[1]/@updated");
+
+		// override the names for the methods
+		xt.assertAttribute("B", "scr:component/reference[2]/@name");
+		xt.assertAttribute("setB", "scr:component/reference[2]/@bind");
+		xt.assertAttribute("_B", "scr:component/reference[2]/@unbind");
+		xt.assertAttribute("__B", "scr:component/reference[2]/@updated");
+
+		xt.assertAttribute("C", "scr:component/reference[3]/@name");
+		xt.assertAttribute("setC", "scr:component/reference[3]/@bind");
+		xt.assertAttribute("unsetC", "scr:component/reference[3]/@unbind");
+		xt.assertAttribute("updatedC", "scr:component/reference[3]/@updated");
+
+		xt.assertAttribute("D", "scr:component/reference[4]/@name");
+		xt.assertAttribute("setD", "scr:component/reference[4]/@bind");
+		xt.assertAttribute("", "scr:component/reference[4]/@unbind");
+		xt.assertAttribute("", "scr:component/reference[4]/@updated");
+	}
+
+	/**
+	 * Test inheritance (this is not official)
+	 */
+
+	public static class Top {
+
+		@Reference
+		void setLogService(@SuppressWarnings("unused") LogService l) {}
+
+		void updatedLogService(@SuppressWarnings("unused") ServiceReference ref) {
+
+		}
+
+		@Reference
+		protected void setPrivateLogService(@SuppressWarnings("unused") LogService l) {
+
+		}
+
+		@SuppressWarnings("unused")
+		private void updatedPrivateLogService(ServiceReference ref) {
+
+		}
+	}
+
+	@Component(name = "bottom")
+	public static class Bottom extends Top {
+		void unsetLogService(@SuppressWarnings("unused") LogService l, @SuppressWarnings("unused") Map<Object,Object> map) {
+
+		}
+
+		void unsetPrivateLogService(@SuppressWarnings("unused") ServiceReference ref) {
+
+		}
+	}
+
+	public static void testInheritance() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("-dsannotations", "test.component.DSAnnotationTest*Bottom");
+		b.setProperty("-dsannotations-inherit", "true");
+		b.setProperty("Private-Package", "test.component");
+		b.addClasspath(new File("bin"));
+
+		Jar jar = b.build();
+		assertOk(b);
+
+		Resource r = jar.getResource("OSGI-INF/bottom.xml");
+		assertNotNull(r);
+		r.write(System.err);
+		XmlTester xt = new XmlTester(r.openInputStream(), "scr", "http://www.osgi.org/xmlns/scr/v1.2.0");
+
+		xt.assertAttribute("LogService", "scr:component/reference[1]/@name");
+		xt.assertAttribute("setLogService", "scr:component/reference[1]/@bind");
+		xt.assertAttribute("unsetLogService", "scr:component/reference[1]/@unbind");
+		xt.assertAttribute("updatedLogService", "scr:component/reference[1]/@updated");
+
+		xt.assertAttribute("PrivateLogService", "scr:component/reference[2]/@name");
+		xt.assertAttribute("setPrivateLogService", "scr:component/reference[2]/@bind");
+		xt.assertAttribute("unsetPrivateLogService", "scr:component/reference[2]/@unbind");
+		xt.assertAttribute("", "scr:component/reference[2]/@updated"); // is
+																		// private
+																		// in
+																		// super
+																		// class
+
+	}
+
+	/**
+	 * Test the different prototypes ...
+	 */
+
+	@Component(name = "prototypes")
+	public static class Prototypes {
+		@SuppressWarnings("unused")
+		@Activate
+		private void activate() {}
+
+		@Deactivate
+		protected void deactivate(@SuppressWarnings("unused") ComponentContext ctx) {
+
+		}
+
+		@Modified
+		void modified(@SuppressWarnings("unused") BundleContext context) {
+
+		}
+
+		@SuppressWarnings("unused")
+		@Reference
+		private void setLogService(LogService l) {
+
+		}
+
+		protected void unsetLogService(@SuppressWarnings("unused") LogService l, @SuppressWarnings("unused") Map<Object,Object> map) {
+
+		}
+
+		void updatedLogService(@SuppressWarnings("unused") ServiceReference ref) {
+
+		}
+
+	}
+
+	public static void testPrototypes() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("-dsannotations", "test.component.DSAnnotationTest*Prototypes");
+		b.setProperty("Private-Package", "test.component");
+		b.addClasspath(new File("bin"));
+
+		Jar jar = b.build();
+		assertOk(b);
+
+		Resource r = jar.getResource("OSGI-INF/prototypes.xml");
+		assertNotNull(r);
+		r.write(System.err);
+		XmlTester xt = new XmlTester(r.openInputStream(), "scr", "http://www.osgi.org/xmlns/scr/v1.2.0");
+
+		xt.assertAttribute("LogService", "scr:component/reference[1]/@name");
+		xt.assertAttribute("setLogService", "scr:component/reference[1]/@bind");
+		xt.assertAttribute("unsetLogService", "scr:component/reference[1]/@unbind");
+		xt.assertAttribute("updatedLogService", "scr:component/reference[1]/@updated");
+
+	}
+
+	/**
+	 * Test the different prototypes ...
+	 */
+
+	@Component(name = "prototypes")
+	public static class CheckBinds {
+		@SuppressWarnings("unused")
+		@Activate
+		private void activate() {}
+
+		@Deactivate
+		protected void deactivate(@SuppressWarnings("unused") ComponentContext ctx) {
+
+		}
+
+		@Modified
+		void modified(@SuppressWarnings("unused") BundleContext context) {
+
+		}
+
+		@SuppressWarnings("unused")
+		@Reference
+		private void bindLogService(LogService l) {
+
+		}
+
+		protected void unbindLogService(@SuppressWarnings("unused") LogService l, @SuppressWarnings("unused") Map<Object,Object> map) {
+
+		}
+
+		void updatedLogService(@SuppressWarnings("unused") ServiceReference ref) {
+
+		}
+
+	}
+
+	public static void testBinds() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("-dsannotations", "test.component.DSAnnotationTest*CheckBinds");
+		b.setProperty("Private-Package", "test.component");
+		b.addClasspath(new File("bin"));
+
+		Jar jar = b.build();
+		assertOk(b);
+
+		Resource r = jar.getResource("OSGI-INF/prototypes.xml");
+		assertNotNull(r);
+		r.write(System.err);
+		XmlTester xt = new XmlTester(r.openInputStream(), "scr", "http://www.osgi.org/xmlns/scr/v1.2.0");
+
+		xt.assertAttribute("LogService", "scr:component/reference[1]/@name");
+		xt.assertAttribute("bindLogService", "scr:component/reference[1]/@bind");
+		xt.assertAttribute("unbindLogService", "scr:component/reference[1]/@unbind");
+		xt.assertAttribute("updatedLogService", "scr:component/reference[1]/@updated");
+
+	}
+	
+	@Component(name = "NoUnbindDynamic")
+	public static class NoUnbindDynamic {
+		@SuppressWarnings("unused")
+		@Reference(policy = ReferencePolicy.DYNAMIC)
+		private void bindLogService(LogService l) {
+		}
+	}
+	
+	public static void testNoUnbindDynamic() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("-dsannotations", "test.component.DSAnnotationTest*NoUnbindDynamic");
+		b.setProperty("Private-Package", "test.component");
+		b.addClasspath(new File("bin"));
+
+		Jar jar = b.build();
+		assertEquals(1, b.getErrors().size());
+		assertTrue(b.getErrors().get(0).endsWith("dynamic but has no unbind method."));
+	}
+	
+	
+	@Component(name="testConfigPolicy", configurationPolicy=ConfigurationPolicy.IGNORE)
+	public static class TestConfigPolicy {}
+	
+	public static void testConfigPolicySetsNamespace() throws Exception {
+		Builder b = new Builder();
+		b.setProperty("-dsannotations", "test.component.DSAnnotationTest*TestConfigPolicy");
+		b.setProperty("Private-Package", "test.component");
+		b.addClasspath(new File("bin"));
+
+		Jar jar = b.build();
+		assertOk(b);
+
+		Resource r = jar.getResource("OSGI-INF/testConfigPolicy.xml");
+		assertNotNull(r);
+		r.write(System.err);
+		XmlTester xt = new XmlTester(r.openInputStream(), "scr", "http://www.osgi.org/xmlns/scr/v1.1.0");
+		xt.assertNamespace("http://www.osgi.org/xmlns/scr/v1.1.0");
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/test/defaultbsn.bnd b/biz.aQute.bndlib.tests/src/test/defaultbsn.bnd
similarity index 100%
rename from biz.aQute.bndlib/src/test/defaultbsn.bnd
rename to biz.aQute.bndlib.tests/src/test/defaultbsn.bnd
diff --git a/biz.aQute.bndlib.tests/src/test/deployer/FileRepoTest.java b/biz.aQute.bndlib.tests/src/test/deployer/FileRepoTest.java
new file mode 100644
index 0000000..94cc0aa
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/deployer/FileRepoTest.java
@@ -0,0 +1,223 @@
+package test.deployer;
+
+import static aQute.lib.io.IO.*;
+
+import java.io.*;
+import java.security.*;
+import java.util.*;
+
+import junit.framework.*;
+
+import org.mockito.*;
+
+import aQute.bnd.service.*;
+import aQute.bnd.service.RepositoryPlugin.DownloadListener;
+import aQute.bnd.service.RepositoryPlugin.PutOptions;
+import aQute.bnd.service.RepositoryPlugin.PutResult;
+import aQute.bnd.version.*;
+import aQute.lib.deployer.*;
+import aQute.lib.io.*;
+import aQute.libg.cryptography.*;
+
+public class FileRepoTest extends TestCase {
+
+	private static FileRepo	testRepo;
+	private static FileRepo	nonExistentRepo;
+
+	private static String hashToString(byte[] hash) {
+		Formatter formatter = new Formatter();
+		for (byte b : hash) {
+			formatter.format("%02x", b);
+		}
+		return formatter.toString();
+	}
+
+	private static byte[] calculateHash(MessageDigest algorithm, File file) throws Exception {
+		algorithm.reset();
+		copy(file, algorithm);
+		return algorithm.digest();
+	}
+
+	@Override
+	protected void setUp() throws Exception {
+		File testRepoDir = new File("src/test/repo");
+		assertTrue(testRepoDir.isDirectory());
+		testRepo = createRepo(testRepoDir);
+
+		File nonExistentDir = new File("invalidrepo");
+		nonExistentDir.mkdir();
+		nonExistentDir.setReadOnly();
+		nonExistentRepo = createRepo(nonExistentDir);
+	}
+
+	@Override
+	protected void tearDown() throws Exception {
+		File nonExistentDir = new File("invalidrepo");
+		delete(nonExistentDir);
+	}
+
+	private static FileRepo createRepo(File root) {
+		FileRepo repo = new FileRepo();
+
+		Map<String,String> props = new HashMap<String,String>();
+		props.put("location", root.getAbsolutePath());
+		repo.setProperties(props);
+
+		return repo;
+	}
+
+	public static void testListBSNs() throws Exception {
+		List<String> list = testRepo.list(null);
+		assertNotNull(list);
+		assertEquals(4, list.size());
+
+		assertTrue(list.contains("ee.minimum"));
+		assertTrue(list.contains("org.osgi.impl.service.cm"));
+		assertTrue(list.contains("org.osgi.impl.service.io"));
+		assertTrue(list.contains("osgi"));
+	}
+
+	public static void testListNonExistentRepo() throws Exception {
+		// Listing should succeed and return non-null empty list
+		List<String> list = nonExistentRepo.list(null);
+		assertNotNull(list);
+		assertEquals(0, list.size());
+	}
+
+	public static void testBundleNotModifiedOnPut() throws Exception {
+		MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
+		File dstBundle = null;
+		try {
+			File srcBundle = new File("test/test.jar");
+			byte[] srcSha = calculateHash(sha1, srcBundle);
+
+			PutOptions options = new RepositoryPlugin.PutOptions();
+			options.digest = srcSha;
+
+			PutResult r = testRepo.put(new BufferedInputStream(new FileInputStream(srcBundle)), options);
+
+			dstBundle = new File(r.artifact);
+
+			assertEquals(hashToString(srcSha), hashToString(r.digest));
+			assertTrue(MessageDigest.isEqual(srcSha, r.digest));
+		}
+		finally {
+			if (dstBundle != null) {
+				delete(dstBundle.getParentFile());
+			}
+		}
+	}
+
+	public static void testDownloadListenerCallback() throws Exception {
+		File tmp = new File("tmp");
+		try {
+			FileRepo repo = new FileRepo("tmp", tmp, true);
+			File srcBundle = new File("test/test.jar");
+
+			PutResult r = repo.put(IO.stream(new File("test/test.jar")), null);
+
+			assertNotNull(r);
+			assertNotNull(r.artifact);
+			File f = new File(r.artifact); // file repo, so should match
+			SHA1 sha1 = SHA1.digest(srcBundle);
+			sha1.equals(SHA1.digest(f));
+
+			DownloadListener mock = Mockito.mock(DownloadListener.class);
+
+			f = repo.get("test", new Version("0"), null, mock);
+			Mockito.verify(mock).success(f);
+			Mockito.verifyNoMoreInteractions(mock);
+			Mockito.reset(mock);
+
+			f = repo.get("XXXXXXXXXXXXXXXXX", new Version("0"), null, mock);
+			assertNull(f);
+			Mockito.verifyZeroInteractions(mock);
+		}
+		finally {
+			IO.delete(tmp);
+		}
+	}
+
+	public static void testDeployToNonexistentRepoFails() throws Exception {
+
+		if(System.getProperty("os.name").toLowerCase().indexOf("win") >= 0 ) {
+			// File#setReadonly() is broken on windows
+			return;
+		}
+		try {
+			nonExistentRepo.put(new BufferedInputStream(new FileInputStream("test/test.jar")),
+					new RepositoryPlugin.PutOptions());
+			fail("Should have thrown exception");
+		}
+		catch (Exception e) {
+			// OK, you cannot check for exception messages or exception type
+		}
+	}
+
+	public void testCommands() throws Exception {
+		FileRepo repo = new FileRepo();
+		File root = new File("tmp");
+		delete(root);
+		try {
+			Map<String,String> props = new HashMap<String,String>();
+			props.put(FileRepo.LOCATION, root.getAbsolutePath());
+			props.put(FileRepo.CMD_INIT, "echo init $0 $1 $2 $3>>report");
+			props.put(FileRepo.CMD_OPEN, "echo open $0 $1 $2 $3 >>report");
+			props.put(FileRepo.CMD_BEFORE_GET, "echo beforeGet $0 $1 $2 $3 >>report");
+			props.put(FileRepo.CMD_BEFORE_PUT, "echo beforePut $0 $1 $2 $3>>report");
+			props.put(FileRepo.CMD_AFTER_PUT, "echo afterPut $0 $1 $2 $3>>report");
+			props.put(FileRepo.CMD_ABORT_PUT, "echo abortPut $0 $1 $2 $3>>report");
+			props.put(FileRepo.CMD_REFRESH, "echo refresh  $0 $1 $2 $3>>report");
+			props.put(FileRepo.CMD_CLOSE, "echo close  $0 $1 $2 $3>>report");
+			props.put(FileRepo.CMD_PATH, "/xxx,$@,/yyy");
+			props.put(FileRepo.TRACE, true + "");
+			repo.setProperties(props);
+
+			repo.refresh();
+			{
+				InputStream in = stream(getFile("jar/osgi.jar"));
+				try {
+					repo.put(in, null);
+
+				}
+				finally {
+					in.close();
+				}
+			}
+			{
+				InputStream in = stream("not a valid zip");
+				try {
+					repo.put(in, null);
+					fail("expected failure");
+				}
+				catch (Exception e) {
+					// ignore
+				}
+				finally {
+					in.close();
+				}
+			}
+			repo.close();
+			String s = collect(new File(root, "report"));
+			s = s.replaceAll("\\\\", "/");
+			s = s.replaceAll(root.getAbsolutePath().replaceAll("\\\\", "/"), "@");
+			System.out.println(s);
+
+			String parts[] = s.split("\r?\n");
+			assertEquals(8, parts.length);
+			assertEquals(parts[0], "init @");
+			assertEquals(parts[1], "open @");
+			assertEquals(parts[2], "refresh @");
+			assertTrue(parts[3].matches("beforePut @ @/.*"));
+			assertEquals(parts[4],
+					"afterPut @ @/osgi/osgi-4.0.0.jar D37A1C9D5A9D3774F057B5452B7E47B6D1BB12D0");
+			assertTrue(parts[5].matches("beforePut @ @/.*"));
+			assertTrue(parts[6].matches("abortPut @ @/.*"));
+			assertEquals(parts[7], "close @");
+		}
+		finally {
+			delete(root);
+		}
+
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/diff/DiffTest.java b/biz.aQute.bndlib.tests/src/test/diff/DiffTest.java
new file mode 100644
index 0000000..6d9d4a7
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/diff/DiffTest.java
@@ -0,0 +1,144 @@
+package test.diff;
+
+import java.io.*;
+
+import junit.framework.*;
+import aQute.bnd.differ.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.diff.*;
+
+public class DiffTest extends TestCase {
+	static DiffPluginImpl	differ	= new DiffPluginImpl();
+
+	public static void testAwtGeom() throws Exception {
+		Tree newer = differ.tree(new File("../cnf/repo/ee.j2se/ee.j2se-1.5.0.jar"));
+		Tree gp = newer.get("<api>").get("java.awt.geom").get("java.awt.geom.GeneralPath");
+		assertNotNull(gp);
+		show(gp, 0);
+	}
+
+	public static final class Final {
+		public void foo() {}
+	}
+
+	public static class II {
+		final int	x	= 3;
+
+		public void foo() {}
+	}
+
+	public static class I extends II {
+		public static I bar() {
+			return null;
+		}
+
+		@Override
+		public void foo() {}
+	}
+
+	public static void testInheritance() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("bin"));
+		b.setProperty(Constants.EXPORT_PACKAGE, "test.diff");
+		b.build();
+		Tree newer = differ.tree(b);
+		Tree older = differ.tree(b);
+		Diff diff = newer.diff(older);
+		Diff p = diff.get("<api>").get("test.diff");
+		show(p, 0);
+		Diff c = p.get("test.diff.DiffTest$I");
+		assertNotNull(c.get("hashCode()"));
+		assertNotNull(c.get("finalize()"));
+		assertNotNull(c.get("foo()"));
+
+		Diff cc = p.get("test.diff.DiffTest$Final");
+		assertNotNull(cc.get("foo()"));
+		b.close();
+	}
+
+	public static interface Intf {
+		void foo();
+	}
+
+	public static abstract class X implements Intf {
+
+		@Override
+		public void foo() {}
+	}
+
+	static interface A extends Comparable<Object>, Serializable {
+
+	}
+
+	public static void testSimple() throws Exception {
+
+		Tree newer = differ.tree(new Jar(new File("jar/osgi.core-4.3.0.jar")));
+		Tree older = differ.tree(new Jar(new File("jar/osgi.core.jar"))); // 4.2
+		Diff diff = newer.diff(older);
+
+		show(diff, 0);
+	}
+
+	static abstract class SBB {}
+
+	public static class CMP implements Comparable<Number> {
+
+		@Override
+		public int compareTo(Number var0) {
+			// TODO Auto-generated method stub
+			return 0;
+		}
+
+	}
+
+	static class SB extends SBB implements Appendable {
+
+		@Override
+		public SB append(char var0) throws IOException {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public SB append(CharSequence var0) throws IOException {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public SB append(CharSequence var0, int var1, int var2) throws IOException {
+			// TODO Auto-generated method stub
+			return null;
+		}
+	}
+
+	static void show(Diff diff, int indent) {
+		// if (diff.getDelta() == Delta.UNCHANGED || diff.getDelta() ==
+		// Delta.IGNORED)
+		// return;
+
+		for (int i = 0; i < indent; i++)
+			System.err.print("   ");
+
+		System.err.println(diff.toString());
+
+		// if (diff.getDelta().isStructural())
+		// return;
+
+		for (Diff c : diff.getChildren()) {
+			show(c, indent + 1);
+		}
+	}
+
+	static void show(Tree tree, int indent) {
+
+		for (int i = 0; i < indent; i++)
+			System.err.print("   ");
+
+		System.err.println(tree.toString());
+
+		for (Tree c : tree.getChildren()) {
+			show(c, indent + 1);
+		}
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/genericinterf/a/A.java b/biz.aQute.bndlib.tests/src/test/genericinterf/a/A.java
new file mode 100644
index 0000000..469e55b
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/genericinterf/a/A.java
@@ -0,0 +1,12 @@
+package test.genericinterf.a;
+
+import test.genericinterf.b.*;
+import test.genericinterf.c.*;
+
+public class A<T> implements B<C<T>> {
+	public T	field;
+
+	public static <X> X foo(@SuppressWarnings("unused") X x) {
+		return null;
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/genericinterf/b/B.java b/biz.aQute.bndlib.tests/src/test/genericinterf/b/B.java
new file mode 100644
index 0000000..16f514f
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/genericinterf/b/B.java
@@ -0,0 +1,5 @@
+package test.genericinterf.b;
+
+public interface B<T> {
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/genericinterf/c/C.java b/biz.aQute.bndlib.tests/src/test/genericinterf/c/C.java
new file mode 100644
index 0000000..3a607d0
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/genericinterf/c/C.java
@@ -0,0 +1,5 @@
+package test.genericinterf.c;
+
+public class C<T> {
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/generics.clazz b/biz.aQute.bndlib.tests/src/test/generics.clazz
new file mode 100644
index 0000000..57525b8
Binary files /dev/null and b/biz.aQute.bndlib.tests/src/test/generics.clazz differ
diff --git a/biz.aQute.bndlib/src/test/iht/test.prop b/biz.aQute.bndlib.tests/src/test/iht/test.prop
similarity index 100%
rename from biz.aQute.bndlib/src/test/iht/test.prop
rename to biz.aQute.bndlib.tests/src/test/iht/test.prop
diff --git a/biz.aQute.bndlib/src/test/include.bnd/bottom.bnd b/biz.aQute.bndlib.tests/src/test/include.bnd/bottom.bnd
similarity index 100%
rename from biz.aQute.bndlib/src/test/include.bnd/bottom.bnd
rename to biz.aQute.bndlib.tests/src/test/include.bnd/bottom.bnd
diff --git a/biz.aQute.bndlib/src/test/include.bnd/top.bnd b/biz.aQute.bndlib.tests/src/test/include.bnd/top.bnd
similarity index 100%
rename from biz.aQute.bndlib/src/test/include.bnd/top.bnd
rename to biz.aQute.bndlib.tests/src/test/include.bnd/top.bnd
diff --git a/biz.aQute.bndlib/src/test/include.mf b/biz.aQute.bndlib.tests/src/test/include.mf
similarity index 100%
rename from biz.aQute.bndlib/src/test/include.mf
rename to biz.aQute.bndlib.tests/src/test/include.mf
diff --git a/biz.aQute.bndlib/src/test/includeheadertest.mf b/biz.aQute.bndlib.tests/src/test/includeheadertest.mf
similarity index 100%
rename from biz.aQute.bndlib/src/test/includeheadertest.mf
rename to biz.aQute.bndlib.tests/src/test/includeheadertest.mf
diff --git a/biz.aQute.bndlib/src/test/includeheadertest.prop b/biz.aQute.bndlib.tests/src/test/includeheadertest.prop
similarity index 100%
rename from biz.aQute.bndlib/src/test/includeheadertest.prop
rename to biz.aQute.bndlib.tests/src/test/includeheadertest.prop
diff --git a/biz.aQute.bndlib.tests/src/test/lib/NanoHTTPD.java b/biz.aQute.bndlib.tests/src/test/lib/NanoHTTPD.java
new file mode 100644
index 0000000..92ed5c2
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/lib/NanoHTTPD.java
@@ -0,0 +1,987 @@
+package test.lib;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+/**
+ * A simple, tiny, nicely embeddable HTTP 1.0 (partially 1.1) server in Java
+ * <p>
+ * NanoHTTPD version 1.25, Copyright © 2001,2005-2012 Jarno Elonen
+ * (elonen at iki.fi, http://iki.fi/elonen/) and Copyright © 2010 Konstantinos
+ * Togias (info at ktogias.gr, http://ktogias.gr)
+ * <p>
+ * <b>Features + limitations: </b>
+ * <ul>
+ * <li>Only one Java file</li>
+ * <li>Java 1.1 compatible</li>
+ * <li>Released as open source, Modified BSD licence</li>
+ * <li>No fixed config files, logging, authorization etc. (Implement yourself if
+ * you need them.)</li>
+ * <li>Supports parameter parsing of GET and POST methods (+ rudimentary PUT
+ * support in 1.25)</li>
+ * <li>Supports both dynamic content and file serving</li>
+ * <li>Supports file upload (since version 1.2, 2010)</li>
+ * <li>Supports partial content (streaming)</li>
+ * <li>Supports ETags</li>
+ * <li>Never caches anything</li>
+ * <li>Doesn't limit bandwidth, request time or simultaneous connections</li>
+ * <li>Default code serves files and shows all HTTP parameters and headers</li>
+ * <li>File server supports directory listing, index.html and index.htm</li>
+ * <li>File server supports partial content (streaming)</li>
+ * <li>File server supports ETags</li>
+ * <li>File server does the 301 redirection trick for directories without '/'</li>
+ * <li>File server supports simple skipping for files (continue download)</li>
+ * <li>File server serves also very long files without memory overhead</li>
+ * <li>Contains a built-in list of most common mime types</li>
+ * <li>All header names are converted lowercase so they don't vary between
+ * browsers/clients</li>
+ * </ul>
+ * <p>
+ * <b>Ways to use: </b>
+ * <ul>
+ * <li>Run as a standalone app, serves files and shows requests</li>
+ * <li>Subclass serve() and embed to your own program</li>
+ * <li>Call serveFile() from serve() with your own base directory</li>
+ * </ul>
+ * See the end of the source file for distribution license (Modified BSD
+ * licence)
+ */
+public class NanoHTTPD {
+	// ==================================================
+	// API parts
+	// ==================================================
+
+	/**
+	 * Override this to customize the server.
+	 * <p>
+	 * (By default, this delegates to serveFile() and allows directory listing.)
+	 * 
+	 * @param uri
+	 *            Percent-decoded URI without parameters, for example
+	 *            "/index.cgi"
+	 * @param method
+	 *            "GET", "POST" etc.
+	 * @param parms
+	 *            Parsed, percent decoded parameters from URI and, in case of
+	 *            POST, data.
+	 * @param header
+	 *            Header entries, percent decoded
+	 * @return HTTP response, see class Response for details
+	 */
+	public Response serve(String uri, String method, Properties header, Properties parms, Properties files) {
+		myOut.println(method + " '" + uri + "' ");
+
+		Enumeration< ? > e = header.propertyNames();
+		while (e.hasMoreElements()) {
+			String value = (String) e.nextElement();
+			myOut.println("  HDR: '" + value + "' = '" + header.getProperty(value) + "'");
+		}
+		e = parms.propertyNames();
+		while (e.hasMoreElements()) {
+			String value = (String) e.nextElement();
+			myOut.println("  PRM: '" + value + "' = '" + parms.getProperty(value) + "'");
+		}
+		e = files.propertyNames();
+		while (e.hasMoreElements()) {
+			String value = (String) e.nextElement();
+			myOut.println("  UPLOADED: '" + value + "' = '" + files.getProperty(value) + "'");
+		}
+
+		return serveFile(uri, header, myRootDir, true);
+	}
+
+	/**
+	 * HTTP response. Return one of these from serve().
+	 */
+	public class Response {
+		/**
+		 * Default constructor: response = HTTP_OK, data = mime = 'null'
+		 */
+		public Response() {
+			this.status = HTTP_OK;
+		}
+
+		/**
+		 * Basic constructor.
+		 */
+		public Response(String status, String mimeType, InputStream data) {
+			this.status = status;
+			this.mimeType = mimeType;
+			this.data = data;
+		}
+
+		/**
+		 * Convenience method that makes an InputStream out of given text.
+		 */
+		public Response(String status, String mimeType, String txt) {
+			this.status = status;
+			this.mimeType = mimeType;
+			try {
+				this.data = new ByteArrayInputStream(txt.getBytes("UTF-8"));
+			}
+			catch (java.io.UnsupportedEncodingException uee) {
+				uee.printStackTrace();
+			}
+		}
+
+		/**
+		 * Adds given line to the header.
+		 */
+		public void addHeader(String name, String value) {
+			header.put(name, value);
+		}
+
+		/**
+		 * HTTP status code after processing, e.g. "200 OK", HTTP_OK
+		 */
+		public String		status;
+
+		/**
+		 * MIME type of content, e.g. "text/html"
+		 */
+		public String		mimeType;
+
+		/**
+		 * Data of the response, may be null.
+		 */
+		public InputStream	data;
+
+		/**
+		 * Headers for the HTTP response. Use addHeader() to add lines.
+		 */
+		public Properties	header	= new Properties();
+	}
+
+	/**
+	 * Some HTTP response status codes
+	 */
+	public static final String	HTTP_OK	= "200 OK", HTTP_PARTIALCONTENT = "206 Partial Content",
+			HTTP_RANGE_NOT_SATISFIABLE = "416 Requested Range Not Satisfiable",
+			HTTP_REDIRECT = "301 Moved Permanently", HTTP_NOTMODIFIED = "304 Not Modified",
+			HTTP_FORBIDDEN = "403 Forbidden", HTTP_NOTFOUND = "404 Not Found", HTTP_BADREQUEST = "400 Bad Request",
+			HTTP_INTERNALERROR = "500 Internal Server Error", HTTP_NOTIMPLEMENTED = "501 Not Implemented";
+
+	/**
+	 * Common mime types for dynamic content
+	 */
+	public static final String	MIME_PLAINTEXT	= "text/plain", MIME_HTML = "text/html",
+			MIME_DEFAULT_BINARY = "application/octet-stream", MIME_XML = "text/xml";
+
+	// ==================================================
+	// Socket & server code
+	// ==================================================
+
+	/**
+	 * Starts a HTTP server to given port.
+	 * <p>
+	 * Throws an IOException if the socket is already in use
+	 */
+	public NanoHTTPD(int port, File wwwroot) throws IOException {
+		myTcpPort = port;
+		this.myRootDir = wwwroot;
+		myServerSocket = new ServerSocket(myTcpPort);
+		myThread = new Thread(new Runnable() {
+			@Override
+			public void run() {
+				try {
+					while (true)
+						new HTTPSession(myServerSocket.accept());
+				}
+				catch (IOException ioe) {}
+			}
+		});
+		myThread.setDaemon(true);
+		myThread.start();
+	}
+
+	/**
+	 * Stops the server.
+	 */
+	public void stop() {
+		try {
+			myServerSocket.close();
+			myThread.join();
+		}
+		catch (IOException ioe) {}
+		catch (InterruptedException e) {}
+	}
+
+	/**
+	 * Starts as a standalone file server and waits for Enter.
+	 */
+	public static void main(String[] args) {
+		myOut.println("NanoHTTPD 1.25 (C) 2001,2005-2011 Jarno Elonen and (C) 2010 Konstantinos Togias\n"
+				+ "(Command line options: [-p port] [-d root-dir] [--licence])\n");
+
+		// Defaults
+		int port = 80;
+		File wwwroot = new File(".").getAbsoluteFile();
+
+		// Show licence if requested
+		for (int i = 0; i < args.length; ++i)
+			if (args[i].equalsIgnoreCase("-p"))
+				port = Integer.parseInt(args[i + 1]);
+			else if (args[i].equalsIgnoreCase("-d"))
+				wwwroot = new File(args[i + 1]).getAbsoluteFile();
+			else if (args[i].toLowerCase().endsWith("licence")) {
+				myOut.println(LICENCE + "\n");
+				break;
+			}
+
+		try {
+			@SuppressWarnings("unused")
+			NanoHTTPD nanoHTTPD = new NanoHTTPD(port, wwwroot);
+		}
+		catch (IOException ioe) {
+			System.err.println("Couldn't start server:\n" + ioe);
+			System.exit(-1);
+		}
+
+		myOut.println("Now serving files in port " + port + " from \"" + wwwroot + "\"");
+		myOut.println("Hit Enter to stop.\n");
+
+		try {
+			System.in.read();
+		}
+		catch (Throwable t) {}
+	}
+
+	/**
+	 * Handles one session, i.e. parses the HTTP request and returns the
+	 * response.
+	 */
+	private class HTTPSession implements Runnable {
+		public HTTPSession(Socket s) {
+			mySocket = s;
+			Thread t = new Thread(this);
+			t.setDaemon(true);
+			t.start();
+		}
+
+		@Override
+		public void run() {
+			try {
+				InputStream is = mySocket.getInputStream();
+				if (is == null)
+					return;
+
+				// Read the first 8192 bytes.
+				// The full header should fit in here.
+				// Apache's default header limit is 8KB.
+				int bufsize = 8192;
+				byte[] buf = new byte[bufsize];
+				int rlen = is.read(buf, 0, bufsize);
+				if (rlen <= 0)
+					return;
+
+				// Create a BufferedReader for parsing the header.
+				ByteArrayInputStream hbis = new ByteArrayInputStream(buf, 0, rlen);
+				BufferedReader hin = new BufferedReader(new InputStreamReader(hbis));
+				Properties pre = new Properties();
+				Properties parms = new Properties();
+				Properties header = new Properties();
+				Properties files = new Properties();
+
+				// Decode the header into parms and header java properties
+				decodeHeader(hin, pre, parms, header);
+				String method = pre.getProperty("method");
+				String uri = pre.getProperty("uri");
+
+				long size = 0x7FFFFFFFFFFFFFFFl;
+				String contentLength = header.getProperty("content-length");
+				if (contentLength != null) {
+					try {
+						size = Integer.parseInt(contentLength);
+					}
+					catch (NumberFormatException ex) {}
+				}
+
+				// We are looking for the byte separating header from body.
+				// It must be the last byte of the first two sequential new
+				// lines.
+				int splitbyte = 0;
+				boolean sbfound = false;
+				while (splitbyte < rlen) {
+					if (buf[splitbyte] == '\r' && buf[++splitbyte] == '\n' && buf[++splitbyte] == '\r'
+							&& buf[++splitbyte] == '\n') {
+						sbfound = true;
+						break;
+					}
+					splitbyte++;
+				}
+				splitbyte++;
+
+				// Write the part of body already read to ByteArrayOutputStream
+				// f
+				ByteArrayOutputStream f = new ByteArrayOutputStream();
+				if (splitbyte < rlen)
+					f.write(buf, splitbyte, rlen - splitbyte);
+
+				// While Firefox sends on the first read all the data fitting
+				// our buffer, Chrome and Opera sends only the headers even if
+				// there is data for the body. So we do some magic here to find
+				// out whether we have already consumed part of body, if we
+				// have reached the end of the data to be sent or we should
+				// expect the first byte of the body at the next read.
+				if (splitbyte < rlen)
+					size -= rlen - splitbyte + 1;
+				else if (!sbfound || size == 0x7FFFFFFFFFFFFFFFl)
+					size = 0;
+
+				// Now read all the body and write it to f
+				buf = new byte[512];
+				while (rlen >= 0 && size > 0) {
+					rlen = is.read(buf, 0, 512);
+					size -= rlen;
+					if (rlen > 0)
+						f.write(buf, 0, rlen);
+				}
+
+				// Get the raw body as a byte []
+				byte[] fbuf = f.toByteArray();
+
+				// Create a BufferedReader for easily reading it as string.
+				ByteArrayInputStream bin = new ByteArrayInputStream(fbuf);
+				BufferedReader in = new BufferedReader(new InputStreamReader(bin));
+
+				// If the method is POST, there may be parameters
+				// in data section, too, read it:
+				if (method.equalsIgnoreCase("POST")) {
+					String contentType = "";
+					String contentTypeHeader = header.getProperty("content-type");
+					StringTokenizer st = new StringTokenizer(contentTypeHeader, "; ");
+					if (st.hasMoreTokens()) {
+						contentType = st.nextToken();
+					}
+
+					if (contentType.equalsIgnoreCase("multipart/form-data")) {
+						// Handle multipart/form-data
+						if (!st.hasMoreTokens())
+							sendError(HTTP_BADREQUEST,
+									"BAD REQUEST: Content type is multipart/form-data but boundary missing. Usage: GET /example/file.html");
+						String boundaryExp = st.nextToken();
+						st = new StringTokenizer(boundaryExp, "=");
+						if (st.countTokens() != 2)
+							sendError(HTTP_BADREQUEST,
+									"BAD REQUEST: Content type is multipart/form-data but boundary syntax error. Usage: GET /example/file.html");
+						st.nextToken();
+						String boundary = st.nextToken();
+
+						decodeMultipartData(boundary, fbuf, in, parms, files);
+					} else {
+						// Handle application/x-www-form-urlencoded
+						String postLine = "";
+						char pbuf[] = new char[512];
+						int read = in.read(pbuf);
+						while (read >= 0 && !postLine.endsWith("\r\n")) {
+							postLine += String.valueOf(pbuf, 0, read);
+							read = in.read(pbuf);
+						}
+						postLine = postLine.trim();
+						decodeParms(postLine, parms);
+					}
+				}
+
+				if (method.equalsIgnoreCase("PUT"))
+					files.put("content", saveTmpFile(fbuf, 0, f.size()));
+
+				// Ok, now do the serve()
+				Response r = serve(uri, method, header, parms, files);
+				if (r == null)
+					sendError(HTTP_INTERNALERROR, "SERVER INTERNAL ERROR: Serve() returned a null response.");
+				else
+					sendResponse(r.status, r.mimeType, r.header, r.data);
+
+				in.close();
+				is.close();
+			}
+			catch (IOException ioe) {
+				try {
+					sendError(HTTP_INTERNALERROR, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage());
+				}
+				catch (Throwable t) {}
+			}
+			catch (InterruptedException ie) {
+				// Thrown by sendError, ignore and exit the thread.
+			}
+		}
+
+		/**
+		 * Decodes the sent headers and loads the data into java Properties' key
+		 * - value pairs
+		 **/
+		private void decodeHeader(BufferedReader in, Properties pre, Properties parms, Properties header)
+				throws InterruptedException {
+			try {
+				// Read the request line
+				String inLine = in.readLine();
+				if (inLine == null)
+					return;
+				StringTokenizer st = new StringTokenizer(inLine);
+				if (!st.hasMoreTokens())
+					sendError(HTTP_BADREQUEST, "BAD REQUEST: Syntax error. Usage: GET /example/file.html");
+
+				String method = st.nextToken();
+				pre.put("method", method);
+
+				if (!st.hasMoreTokens())
+					sendError(HTTP_BADREQUEST, "BAD REQUEST: Missing URI. Usage: GET /example/file.html");
+
+				String uri = st.nextToken();
+
+				// Decode parameters from the URI
+				int qmi = uri.indexOf('?');
+				if (qmi >= 0) {
+					decodeParms(uri.substring(qmi + 1), parms);
+					uri = decodePercent(uri.substring(0, qmi));
+				} else
+					uri = decodePercent(uri);
+
+				// If there's another token, it's protocol version,
+				// followed by HTTP headers. Ignore version but parse headers.
+				// NOTE: this now forces header names lowercase since they are
+				// case insensitive and vary by client.
+				if (st.hasMoreTokens()) {
+					String line = in.readLine();
+					while (line != null && line.trim().length() > 0) {
+						int p = line.indexOf(':');
+						if (p >= 0)
+							header.put(line.substring(0, p).trim().toLowerCase(), line.substring(p + 1).trim());
+						line = in.readLine();
+					}
+				}
+
+				pre.put("uri", uri);
+			}
+			catch (IOException ioe) {
+				sendError(HTTP_INTERNALERROR, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage());
+			}
+		}
+
+		/**
+		 * Decodes the Multipart Body data and put it into java Properties' key
+		 * - value pairs.
+		 **/
+		private void decodeMultipartData(String boundary, byte[] fbuf, BufferedReader in, Properties parms,
+				Properties files) throws InterruptedException {
+			try {
+				int[] bpositions = getBoundaryPositions(fbuf, boundary.getBytes());
+				int boundarycount = 1;
+				String mpline = in.readLine();
+				while (mpline != null) {
+					if (mpline.indexOf(boundary) == -1)
+						sendError(
+								HTTP_BADREQUEST,
+								"BAD REQUEST: Content type is multipart/form-data but next chunk does not start with boundary. Usage: GET /example/file.html");
+					boundarycount++;
+					Properties item = new Properties();
+					mpline = in.readLine();
+					while (mpline != null && mpline.trim().length() > 0) {
+						int p = mpline.indexOf(':');
+						if (p != -1)
+							item.put(mpline.substring(0, p).trim().toLowerCase(), mpline.substring(p + 1).trim());
+						mpline = in.readLine();
+					}
+					if (mpline != null) {
+						String contentDisposition = item.getProperty("content-disposition");
+						if (contentDisposition == null) {
+							sendError(HTTP_BADREQUEST,
+									"BAD REQUEST: Content type is multipart/form-data but no content-disposition info found. Usage: GET /example/file.html");
+						}
+						StringTokenizer st = new StringTokenizer(contentDisposition, "; ");
+						Properties disposition = new Properties();
+						while (st.hasMoreTokens()) {
+							String token = st.nextToken();
+							int p = token.indexOf('=');
+							if (p != -1)
+								disposition.put(token.substring(0, p).trim().toLowerCase(), token.substring(p + 1)
+										.trim());
+						}
+						String pname = disposition.getProperty("name");
+						pname = pname.substring(1, pname.length() - 1);
+
+						String value = "";
+						if (item.getProperty("content-type") == null) {
+							while (mpline != null && mpline.indexOf(boundary) == -1) {
+								mpline = in.readLine();
+								if (mpline != null) {
+									int d = mpline.indexOf(boundary);
+									if (d == -1)
+										value += mpline;
+									else
+										value += mpline.substring(0, d - 2);
+								}
+							}
+						} else {
+							if (boundarycount > bpositions.length)
+								sendError(HTTP_INTERNALERROR, "Error processing request");
+							int offset = stripMultipartHeaders(fbuf, bpositions[boundarycount - 2]);
+							String path = saveTmpFile(fbuf, offset, bpositions[boundarycount - 1] - offset - 4);
+							files.put(pname, path);
+							value = disposition.getProperty("filename");
+							value = value.substring(1, value.length() - 1);
+							do {
+								mpline = in.readLine();
+							} while (mpline != null && mpline.indexOf(boundary) == -1);
+						}
+						parms.put(pname, value);
+					}
+				}
+			}
+			catch (IOException ioe) {
+				sendError(HTTP_INTERNALERROR, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage());
+			}
+		}
+
+		/**
+		 * Find the byte positions where multipart boundaries start.
+		 **/
+		public int[] getBoundaryPositions(byte[] b, byte[] boundary) {
+			int matchcount = 0;
+			int matchbyte = -1;
+			Vector<Integer> matchbytes = new Vector<Integer>();
+			for (int i = 0; i < b.length; i++) {
+				if (b[i] == boundary[matchcount]) {
+					if (matchcount == 0)
+						matchbyte = i;
+					matchcount++;
+					if (matchcount == boundary.length) {
+						matchbytes.addElement(new Integer(matchbyte));
+						matchcount = 0;
+						matchbyte = -1;
+					}
+				} else {
+					i -= matchcount;
+					matchcount = 0;
+					matchbyte = -1;
+				}
+			}
+			int[] ret = new int[matchbytes.size()];
+			for (int i = 0; i < ret.length; i++) {
+				ret[i] = matchbytes.elementAt(i).intValue();
+			}
+			return ret;
+		}
+
+		/**
+		 * Retrieves the content of a sent file and saves it to a temporary
+		 * file. The full path to the saved file is returned.
+		 **/
+		private String saveTmpFile(byte[] b, int offset, int len) {
+			String path = "";
+			if (len > 0) {
+				String tmpdir = System.getProperty("java.io.tmpdir");
+				try {
+					File temp = File.createTempFile("NanoHTTPD", "", new File(tmpdir));
+					OutputStream fstream = new FileOutputStream(temp);
+					fstream.write(b, offset, len);
+					fstream.close();
+					path = temp.getAbsolutePath();
+				}
+				catch (Exception e) { // Catch exception if any
+					System.err.println("Error: " + e.getMessage());
+				}
+			}
+			return path;
+		}
+
+		/**
+		 * It returns the offset separating multipart file headers from the
+		 * file's data.
+		 **/
+		private int stripMultipartHeaders(byte[] b, int offset) {
+			int i = 0;
+			for (i = offset; i < b.length; i++) {
+				if (b[i] == '\r' && b[++i] == '\n' && b[++i] == '\r' && b[++i] == '\n')
+					break;
+			}
+			return i + 1;
+		}
+
+		/**
+		 * Decodes the percent encoding scheme. <br/>
+		 * For example: "an+example%20string" -> "an example string"
+		 */
+		private String decodePercent(String str) throws InterruptedException {
+			try {
+				StringBuffer sb = new StringBuffer();
+				for (int i = 0; i < str.length(); i++) {
+					char c = str.charAt(i);
+					switch (c) {
+						case '+' :
+							sb.append(' ');
+							break;
+						case '%' :
+							sb.append((char) Integer.parseInt(str.substring(i + 1, i + 3), 16));
+							i += 2;
+							break;
+						default :
+							sb.append(c);
+							break;
+					}
+				}
+				return sb.toString();
+			}
+			catch (Exception e) {
+				sendError(HTTP_BADREQUEST, "BAD REQUEST: Bad percent-encoding.");
+				return null;
+			}
+		}
+
+		/**
+		 * Decodes parameters in percent-encoded URI-format ( e.g.
+		 * "name=Jack%20Daniels&pass=Single%20Malt" ) and adds them to given
+		 * Properties. NOTE: this doesn't support multiple identical keys due to
+		 * the simplicity of Properties -- if you need multiples, you might want
+		 * to replace the Properties with a Hashtable of Vectors or such.
+		 */
+		private void decodeParms(String parms, Properties p) throws InterruptedException {
+			if (parms == null)
+				return;
+
+			StringTokenizer st = new StringTokenizer(parms, "&");
+			while (st.hasMoreTokens()) {
+				String e = st.nextToken();
+				int sep = e.indexOf('=');
+				if (sep >= 0)
+					p.put(decodePercent(e.substring(0, sep)).trim(), decodePercent(e.substring(sep + 1)));
+			}
+		}
+
+		/**
+		 * Returns an error message as a HTTP response and throws
+		 * InterruptedException to stop further request processing.
+		 */
+		private void sendError(String status, String msg) throws InterruptedException {
+			sendResponse(status, MIME_PLAINTEXT, null, new ByteArrayInputStream(msg.getBytes()));
+			throw new InterruptedException();
+		}
+
+		/**
+		 * Sends given response to the socket.
+		 */
+		private void sendResponse(String status, String mime, Properties header, InputStream data) {
+			try {
+				if (status == null)
+					throw new Error("sendResponse(): Status can't be null.");
+
+				OutputStream out = mySocket.getOutputStream();
+				PrintWriter pw = new PrintWriter(out);
+				pw.print("HTTP/1.0 " + status + " \r\n");
+
+				if (mime != null)
+					pw.print("Content-Type: " + mime + "\r\n");
+
+				if (header == null || header.getProperty("Date") == null)
+					pw.print("Date: " + gmtFrmt.format(new Date()) + "\r\n");
+
+				if (header != null) {
+					Enumeration<Object> e = header.keys();
+					while (e.hasMoreElements()) {
+						String key = (String) e.nextElement();
+						String value = header.getProperty(key);
+						pw.print(key + ": " + value + "\r\n");
+					}
+				}
+
+				pw.print("\r\n");
+				pw.flush();
+
+				if (data != null) {
+					int pending = data.available(); // This is to support
+													// partial sends, see
+													// serveFile()
+					byte[] buff = new byte[theBufferSize];
+					while (pending > 0) {
+						int read = data.read(buff, 0, ((pending > theBufferSize) ? theBufferSize : pending));
+						if (read <= 0)
+							break;
+						out.write(buff, 0, read);
+						pending -= read;
+					}
+				}
+				out.flush();
+				out.close();
+				if (data != null)
+					data.close();
+			}
+			catch (IOException ioe) {
+				// Couldn't write? No can do.
+				try {
+					mySocket.close();
+				}
+				catch (Throwable t) {}
+			}
+		}
+
+		private Socket	mySocket;
+	}
+
+	/**
+	 * URL-encodes everything between "/"-characters. Encodes spaces as '%20'
+	 * instead of '+'.
+	 */
+	@SuppressWarnings("deprecation")
+	private String encodeUri(String uri) {
+		String newUri = "";
+		StringTokenizer st = new StringTokenizer(uri, "/ ", true);
+		while (st.hasMoreTokens()) {
+			String tok = st.nextToken();
+			if (tok.equals("/"))
+				newUri += "/";
+			else if (tok.equals(" "))
+				newUri += "%20";
+			else {
+				newUri += URLEncoder.encode(tok);
+				// For Java 1.4 you'll want to use this instead:
+				// try { newUri += URLEncoder.encode( tok, "UTF-8" ); } catch (
+				// java.io.UnsupportedEncodingException uee ) {}
+			}
+		}
+		return newUri;
+	}
+
+	private int					myTcpPort;
+	final ServerSocket	myServerSocket;
+	private Thread				myThread;
+	private File				myRootDir;
+
+	// ==================================================
+	// File server code
+	// ==================================================
+
+	/**
+	 * Serves file from homeDir and its' subdirectories (only). Uses only URI,
+	 * ignores all headers and HTTP parameters.
+	 */
+	public Response serveFile(String uri, Properties header, File homeDir, boolean allowDirectoryListing) {
+		Response res = null;
+
+		// Make sure we won't die of an exception later
+		if (!homeDir.isDirectory())
+			res = new Response(HTTP_INTERNALERROR, MIME_PLAINTEXT,
+					"INTERNAL ERRROR: serveFile(): given homeDir is not a directory.");
+
+		if (res == null) {
+			// Remove URL arguments
+			uri = uri.trim().replace(File.separatorChar, '/');
+			if (uri.indexOf('?') >= 0)
+				uri = uri.substring(0, uri.indexOf('?'));
+
+			// Prohibit getting out of current directory
+			if (uri.startsWith("..") || uri.endsWith("..") || uri.indexOf("../") >= 0)
+				res = new Response(HTTP_FORBIDDEN, MIME_PLAINTEXT, "FORBIDDEN: Won't serve ../ for security reasons.");
+		}
+
+		File f = new File(homeDir, uri);
+		if (res == null && !f.exists())
+			res = new Response(HTTP_NOTFOUND, MIME_PLAINTEXT, "Error 404, file not found.");
+
+		// List the directory, if necessary
+		if (res == null && f.isDirectory()) {
+			// Browsers get confused without '/' after the
+			// directory, send a redirect.
+			if (!uri.endsWith("/")) {
+				uri += "/";
+				res = new Response(HTTP_REDIRECT, MIME_HTML, "<html><body>Redirected: <a href=\"" + uri + "\">" + uri
+						+ "</a></body></html>");
+				res.addHeader("Location", uri);
+			}
+
+			if (res == null) {
+				// First try index.html and index.htm
+				if (new File(f, "index.html").exists())
+					f = new File(homeDir, uri + "/index.html");
+				else if (new File(f, "index.htm").exists())
+					f = new File(homeDir, uri + "/index.htm");
+				// No index file, list the directory if it is readable
+				else if (allowDirectoryListing && f.canRead()) {
+					String[] files = f.list();
+					String msg = "<html><body><h1>Directory " + uri + "</h1><br/>";
+
+					if (uri.length() > 1) {
+						String u = uri.substring(0, uri.length() - 1);
+						int slash = u.lastIndexOf('/');
+						if (slash >= 0 && slash < u.length())
+							msg += "<b><a href=\"" + uri.substring(0, slash + 1) + "\">..</a></b><br/>";
+					}
+
+					if (files != null) {
+						for (int i = 0; i < files.length; ++i) {
+							File curFile = new File(f, files[i]);
+							boolean dir = curFile.isDirectory();
+							if (dir) {
+								msg += "<b>";
+								files[i] += "/";
+							}
+
+							msg += "<a href=\"" + encodeUri(uri + files[i]) + "\">" + files[i] + "</a>";
+
+							// Show file size
+							if (curFile.isFile()) {
+								long len = curFile.length();
+								msg += "  <font size=2>(";
+								if (len < 1024)
+									msg += len + " bytes";
+								else if (len < 1024 * 1024)
+									msg += len / 1024 + "." + (len % 1024 / 10 % 100) + " KB";
+								else
+									msg += len / (1024 * 1024) + "." + len % (1024 * 1024) / 10 % 100 + " MB";
+
+								msg += ")</font>";
+							}
+							msg += "<br/>";
+							if (dir)
+								msg += "</b>";
+						}
+					}
+					msg += "</body></html>";
+					res = new Response(HTTP_OK, MIME_HTML, msg);
+				} else {
+					res = new Response(HTTP_FORBIDDEN, MIME_PLAINTEXT, "FORBIDDEN: No directory listing.");
+				}
+			}
+		}
+
+		try {
+			if (res == null) {
+				// Get MIME type from file name extension, if possible
+				String mime = null;
+				int dot = f.getCanonicalPath().lastIndexOf('.');
+				if (dot >= 0)
+					mime = theMimeTypes.get(f.getCanonicalPath().substring(dot + 1).toLowerCase());
+				if (mime == null)
+					mime = MIME_DEFAULT_BINARY;
+
+				// Calculate etag
+				String etag = Integer
+						.toHexString((f.getAbsolutePath() + f.lastModified() + "" + f.length()).hashCode());
+
+				// Support (simple) skipping:
+				long startFrom = 0;
+				long endAt = -1;
+				String range = header.getProperty("range");
+				if (range != null) {
+					if (range.startsWith("bytes=")) {
+						range = range.substring("bytes=".length());
+						int minus = range.indexOf('-');
+						try {
+							if (minus > 0) {
+								startFrom = Long.parseLong(range.substring(0, minus));
+								endAt = Long.parseLong(range.substring(minus + 1));
+							}
+						}
+						catch (NumberFormatException nfe) {}
+					}
+				}
+
+				// Change return code and add Content-Range header when skipping
+				// is requested
+				long fileLen = f.length();
+				if (range != null && startFrom >= 0) {
+					if (startFrom >= fileLen) {
+						res = new Response(HTTP_RANGE_NOT_SATISFIABLE, MIME_PLAINTEXT, "");
+						res.addHeader("Content-Range", "bytes 0-0/" + fileLen);
+						res.addHeader("ETag", etag);
+					} else {
+						if (endAt < 0)
+							endAt = fileLen - 1;
+						long newLen = endAt - startFrom + 1;
+						if (newLen < 0)
+							newLen = 0;
+
+						final long dataLen = newLen;
+						FileInputStream fis = new FileInputStream(f) {
+							@Override
+							public int available() throws IOException {
+								return (int) dataLen;
+							}
+						};
+						fis.skip(startFrom);
+
+						res = new Response(HTTP_PARTIALCONTENT, mime, fis);
+						res.addHeader("Content-Length", "" + dataLen);
+						res.addHeader("Content-Range", "bytes " + startFrom + "-" + endAt + "/" + fileLen);
+						res.addHeader("ETag", etag);
+					}
+				} else {
+					if (etag.equals(header.getProperty("if-none-match")))
+						res = new Response(HTTP_NOTMODIFIED, mime, "");
+					else {
+						res = new Response(HTTP_OK, mime, new FileInputStream(f));
+						res.addHeader("Content-Length", "" + fileLen);
+						res.addHeader("ETag", etag);
+					}
+				}
+			}
+		}
+		catch (IOException ioe) {
+			res = new Response(HTTP_FORBIDDEN, MIME_PLAINTEXT, "FORBIDDEN: Reading file failed.");
+		}
+
+		res.addHeader("Accept-Ranges", "bytes"); // Announce that the file
+													// server accepts partial
+													// content requestes
+		return res;
+	}
+
+	/**
+	 * Hashtable mapping (String)FILENAME_EXTENSION -> (String)MIME_TYPE
+	 */
+	private static Hashtable<String,String>		theMimeTypes	= new Hashtable<String,String>();
+	static {
+		StringTokenizer st = new StringTokenizer("css		text/css " + "htm		text/html " + "html		text/html "
+				+ "xml		text/xml " + "txt		text/plain " + "asc		text/plain " + "gif		image/gif " + "jpg		image/jpeg "
+				+ "jpeg		image/jpeg " + "png		image/png " + "mp3		audio/mpeg " + "m3u		audio/mpeg-url "
+				+ "mp4		video/mp4 " + "ogv		video/ogg " + "flv		video/x-flv " + "mov		video/quicktime "
+				+ "swf		application/x-shockwave-flash " + "js			application/javascript " + "pdf		application/pdf "
+				+ "doc		application/msword " + "ogg		application/x-ogg " + "zip		application/octet-stream "
+				+ "exe		application/octet-stream " + "class		application/octet-stream ");
+		while (st.hasMoreTokens())
+			theMimeTypes.put(st.nextToken(), st.nextToken());
+	}
+
+	static int							theBufferSize	= 16 * 1024;
+
+	// Change this if you want to log to somewhere else than stdout
+	protected static PrintStream				myOut			= System.out;
+
+	/**
+	 * GMT date formatter
+	 */
+	static java.text.SimpleDateFormat	gmtFrmt;
+	static {
+		gmtFrmt = new java.text.SimpleDateFormat("E, d MMM yyyy HH:mm:ss 'GMT'", Locale.US);
+		gmtFrmt.setTimeZone(TimeZone.getTimeZone("GMT"));
+	}
+
+	/**
+	 * The distribution licence
+	 */
+	private static final String					LICENCE			= "Copyright (C) 2001,2005-2011 by Jarno Elonen <elonen at iki.fi>\n"
+																		+ "and Copyright (C) 2010 by Konstantinos Togias <info at ktogias.gr>\n"
+																		+ "\n"
+																		+ "Redistribution and use in source and binary forms, with or without\n"
+																		+ "modification, are permitted provided that the following conditions\n"
+																		+ "are met:\n"
+																		+ "\n"
+																		+ "Redistributions of source code must retain the above copyright notice,\n"
+																		+ "this list of conditions and the following disclaimer. Redistributions in\n"
+																		+ "binary form must reproduce the above copyright notice, this list of\n"
+																		+ "conditions and the following disclaimer in the documentation and/or other\n"
+																		+ "materials provided with the distribution. The name of the author may not\n"
+																		+ "be used to endorse or promote products derived from this software without\n"
+																		+ "specific prior written permission. \n"
+																		+ " \n"
+																		+ "THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n"
+																		+ "IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n"
+																		+ "OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n"
+																		+ "IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n"
+																		+ "INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n"
+																		+ "NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
+																		+ "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
+																		+ "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
+																		+ "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
+																		+ "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.";
+}
diff --git a/biz.aQute.bndlib.tests/src/test/make/MD5.java b/biz.aQute.bndlib.tests/src/test/make/MD5.java
new file mode 100644
index 0000000..67f53de
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/make/MD5.java
@@ -0,0 +1,44 @@
+package test.make;
+
+import java.io.*;
+import java.security.*;
+import java.util.*;
+
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.*;
+
+public class MD5 implements MakePlugin {
+
+	@Override
+	public Resource make(Builder builder, String source, Map<String,String> arguments) throws Exception {
+		if (!arguments.get("type").equals("md5"))
+			return null;
+		source = source.substring(0, source.length() - 4);
+		final File f = builder.getFile(source);
+		if (f.isFile()) {
+			return new AbstractResource(f.lastModified()) {
+				@Override
+				public byte[] getBytes() throws Exception {
+					return md5(f);
+				}
+			};
+		}
+		throw new FileNotFoundException("No such file: " + source);
+	}
+
+	static byte[] md5(File f) throws Exception {
+		MessageDigest md5 = MessageDigest.getInstance("MD5");
+		InputStream in = new FileInputStream(f);
+		try {
+			byte[] b = new byte[1000];
+			int size;
+			while ((size = in.read()) > 0) {
+				md5.update(b, 0, size);
+			}
+			return md5.digest();
+		}
+		finally {
+			in.close();
+		}
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/metatype/MetatypeTest.java b/biz.aQute.bndlib.tests/src/test/metatype/MetatypeTest.java
new file mode 100644
index 0000000..dc98996
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/metatype/MetatypeTest.java
@@ -0,0 +1,1161 @@
+package test.metatype;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.net.*;
+import java.util.*;
+import java.util.regex.*;
+
+import javax.xml.namespace.*;
+import javax.xml.parsers.*;
+import javax.xml.xpath.*;
+
+import junit.framework.*;
+
+import org.w3c.dom.*;
+
+import aQute.bnd.annotation.metatype.*;
+import aQute.bnd.osgi.*;
+import aQute.lib.io.*;
+import aQute.libg.generics.*;
+
+public class MetatypeTest extends TestCase {
+	static DocumentBuilderFactory	dbf		= DocumentBuilderFactory.newInstance();
+	static XPathFactory				xpathf	= XPathFactory.newInstance();
+	static XPath					xpath	= xpathf.newXPath();
+
+	static DocumentBuilder			db;
+	static {
+		try {
+			dbf.setNamespaceAware(true);
+			db = dbf.newDocumentBuilder();
+			xpath.setNamespaceContext(new NamespaceContext() {
+
+				@Override
+				public Iterator<String> getPrefixes(String namespaceURI) {
+					return Arrays.asList("md").iterator();
+				}
+
+				@Override
+				public String getPrefix(String namespaceURI) {
+					return "md";
+				}
+
+				@Override
+				public String getNamespaceURI(String prefix) {
+					return "http://www.osgi.org/xmlns/metatype/v1.1.0";
+				}
+			});
+		}
+		catch (ParserConfigurationException e) {
+			e.printStackTrace();
+			throw new ExceptionInInitializerError(e);
+		}
+	}
+
+	public static void testOptions() {
+
+	}
+
+	/**
+	 * Configuration should return null for nonprimitive properties if not
+	 * defined. Now it returns 0. Testcase:
+	 * 
+	 * @OCD interface Config {
+	 * @ad(required = false) Integer port(); } Config config =
+	 *              Configurable.createConfigurable(Config.class, properties);
+	 *              assert config.port() == null; // property port is not set
+	 *              Fix: Please delete
+	 *              "|| Number.class.isAssignableFrom(method.getReturnType())"
+	 *              from aQute/bnd/annotation/metatype/Configurable.java
+	 */
+	@Meta.OCD
+	static interface C {
+		@Meta.AD(required = false)
+		Integer port();
+	}
+
+	public static void testConfigurableForNonPrimitives() {
+		Map<String,String> p = new HashMap<String,String>();
+		C config = Configurable.createConfigurable(C.class, p);
+		assertNull(config.port());
+		p.put("port", "10");
+		config = Configurable.createConfigurable(C.class, p);
+		assertEquals(Integer.valueOf(10), config.port()); // property port is
+															// not set
+	}
+
+	/**
+	 * Test method naming options with '.' and reserved names
+	 */
+
+	@Meta.OCD
+	public static interface Naming {
+		String secret();
+
+		String _secret(); // .secret
+
+		String __secret(); // _secret
+
+		String $new(); // new
+
+		String $$new(); // $new
+
+		String a_b_c(); // a.b.c
+
+		String a__b__c(); // a_b_c
+
+		String _a__b(); // .a_b
+
+		String $$$$$$$$a__b(); // $$$$a_b
+
+		String $$$$$$$$a_b(); // $$$$a.b
+
+		String a$(); // a
+
+		String a$$(); // a$
+
+		String a$$$(); // a$
+
+		String a$$$$(); // a$$
+
+		String a$$_$$(); // a$.$
+
+		String a$$__$$(); // a$_$
+
+		String a_$_(); // a..
+
+		@Meta.AD(id = "secret")
+		String xsecret();
+
+		@Meta.AD(id = ".secret")
+		String x_secret();
+
+		@Meta.AD(id = "_secret")
+		String x__secret(); // _secret
+
+		@Meta.AD(id = "new")
+		String x$new(); // new
+
+		@Meta.AD(id = "$new")
+		String x$$new(); // $new
+
+		@Meta.AD(id = "a.b.c")
+		String xa_b_c(); // a.b.c
+
+		@Meta.AD(id = "a_b_c")
+		String xa__b__c(); // a_b_c
+
+		@Meta.AD(id = ".a_b")
+		String x_a__b(); // .a_b
+
+		@Meta.AD(id = "$$$$a_b")
+		String x$$$$$$$$a__b(); // $$$$a_b
+
+		@Meta.AD(id = "$$$$a.b")
+		String x$$$$$$$$a_b(); // $$$$a.b
+
+		@Meta.AD(id = "a")
+		String xa$(); // a
+
+		@Meta.AD(id = "a$")
+		String xa$$(); // a$
+
+		@Meta.AD(id = "a$")
+		String xa$$$(); // a$
+
+		@Meta.AD(id = "a$$")
+		String xa$$$$(); // a$$
+
+		@Meta.AD(id = "a$.$")
+		String xa$$_$$(); // a$.$
+
+		@Meta.AD(id = "a$_$")
+		String xa$$__$$(); // a$_$
+
+		@Meta.AD(id = "a..")
+		String xa_$_(); // a..
+
+		String noid();
+
+		@Meta.AD(id = Meta.NULL)
+		String nullid();
+	}
+
+	public static void testNaming() throws Exception {
+		Map<String,Object> map = Create.map();
+
+		map.put("_secret", "_secret");
+		map.put("_secret", "_secret");
+		map.put(".secret", ".secret");
+		map.put("$new", "$new");
+		map.put("new", "new");
+		map.put("secret", "secret");
+		map.put("a_b_c", "a_b_c");
+		map.put("a.b.c", "a.b.c");
+		map.put(".a_b", ".a_b");
+		map.put("$$$$a_b", "$$$$a_b");
+		map.put("$$$$a.b", "$$$$a.b");
+		map.put("a", "a");
+		map.put("a$", "a$");
+		map.put("a$$", "a$$");
+		map.put("a$.$", "a$.$");
+		map.put("a$_$", "a$_$");
+		map.put("a..", "a..");
+		map.put("noid", "noid");
+		map.put("nullid", "nullid");
+
+		Naming trt = Configurable.createConfigurable(Naming.class, map);
+
+		// By name
+		assertEquals("secret", trt.secret());
+		assertEquals("_secret", trt.__secret());
+		assertEquals(".secret", trt._secret());
+		assertEquals("new", trt.$new());
+		assertEquals("$new", trt.$$new());
+		assertEquals("a.b.c", trt.a_b_c());
+		assertEquals("a_b_c", trt.a__b__c());
+		assertEquals(".a_b", trt._a__b());
+		assertEquals("$$$$a.b", trt.$$$$$$$$a_b());
+		assertEquals("$$$$a_b", trt.$$$$$$$$a__b());
+		assertEquals("a", trt.a$());
+		assertEquals("a$", trt.a$$());
+		assertEquals("a$", trt.a$$$());
+		assertEquals("a$.$", trt.a$$_$$());
+		assertEquals("a$_$", trt.a$$__$$());
+		assertEquals("a..", trt.a_$_());
+		assertEquals("noid", trt.noid());
+		assertEquals("nullid", trt.nullid());
+
+		// By AD
+		assertEquals("secret", trt.xsecret());
+		assertEquals("_secret", trt.x__secret());
+		assertEquals(".secret", trt.x_secret());
+		assertEquals("new", trt.x$new());
+		assertEquals("$new", trt.x$$new());
+		assertEquals("a.b.c", trt.xa_b_c());
+		assertEquals("a_b_c", trt.xa__b__c());
+		assertEquals(".a_b", trt.x_a__b());
+		assertEquals("$$$$a.b", trt.x$$$$$$$$a_b());
+		assertEquals("$$$$a_b", trt.x$$$$$$$$a__b());
+		assertEquals("a", trt.xa$());
+		assertEquals("a$", trt.xa$$());
+		assertEquals("a$", trt.xa$$$());
+		assertEquals("a$.$", trt.xa$$_$$());
+
+		Builder b = new Builder();
+		b.addClasspath(new File("bin"));
+		b.setProperty("Export-Package", "test.metatype");
+		b.setProperty("-metatype", "*");
+		b.build();
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+
+		Resource r = b.getJar().getResource("OSGI-INF/metatype/test.metatype.MetatypeTest$Naming.xml");
+		IO.copy(r.openInputStream(), System.err);
+		Document d = db.parse(r.openInputStream(), "UTF-8");
+		assertEquals("http://www.osgi.org/xmlns/metatype/v1.1.0", d.getDocumentElement().getNamespaceURI());
+
+	}
+
+	/**
+	 * Test the special conversions.
+	 */
+
+	public static class MyList<T> extends ArrayList<T> {
+		private static final long	serialVersionUID	= 1L;
+
+		public MyList() {
+			System.err.println("Constr");
+
+		}
+	}
+
+	static interface CollectionsTest {
+		Collection<String> collection();
+
+		List<String> list();
+
+		Set<String> set();
+
+		Queue<String> queue();
+
+		// Deque<String> deque();
+		Stack<String> stack();
+
+		ArrayList<String> arrayList();
+
+		LinkedList<String> linkedList();
+
+		LinkedHashSet<String> linkedHashSet();
+
+		MyList<String> myList();
+	}
+
+	public static void testCollections() throws Exception {
+		CollectionsTest trt = set(CollectionsTest.class, new int[] {
+				1, 2, 3
+		});
+		List<String> source = Arrays.asList("1", "2", "3");
+
+		assertTrue(trt.collection() instanceof Collection);
+		assertEqualList(source, trt.collection());
+
+		assertTrue(trt.list() instanceof List);
+		assertEqualList(source, trt.list());
+		assertTrue(trt.set() instanceof Set);
+		assertEqualList(source, trt.set());
+		assertTrue(trt.queue() instanceof Queue);
+		assertEqualList(source, trt.queue());
+		// assertTrue( trt.deque() instanceof Deque);
+		// assertEqualList( source, trt.deque());
+		assertTrue(trt.stack() instanceof Stack);
+		assertEqualList(source, trt.stack());
+		assertTrue(trt.arrayList() instanceof ArrayList);
+		assertEqualList(source, trt.arrayList());
+		assertTrue(trt.linkedList() instanceof LinkedList);
+		assertEqualList(source, trt.linkedList());
+		assertTrue(trt.linkedHashSet() instanceof LinkedHashSet);
+		assertEqualList(source, trt.linkedHashSet());
+		assertTrue(trt.myList() instanceof MyList);
+		assertEqualList(source, trt.myList());
+	}
+
+	private static void assertEqualList(List< ? > a, Collection< ? > b) {
+		if (a.size() == b.size()) {
+			for (Object x : a) {
+				if (!b.contains(x))
+					throw new AssertionFailedError("expected:<" + a + "> but was: <" + b + ">");
+			}
+			return;
+		}
+		throw new AssertionFailedError("expected:<" + a + "> but was: <" + b + ">");
+	}
+
+	/**
+	 * Test the special conversions.
+	 */
+	static interface SpecialConversions {
+		enum X {
+			A, B, C
+		}
+
+		X enumv();
+
+		Pattern pattern();
+
+		Class< ? > clazz();
+
+		URI constructor();
+	}
+
+	public static void testSpecialConversions() throws URISyntaxException {
+		Properties p = new Properties();
+		p.put("enumv", "A");
+		p.put("pattern", ".*");
+		p.put("clazz", "java.lang.Object");
+		p.put("constructor", "http://www.aQute.biz");
+
+		SpecialConversions trt = Configurable.createConfigurable(SpecialConversions.class, (Map<Object,Object>) p);
+		assertEquals(SpecialConversions.X.A, trt.enumv());
+		assertEquals(".*", trt.pattern().pattern());
+		assertEquals(Object.class, trt.clazz());
+		assertEquals(new URI("http://www.aQute.biz"), trt.constructor());
+	}
+
+	/**
+	 * Test the converter.
+	 * 
+	 * @throws URISyntaxException
+	 */
+
+	public static void testConverter() throws URISyntaxException {
+		{
+			// Test collections as value
+			TestReturnTypes trt = set(TestReturnTypes.class, Arrays.asList(55));
+			assertTrue(Arrays.equals(new boolean[] {
+				true
+			}, trt.rpaBoolean()));
+			assertTrue(Arrays.equals(new byte[] {
+				55
+			}, trt.rpaByte()));
+			assertTrue(Arrays.equals(new short[] {
+				55
+			}, trt.rpaShort()));
+			assertTrue(Arrays.equals(new int[] {
+				55
+			}, trt.rpaInt()));
+			assertTrue(Arrays.equals(new long[] {
+				55
+			}, trt.rpaLong()));
+			assertTrue(Arrays.equals(new float[] {
+				55
+			}, trt.rpaFloat()));
+			assertTrue(Arrays.equals(new double[] {
+				55
+			}, trt.rpaDouble()));
+			assertEquals(Arrays.asList(true), trt.rBooleans());
+			assertEquals(Arrays.asList(new Byte((byte) 55)), trt.rBytes());
+			assertEquals(Arrays.asList(new Short((short) 55)), trt.rShorts());
+			assertEquals(Arrays.asList(Integer.valueOf(55)), trt.rInts());
+			assertEquals(Arrays.asList(new Long(55L)), trt.rLongs());
+			assertEquals(Arrays.asList(new Float(55F)), trt.rFloats());
+			assertEquals(Arrays.asList(new Double(55D)), trt.rDoubles());
+			assertEquals(Arrays.asList("55"), trt.rStrings());
+			assertEquals(Arrays.asList(new URI("55")), trt.rURIs());
+
+			assertTrue(Arrays.equals(new Boolean[] {
+				true
+			}, trt.raBoolean()));
+			assertTrue(Arrays.equals(new Byte[] {
+				55
+			}, trt.raByte()));
+			assertTrue(Arrays.equals(new Short[] {
+				55
+			}, trt.raShort()));
+			assertTrue(Arrays.equals(new Integer[] {
+				55
+			}, trt.raInt()));
+			assertTrue(Arrays.equals(new Long[] {
+				55L
+			}, trt.raLong()));
+			assertTrue(Arrays.equals(new Float[] {
+				55F
+			}, trt.raFloat()));
+			assertTrue(Arrays.equals(new Double[] {
+				55D
+			}, trt.raDouble()));
+			assertTrue(Arrays.equals(new String[] {
+				"55"
+			}, trt.raString()));
+			assertTrue(Arrays.equals(new URI[] {
+				new URI("55")
+			}, trt.raURI()));
+
+		}
+		{
+			// Test primitive arrays as value
+			TestReturnTypes trt = set(TestReturnTypes.class, new int[] {
+				55
+			});
+			assertTrue(Arrays.equals(new boolean[] {
+				true
+			}, trt.rpaBoolean()));
+			assertTrue(Arrays.equals(new byte[] {
+				55
+			}, trt.rpaByte()));
+			assertTrue(Arrays.equals(new short[] {
+				55
+			}, trt.rpaShort()));
+			assertTrue(Arrays.equals(new int[] {
+				55
+			}, trt.rpaInt()));
+			assertTrue(Arrays.equals(new long[] {
+				55
+			}, trt.rpaLong()));
+			assertTrue(Arrays.equals(new float[] {
+				55
+			}, trt.rpaFloat()));
+			assertTrue(Arrays.equals(new double[] {
+				55
+			}, trt.rpaDouble()));
+			assertEquals(Arrays.asList(true), trt.rBooleans());
+			assertEquals(Arrays.asList(new Byte((byte) 55)), trt.rBytes());
+			assertEquals(Arrays.asList(new Short((short) 55)), trt.rShorts());
+			assertEquals(Arrays.asList(Integer.valueOf(55)), trt.rInts());
+			assertEquals(Arrays.asList(new Long(55L)), trt.rLongs());
+			assertEquals(Arrays.asList(new Float(55F)), trt.rFloats());
+			assertEquals(Arrays.asList(new Double(55D)), trt.rDoubles());
+			assertEquals(Arrays.asList("55"), trt.rStrings());
+			assertEquals(Arrays.asList(new URI("55")), trt.rURIs());
+
+			assertTrue(Arrays.equals(new Boolean[] {
+				true
+			}, trt.raBoolean()));
+			assertTrue(Arrays.equals(new Byte[] {
+				55
+			}, trt.raByte()));
+			assertTrue(Arrays.equals(new Short[] {
+				55
+			}, trt.raShort()));
+			assertTrue(Arrays.equals(new Integer[] {
+				55
+			}, trt.raInt()));
+			assertTrue(Arrays.equals(new Long[] {
+				55L
+			}, trt.raLong()));
+			assertTrue(Arrays.equals(new Float[] {
+				55F
+			}, trt.raFloat()));
+			assertTrue(Arrays.equals(new Double[] {
+				55D
+			}, trt.raDouble()));
+			assertTrue(Arrays.equals(new String[] {
+				"55"
+			}, trt.raString()));
+			assertTrue(Arrays.equals(new URI[] {
+				new URI("55")
+			}, trt.raURI()));
+
+		}
+
+		{
+			// Test single value
+			TestReturnTypes trt = set(TestReturnTypes.class, 55);
+			assertEquals(true, trt.rpBoolean());
+			assertEquals(55, trt.rpByte());
+			assertEquals(55, trt.rpShort());
+			assertEquals(55, trt.rpInt());
+			assertEquals(55L, trt.rpLong());
+			assertEquals(55.0D, trt.rpDouble());
+			assertEquals(55.0F, trt.rpFloat());
+			assertEquals((Boolean) true, trt.rBoolean());
+			assertEquals(new Byte((byte) 55), trt.rByte());
+			assertEquals(new Short((short) 55), trt.rShort());
+			assertEquals(Integer.valueOf(55), trt.rInt());
+			assertEquals(new Long(55L), trt.rLong());
+			assertEquals(new Float(55F), trt.rFloat());
+			assertEquals(new Double(55), trt.rDouble());
+			assertEquals("55", trt.rString());
+			assertEquals(new URI("55"), trt.rURI());
+			assertTrue(Arrays.equals(new boolean[] {
+				true
+			}, trt.rpaBoolean()));
+			assertTrue(Arrays.equals(new byte[] {
+				55
+			}, trt.rpaByte()));
+			assertTrue(Arrays.equals(new short[] {
+				55
+			}, trt.rpaShort()));
+			assertTrue(Arrays.equals(new int[] {
+				55
+			}, trt.rpaInt()));
+			assertTrue(Arrays.equals(new long[] {
+				55
+			}, trt.rpaLong()));
+			assertTrue(Arrays.equals(new float[] {
+				55
+			}, trt.rpaFloat()));
+			assertTrue(Arrays.equals(new double[] {
+				55
+			}, trt.rpaDouble()));
+			assertEquals(Arrays.asList(true), trt.rBooleans());
+			assertEquals(Arrays.asList(new Byte((byte) 55)), trt.rBytes());
+			assertEquals(Arrays.asList(new Short((short) 55)), trt.rShorts());
+			assertEquals(Arrays.asList(Integer.valueOf(55)), trt.rInts());
+			assertEquals(Arrays.asList(new Long(55L)), trt.rLongs());
+			assertEquals(Arrays.asList(new Float(55F)), trt.rFloats());
+			assertEquals(Arrays.asList(new Double(55D)), trt.rDoubles());
+			assertEquals(Arrays.asList("55"), trt.rStrings());
+			assertEquals(Arrays.asList(new URI("55")), trt.rURIs());
+
+			assertTrue(Arrays.equals(new Boolean[] {
+				true
+			}, trt.raBoolean()));
+			assertTrue(Arrays.equals(new Byte[] {
+				55
+			}, trt.raByte()));
+			assertTrue(Arrays.equals(new Short[] {
+				55
+			}, trt.raShort()));
+			assertTrue(Arrays.equals(new Integer[] {
+				55
+			}, trt.raInt()));
+			assertTrue(Arrays.equals(new Long[] {
+				55L
+			}, trt.raLong()));
+			assertTrue(Arrays.equals(new Float[] {
+				55F
+			}, trt.raFloat()));
+			assertTrue(Arrays.equals(new Double[] {
+				55D
+			}, trt.raDouble()));
+			assertTrue(Arrays.equals(new String[] {
+				"55"
+			}, trt.raString()));
+			assertTrue(Arrays.equals(new URI[] {
+				new URI("55")
+			}, trt.raURI()));
+		}
+	}
+
+	static <T> T set(Class<T> interf, Object value) {
+		Properties p = new Properties();
+		Method ms[] = interf.getMethods();
+
+		for (Method m : ms) {
+			p.put(m.getName(), value);
+		}
+		return Configurable.createConfigurable(interf, (Map<Object,Object>) p);
+	}
+
+	/**
+	 * Test enum handling
+	 */
+
+	@Meta.OCD
+	public static interface Enums {
+		enum X {
+			requireConfiguration, optionalConfiguration, ignoreConfiguration
+		}
+
+		X r();
+
+		X i();
+
+		X o();
+	}
+
+	public static void testEnum() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("bin"));
+		b.setProperty("Export-Package", "test.metatype");
+		b.setProperty("-metatype", "*");
+		b.build();
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+
+		Resource r = b.getJar().getResource("OSGI-INF/metatype/test.metatype.MetatypeTest$Enums.xml");
+		IO.copy(r.openInputStream(), System.err);
+
+		Document d = db.parse(r.openInputStream());
+		assertEquals("http://www.osgi.org/xmlns/metatype/v1.1.0", d.getDocumentElement().getNamespaceURI());
+
+		Properties p = new Properties();
+		p.setProperty("r", "requireConfiguration");
+		p.setProperty("i", "ignoreConfiguration");
+		p.setProperty("o", "optionalConfiguration");
+		Enums enums = Configurable.createConfigurable(Enums.class, (Map<Object,Object>) p);
+		assertEquals(Enums.X.requireConfiguration, enums.r());
+		assertEquals(Enums.X.ignoreConfiguration, enums.i());
+		assertEquals(Enums.X.optionalConfiguration, enums.o());
+	}
+
+	/**
+	 * Test the OCD settings
+	 */
+	@Meta.OCD()
+	public static interface OCDEmpty {}
+
+	@Meta.OCD(description = "description")
+	public static interface OCDDescription {}
+
+	@Meta.OCD()
+	public static interface OCDDesignatePidOnly {}
+
+	@Meta.OCD(factory = true)
+	public static interface OCDDesignatePidFactory {}
+
+	@Meta.OCD(id = "id")
+	public static interface OCDId {}
+
+	@Meta.OCD(id = "id")
+	public static interface OCDIdWithPid {}
+
+	@Meta.OCD(localization = "localization")
+	public static interface OCDLocalization {}
+
+	@Meta.OCD(name = "name")
+	public static interface OCDName {}
+
+	public static void testOCD() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("bin"));
+		b.setProperty("Export-Package", "test.metatype");
+		b.setProperty("-metatype", "*");
+		b.build();
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+		System.err.println(b.getJar().getResources().keySet());
+
+		assertOCD(b, "test.metatype.MetatypeTest$OCDEmpty", "test.metatype.MetatypeTest$OCDEmpty",
+				"Metatype test OCDEmpty", null, "test.metatype.MetatypeTest$OCDEmpty", false, null);
+		assertOCD(b, "test.metatype.MetatypeTest$OCDName", "test.metatype.MetatypeTest$OCDName", "name", null,
+				"test.metatype.MetatypeTest$OCDName", false, null);
+		assertOCD(b, "test.metatype.MetatypeTest$OCDDescription", "test.metatype.MetatypeTest$OCDDescription",
+				"Metatype test OCDDescription", "description", "test.metatype.MetatypeTest$OCDDescription", false, null);
+		assertOCD(b, "test.metatype.MetatypeTest$OCDDesignatePidOnly",
+				"test.metatype.MetatypeTest$OCDDesignatePidOnly", "Metatype test OCDDesignate pid only", null,
+				"test.metatype.MetatypeTest$OCDDesignatePidOnly", false, null);
+		assertOCD(b, "test.metatype.MetatypeTest$OCDDesignatePidFactory",
+				"test.metatype.MetatypeTest$OCDDesignatePidFactory", "Metatype test OCDDesignate pid factory", null,
+				"test.metatype.MetatypeTest$OCDDesignatePidFactory", true, null);
+		assertOCD(b, "test.metatype.MetatypeTest$OCDId", "id", "Metatype test OCDId", null, "id", false, null);
+		assertOCD(b, "test.metatype.MetatypeTest$OCDIdWithPid", "id", "Metatype test OCDId with pid", null, "id",
+				false, null);
+		assertOCD(b, "test.metatype.MetatypeTest$OCDLocalization", "test.metatype.MetatypeTest$OCDLocalization",
+				"Metatype test OCDLocalization", null, "test.metatype.MetatypeTest$OCDLocalization", false,
+				"localization");
+	}
+
+	static void assertOCD(Builder b, String cname, String id, String name, String description, String designate,
+			boolean factory, String localization) throws Exception {
+		Resource r = b.getJar().getResource("OSGI-INF/metatype/" + cname + ".xml");
+		assertNotNull(r);
+		IO.copy(r.openInputStream(), System.err);
+		Document d = db.parse(r.openInputStream());
+		assertEquals(id, xpath.evaluate("//OCD/@id", d, XPathConstants.STRING));
+		assertEquals(name, xpath.evaluate("//OCD/@name", d, XPathConstants.STRING));
+		assertEquals(localization == null ? cname : localization,
+				xpath.evaluate("//OCD/@localization", d, XPathConstants.STRING));
+		assertEquals(description == null ? "" : description,
+				xpath.evaluate("//OCD/@description", d, XPathConstants.STRING));
+
+		if (designate == null) {
+			assertEquals(id, xpath.evaluate("//Designate/@pid", d, XPathConstants.STRING));
+			if (factory)
+				assertEquals(id, xpath.evaluate("//Designate/@factoryPid", d, XPathConstants.STRING));
+		} else {
+			assertEquals(designate, xpath.evaluate("//Designate/@pid", d, XPathConstants.STRING));
+			if (factory)
+				assertEquals(designate, xpath.evaluate("//Designate/@factoryPid", d, XPathConstants.STRING));
+		}
+
+		assertEquals(id, xpath.evaluate("//Object/@ocdref", d, XPathConstants.STRING));
+	}
+
+	/**
+	 * Test the AD settings.
+	 */
+
+	@Meta.OCD(description = "advariations")
+	public static interface TestAD {
+		@Meta.AD
+		String noSettings();
+
+		@Meta.AD(id = "id")
+		String withId();
+
+		@Meta.AD(name = "name")
+		String withName();
+
+		@Meta.AD(max = "1")
+		String withMax();
+
+		@Meta.AD(min = "-1")
+		String withMin();
+
+		@Meta.AD(deflt = "deflt")
+		String withDefault();
+
+		@Meta.AD(cardinality = 0)
+		String[] withC0();
+
+		@Meta.AD(cardinality = 1)
+		String[] withC1();
+
+		@Meta.AD(cardinality = -1)
+		Collection<String> withC_1();
+
+		@Meta.AD(cardinality = -1)
+		String[] withC_1ButArray();
+
+		@Meta.AD(cardinality = 1)
+		Collection<String> withC1ButCollection();
+
+		@Meta.AD(type = Meta.Type.String)
+		int withInt();
+
+		@Meta.AD(type = Meta.Type.Integer)
+		String withString();
+
+		@Meta.AD(description = "description_xxx\"xxx'xxx")
+		String a();
+
+		@Meta.AD(optionValues = {
+				"a", "b"
+		})
+		String valuesOnly();
+
+		@Meta.AD(optionValues = {
+				"a", "b"
+		}, optionLabels = {
+				"A", "B"
+		})
+		String labelsAndValues();
+
+		@Meta.AD(required = true)
+		String required();
+
+		@Meta.AD(required = false)
+		String notRequired();
+	}
+
+	public static void testAD() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("bin"));
+		b.setProperty("Export-Package", "test.metatype");
+		b.setProperty("-metatype", "*");
+		b.build();
+		Resource r = b.getJar().getResource("OSGI-INF/metatype/test.metatype.MetatypeTest$TestAD.xml");
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+		System.err.println(b.getJar().getResources().keySet());
+		assertNotNull(r);
+		IO.copy(r.openInputStream(), System.err);
+
+		Document d = db.parse(r.openInputStream());
+
+		assertAD(d, "noSettings", "No settings", "noSettings", null, null, null, 0, "String", null, null, null);
+		assertAD(d, "withId", "With id", "id", null, null, null, 0, "String", null, null, null);
+		assertAD(d, "name", "name", "withName", null, null, null, 0, "String", null, null, null);
+		assertAD(d, "withMax", "With max", "withMax", null, "1", null, 0, "String", null, null, null);
+		assertAD(d, "withMin", "With min", "withMin", "-1", null, null, 0, "String", null, null, null);
+		assertAD(d, "withC1", "With c1", "withC1", null, null, null, 1, "String", null, null, null);
+		assertAD(d, "withC0", "With c0", "withC0", null, null, null, 2147483647, "String", null, null, null);
+		assertAD(d, "withC_1", "With c 1", "withC.1", null, null, null, -1, "String", null, null, null);
+		assertAD(d, "withC_1ButArray", "With c 1 but array", "withC.1ButArray", null, null, null, -1, "String", null,
+				null, null);
+		assertAD(d, "withC1ButCollection", "With c1 but collection", "withC1ButCollection", null, null, null, 1,
+				"String", null, null, null);
+		assertAD(d, "withInt", "With int", "withInt", null, null, null, 0, "String", null, null, null);
+		assertAD(d, "withString", "With string", "withString", null, null, null, 0, "Integer", null, null, null);
+		assertAD(d, "a", "A", "a", null, null, null, 0, "String", "description_xxx\"xxx'xxx", null, null);
+		assertAD(d, "valuesOnly", "Values only", "valuesOnly", null, null, null, 0, "String", null, new String[] {
+				"a", "b"
+		}, new String[] {
+				"a", "b"
+		});
+		assertAD(d, "labelsAndValues", "Labels and values", "labelsAndValues", null, null, null, 0, "String", null,
+				new String[] {
+						"a", "b"
+				}, new String[] {
+						"A", "A"
+				});
+	}
+
+	static void assertAD(Document d, @SuppressWarnings("unused")
+	String mname, String name, String id, String min, String max, String deflt, int cardinality, String type,
+			String description, @SuppressWarnings("unused")
+			String[] optionvalues, @SuppressWarnings("unused")
+			String optionLabels[]) throws XPathExpressionException {
+		assertEquals(name, xpath.evaluate("//OCD/AD[@id='" + id + "']/@name", d, XPathConstants.STRING));
+		assertEquals(id, xpath.evaluate("//OCD/AD[@id='" + id + "']/@id", d, XPathConstants.STRING));
+		assertEquals(min == null ? "" : min,
+				xpath.evaluate("//OCD/AD[@id='" + id + "']/@min", d, XPathConstants.STRING));
+		assertEquals(max == null ? "" : max,
+				xpath.evaluate("//OCD/AD[@id='" + id + "']/@max", d, XPathConstants.STRING));
+		assertEquals(deflt == null ? "" : deflt,
+				xpath.evaluate("//OCD/AD[@id='" + id + "']/@deflt", d, XPathConstants.STRING));
+		assertEquals(cardinality + "",
+				xpath.evaluate("//OCD/AD[@id='" + id + "']/@cardinality", d, XPathConstants.STRING));
+		assertEquals(type, xpath.evaluate("//OCD/AD[@id='" + id + "']/@type", d, XPathConstants.STRING));
+		assertEquals(description == null ? "" : description,
+				xpath.evaluate("//OCD/AD[@id='" + id + "']/@description", d, XPathConstants.STRING));
+	}
+
+	/**
+	 * Test all the return types.
+	 */
+	@Meta.OCD(description = "simple", name = "TestSimple")
+	public static interface TestReturnTypes {
+		boolean rpBoolean();
+
+		byte rpByte();
+
+		char rpCharacter();
+
+		short rpShort();
+
+		int rpInt();
+
+		long rpLong();
+
+		float rpFloat();
+
+		double rpDouble();
+
+		Boolean rBoolean();
+
+		Byte rByte();
+
+		Character rCharacter();
+
+		Short rShort();
+
+		Integer rInt();
+
+		Long rLong();
+
+		Float rFloat();
+
+		Double rDouble();
+
+		String rString();
+
+		URI rURI();
+
+		boolean[] rpaBoolean();
+
+		byte[] rpaByte();
+
+		char[] rpaCharacter();
+
+		short[] rpaShort();
+
+		int[] rpaInt();
+
+		long[] rpaLong();
+
+		float[] rpaFloat();
+
+		double[] rpaDouble();
+
+		Collection<Boolean> rBooleans();
+
+		Collection<Byte> rBytes();
+
+		Collection<Character> rCharacters();
+
+		Collection<Short> rShorts();
+
+		Collection<Integer> rInts();
+
+		Collection<Long> rLongs();
+
+		Collection<Float> rFloats();
+
+		Collection<Double> rDoubles();
+
+		Collection<String> rStrings();
+
+		Collection<URI> rURIs();
+
+		Boolean[] raBoolean();
+
+		Byte[] raByte();
+
+		Character[] raCharacter();
+
+		Short[] raShort();
+
+		Integer[] raInt();
+
+		Long[] raLong();
+
+		Float[] raFloat();
+
+		Double[] raDouble();
+
+		String[] raString();
+
+		URI[] raURI();
+	}
+
+	public static void testReturnTypes() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("bin"));
+		b.setProperty("Export-Package", "test.metatype");
+		b.setProperty("-metatype", "*");
+		b.build();
+		Resource r = b.getJar().getResource("OSGI-INF/metatype/test.metatype.MetatypeTest$TestReturnTypes.xml");
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+		System.err.println(b.getJar().getResources().keySet());
+		assertNotNull(r);
+		IO.copy(r.openInputStream(), System.err);
+
+		Document d = db.parse(r.openInputStream());
+		assertEquals("http://www.osgi.org/xmlns/metatype/v1.1.0", d.getDocumentElement().getNamespaceURI());
+		// Primitives
+		assertEquals("Boolean", xpath.evaluate("//OCD/AD[@id='rpBoolean']/@type", d));
+		assertEquals("Byte", xpath.evaluate("//OCD/AD[@id='rpByte']/@type", d));
+		assertEquals("Character", xpath.evaluate("//OCD/AD[@id='rpCharacter']/@type", d));
+		assertEquals("Short", xpath.evaluate("//OCD/AD[@id='rpShort']/@type", d));
+		assertEquals("Integer", xpath.evaluate("//OCD/AD[@id='rpInt']/@type", d));
+		assertEquals("Long", xpath.evaluate("//OCD/AD[@id='rpLong']/@type", d));
+		assertEquals("Float", xpath.evaluate("//OCD/AD[@id='rpFloat']/@type", d));
+		assertEquals("Double", xpath.evaluate("//OCD/AD[@id='rpDouble']/@type", d));
+
+		// Primitive Wrappers
+		assertEquals("Boolean", xpath.evaluate("//OCD/AD[@id='rBoolean']/@type", d));
+		assertEquals("Byte", xpath.evaluate("//OCD/AD[@id='rByte']/@type", d));
+		assertEquals("Character", xpath.evaluate("//OCD/AD[@id='rCharacter']/@type", d));
+		assertEquals("Short", xpath.evaluate("//OCD/AD[@id='rShort']/@type", d));
+		assertEquals("Integer", xpath.evaluate("//OCD/AD[@id='rInt']/@type", d));
+		assertEquals("Long", xpath.evaluate("//OCD/AD[@id='rLong']/@type", d));
+		assertEquals("Float", xpath.evaluate("//OCD/AD[@id='rFloat']/@type", d));
+		assertEquals("Double", xpath.evaluate("//OCD/AD[@id='rDouble']/@type", d));
+
+		// Primitive Arrays
+		assertEquals("Boolean", xpath.evaluate("//OCD/AD[@id='rpaBoolean']/@type", d));
+		assertEquals("Byte", xpath.evaluate("//OCD/AD[@id='rpaByte']/@type", d));
+		assertEquals("Character", xpath.evaluate("//OCD/AD[@id='rpaCharacter']/@type", d));
+		assertEquals("Short", xpath.evaluate("//OCD/AD[@id='rpaShort']/@type", d));
+		assertEquals("Integer", xpath.evaluate("//OCD/AD[@id='rpaInt']/@type", d));
+		assertEquals("Long", xpath.evaluate("//OCD/AD[@id='rpaLong']/@type", d));
+		assertEquals("Float", xpath.evaluate("//OCD/AD[@id='rpaFloat']/@type", d));
+		assertEquals("Double", xpath.evaluate("//OCD/AD[@id='rpaDouble']/@type", d));
+
+		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='rpaBoolean']/@cardinality", d));
+		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='rpaByte']/@cardinality", d));
+		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='rpaCharacter']/@cardinality", d));
+		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='rpaShort']/@cardinality", d));
+		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='rpaInt']/@cardinality", d));
+		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='rpaLong']/@cardinality", d));
+		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='rpaFloat']/@cardinality", d));
+		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='rpaDouble']/@cardinality", d));
+
+		// Wrapper + Object arrays
+		assertEquals("Boolean", xpath.evaluate("//OCD/AD[@id='raBoolean']/@type", d));
+		assertEquals("Byte", xpath.evaluate("//OCD/AD[@id='raByte']/@type", d));
+		assertEquals("Character", xpath.evaluate("//OCD/AD[@id='raCharacter']/@type", d));
+		assertEquals("Short", xpath.evaluate("//OCD/AD[@id='raShort']/@type", d));
+		assertEquals("Integer", xpath.evaluate("//OCD/AD[@id='raInt']/@type", d));
+		assertEquals("Long", xpath.evaluate("//OCD/AD[@id='raLong']/@type", d));
+		assertEquals("Float", xpath.evaluate("//OCD/AD[@id='raFloat']/@type", d));
+		assertEquals("Double", xpath.evaluate("//OCD/AD[@id='raDouble']/@type", d));
+		assertEquals("String", xpath.evaluate("//OCD/AD[@id='raString']/@type", d));
+		assertEquals("String", xpath.evaluate("//OCD/AD[@id='raURI']/@type", d));
+
+		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='raBoolean']/@cardinality", d));
+		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='raByte']/@cardinality", d));
+		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='raCharacter']/@cardinality", d));
+		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='raShort']/@cardinality", d));
+		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='raInt']/@cardinality", d));
+		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='raLong']/@cardinality", d));
+		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='raFloat']/@cardinality", d));
+		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='raDouble']/@cardinality", d));
+		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='raString']/@cardinality", d));
+		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='raURI']/@cardinality", d));
+
+		// Wrapper + Object collections
+		assertEquals("Boolean", xpath.evaluate("//OCD/AD[@id='rBooleans']/@type", d));
+		assertEquals("Byte", xpath.evaluate("//OCD/AD[@id='rBytes']/@type", d));
+		assertEquals("Character", xpath.evaluate("//OCD/AD[@id='rCharacter']/@type", d));
+		assertEquals("Short", xpath.evaluate("//OCD/AD[@id='rShorts']/@type", d));
+		assertEquals("Integer", xpath.evaluate("//OCD/AD[@id='rInts']/@type", d));
+		assertEquals("Long", xpath.evaluate("//OCD/AD[@id='rLongs']/@type", d));
+		assertEquals("Float", xpath.evaluate("//OCD/AD[@id='rFloats']/@type", d));
+		assertEquals("Double", xpath.evaluate("//OCD/AD[@id='rDoubles']/@type", d));
+		assertEquals("String", xpath.evaluate("//OCD/AD[@id='rStrings']/@type", d));
+		assertEquals("String", xpath.evaluate("//OCD/AD[@id='rURIs']/@type", d));
+
+		assertEquals("-2147483648", xpath.evaluate("//OCD/AD[@id='rBooleans']/@cardinality", d));
+		assertEquals("-2147483648", xpath.evaluate("//OCD/AD[@id='rBytes']/@cardinality", d));
+		assertEquals("-2147483648", xpath.evaluate("//OCD/AD[@id='rCharacters']/@cardinality", d));
+		assertEquals("-2147483648", xpath.evaluate("//OCD/AD[@id='rShorts']/@cardinality", d));
+		assertEquals("-2147483648", xpath.evaluate("//OCD/AD[@id='rInts']/@cardinality", d));
+		assertEquals("-2147483648", xpath.evaluate("//OCD/AD[@id='rLongs']/@cardinality", d));
+		assertEquals("-2147483648", xpath.evaluate("//OCD/AD[@id='rFloats']/@cardinality", d));
+		assertEquals("-2147483648", xpath.evaluate("//OCD/AD[@id='rDoubles']/@cardinality", d));
+		assertEquals("-2147483648", xpath.evaluate("//OCD/AD[@id='rStrings']/@cardinality", d));
+		assertEquals("-2147483648", xpath.evaluate("//OCD/AD[@id='rURIs']/@cardinality", d));
+	}
+
+	/**
+	 * Test simple
+	 * 
+	 * @author aqute
+	 */
+	@Meta.OCD(description = "simple", name = "TestSimple")
+	public static interface TestSimple {
+		@Meta.AD
+		String simple();
+
+		String[] notSoSimple();
+
+		Collection<String> stringCollection();
+
+		@Meta.AD(deflt = "true")
+		boolean enabled();
+	}
+
+	public static void testSimple() throws Exception {
+		Builder b = new Builder();
+		b.addClasspath(new File("bin"));
+		b.setProperty("Export-Package", "test.metatype");
+		b.setProperty("-metatype", "*");
+		b.build();
+		Resource r = b.getJar().getResource("OSGI-INF/metatype/test.metatype.MetatypeTest$TestSimple.xml");
+		assertEquals(0, b.getErrors().size());
+		assertEquals(0, b.getWarnings().size());
+		System.err.println(b.getJar().getResources().keySet());
+		assertNotNull(r);
+		IO.copy(r.openInputStream(), System.err);
+
+		Document d = db.parse(r.openInputStream());
+
+		assertEquals("TestSimple", xpath.evaluate("//OCD/@name", d));
+		assertEquals("simple", xpath.evaluate("//OCD/@description", d));
+		assertEquals("test.metatype.MetatypeTest$TestSimple", xpath.evaluate("//OCD/@id", d));
+		assertEquals("test.metatype.MetatypeTest$TestSimple", xpath.evaluate("//Designate/@pid", d));
+		assertEquals("test.metatype.MetatypeTest$TestSimple", xpath.evaluate("//Object/@ocdref", d));
+		assertEquals("simple", xpath.evaluate("//OCD/AD[@id='simple']/@id", d));
+		assertEquals("Simple", xpath.evaluate("//OCD/AD[@id='simple']/@name", d));
+		assertEquals("String", xpath.evaluate("//OCD/AD[@id='simple']/@type", d));
+		assertEquals("true", xpath.evaluate("//OCD/AD[@id='notSoSimple']/@required", d));
+		/**
+		 * https://github.com/bndtools/bnd/issues/281
+		 * 
+		 * Using the Bnd annotations library (1.52.3), the generated metatype
+		 * file will have required='false' for all fields annotated with
+		 * @Meta.AD(). When this annotation is omitted, or when the required
+		 * property is explicitly set, the field is correctly marked as
+		 * required. Taking a glance at the code, the bug appears to be due to
+		 * aQute.bnd.osgi.Annotation using
+		 * aQute.bnd.annotation.metatype.Configurable internally for bridging
+		 * Bnd-annotations to Java-annotations. This configurable only obtains
+		 * the values from the Bnd-annotation, omitting the defaults defined in
+		 * the Java annotation. The workaround is to explicitly mention the
+		 * required property on each field annotated with @Meta.AD.
+		 */
+		assertEquals("true", xpath.evaluate("//OCD/AD[@id='simple']/@required", d));
+		assertEquals(Integer.MAX_VALUE + "", xpath.evaluate("//OCD/AD[@id='notSoSimple']/@cardinality", d));
+
+	}
+
+	/**
+	 * https://github.com/bndtools/bnd/issues/316 Example Configuration:
+	 * 
+	 * <pre>
+	 *  @Meta.AD(required = false, type = Type.Boolean, deflt = "false")
+	 *  boolean enabled();
+	 * It appears that in the configurable class that this logic
+	 * 
+	 * if (resultType == boolean.class || resultType == Boolean.class) {
+	 *         if ( actualType == boolean.class || actualType ==   Boolean.class)
+	 *             return o;
+	 * 
+	 *         if (Number.class.isAssignableFrom(actualType)) {
+	 *             double b = ((Number) o).doubleValue();
+	 *             if (b == 0)
+	 *                 return false;
+	 *             else
+	 *                 return true;
+	 *         }
+	 *         return true;
+	 * </pre>
+	 * 
+	 * Does not perform as expected. The deflt value from the configuration
+	 * interface will always be a string, and the value is never parsed,
+	 * therefore the third if statement is basically unreachable for a default
+	 * value. Additionally the default behavior of returning true is unexpected
+	 * because default values for booleans is false, configuration admin would
+	 * use false for anything NOT equal, ignore case "true", so why would this
+	 * be true, and how could that assumption even be made when, at least in the
+	 * aforementioned case of the default value, the incoming value isn't
+	 * processed(parsed, or in someway checked for actual content). Note that
+	 * per documentation available an number value was tried for the deflt, ie
+	 * "0", but again the value isn't processed so this had no effect.
+	 */
+	static interface DefaultBoolean {
+		@Meta.AD(deflt = "true", required = false)
+		boolean istrue();
+
+		@Meta.AD(deflt = "FALSE", required = false)
+		boolean isfalse();
+
+		@Meta.AD(required = false)
+		boolean isAlsoFalse();
+	}
+
+	public static void testConfigurable() {
+		Map<String,Object> ht = new Hashtable<String,Object>();
+		DefaultBoolean db = Configurable.createConfigurable(DefaultBoolean.class, ht);
+		assertTrue(db.istrue());
+		assertFalse(db.isfalse());
+		assertFalse(db.isAlsoFalse());
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/packageinfo/Dummy.java b/biz.aQute.bndlib.tests/src/test/packageinfo/Dummy.java
new file mode 100644
index 0000000..0d09cc6
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/packageinfo/Dummy.java
@@ -0,0 +1,3 @@
+package test.packageinfo;
+
+public class Dummy {}
diff --git a/biz.aQute.bndlib/src/test/packageinfo/packageinfo b/biz.aQute.bndlib.tests/src/test/packageinfo/packageinfo
similarity index 100%
rename from biz.aQute.bndlib/src/test/packageinfo/packageinfo
rename to biz.aQute.bndlib.tests/src/test/packageinfo/packageinfo
diff --git a/biz.aQute.bndlib.tests/src/test/packageinfo/ref/DummyRef.java b/biz.aQute.bndlib.tests/src/test/packageinfo/ref/DummyRef.java
new file mode 100644
index 0000000..f15f82d
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/packageinfo/ref/DummyRef.java
@@ -0,0 +1,7 @@
+package test.packageinfo.ref;
+
+import test.packageinfo.*;
+
+public class DummyRef {
+	Dummy	dummy	= new Dummy();
+}
diff --git a/biz.aQute.bndlib.tests/src/test/privateimport/PrivateImport.java b/biz.aQute.bndlib.tests/src/test/privateimport/PrivateImport.java
new file mode 100644
index 0000000..e982f04
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/privateimport/PrivateImport.java
@@ -0,0 +1,40 @@
+package test.privateimport;
+
+import java.io.*;
+
+import org.osgi.framework.*;
+import org.osgi.service.cm.*;
+
+public class PrivateImport implements ConfigurationAdmin {
+
+	@Override
+	public Configuration createFactoryConfiguration(String factoryPid) throws IOException {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public Configuration createFactoryConfiguration(String factoryPid, String location) throws IOException {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public Configuration getConfiguration(String pid) throws IOException {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public Configuration getConfiguration(String pid, String location) throws IOException {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public Configuration[] listConfigurations(String filter) throws IOException, InvalidSyntaxException {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/properties/PropertiesTest.java b/biz.aQute.bndlib.tests/src/test/properties/PropertiesTest.java
new file mode 100644
index 0000000..70e2532
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/properties/PropertiesTest.java
@@ -0,0 +1,53 @@
+package test.properties;
+
+import java.io.*;
+import java.util.*;
+
+import junit.framework.*;
+import aQute.bnd.build.model.*;
+import aQute.bnd.properties.*;
+import aQute.lib.io.*;
+
+public class PropertiesTest extends TestCase {
+
+	public static void testBndEditModel() throws Exception {
+		
+		Document doc = new Document("Bundle-Description:\tTest\n" +
+									"Bundle-SymbolicName:\ttest.properties\n" +
+									"Private-Package:\tpp1\n");
+		
+		
+		BndEditModel model = new BndEditModel();
+
+		model.loadFrom(doc);
+		
+		model.addPrivatePackage("pp2");
+		model.addPrivatePackage("pp3");
+		
+		model.setBundleVersion("1.0.0");
+		model.setBundleVersion("1.1.0");
+		
+		model.saveChangesTo(doc);
+		
+		File file = File.createTempFile("test", ".properties");
+		IO.store(doc.get(), file, "ISO-8859-1");
+
+		model = new BndEditModel();
+		model.loadFrom(file);
+		
+		Properties props = new Properties();
+		props.load(new FileInputStream(file));
+		
+		
+		assertEquals(props.getProperty("Bundle-Version"), model.getBundleVersionString());
+	
+		List<String> privatePackages = model.getPrivatePackages();
+		
+		String s = props.getProperty("Private-Package");
+		String[] pkgs = s.split("\\,");
+		for (String pkg : pkgs) {
+			assertTrue(privatePackages.remove(pkg));
+		}
+		assertEquals(0, privatePackages.size());
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/refer/RefersToEventAdmin.java b/biz.aQute.bndlib.tests/src/test/refer/RefersToEventAdmin.java
new file mode 100644
index 0000000..9645f95
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/refer/RefersToEventAdmin.java
@@ -0,0 +1,7 @@
+package test.refer;
+
+import org.osgi.service.event.*;
+
+public class RefersToEventAdmin {
+	EventAdmin	acmin;
+}
diff --git a/biz.aQute.bndlib.tests/src/test/refer/RefersToHttp.java b/biz.aQute.bndlib.tests/src/test/refer/RefersToHttp.java
new file mode 100644
index 0000000..07b357c
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/refer/RefersToHttp.java
@@ -0,0 +1,7 @@
+package test.refer;
+
+import org.osgi.service.http.*;
+
+public class RefersToHttp {
+	HttpService	acmin;
+}
diff --git a/biz.aQute.bndlib.tests/src/test/refer/RefersToMeasurement.java b/biz.aQute.bndlib.tests/src/test/refer/RefersToMeasurement.java
new file mode 100644
index 0000000..2fac205
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/refer/RefersToMeasurement.java
@@ -0,0 +1,7 @@
+package test.refer;
+
+import org.osgi.util.measurement.*;
+
+public class RefersToMeasurement {
+	Measurement	acmin;
+}
diff --git a/biz.aQute.bndlib.tests/src/test/referApi/APIReferrer.java b/biz.aQute.bndlib.tests/src/test/referApi/APIReferrer.java
new file mode 100644
index 0000000..80f60ae
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/referApi/APIReferrer.java
@@ -0,0 +1,48 @@
+package test.referApi;
+
+import java.util.concurrent.atomic.*;
+
+import org.osgi.service.blueprint.reflect.*;
+import org.osgi.service.cm.*;
+import org.osgi.service.device.*;
+import org.osgi.service.event.*;
+import org.osgi.service.http.*;
+import org.osgi.service.log.*;
+import org.osgi.service.wireadmin.*;
+
+// 000: Export test.referApi,  has private references [org.osgi.service.http, org.osgi.service.component, org.osgi.service.condpermadmin, org.osgi.service.wireadmin, org.osgi.service.event, org.osgi.service.log, org.osgi.service.device], 
+
+ at SuppressWarnings("unused")
+public abstract class APIReferrer extends AtomicReference<Device> implements   EventAdmin {
+	// refers to org.osgi.service.device and org.osgi.service.event
+
+	private static final long	serialVersionUID	= 1L;
+	
+	static Configuration config;
+	
+	
+	public static HttpService publicReference() { return null; }		// org.osgi.service.http
+	protected static Wire protectedReference() { return null; }        // org.osgi.service.wireadmin
+	
+	private static Configuration privateReference() { return null; }
+	static Configuration packagePrivateReference() { return null; }
+    
+    public static void publicReference( org.osgi.service.component.ComponentConstants ad) {} // org.osgi.service.component
+    protected static void protectedReference( BeanArgument ad) {}  // org.osgi.service.blueprint.reflect
+    
+    static void packagePrivateReference( Configuration ad) {}
+    private static void privateReference( Configuration ad) {}
+	
+    public static void publicFoo( Class<org.osgi.service.condpermadmin.BundleLocationCondition> foo) {} // org.osgi.service.condpermadmin
+    protected static void protectedFoo( Class<LogService> foo) {} // org.osgi.service.log
+    
+	private static void privateFoo( Class<Configuration> foo) {}
+	static void packagePrivateFoo( Class<Configuration> foo) {}
+    
+    public static void foo() {
+    	Configuration foo;
+    }
+    private static void foop() {
+    	Configuration foo;
+    }
+}
diff --git a/biz.aQute.bndlib/src/test/resourcesonly/include.mf b/biz.aQute.bndlib.tests/src/test/resourcesonly/include.mf
similarity index 100%
rename from biz.aQute.bndlib/src/test/resourcesonly/include.mf
rename to biz.aQute.bndlib.tests/src/test/resourcesonly/include.mf
diff --git a/biz.aQute.bndlib/src/test/resourcesonly/simple.mf b/biz.aQute.bndlib.tests/src/test/resourcesonly/simple.mf
similarity index 100%
rename from biz.aQute.bndlib/src/test/resourcesonly/simple.mf
rename to biz.aQute.bndlib.tests/src/test/resourcesonly/simple.mf
diff --git a/biz.aQute.bndlib/src/test/resourcesonly/top.mf b/biz.aQute.bndlib.tests/src/test/resourcesonly/top.mf
similarity index 100%
rename from biz.aQute.bndlib/src/test/resourcesonly/top.mf
rename to biz.aQute.bndlib.tests/src/test/resourcesonly/top.mf
diff --git a/biz.aQute.bndlib/src/test/resourcesonly/variables.mf b/biz.aQute.bndlib.tests/src/test/resourcesonly/variables.mf
similarity index 100%
rename from biz.aQute.bndlib/src/test/resourcesonly/variables.mf
rename to biz.aQute.bndlib.tests/src/test/resourcesonly/variables.mf
diff --git a/biz.aQute.bndlib.tests/src/test/signatures/Z.java b/biz.aQute.bndlib.tests/src/test/signatures/Z.java
new file mode 100644
index 0000000..1c7ec67
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/signatures/Z.java
@@ -0,0 +1,77 @@
+package test.signatures;
+
+import java.io.*;
+import java.util.*;
+
+class X<A> {}
+
+interface Y<B> {}
+
+public class Z<C> extends X<String> implements Y<Integer> {
+
+	public class V<D> {
+		public <E> void fooLCO(@SuppressWarnings("unused") E e, @SuppressWarnings("unused") C c, @SuppressWarnings("unused") D d) {}
+	}
+
+	public abstract class U extends Z<String> implements Cloneable, Serializable {
+		private static final long	serialVersionUID	= 1L;
+	}
+
+	// Constructors
+	public Z() {}
+
+	public Z(@SuppressWarnings("unused") C c) {}
+
+	// Fields
+	public X<Y<C>>				field;
+	public Z<Long>.V<Integer>	referenceToNestedClass;
+	public V<C>					vc	= new V<C>();
+
+	// Methods
+	public <T> void method() {}
+
+	// Test all possible declarations
+	public <E> void foo(@SuppressWarnings("unused") E e) {}
+
+	public <E extends InputStream & Cloneable> void fooCI(@SuppressWarnings("unused") E e) {}
+
+	public <E extends InputStream & Cloneable & Serializable> void fooCII(@SuppressWarnings("unused") E e) {}
+
+	public <E extends Serializable & Cloneable> void fooII(@SuppressWarnings("unused") E e) {}
+
+	public <E extends Cloneable> void fooI(@SuppressWarnings("unused") E e) {}
+
+	public <E extends InputStream> void fooC(@SuppressWarnings("unused") E e) {}
+
+	public <E extends C> void fooP(@SuppressWarnings("unused") E e) {}
+
+	public <E, F> void foo(@SuppressWarnings("unused") E e, @SuppressWarnings("unused") F f) {}
+
+	// test with variable in signature
+	public <E> void fooLC(@SuppressWarnings("unused") E e, @SuppressWarnings("unused") C f) {}
+
+	// test wildcards
+	public Collection< ? >							wildcard_001;
+	public Collection< ? extends Cloneable>			wildcard_002;
+	public Collection< ? super Cloneable>			wildcard_003;
+	public Collection< ? extends C>					wildcard_004;
+	public Collection< ? super C>					wildcard_005;
+	public Collection< ? extends Z<C>.V<Integer>>	wildcard_006;
+	public Collection< ? super Z<C>.V<Integer>>		wildcard_007;
+
+	// test compatibility
+	public static <E extends Cloneable> Collection<E> compatibility_001() {
+		return null;
+	}
+
+	public static <F extends Cloneable> Collection<F> compatibility_002() {
+		return null;
+	}
+
+	public static <F extends InputStream> Collection<F> compatibility_003() {
+		return null;
+	}
+
+	public C[]	typevarArray;
+
+}
diff --git a/biz.aQute.bndlib/src/test/signing/.cvsignore b/biz.aQute.bndlib.tests/src/test/signing/.cvsignore
similarity index 100%
rename from biz.aQute.bndlib/src/test/signing/.cvsignore
rename to biz.aQute.bndlib.tests/src/test/signing/.cvsignore
diff --git a/biz.aQute.bndlib/src/test/signing/META-INF/MANIFEST.MF b/biz.aQute.bndlib.tests/src/test/signing/META-INF/MANIFEST.MF
similarity index 100%
rename from biz.aQute.bndlib/src/test/signing/META-INF/MANIFEST.MF
rename to biz.aQute.bndlib.tests/src/test/signing/META-INF/MANIFEST.MF
diff --git a/biz.aQute.bndlib/src/test/signing/META-INF/test.RSA b/biz.aQute.bndlib.tests/src/test/signing/META-INF/test.RSA
similarity index 100%
rename from biz.aQute.bndlib/src/test/signing/META-INF/test.RSA
rename to biz.aQute.bndlib.tests/src/test/signing/META-INF/test.RSA
diff --git a/biz.aQute.bndlib/src/test/signing/META-INF/test.SF b/biz.aQute.bndlib.tests/src/test/signing/META-INF/test.SF
similarity index 100%
rename from biz.aQute.bndlib/src/test/signing/META-INF/test.SF
rename to biz.aQute.bndlib.tests/src/test/signing/META-INF/test.SF
diff --git a/biz.aQute.bndlib/src/test/signing/keystore b/biz.aQute.bndlib.tests/src/test/signing/keystore
similarity index 100%
rename from biz.aQute.bndlib/src/test/signing/keystore
rename to biz.aQute.bndlib.tests/src/test/signing/keystore
diff --git a/biz.aQute.bndlib/src/test/simple.mf b/biz.aQute.bndlib.tests/src/test/simple.mf
similarity index 100%
rename from biz.aQute.bndlib/src/test/simple.mf
rename to biz.aQute.bndlib.tests/src/test/simple.mf
diff --git a/biz.aQute.bndlib/src/test/split/A b/biz.aQute.bndlib.tests/src/test/split/A
similarity index 100%
copy from biz.aQute.bndlib/src/test/split/A
copy to biz.aQute.bndlib.tests/src/test/split/A
diff --git a/biz.aQute.bndlib/src/test/split/B b/biz.aQute.bndlib.tests/src/test/split/B
similarity index 100%
rename from biz.aQute.bndlib/src/test/split/B
rename to biz.aQute.bndlib.tests/src/test/split/B
diff --git a/biz.aQute.bndlib/src/test/split/first b/biz.aQute.bndlib.tests/src/test/split/first
similarity index 100%
rename from biz.aQute.bndlib/src/test/split/first
rename to biz.aQute.bndlib.tests/src/test/split/first
diff --git a/biz.aQute.bndlib/src/test/split/last b/biz.aQute.bndlib.tests/src/test/split/last
similarity index 100%
rename from biz.aQute.bndlib/src/test/split/last
rename to biz.aQute.bndlib.tests/src/test/split/last
diff --git a/biz.aQute.bndlib/src/test/split/split-a.bnd b/biz.aQute.bndlib.tests/src/test/split/split-a.bnd
similarity index 100%
rename from biz.aQute.bndlib/src/test/split/split-a.bnd
rename to biz.aQute.bndlib.tests/src/test/split/split-a.bnd
diff --git a/biz.aQute.bndlib/src/test/split/split-b.bnd b/biz.aQute.bndlib.tests/src/test/split/split-b.bnd
similarity index 100%
rename from biz.aQute.bndlib/src/test/split/split-b.bnd
rename to biz.aQute.bndlib.tests/src/test/split/split-b.bnd
diff --git a/biz.aQute.bndlib/src/test/spring-test1.spring b/biz.aQute.bndlib.tests/src/test/spring-test1.spring
similarity index 100%
rename from biz.aQute.bndlib/src/test/spring-test1.spring
rename to biz.aQute.bndlib.tests/src/test/spring-test1.spring
diff --git a/biz.aQute.bndlib/src/test/top.mf b/biz.aQute.bndlib.tests/src/test/top.mf
similarity index 100%
rename from biz.aQute.bndlib/src/test/top.mf
rename to biz.aQute.bndlib.tests/src/test/top.mf
diff --git a/biz.aQute.bndlib.tests/src/test/top/Top.java b/biz.aQute.bndlib.tests/src/test/top/Top.java
new file mode 100644
index 0000000..3e2a026
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/top/Top.java
@@ -0,0 +1,3 @@
+package test.top;
+
+public class Top {}
diff --git a/biz.aQute.bndlib/src/test/top/middle/Middle.java b/biz.aQute.bndlib.tests/src/test/top/middle/Middle.java
similarity index 100%
rename from biz.aQute.bndlib/src/test/top/middle/Middle.java
rename to biz.aQute.bndlib.tests/src/test/top/middle/Middle.java
diff --git a/biz.aQute.bndlib/src/test/top/middle/bottom/Bottom.java b/biz.aQute.bndlib.tests/src/test/top/middle/bottom/Bottom.java
similarity index 100%
rename from biz.aQute.bndlib/src/test/top/middle/bottom/Bottom.java
rename to biz.aQute.bndlib.tests/src/test/top/middle/bottom/Bottom.java
diff --git a/biz.aQute.bndlib.tests/src/test/uses/annotation/UsesAnnotation.java b/biz.aQute.bndlib.tests/src/test/uses/annotation/UsesAnnotation.java
new file mode 100644
index 0000000..af4c296
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/uses/annotation/UsesAnnotation.java
@@ -0,0 +1,14 @@
+package test.uses.annotation;
+
+import javax.security.auth.Subject;
+
+import test.uses.annotation.annotation.Annotation;
+
+ at Annotation
+public class UsesAnnotation {
+	
+	private UsesAnnotation(Subject subject) {
+		
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/uses/annotation/annotation/Annotation.java b/biz.aQute.bndlib.tests/src/test/uses/annotation/annotation/Annotation.java
new file mode 100644
index 0000000..85e498e
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/uses/annotation/annotation/Annotation.java
@@ -0,0 +1,9 @@
+package test.uses.annotation.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface Annotation {
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/uses/constructor/UsesConstructor.java b/biz.aQute.bndlib.tests/src/test/uses/constructor/UsesConstructor.java
new file mode 100644
index 0000000..c6b9f5e
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/uses/constructor/UsesConstructor.java
@@ -0,0 +1,17 @@
+package test.uses.constructor;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+
+public class UsesConstructor {
+	
+	public UsesConstructor(CallbackHandler ch) {
+		Subject subject = new Subject();
+	}
+	
+	@SuppressWarnings("unused")
+	private UsesConstructor(Subject subject) {
+		
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/uses/exception/UsesException.java b/biz.aQute.bndlib.tests/src/test/uses/exception/UsesException.java
new file mode 100644
index 0000000..ba4a86a
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/uses/exception/UsesException.java
@@ -0,0 +1,11 @@
+package test.uses.exception;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+public class UsesException {
+	public static void foo() throws UnsupportedCallbackException {
+		Subject subject = new Subject();
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/uses/extend/UsesExtend.java b/biz.aQute.bndlib.tests/src/test/uses/extend/UsesExtend.java
new file mode 100644
index 0000000..d2dd8b2
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/uses/extend/UsesExtend.java
@@ -0,0 +1,15 @@
+package test.uses.extend;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.NameCallback;
+
+ at SuppressWarnings({"serial","unused"})
+public class UsesExtend extends NameCallback {
+
+	private Subject subject;
+	
+	public UsesExtend(String arg0) {
+		super(arg0);
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/uses/field/UsesField.java b/biz.aQute.bndlib.tests/src/test/uses/field/UsesField.java
new file mode 100644
index 0000000..f204361
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/uses/field/UsesField.java
@@ -0,0 +1,12 @@
+package test.uses.field;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+
+ at SuppressWarnings("unused")
+public class UsesField {
+	
+	public CallbackHandler config;
+	private Subject subject;
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/uses/generic/extend/UsesGenericExtend.java b/biz.aQute.bndlib.tests/src/test/uses/generic/extend/UsesGenericExtend.java
new file mode 100644
index 0000000..e390889
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/uses/generic/extend/UsesGenericExtend.java
@@ -0,0 +1,15 @@
+package test.uses.generic.extend;
+
+import java.util.ArrayList;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+
+ at SuppressWarnings("serial")
+public class UsesGenericExtend extends ArrayList<Callback> {
+
+	@SuppressWarnings("unused")
+	private Subject subject;
+	
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/uses/generic/implement/Marker.java b/biz.aQute.bndlib.tests/src/test/uses/generic/implement/Marker.java
new file mode 100644
index 0000000..6bd0708
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/uses/generic/implement/Marker.java
@@ -0,0 +1,5 @@
+package test.uses.generic.implement;
+
+public interface Marker<T> {
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/uses/generic/implement/UsesGenericImplement.java b/biz.aQute.bndlib.tests/src/test/uses/generic/implement/UsesGenericImplement.java
new file mode 100644
index 0000000..a6d3049
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/uses/generic/implement/UsesGenericImplement.java
@@ -0,0 +1,12 @@
+package test.uses.generic.implement;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+
+public class UsesGenericImplement implements Marker<Callback> {
+
+	@SuppressWarnings("unused")
+	private Subject subject;
+	
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/uses/generic/param/UsesGenericParam.java b/biz.aQute.bndlib.tests/src/test/uses/generic/param/UsesGenericParam.java
new file mode 100644
index 0000000..2bc13aa
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/uses/generic/param/UsesGenericParam.java
@@ -0,0 +1,15 @@
+package test.uses.generic.param;
+
+import java.util.List;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+
+public class UsesGenericParam {
+	
+	public void foo(List<Callback> config) {
+		Subject subject = new Subject();
+	}
+
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/uses/generic/rvalue/UsesGenericRValue.java b/biz.aQute.bndlib.tests/src/test/uses/generic/rvalue/UsesGenericRValue.java
new file mode 100644
index 0000000..a2a9c60
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/uses/generic/rvalue/UsesGenericRValue.java
@@ -0,0 +1,20 @@
+package test.uses.generic.rvalue;
+
+import java.util.List;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+
+public class UsesGenericRValue {
+	public static List<Callback> foo(){
+		Subject subject = new Subject();
+		return null;
+	}
+	
+	@SuppressWarnings("unused")
+	private static List<Subject> bar() {
+		return null;
+	}
+
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/uses/implement/UsesImplement.java b/biz.aQute.bndlib.tests/src/test/uses/implement/UsesImplement.java
new file mode 100644
index 0000000..31d7f8d
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/uses/implement/UsesImplement.java
@@ -0,0 +1,9 @@
+package test.uses.implement;
+
+
+import javax.security.auth.callback.Callback;
+
+public class UsesImplement implements Callback {
+
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/uses/multi/UsesMulti.java b/biz.aQute.bndlib.tests/src/test/uses/multi/UsesMulti.java
new file mode 100644
index 0000000..4b0e16f
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/uses/multi/UsesMulti.java
@@ -0,0 +1,16 @@
+package test.uses.multi;
+
+import javax.security.auth.callback.*;
+import javax.sql.*;
+
+public class UsesMulti {
+	
+	public static Callback foo(){
+		return null;
+	}
+	
+	public static DataSource dataSource() {
+		return null;
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/uses/order/UsesOrderingTest.java b/biz.aQute.bndlib.tests/src/test/uses/order/UsesOrderingTest.java
new file mode 100644
index 0000000..8c6902f
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/uses/order/UsesOrderingTest.java
@@ -0,0 +1,56 @@
+package test.uses.order;
+
+import java.io.*;
+
+import junit.framework.*;
+import aQute.bnd.differ.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.diff.*;
+
+public class UsesOrderingTest extends TestCase {
+
+	static DiffPluginImpl	differ	= new DiffPluginImpl();
+
+	public static void testOrdering() throws Exception {
+		Builder builder = new Builder();
+		builder.addClasspath(new File("bin"));
+		builder.setProperty(Constants.EXPORT_PACKAGE, "test.diff;uses:=\"d,c,a,b\"");
+		Jar a = builder.build();
+
+		String exa = (String) a.getManifest().getMainAttributes().getValue(Constants.EXPORT_PACKAGE);
+		
+		builder = new Builder();
+		builder.addClasspath(new File("bin"));
+		builder.setProperty(Constants.EXPORT_PACKAGE, "test.diff;uses:=\"d,b,a,c\"");
+		Jar b = builder.build();
+
+		String exb = (String) b.getManifest().getMainAttributes().getValue(Constants.EXPORT_PACKAGE);
+
+		Tree newer = differ.tree(b);
+		Tree older = differ.tree(a);
+
+		Diff diff = newer.diff(older);
+
+		show(diff, 0);
+		
+		assertEquals(Delta.UNCHANGED, diff.getDelta());
+	}
+
+	static void show(Diff diff, int indent) {
+		// if (diff.getDelta() == Delta.UNCHANGED || diff.getDelta() ==
+		// Delta.IGNORED)
+		// return;
+
+		for (int i = 0; i < indent; i++)
+			System.err.print("   ");
+
+		System.err.println(diff.toString());
+
+		// if (diff.getDelta().isStructural())
+		// return;
+
+		for (Diff c : diff.getChildren()) {
+			show(c, indent + 1);
+		}
+	}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/uses/param/UsesParam.java b/biz.aQute.bndlib.tests/src/test/uses/param/UsesParam.java
new file mode 100644
index 0000000..1f82f97
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/uses/param/UsesParam.java
@@ -0,0 +1,17 @@
+package test.uses.param;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+
+public class UsesParam {
+	
+	public static void foo(Callback config) {
+		Subject subject = new Subject();
+	}
+	
+	@SuppressWarnings("unused")
+	private static void bar(Subject subject) {
+		
+	}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/uses/rvalue/UsesRValue.java b/biz.aQute.bndlib.tests/src/test/uses/rvalue/UsesRValue.java
new file mode 100644
index 0000000..d625f1c
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/uses/rvalue/UsesRValue.java
@@ -0,0 +1,18 @@
+package test.uses.rvalue;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+
+public class UsesRValue {
+	
+	public static Callback foo(){
+		Subject subject = new Subject();
+		return null;
+	}
+	
+	@SuppressWarnings("unused")
+	private static Subject bar() {
+		return null;
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/test/variables.mf b/biz.aQute.bndlib.tests/src/test/variables.mf
similarity index 100%
rename from biz.aQute.bndlib/src/test/variables.mf
rename to biz.aQute.bndlib.tests/src/test/variables.mf
diff --git a/biz.aQute.bndlib.tests/src/test/versionpolicy/api/EventAdmin.java b/biz.aQute.bndlib.tests/src/test/versionpolicy/api/EventAdmin.java
new file mode 100644
index 0000000..0c367d1
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/versionpolicy/api/EventAdmin.java
@@ -0,0 +1,8 @@
+package test.versionpolicy.api;
+
+import aQute.bnd.annotation.*;
+
+ at ProviderType
+public interface EventAdmin {
+	void post(Object o);
+}
diff --git a/biz.aQute.bndlib.tests/src/test/versionpolicy/api/EventHandler.java b/biz.aQute.bndlib.tests/src/test/versionpolicy/api/EventHandler.java
new file mode 100644
index 0000000..0ef6357
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/versionpolicy/api/EventHandler.java
@@ -0,0 +1,8 @@
+package test.versionpolicy.api;
+
+import aQute.bnd.annotation.*;
+
+ at ConsumerType
+public interface EventHandler {
+	void listen(Object o);
+}
diff --git a/biz.aQute.bndlib/src/test/versionpolicy/api/PrivateImpl.java b/biz.aQute.bndlib.tests/src/test/versionpolicy/api/PrivateImpl.java
similarity index 100%
rename from biz.aQute.bndlib/src/test/versionpolicy/api/PrivateImpl.java
rename to biz.aQute.bndlib.tests/src/test/versionpolicy/api/PrivateImpl.java
diff --git a/biz.aQute.bndlib.tests/src/test/versionpolicy/api/package-info.java b/biz.aQute.bndlib.tests/src/test/versionpolicy/api/package-info.java
new file mode 100644
index 0000000..8ab14f6
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/versionpolicy/api/package-info.java
@@ -0,0 +1,6 @@
+ at Version("1.2.0.${build}")
+ at Export(exclude = PrivateImpl.class, mandatory = "a=b")
+package test.versionpolicy.api;
+
+import aQute.bnd.annotation.*;
+
diff --git a/biz.aQute.bndlib.tests/src/test/versionpolicy/implemented/Implemented.java b/biz.aQute.bndlib.tests/src/test/versionpolicy/implemented/Implemented.java
new file mode 100644
index 0000000..e324c3d
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/versionpolicy/implemented/Implemented.java
@@ -0,0 +1,8 @@
+package test.versionpolicy.implemented;
+
+import test.versionpolicy.api.*;
+
+public class Implemented implements EventAdmin {
+	@Override
+	public void post(Object o) {}
+}
diff --git a/biz.aQute.bndlib.tests/src/test/versionpolicy/implmajor/MajorImplemented.java b/biz.aQute.bndlib.tests/src/test/versionpolicy/implmajor/MajorImplemented.java
new file mode 100644
index 0000000..99be0af
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/versionpolicy/implmajor/MajorImplemented.java
@@ -0,0 +1,10 @@
+package test.versionpolicy.implmajor;
+
+import test.versionpolicy.api.*;
+
+public class MajorImplemented implements EventHandler {
+
+	@Override
+	public void listen(Object o) {}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/versionpolicy/uses/EventHandlerImpl.java b/biz.aQute.bndlib.tests/src/test/versionpolicy/uses/EventHandlerImpl.java
new file mode 100644
index 0000000..ed06d5a
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/versionpolicy/uses/EventHandlerImpl.java
@@ -0,0 +1,10 @@
+package test.versionpolicy.uses;
+
+import test.versionpolicy.api.*;
+
+public class EventHandlerImpl implements EventHandler {
+
+	@Override
+	public void listen(Object o) {}
+
+}
diff --git a/biz.aQute.bndlib.tests/src/test/versionpolicy/uses/Uses.java b/biz.aQute.bndlib.tests/src/test/versionpolicy/uses/Uses.java
new file mode 100644
index 0000000..7d72847
--- /dev/null
+++ b/biz.aQute.bndlib.tests/src/test/versionpolicy/uses/Uses.java
@@ -0,0 +1,7 @@
+package test.versionpolicy.uses;
+
+import test.versionpolicy.api.*;
+
+public class Uses {
+	EventAdmin	admin;
+}
diff --git a/biz.aQute.bndlib.tests/test/a space/cnf/build.bnd b/biz.aQute.bndlib.tests/test/a space/cnf/build.bnd
new file mode 100644
index 0000000..6d92366
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/a space/cnf/build.bnd	
@@ -0,0 +1,7 @@
+dir: ${workspace}/../../../
+
+-pluginpath: ${dir}/biz.aQute.repository/generated/biz.aQute.repository.jar
+
+-plugin:\
+	aQute.lib.deployer.FileRepo; name=Bndtools Local; location=${workspace}/cnf/local,\
+	aQute.lib.deployer.FileRepo; name=Build;          location=${dir}/cnf/repo
diff --git a/biz.aQute.bndlib.tests/test/a space/cnf/ext/defaults.bnd b/biz.aQute.bndlib.tests/test/a space/cnf/ext/defaults.bnd
new file mode 100644
index 0000000..4593c14
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/a space/cnf/ext/defaults.bnd	
@@ -0,0 +1,29 @@
+# General Options
+project.dependson       = ${p-dependson;:}
+project.bootclasspath   = ${p-bootclasspath;:}
+project.buildpath       = ${p-buildpath;:}
+project.sourcepath      = ${p-sourcepath;:}
+project.allsourcepath   = ${p-allsourcepath;:}
+project.output          = ${p-output}
+project.testpath        = ${p-testpath;:}
+
+-verbose:     true
+project:      ${basedir}
+src:          src
+bin:          bin
+target-dir:   generated
+target:       ${project}/${target-dir}
+build:        ${workspace}/cnf
+p:            ${basename;${project}}
+project.name: ${p}
+
+# Java Compiler Options
+java:         java
+javac:        javac
+javac.source: 1.5
+javac.target: 1.5
+javac.debug:  on
+
+# Bnd Options
+-sources:       true
+-sourcepath:    ${project}/src
diff --git a/biz.aQute.bndlib.tests/test/a space/test/bnd.bnd b/biz.aQute.bndlib.tests/test/a space/test/bnd.bnd
new file mode 100644
index 0000000..189a8af
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/a space/test/bnd.bnd	
@@ -0,0 +1,8 @@
+Private-Package: test
+-buildpath: biz.aQute.bnd.annotation
+Service-Component: *
+-runfw: org.apache.felix.framework;version='[2.0.5,2.0.5]'
+-runee: JavaSE-1.7
+-runrequires: osgi.identity;filter:='(osgi.identity=test)'
+
+Bundle-Activator: test.TestActivator
\ No newline at end of file
diff --git a/biz.aQute.bndlib/test/eclipse/bnd.index b/biz.aQute.bndlib.tests/test/a space/test/src/test/placeholder
similarity index 100%
copy from biz.aQute.bndlib/test/eclipse/bnd.index
copy to biz.aQute.bndlib.tests/test/a space/test/src/test/placeholder
diff --git a/biz.aQute.bndlib.tests/test/beasymock.bar b/biz.aQute.bndlib.tests/test/beasymock.bar
new file mode 100755
index 0000000..a880863
Binary files /dev/null and b/biz.aQute.bndlib.tests/test/beasymock.bar differ
diff --git a/biz.aQute.bndlib/test/eclipse/bnd.index b/biz.aQute.bndlib.tests/test/eclipse/bnd.index
similarity index 100%
rename from biz.aQute.bndlib/test/eclipse/bnd.index
rename to biz.aQute.bndlib.tests/test/eclipse/bnd.index
diff --git a/biz.aQute.bndlib.tests/test/eclipse/plugins/beasymock.bar b/biz.aQute.bndlib.tests/test/eclipse/plugins/beasymock.bar
new file mode 100755
index 0000000..a880863
Binary files /dev/null and b/biz.aQute.bndlib.tests/test/eclipse/plugins/beasymock.bar differ
diff --git a/biz.aQute.bndlib/test/keystore b/biz.aQute.bndlib.tests/test/keystore
similarity index 100%
rename from biz.aQute.bndlib/test/keystore
rename to biz.aQute.bndlib.tests/test/keystore
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/activation/activation/1.0.2/activation-1.0.2.pom b/biz.aQute.bndlib.tests/test/maven-repo/activation/activation/1.0.2/activation-1.0.2.pom
new file mode 100644
index 0000000..cfe5fa8
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/activation/activation/1.0.2/activation-1.0.2.pom
@@ -0,0 +1,13 @@
+<project>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>activation</groupId>
+  <artifactId>activation</artifactId>
+  <version>1.0.2</version>
+
+  <distributionManagement>
+    <relocation>
+      <groupId>javax.activation</groupId>
+    </relocation>
+  </distributionManagement>
+
+</project>
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/activation/activation/1.0.2/activation-1.0.2.pom.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/activation/activation/1.0.2/activation-1.0.2.pom.sha1
new file mode 100644
index 0000000..23bbf8f
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/activation/activation/1.0.2/activation-1.0.2.pom.sha1
@@ -0,0 +1 @@
+9a26a44c6c174fb90ec04e1a29ecce1f1a3653d1  -
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.145/bndlib-0.0.145.jar.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.145/bndlib-0.0.145.jar.sha1
new file mode 100644
index 0000000..2ebdd24
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.145/bndlib-0.0.145.jar.sha1
@@ -0,0 +1 @@
+177e86b99566d318246109c99c7d2ea6bf2c3f7e
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.145/bndlib-0.0.145.pom b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.145/bndlib-0.0.145.pom
new file mode 100644
index 0000000..889e470
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.145/bndlib-0.0.145.pom
@@ -0,0 +1,22 @@
+<project xmlns='http://maven.apache.org/POM/4.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd'>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>biz.aQute</groupId>
+  <artifactId>bndlib</artifactId>
+  <version>0.0.145</version>
+  <description>
+    JAR Processing Library for creating and verifying OSGi manifest headers
+  </description>
+  <name>BND Library</name>
+  <url>http://www.aQute.biz/Code/Bnd</url>
+  <organization>
+    <name>aQute SARL</name>
+    <url>http://www.aQute.biz</url>
+  </organization>
+  <licenses>
+    <license>
+    <name>This material is licensed under the Apache Software License, Version 2.0</name>
+    <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+    <distribution>repo</distribution>
+    </license>
+  </licenses>
+</project>
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.145/bndlib-0.0.145.pom.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.145/bndlib-0.0.145.pom.sha1
new file mode 100644
index 0000000..13e757e
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.145/bndlib-0.0.145.pom.sha1
@@ -0,0 +1 @@
+fce5b3aa49d29a80d03f0c5f765cd2b333d51572
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.203/bndlib-0.0.203.pom b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.203/bndlib-0.0.203.pom
new file mode 100644
index 0000000..67d1516
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.203/bndlib-0.0.203.pom
@@ -0,0 +1,22 @@
+<project xmlns='http://maven.apache.org/POM/4.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd'>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>biz.aQute</groupId>
+  <artifactId>bndlib</artifactId>
+  <version>0.0.203</version>
+  <description>
+    JAR Processing Library for creating and verifying OSGi manifest headers
+  </description>
+  <name>BND Library</name>
+  <url>http://www.aQute.biz/Code/Bnd</url>
+  <organization>
+    <name>aQute SARL</name>
+    <url>http://www.aQute.biz</url>
+  </organization>
+  <licenses>
+    <license>
+    <name>This material is licensed under the Apache Software License, Version 2.0</name>
+    <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+    <distribution>repo</distribution>
+    </license>
+  </licenses>
+</project>
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.203/bndlib-0.0.203.pom.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.203/bndlib-0.0.203.pom.sha1
new file mode 100644
index 0000000..3652ebc
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.203/bndlib-0.0.203.pom.sha1
@@ -0,0 +1 @@
+2e72bda90f59eac265c9e9c03ffd947bfbe3ec38
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.227/bndlib-0.0.227.jar.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.227/bndlib-0.0.227.jar.sha1
new file mode 100644
index 0000000..6d83b4e
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.227/bndlib-0.0.227.jar.sha1
@@ -0,0 +1 @@
+b9cd43d30f74e2106e9fd8f9bd2de5d49146aaf4
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.227/bndlib-0.0.227.pom b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.227/bndlib-0.0.227.pom
new file mode 100644
index 0000000..82b6bbe
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.227/bndlib-0.0.227.pom
@@ -0,0 +1,22 @@
+<project xmlns='http://maven.apache.org/POM/4.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd'>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>biz.aQute</groupId>
+  <artifactId>bndlib</artifactId>
+  <version>0.0.227</version>
+  <description>
+    JAR Processing Library for creating and verifying OSGi manifest headers
+  </description>
+  <name>BND Library</name>
+  <url>http://www.aQute.biz/Code/Bnd</url>
+  <organization>
+    <name>aQute SARL</name>
+    <url>http://www.aQute.biz</url>
+  </organization>
+  <licenses>
+    <license>
+    <name>This material is licensed under the Apache Software License, Version 2.0</name>
+    <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+    <distribution>repo</distribution>
+    </license>
+  </licenses>
+</project>
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.227/bndlib-0.0.227.pom.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.227/bndlib-0.0.227.pom.sha1
new file mode 100644
index 0000000..74d6225
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.227/bndlib-0.0.227.pom.sha1
@@ -0,0 +1 @@
+20c199cd9e33c1015c741ae0d992be6c7ab45f9e
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.236/bndlib-0.0.236.jar.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.236/bndlib-0.0.236.jar.sha1
new file mode 100644
index 0000000..4a29f19
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.236/bndlib-0.0.236.jar.sha1
@@ -0,0 +1 @@
+c2e10267a70d21c3a574f14a97b56324a1adf467
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.236/bndlib-0.0.236.pom b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.236/bndlib-0.0.236.pom
new file mode 100644
index 0000000..f250d06
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.236/bndlib-0.0.236.pom
@@ -0,0 +1,22 @@
+<project xmlns='http://maven.apache.org/POM/4.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd'>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>biz.aQute</groupId>
+  <artifactId>bndlib</artifactId>
+  <version>0.0.236</version>
+  <description>
+    JAR Processing Library for creating and verifying OSGi manifest headers
+  </description>
+  <name>BND Library</name>
+  <url>http://www.aQute.biz/Code/Bnd</url>
+  <organization>
+    <name>aQute SARL</name>
+    <url>http://www.aQute.biz</url>
+  </organization>
+  <licenses>
+    <license>
+    <name>This material is licensed under the Apache Software License, Version 2.0</name>
+    <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+    <distribution>repo</distribution>
+    </license>
+  </licenses>
+</project>
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.238/bndlib-0.0.238.jar.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.238/bndlib-0.0.238.jar.sha1
new file mode 100644
index 0000000..e821f68
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.238/bndlib-0.0.238.jar.sha1
@@ -0,0 +1 @@
+ee837469c630f7f6f22fd64d61f88e1ef75a7820
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.238/bndlib-0.0.238.pom b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.238/bndlib-0.0.238.pom
new file mode 100644
index 0000000..ddd04b4
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.238/bndlib-0.0.238.pom
@@ -0,0 +1,22 @@
+<project xmlns='http://maven.apache.org/POM/4.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd'>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>biz.aQute</groupId>
+  <artifactId>bndlib</artifactId>
+  <version>0.0.238</version>
+  <description>
+    JAR Processing Library for creating and verifying OSGi manifest headers
+  </description>
+  <name>BND Library</name>
+  <url>http://www.aQute.biz/Code/Bnd</url>
+  <organization>
+    <name>aQute SARL</name>
+    <url>http://www.aQute.biz</url>
+  </organization>
+  <licenses>
+    <license>
+    <name>This material is licensed under the Apache Software License, Version 2.0</name>
+    <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+    <distribution>repo</distribution>
+    </license>
+  </licenses>
+</project>
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.238/bndlib-0.0.238.pom.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.238/bndlib-0.0.238.pom.sha1
new file mode 100644
index 0000000..2580948
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.238/bndlib-0.0.238.pom.sha1
@@ -0,0 +1 @@
+4f097e922de8118e76027352ca1521380f14a465
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.255/bndlib-0.0.255.jar.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.255/bndlib-0.0.255.jar.sha1
new file mode 100644
index 0000000..7f29bd3
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.255/bndlib-0.0.255.jar.sha1
@@ -0,0 +1 @@
+eae5fb9abb1801896bab29611d24a1b828966c89
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.255/bndlib-0.0.255.pom b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.255/bndlib-0.0.255.pom
new file mode 100644
index 0000000..e9e0cba
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.255/bndlib-0.0.255.pom
@@ -0,0 +1,22 @@
+<project xmlns='http://maven.apache.org/POM/4.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd'>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>biz.aQute</groupId>
+  <artifactId>bndlib</artifactId>
+  <version>0.0.255</version>
+  <description>
+    JAR Processing Library for creating and verifying OSGi manifest headers
+  </description>
+  <name>BND Library</name>
+  <url>http://www.aQute.biz/Code/Bnd</url>
+  <organization>
+    <name>aQute SARL</name>
+    <url>http://www.aQute.biz</url>
+  </organization>
+  <licenses>
+    <license>
+    <name>This material is licensed under the Apache Software License, Version 2.0</name>
+    <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+    <distribution>repo</distribution>
+    </license>
+  </licenses>
+</project>
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.255/bndlib-0.0.255.pom.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.255/bndlib-0.0.255.pom.sha1
new file mode 100644
index 0000000..c070fb9
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/biz/aQute/bndlib/0.0.255/bndlib-0.0.255.pom.sha1
@@ -0,0 +1 @@
+47bb794b00a5bb17e6c9b7280a6e771ba1e9ad3f
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar.sha1
new file mode 100644
index 0000000..a7b4a8c
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar.sha1
@@ -0,0 +1 @@
+5d3ccc056b6f056dbf0dddfdf43894b9065a8f94
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/dom4j/dom4j/1.6.1/dom4j-1.6.1.pom b/biz.aQute.bndlib.tests/test/maven-repo/dom4j/dom4j/1.6.1/dom4j-1.6.1.pom
new file mode 100644
index 0000000..ef8e1f7
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/dom4j/dom4j/1.6.1/dom4j-1.6.1.pom
@@ -0,0 +1,221 @@
+<project>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>dom4j</groupId>
+  <artifactId>dom4j</artifactId>
+  <name>dom4j</name>
+  <version>1.6.1</version>
+  <description>dom4j: the flexible XML framework for Java</description>
+  <url>http://dom4j.org</url>
+  <issueManagement>
+    <url>http://sourceforge.net/tracker/?group_id=16035</url>
+  </issueManagement>
+  <ciManagement>
+    <notifiers>
+      <notifier>
+        <address>dom4j-dev at lists.sourceforge.net</address>
+      </notifier>
+    </notifiers>
+  </ciManagement>
+  <inceptionYear>2001</inceptionYear>
+  <mailingLists>
+    <mailingList>
+      <name>dom4j user list</name>
+      <subscribe>http://lists.sourceforge.net/lists/listinfo/dom4j-user</subscribe>
+      <unsubscribe>http://lists.sourceforge.net/lists/listinfo/dom4j-user</unsubscribe>
+      <archive>http://www.mail-archive.com/dom4j-user%40lists.sourceforge.net/</archive>
+    </mailingList>
+    <mailingList>
+      <name>dom4j developer list</name>
+      <subscribe>http://lists.sourceforge.net/lists/listinfo/dom4j-dev</subscribe>
+      <unsubscribe>http://lists.sourceforge.net/lists/listinfo/dom4j-dev</unsubscribe>
+      <archive>http://www.mail-archive.com/dom4j-dev%40lists.sourceforge.net/</archive>
+    </mailingList>
+    <mailingList>
+      <name>dom4j commits list</name>
+      <subscribe>http://lists.sourceforge.net/lists/listinfo/dom4j-commits</subscribe>
+      <unsubscribe>http://lists.sourceforge.net/lists/listinfo/dom4j-commits</unsubscribe>
+    </mailingList>
+  </mailingLists>
+  <developers>
+    <developer>
+      <id>carnold</id>
+      <name>Curt Arnold</name>
+      <email>carnold at users.sourceforge.net</email>
+    </developer>
+    <developer>
+      <id>ddlucas</id>
+      <name>David Lucas</name>
+      <email>ddlucas at users.sourceforge.net</email>
+    </developer>
+    <developer>
+      <id>drwhite</id>
+      <name>David White</name>
+      <email>drwhite at users.sourceforge.net</email>
+    </developer>
+    <developer>
+      <id>jjenkov</id>
+      <name>Jakob Jenkov</name>
+      <email>jjenkov at users.sourceforge.net</email>
+    </developer>
+    <developer>
+      <id>jstrachan</id>
+      <name>James Strachan</name>
+      <email>jstrachan at apache.org</email>
+      <organization>SpiritSoft, Inc.</organization>
+    </developer>
+    <developer>
+      <id>laramiec</id>
+      <name>Laramie Crocker</name>
+      <email>laramiec at users.sourceforge.net</email>
+    </developer>
+    <developer>
+      <id>maartenc</id>
+      <name>Maarten Coene</name>
+      <email>maartenc at users.sourceforge.net</email>
+      <organization>Cronos</organization>
+    </developer>
+    <developer>
+      <id>mskells</id>
+      <name>Michael Skells</name>
+      <email>mskells at users.sourceforge.net</email>
+    </developer>
+    <developer>
+      <id>nicksanderson</id>
+      <name>Nick Sanderson</name>
+      <email>nicksanderson at users.sourceforge.net</email>
+    </developer>
+    <developer>
+      <id>slehmann</id>
+      <name>Steen Lehmann</name>
+      <email>slehmann at users.sourceforge.net</email>
+    </developer>
+    <developer>
+      <id>tradem</id>
+      <name>Tobias Rademacher</name>
+      <email>tradem at users.sourceforge.net</email>
+    </developer>
+    <developer>
+      <id>werken</id>
+      <name>Bob McWhirter</name>
+      <email>werken at users.sourceforge.net</email>
+    </developer>
+    <developer>
+      <id>wolfftw</id>
+      <name>Todd Wolff</name>
+      <email>wolfftw at users.sourceforge.net</email>
+    </developer>
+    <developer>
+      <id>yeekee</id>
+      <name>OuYang Chen</name>
+      <email>yeekee at users.sourceforge.net</email>
+    </developer>
+    <developer>
+      <id>yruan2</id>
+      <name>Yuxin Ruan</name>
+      <email>yruan2 at users.sourceforge.net</email>
+    </developer>
+  </developers>
+  <scm>
+    <connection>scm:cvs:pserver:anonymous at cvs.sourceforge.net:/cvsroot/dom4j:dom4j</connection>
+    <developerConnection>scm:cvs:ext:${maven.username}@cvs.sourceforge.net:/cvsroot/dom4j:dom4j</developerConnection>
+    <url>http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/dom4j/dom4j/</url>
+  </scm>
+  <organization>
+    <name>MetaStuff Ltd.</name>
+    <url>http://sourceforge.net/projects/dom4j</url>
+  </organization>
+  <build>
+    <sourceDirectory>src/java</sourceDirectory>
+    <testSourceDirectory>src/test</testSourceDirectory>
+    <plugins>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <includes>
+            <include>**/*Test.java</include>
+          </includes>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>jaxme</groupId>
+      <artifactId>jaxme-api</artifactId>
+      <version>0.3</version>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>jaxen</groupId>
+      <artifactId>jaxen</artifactId>
+      <version>1.1-beta-6</version>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>msv</groupId>
+      <artifactId>xsdlib</artifactId>
+      <version>20030807</version>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>msv</groupId>
+      <artifactId>relaxngDatatype</artifactId>
+      <version>20030807</version>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>pull-parser</groupId>
+      <artifactId>pull-parser</artifactId>
+      <version>2</version>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>xpp3</groupId>
+      <artifactId>xpp3</artifactId>
+      <version>1.1.3.3</version>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>stax</groupId>
+      <artifactId>stax-api</artifactId>
+      <version>1.0</version>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>xml-apis</groupId>
+      <artifactId>xml-apis</artifactId>
+      <version>1.0.b2</version>
+    </dependency>
+    <dependency>
+      <groupId>junitperf</groupId>
+      <artifactId>junitperf</artifactId>
+      <version>1.8</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>stax</groupId>
+      <artifactId>stax-ri</artifactId>
+      <version>1.0</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>xerces</groupId>
+      <artifactId>xercesImpl</artifactId>
+      <version>2.6.2</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>xalan</groupId>
+      <artifactId>xalan</artifactId>
+      <version>2.5.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+  <distributionManagement>
+    <site>
+      <id>default</id>
+      <name>Default Site</name>
+      <url>scp://dom4j.org//home/groups/d/do/dom4j/htdocs</url>
+    </site>
+  </distributionManagement>
+</project>
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/dom4j/dom4j/1.6.1/dom4j-1.6.1.pom.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/dom4j/dom4j/1.6.1/dom4j-1.6.1.pom.sha1
new file mode 100644
index 0000000..d0a8885
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/dom4j/dom4j/1.6.1/dom4j-1.6.1.pom.sha1
@@ -0,0 +1 @@
+7ea9ce66f04c02826340f41052fa2883818df602  /home/projects/maven/repository-staging/to-ibiblio/maven2/dom4j/dom4j/1.6.1/dom4j-1.6.1.pom
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/3.8.1/junit-3.8.1.jar.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/3.8.1/junit-3.8.1.jar.sha1
new file mode 100644
index 0000000..ed10f03
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/3.8.1/junit-3.8.1.jar.sha1
@@ -0,0 +1 @@
+99129f16442844f6a4a11ae22fbbee40b14d774f
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/3.8.1/junit-3.8.1.pom b/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/3.8.1/junit-3.8.1.pom
new file mode 100644
index 0000000..2169a65
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/3.8.1/junit-3.8.1.pom
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" 
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd ">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>junit</groupId>
+  <artifactId>junit</artifactId>
+  <version>3.8.1</version>
+  <name>JUnit</name>
+  <url>http://junit.org</url>
+  <description>
+    JUnit is a regression testing framework written by Erich Gamma and Kent Beck. It is used by the developer who implements unit tests in Java.
+  </description>
+  <organization>
+    <name>JUnit</name>
+    <url>http://www.junit.org</url>
+  </organization>
+  <licenses>
+    <license>
+      <name>Common Public License Version 1.0</name>
+      <url>http://www.opensource.org/licenses/cpl1.0.txt</url>
+    </license>
+  </licenses>
+  <scm>
+    <url>http://junit.cvs.sourceforge.net/junit/</url>
+  </scm>
+  <dependencies>
+  </dependencies>
+</project>
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/3.8.1/junit-3.8.1.pom.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/3.8.1/junit-3.8.1.pom.sha1
new file mode 100644
index 0000000..59fcd0c
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/3.8.1/junit-3.8.1.pom.sha1
@@ -0,0 +1 @@
+16d74791c801c89b0071b1680ea0bc85c93417bb  junit-3.8.1.pom
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/3.8/junit-3.8.pom b/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/3.8/junit-3.8.pom
new file mode 100644
index 0000000..ef9c6ba
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/3.8/junit-3.8.pom
@@ -0,0 +1,26 @@
+<project>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>junit</groupId>
+  <artifactId>junit</artifactId>
+  <version>3.8</version>
+  <name>JUnit</name>
+  <url>http://junit.org</url>
+  <description>
+    JUnit is a regression testing framework written by Erich Gamma and Kent Beck. It is used by the developer who implements unit tests in Java.
+  </description>
+  <organization>
+    <name>JUnit</name>
+    <url>http://www.junit.org</url>
+  </organization>
+  <licenses>
+    <license>
+      <name>Common Public License Version 1.0</name>
+      <url>http://www.opensource.org/licenses/cpl1.0.txt</url>
+    </license>
+  </licenses>
+  <scm>
+    <url>http://junit.cvs.sourceforge.net/junit/</url>
+  </scm>
+  <dependencies>
+  </dependencies>
+</project>
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/3.8/junit-3.8.pom.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/3.8/junit-3.8.pom.sha1
new file mode 100644
index 0000000..d420e7c
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/3.8/junit-3.8.pom.sha1
@@ -0,0 +1 @@
+23df9fbef09462d082baebf7afcc62895b8dbf5c  junit-3.8.pom
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/4.4/junit-4.4.jar.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/4.4/junit-4.4.jar.sha1
new file mode 100644
index 0000000..a2a6ffb
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/4.4/junit-4.4.jar.sha1
@@ -0,0 +1 @@
+8f35ee1f35d2dadbb5029991449ee90c1bab4d4a  junit-4.4.jar
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/4.4/junit-4.4.pom b/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/4.4/junit-4.4.pom
new file mode 100644
index 0000000..98bf827
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/4.4/junit-4.4.pom
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" 
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd ">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>junit</groupId>
+  <artifactId>junit</artifactId>
+  <version>4.4</version>
+  <name>JUnit</name>
+  <url>http://junit.org</url>
+  <description>
+    JUnit is a regression testing framework written by Erich Gamma and Kent Beck. It is used by the developer who implements unit tests in Java.
+  </description>
+  <organization>
+    <name>JUnit</name>
+    <url>http://www.junit.org</url>
+  </organization>
+  <licenses>
+    <license>
+      <name>Common Public License Version 1.0</name>
+      <url>http://www.opensource.org/licenses/cpl1.0.txt</url>
+    </license>
+  </licenses>
+  <scm>
+    <url>http://junit.cvs.sourceforge.net/junit/</url>
+  </scm>
+  <dependencies>
+    <!-- this dependency is included in the jar, see MAVENUPLOAD-1651
+    <dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest-core</artifactId>
+      <version>1.1</version>
+    </dependency>
+    -->
+  </dependencies>
+</project>
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/4.4/junit-4.4.pom.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/4.4/junit-4.4.pom.sha1
new file mode 100644
index 0000000..2897635
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/junit/junit/4.4/junit-4.4.pom.sha1
@@ -0,0 +1 @@
+e8c01c806baca44a6d3bf44fef189e725fec3e0d  junit-4.4.pom
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/javax.servlet/1.0.0/javax.servlet-1.0.0.jar.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/javax.servlet/1.0.0/javax.servlet-1.0.0.jar.sha1
new file mode 100644
index 0000000..14db28f
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/javax.servlet/1.0.0/javax.servlet-1.0.0.jar.sha1
@@ -0,0 +1 @@
+69efbcf8385631d57b7b97cc43b3af9ddec29ab6
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/javax.servlet/1.0.0/javax.servlet-1.0.0.pom b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/javax.servlet/1.0.0/javax.servlet-1.0.0.pom
new file mode 100644
index 0000000..53281ae
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/javax.servlet/1.0.0/javax.servlet-1.0.0.pom
@@ -0,0 +1,125 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>felix</artifactId>
+    <version>1.0.0</version>
+    <relativePath>../pom/pom.xml</relativePath>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <name>Servlet 2.1 API</name>
+  <description>Servlet 2.1 API</description>
+  <version>1.0.0</version>
+  <artifactId>javax.servlet</artifactId>
+  <packaging>bundle</packaging>
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-release-plugin</artifactId>
+          <version>2.0-beta-7</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-gpg-plugin</artifactId>
+          <version>1.0-alpha-4</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-assembly-plugin</artifactId>
+          <version>2.2-beta-1</version>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>1.0.0</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-Copyright>Copyright 1999,2005 The Apache Software Foundation</Bundle-Copyright>
+            <Bundle-Category>servlet</Bundle-Category>
+            <Export-Package>javax.servlet;specification-version="2.1",javax.servlet.http;specification-version="2.1"</Export-Package>
+            <Import-Package>!javax.servlet.*,*</Import-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-release-plugin</artifactId>
+        <configuration>
+          <tagBase>https://svn.apache.org/repos/asf/felix/releases</tagBase>
+          <useReleaseProfile>false</useReleaseProfile>
+          <goals>deploy</goals>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <profiles>
+    <profile>
+      <id>release</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-gpg-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>sign-artifacts</id>
+                <phase>verify</phase>
+                <goals>
+                  <goal>sign</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-assembly-plugin</artifactId>
+            <configuration>
+              <descriptorRefs>
+                <descriptorRef>bin</descriptorRef>
+                <descriptorRef>project</descriptorRef>
+              </descriptorRefs>
+            </configuration>
+            <executions>
+              <execution>
+                <id>make-assembly</id>
+                <phase>package</phase>
+                <goals>
+                  <goal>attached</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
+  <scm>
+    <connection>scm:svn:https://svn.apache.org/repos/asf/felix/releases/javax.servlet-1.0.0</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/felix/releases/javax.servlet-1.0.0</developerConnection>
+    <url>scm:svn:https://svn.apache.org/repos/asf/felix/releases/javax.servlet-1.0.0</url>
+  </scm>
+</project>
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/javax.servlet/1.0.0/javax.servlet-1.0.0.pom.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/javax.servlet/1.0.0/javax.servlet-1.0.0.pom.sha1
new file mode 100644
index 0000000..339dbd3
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/javax.servlet/1.0.0/javax.servlet-1.0.0.pom.sha1
@@ -0,0 +1 @@
+4376e654efb7423d3720014da19ac55370383c37
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-obr-plugin/1.0.0/maven-obr-plugin-1.0.0.jar.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-obr-plugin/1.0.0/maven-obr-plugin-1.0.0.jar.sha1
new file mode 100644
index 0000000..040b46c
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-obr-plugin/1.0.0/maven-obr-plugin-1.0.0.jar.sha1
@@ -0,0 +1 @@
+07558b5566ee4244caefeb9392a00a6c738643bc  maven-obr-plugin-1.0.0.jar
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-obr-plugin/1.0.0/maven-obr-plugin-1.0.0.pom b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-obr-plugin/1.0.0/maven-obr-plugin-1.0.0.pom
new file mode 100644
index 0000000..de666b2
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-obr-plugin/1.0.0/maven-obr-plugin-1.0.0.pom
@@ -0,0 +1,56 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <parent>
+    <artifactId>felix</artifactId>
+    <groupId>org.apache.felix</groupId>
+    <version>1.0.1</version>
+    <relativePath>../pom/pom.xml</relativePath>
+ </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>maven-obr-plugin</artifactId>
+  <version>1.0.0</version>
+  <packaging>maven-plugin</packaging>
+  
+  <name>OBR Maven Plugin</name>
+  <description>
+    Provides a maven plugin which allows the automatic cration and update of an
+    OSGi Bundle Repository complaint to OSGi RFC 0112.
+  </description>
+
+  <dependencies>
+    <dependency>
+      <groupId>net.sf.kxml</groupId>
+      <artifactId>kxml2</artifactId>
+      <version>2.2.2</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.osgi.service.obr</artifactId>
+      <version>1.0.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-plugin-api</artifactId>
+      <version>2.0.7</version>
+    </dependency>
+    <dependency>
+      <groupId>xerces</groupId>
+      <artifactId>xercesImpl</artifactId>
+      <version>2.8.1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-project</artifactId>
+      <version>2.0.7</version>
+    </dependency>
+  </dependencies>
+
+
+  <scm>
+    <connection>scm:svn:https://svn.apache.org/repos/asf/felix/releases/maven-obr-plugin-1.0.0</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/felix/releases/maven-obr-plugin-1.0.0</developerConnection>
+    <url>scm:svn:https://svn.apache.org/repos/asf/felix/releases/maven-obr-plugin-1.0.0</url>
+  </scm>
+</project>
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-obr-plugin/1.0.0/maven-obr-plugin-1.0.0.pom.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-obr-plugin/1.0.0/maven-obr-plugin-1.0.0.pom.sha1
new file mode 100644
index 0000000..bb84d18
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-obr-plugin/1.0.0/maven-obr-plugin-1.0.0.pom.sha1
@@ -0,0 +1 @@
+ce567323f7f18374984eefffe1b0100f32e8ee00  maven-obr-plugin-1.0.0.pom
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-scr-plugin/1.0.8/maven-scr-plugin-1.0.8.jar.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-scr-plugin/1.0.8/maven-scr-plugin-1.0.8.jar.sha1
new file mode 100644
index 0000000..b907699
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-scr-plugin/1.0.8/maven-scr-plugin-1.0.8.jar.sha1
@@ -0,0 +1 @@
+0960b0d9c00d554589471da564b962b68b30ae02
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-scr-plugin/1.0.8/maven-scr-plugin-1.0.8.pom b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-scr-plugin/1.0.8/maven-scr-plugin-1.0.8.pom
new file mode 100644
index 0000000..c525bc8
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-scr-plugin/1.0.8/maven-scr-plugin-1.0.8.pom
@@ -0,0 +1,101 @@
+<!-- 
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+ 
+    http://www.apache.org/licenses/LICENSE-2.0
+ 
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License. 
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>felix</artifactId>
+        <groupId>org.apache.felix</groupId>
+        <version>1.0.2</version>
+    </parent>
+
+    <groupId>org.apache.felix</groupId>
+    <artifactId>maven-scr-plugin</artifactId>
+
+	<version>1.0.8</version>
+	<packaging>maven-plugin</packaging>
+
+	<name>Maven SCR Plugin</name>
+	<description>
+		Maven plugin for generating OSGi service descriptors based on annotations.
+	</description>
+
+	<scm>
+		<connection>scm:svn:https://svn.apache.org/repos/asf/felix/releases/maven-scr-plugin-1.0.8</connection>
+		<developerConnection>scm:svn:https://svn.apache.org/repos/asf/felix/releases/maven-scr-plugin-1.0.8</developerConnection>
+		<url>scm:svn:https://svn.apache.org/repos/asf/felix/releases/maven-scr-plugin-1.0.8</url>
+	</scm>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.felix</groupId>
+			<artifactId>org.osgi.core</artifactId>
+			<version>1.0.0</version>
+			<scope>compile</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.felix</groupId>
+			<artifactId>org.osgi.compendium</artifactId>
+			<version>1.0.0</version>
+			<scope>compile</scope>
+		</dependency>
+		
+		<dependency>
+		   <groupId>asm</groupId>
+		   <artifactId>asm-all</artifactId>
+		   <version>3.0</version>
+		</dependency>
+		
+		<dependency>
+		    <groupId>commons-io</groupId>
+		    <artifactId>commons-io</artifactId>
+		    <version>1.4</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.apache.maven</groupId>
+			<artifactId>maven-plugin-api</artifactId>
+			<version>2.0.7</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.apache.maven</groupId>
+			<artifactId>maven-archiver</artifactId>
+			<version>2.2</version>
+		</dependency>
+
+		<dependency>
+			<groupId>com.thoughtworks.qdox</groupId>
+			<artifactId>qdox</artifactId>
+			<version>1.6.3</version>
+		</dependency>
+
+    <!-- Logging support -->
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.4.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <version>1.4.3</version>
+        </dependency>
+	</dependencies>
+</project>
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-scr-plugin/1.0.8/maven-scr-plugin-1.0.8.pom.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-scr-plugin/1.0.8/maven-scr-plugin-1.0.8.pom.sha1
new file mode 100644
index 0000000..f837bf0
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-scr-plugin/1.0.8/maven-scr-plugin-1.0.8.pom.sha1
@@ -0,0 +1 @@
+7a665510c5d4b679342c8284360e9510ccaeedc8
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-scr-plugin/maven-metadata-central.xml b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-scr-plugin/maven-metadata-central.xml
new file mode 100644
index 0000000..f32c5a3
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-scr-plugin/maven-metadata-central.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?><metadata>
+  <groupId>org.apache.felix</groupId>
+  <artifactId>maven-scr-plugin</artifactId>
+  <version>0.2.0</version>
+  <versioning>
+    <latest>1.0.8</latest>
+    <versions>
+      <version>0.2.0</version>
+      <version>1.0.1</version>
+      <version>1.0.2</version>
+      <version>1.0.3</version>
+      <version>1.0.4</version>
+      <version>1.0.5</version>
+      <version>1.0.6</version>
+      <version>1.0.7</version>
+      <version>1.0.8</version>
+    </versions>
+    <lastUpdated>20080911084647</lastUpdated>
+  </versioning>
+</metadata>
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-scr-plugin/maven-metadata-central.xml.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-scr-plugin/maven-metadata-central.xml.sha1
new file mode 100644
index 0000000..dae1306
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/maven-scr-plugin/maven-metadata-central.xml.sha1
@@ -0,0 +1 @@
+6665728af7c50cb1f6260936ce44eba6540fa5fe
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.apache.felix.fileinstall/0.9.0-SNAPSHOT/maven-metadata-local.xml b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.apache.felix.fileinstall/0.9.0-SNAPSHOT/maven-metadata-local.xml
new file mode 100644
index 0000000..176a56d
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.apache.felix.fileinstall/0.9.0-SNAPSHOT/maven-metadata-local.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?><metadata>
+  <groupId>org.apache.felix</groupId>
+  <artifactId>org.apache.felix.fileinstall</artifactId>
+  <version>0.9.0-SNAPSHOT</version>
+  <versioning>
+    <snapshot>
+      <localCopy>true</localCopy>
+    </snapshot>
+    <lastUpdated>20080826071557</lastUpdated>
+  </versioning>
+</metadata>
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.apache.felix.fileinstall/0.9.0-SNAPSHOT/org.apache.felix.fileinstall-0.9.0-SNAPSHOT.pom b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.apache.felix.fileinstall/0.9.0-SNAPSHOT/org.apache.felix.fileinstall-0.9.0-SNAPSHOT.pom
new file mode 100644
index 0000000..7ac3da3
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.apache.felix.fileinstall/0.9.0-SNAPSHOT/org.apache.felix.fileinstall-0.9.0-SNAPSHOT.pom
@@ -0,0 +1,62 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>felix</artifactId>
+    <version>1.0.2</version>
+    <relativePath>../pom/pom.xml</relativePath>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <packaging>bundle</packaging>
+  <name>Apache Felix File Install</name>
+  <description>A utility to automatically install bundles from a directory.</description>
+  <version>0.9.0-SNAPSHOT</version>
+  <artifactId>org.apache.felix.fileinstall</artifactId>
+  <dependencies>
+    <dependency>
+      <groupId>${pom.groupId}</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <version>1.0.0</version>
+    </dependency>
+    <dependency>
+      <groupId>${pom.groupId}</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+      <version>1.0.0</version>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>1.4.0</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Export-Package>org.apache.felix.fileinstall,org.osgi.service.cm</Export-Package>
+            <Bundle-Activator>org.apache.felix.fileinstall.FileInstall</Bundle-Activator>
+            <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
+            <Bundle-Vendor>The Apache Software Foundation</Bundle-Vendor>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.apache.felix.fileinstall/maven-metadata-local.xml b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.apache.felix.fileinstall/maven-metadata-local.xml
new file mode 100644
index 0000000..1091085
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.apache.felix.fileinstall/maven-metadata-local.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?><metadata>
+  <groupId>org.apache.felix</groupId>
+  <artifactId>org.apache.felix.fileinstall</artifactId>
+  <version>0.9.0-SNAPSHOT</version>
+  <versioning>
+    <versions>
+      <version>0.9.0-SNAPSHOT</version>
+    </versions>
+    <lastUpdated>20080826071557</lastUpdated>
+  </versioning>
+</metadata>
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.apache.felix.framework/1.1.0-SNAPSHOT/maven-metadata-local.xml b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.apache.felix.framework/1.1.0-SNAPSHOT/maven-metadata-local.xml
new file mode 100644
index 0000000..b43edef
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.apache.felix.framework/1.1.0-SNAPSHOT/maven-metadata-local.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?><metadata>
+  <groupId>org.apache.felix</groupId>
+  <artifactId>org.apache.felix.framework</artifactId>
+  <version>1.1.0-SNAPSHOT</version>
+  <versioning>
+    <snapshot>
+      <localCopy>true</localCopy>
+    </snapshot>
+    <lastUpdated>20080331104413</lastUpdated>
+  </versioning>
+</metadata>
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.apache.felix.framework/1.1.0-SNAPSHOT/org.apache.felix.framework-1.1.0-SNAPSHOT.pom b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.apache.felix.framework/1.1.0-SNAPSHOT/org.apache.felix.framework-1.1.0-SNAPSHOT.pom
new file mode 100644
index 0000000..d391922
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.apache.felix.framework/1.1.0-SNAPSHOT/org.apache.felix.framework-1.1.0-SNAPSHOT.pom
@@ -0,0 +1,63 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>felix</artifactId>
+    <version>1.0.2</version>
+    <relativePath>../pom/pom.xml</relativePath>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <packaging>bundle</packaging>
+  <name>Apache Felix Framework</name>
+  <artifactId>org.apache.felix.framework</artifactId>
+  <version>1.1.0-SNAPSHOT</version>
+  <dependencies>
+    <dependency>
+      <groupId>${pom.groupId}</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <version>1.1.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>${pom.groupId}</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+      <version>1.0.0</version>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>1.4.0</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-Name>Apache Felix Framework</Bundle-Name>
+            <Bundle-Description>OSGi R4 framework implementation.</Bundle-Description>
+            <Export-Package>org.osgi.framework;-split-package:=merge-first,org.osgi.service.packageadmin,org.osgi.service.url,org.osgi.service.startlevel,org.osgi.util.tracker</Export-Package>
+            <Private-Package>org.apache.felix.moduleloader.*,org.apache.felix.framework.*</Private-Package>
+            <Import-Package>!*</Import-Package>
+            <Include-Resource>{src/main/resources/},org/osgi/framework/=target/classes/org/osgi/framework/</Include-Resource> 
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>  
+</project>
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.apache.felix.framework/maven-metadata-local.xml b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.apache.felix.framework/maven-metadata-local.xml
new file mode 100644
index 0000000..eaf05b3
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.apache.felix.framework/maven-metadata-local.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?><metadata>
+  <groupId>org.apache.felix</groupId>
+  <artifactId>org.apache.felix.framework</artifactId>
+  <version>1.1.0-SNAPSHOT</version>
+  <versioning>
+    <versions>
+      <version>1.1.0-SNAPSHOT</version>
+    </versions>
+    <lastUpdated>20080331104413</lastUpdated>
+  </versioning>
+</metadata>
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.compendium/1.0.0/org.osgi.compendium-1.0.0.jar.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.compendium/1.0.0/org.osgi.compendium-1.0.0.jar.sha1
new file mode 100644
index 0000000..09169b5
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.compendium/1.0.0/org.osgi.compendium-1.0.0.jar.sha1
@@ -0,0 +1 @@
+d786e19619f19835ca20044217dae5a3dec170a8
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.compendium/1.0.0/org.osgi.compendium-1.0.0.pom b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.compendium/1.0.0/org.osgi.compendium-1.0.0.pom
new file mode 100644
index 0000000..d82a577
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.compendium/1.0.0/org.osgi.compendium-1.0.0.pom
@@ -0,0 +1,79 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>felix</artifactId>
+    <version>1.0.2</version>
+    <relativePath>../pom/pom.xml</relativePath>
+  </parent>
+  <organization>
+    <name>OSGi Alliance</name>
+    <url>http://www.osgi.org/</url>
+  </organization>
+  <modelVersion>4.0.0</modelVersion>
+  <name>OSGi R4 Compendium Bundle</name>
+  <description>OSGi Service Platform Release 4 Compendium Interfaces and Classes.</description>
+  <artifactId>org.osgi.compendium</artifactId>
+  <version>1.0.0</version>
+  <packaging>bundle</packaging>
+  <dependencies>
+    <dependency>
+      <groupId>${pom.groupId}</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <version>1.0.0</version>
+    </dependency>
+    <dependency>
+      <groupId>${pom.groupId}</groupId>
+      <artifactId>javax.servlet</artifactId>
+      <version>1.0.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.osgi.foundation</artifactId>
+      <version>1.0.0</version>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>1.2.0</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-SymbolicName>org.osgi.compendium</Bundle-SymbolicName>
+            <Export-Package>org.osgi.service.cm,org.osgi.service.component,org.osgi.service.device,org.osgi.service.event,org.osgi.service.http,org.osgi.service.io,org.osgi.service.log,org.osgi.service.metatype,org.osgi.service.prefs,org.osgi.service.provisioning,org.osgi.service.upnp,org.osgi.service.useradmin,org.osgi.service.wireadmin,org.osgi.util.measurement,org.osgi.util.position,org.osgi.util.tracker,org.osgi.util.xml</Export-Package>
+            <Import-Package>javax.microedition.io;resolution:=optional,org.osgi.framework,!org.osgi.*,*</Import-Package>
+            <DynamicImport-Package>*</DynamicImport-Package>
+            <Bundle-Version>4</Bundle-Version>
+            <Bundle-Copyright>Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.</Bundle-Copyright>
+            <Bundle-Category>osgi</Bundle-Category>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <scm>
+    <connection>scm:svn:https://svn.apache.org/repos/asf/felix/releases/org.osgi.compendium-1.0.0</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/felix/releases/org.osgi.compendium-1.0.0</developerConnection>
+    <url>scm:svn:https://svn.apache.org/repos/asf/felix/releases/org.osgi.compendium-1.0.0</url>
+  </scm>
+</project>
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.compendium/1.0.0/org.osgi.compendium-1.0.0.pom.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.compendium/1.0.0/org.osgi.compendium-1.0.0.pom.sha1
new file mode 100644
index 0000000..fc8b517
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.compendium/1.0.0/org.osgi.compendium-1.0.0.pom.sha1
@@ -0,0 +1 @@
+bbd2343feeefe7458e7a114cbe6c7058a300aba0
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.0.0/org.osgi.core-1.0.0.jar.md5 b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.0.0/org.osgi.core-1.0.0.jar.md5
new file mode 100644
index 0000000..1cf8f24
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.0.0/org.osgi.core-1.0.0.jar.md5
@@ -0,0 +1 @@
+2ea74604c9ab15a51e469fdc17758bd1  org.osgi.core-1.0.0.jar
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.0.0/org.osgi.core-1.0.0.pom b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.0.0/org.osgi.core-1.0.0.pom
new file mode 100644
index 0000000..4e512c0
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.0.0/org.osgi.core-1.0.0.pom
@@ -0,0 +1,56 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project>
+  <parent>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>felix</artifactId>
+    <version>1.0.0</version>
+    <relativePath>../pom/pom.xml</relativePath>
+  </parent>
+  <organization>
+    <name>OSGi Alliance</name>
+    <url>http://www.osgi.org/</url>
+  </organization>
+  <modelVersion>4.0.0</modelVersion>
+  <name>OSGi R4 Core Bundle</name>
+  <description>OSGi Service Platform Release 4 Core Interfaces and Classes.</description>
+  <artifactId>org.osgi.core</artifactId>
+  <version>1.0.0</version>
+  <packaging>bundle</packaging>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>1.0.0</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-SymbolicName>org.osgi.core</Bundle-SymbolicName>
+            <Export-Package>org.osgi.framework, org.osgi.service.condpermadmin, org.osgi.service.packageadmin, org.osgi.service.permissionadmin, org.osgi.service.startlevel, org.osgi.service.url</Export-Package>
+            <Import-Package>org.osgi.framework,org.osgi.service.packageadmin,org.osgi.service.startlevel,org.osgi.service.url,!org.osgi.*,*</Import-Package>
+            <Bundle-Version>4</Bundle-Version>
+            <Bundle-Copyright>Copyright (c) OSGi Alliance (2000, 2006). All Rights Reserved.</Bundle-Copyright>
+            <Bundle-Category>osgi</Bundle-Category>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.0.0/org.osgi.core-1.0.0.pom.md5 b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.0.0/org.osgi.core-1.0.0.pom.md5
new file mode 100644
index 0000000..ba7e3d1
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.0.0/org.osgi.core-1.0.0.pom.md5
@@ -0,0 +1 @@
+8dec79e3913103dac4acaa68263d3296 org.osgi.core-1.0.0.pom
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-20070713.230200-1/org.osgi.core-1.1.0-20070713.230200-1.pom b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-20070713.230200-1/org.osgi.core-1.1.0-20070713.230200-1.pom
new file mode 100644
index 0000000..b7803ab
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-20070713.230200-1/org.osgi.core-1.1.0-20070713.230200-1.pom
@@ -0,0 +1,56 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project>
+  <parent>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>felix</artifactId>
+    <version>1.1.0-SNAPSHOT</version>
+    <relativePath>../pom/pom.xml</relativePath>
+  </parent>
+  <organization>
+    <name>OSGi Alliance</name>
+    <url>http://www.osgi.org/</url>
+  </organization>
+  <modelVersion>4.0.0</modelVersion>
+  <name>OSGi R4 Core Bundle</name>
+  <description>OSGi Service Platform Release 4 Core Interfaces and Classes.</description>
+  <artifactId>org.osgi.core</artifactId>
+  <version>1.1.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>1.1.0-SNAPSHOT</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-SymbolicName>org.osgi.core</Bundle-SymbolicName>
+            <Export-Package>org.osgi.framework, org.osgi.service.condpermadmin, org.osgi.service.packageadmin, org.osgi.service.permissionadmin, org.osgi.service.startlevel, org.osgi.service.url</Export-Package>
+            <Import-Package>org.osgi.framework,org.osgi.service.packageadmin,org.osgi.service.startlevel,org.osgi.service.url,!org.osgi.*,*</Import-Package>
+            <Bundle-Version>4</Bundle-Version>
+            <Bundle-Copyright>Copyright (c) OSGi Alliance (2000, 2006). All Rights Reserved.</Bundle-Copyright>
+            <Bundle-Category>osgi</Bundle-Category>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-20070713.230200-1/org.osgi.core-1.1.0-20070713.230200-1.pom.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-20070713.230200-1/org.osgi.core-1.1.0-20070713.230200-1.pom.sha1
new file mode 100644
index 0000000..535fba0
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-20070713.230200-1/org.osgi.core-1.1.0-20070713.230200-1.pom.sha1
@@ -0,0 +1 @@
+8aac919e2be0bd7bf85fbf55eddcf4a4873c965a
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-SNAPSHOT/maven-metadata-apache.snapshots.xml b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-SNAPSHOT/maven-metadata-apache.snapshots.xml
new file mode 100644
index 0000000..a059c95
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-SNAPSHOT/maven-metadata-apache.snapshots.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?><metadata>
+  <groupId>org.apache.felix</groupId>
+  <artifactId>org.osgi.core</artifactId>
+  <version>1.1.0-SNAPSHOT</version>
+  <versioning>
+    <snapshot>
+      <timestamp>20070713.230200</timestamp>
+      <buildNumber>1</buildNumber>
+    </snapshot>
+    <lastUpdated>20070713230214</lastUpdated>
+  </versioning>
+</metadata>
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-SNAPSHOT/maven-metadata-apache.snapshots.xml.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-SNAPSHOT/maven-metadata-apache.snapshots.xml.sha1
new file mode 100644
index 0000000..646d1f4
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-SNAPSHOT/maven-metadata-apache.snapshots.xml.sha1
@@ -0,0 +1 @@
+31d18a635b676c4fc01359e429d883c2f4a0d43e
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-SNAPSHOT/org.osgi.core-1.1.0-20070713.230200-1.jar.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-SNAPSHOT/org.osgi.core-1.1.0-20070713.230200-1.jar.sha1
new file mode 100644
index 0000000..9c5f7f7
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-SNAPSHOT/org.osgi.core-1.1.0-20070713.230200-1.jar.sha1
@@ -0,0 +1 @@
+7f59188d3518a437b0fc87d49077c7a94e9be325
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-SNAPSHOT/org.osgi.core-1.1.0-20070713.230200-1.pom b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-SNAPSHOT/org.osgi.core-1.1.0-20070713.230200-1.pom
new file mode 100644
index 0000000..b7803ab
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-SNAPSHOT/org.osgi.core-1.1.0-20070713.230200-1.pom
@@ -0,0 +1,56 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project>
+  <parent>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>felix</artifactId>
+    <version>1.1.0-SNAPSHOT</version>
+    <relativePath>../pom/pom.xml</relativePath>
+  </parent>
+  <organization>
+    <name>OSGi Alliance</name>
+    <url>http://www.osgi.org/</url>
+  </organization>
+  <modelVersion>4.0.0</modelVersion>
+  <name>OSGi R4 Core Bundle</name>
+  <description>OSGi Service Platform Release 4 Core Interfaces and Classes.</description>
+  <artifactId>org.osgi.core</artifactId>
+  <version>1.1.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>1.1.0-SNAPSHOT</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-SymbolicName>org.osgi.core</Bundle-SymbolicName>
+            <Export-Package>org.osgi.framework, org.osgi.service.condpermadmin, org.osgi.service.packageadmin, org.osgi.service.permissionadmin, org.osgi.service.startlevel, org.osgi.service.url</Export-Package>
+            <Import-Package>org.osgi.framework,org.osgi.service.packageadmin,org.osgi.service.startlevel,org.osgi.service.url,!org.osgi.*,*</Import-Package>
+            <Bundle-Version>4</Bundle-Version>
+            <Bundle-Copyright>Copyright (c) OSGi Alliance (2000, 2006). All Rights Reserved.</Bundle-Copyright>
+            <Bundle-Category>osgi</Bundle-Category>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-SNAPSHOT/org.osgi.core-1.1.0-20070713.230200-1.pom.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-SNAPSHOT/org.osgi.core-1.1.0-20070713.230200-1.pom.sha1
new file mode 100644
index 0000000..535fba0
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-SNAPSHOT/org.osgi.core-1.1.0-20070713.230200-1.pom.sha1
@@ -0,0 +1 @@
+8aac919e2be0bd7bf85fbf55eddcf4a4873c965a
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-SNAPSHOT/org.osgi.core-1.1.0-SNAPSHOT.pom b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-SNAPSHOT/org.osgi.core-1.1.0-SNAPSHOT.pom
new file mode 100644
index 0000000..b7803ab
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.core/1.1.0-SNAPSHOT/org.osgi.core-1.1.0-SNAPSHOT.pom
@@ -0,0 +1,56 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project>
+  <parent>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>felix</artifactId>
+    <version>1.1.0-SNAPSHOT</version>
+    <relativePath>../pom/pom.xml</relativePath>
+  </parent>
+  <organization>
+    <name>OSGi Alliance</name>
+    <url>http://www.osgi.org/</url>
+  </organization>
+  <modelVersion>4.0.0</modelVersion>
+  <name>OSGi R4 Core Bundle</name>
+  <description>OSGi Service Platform Release 4 Core Interfaces and Classes.</description>
+  <artifactId>org.osgi.core</artifactId>
+  <version>1.1.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>1.1.0-SNAPSHOT</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-SymbolicName>org.osgi.core</Bundle-SymbolicName>
+            <Export-Package>org.osgi.framework, org.osgi.service.condpermadmin, org.osgi.service.packageadmin, org.osgi.service.permissionadmin, org.osgi.service.startlevel, org.osgi.service.url</Export-Package>
+            <Import-Package>org.osgi.framework,org.osgi.service.packageadmin,org.osgi.service.startlevel,org.osgi.service.url,!org.osgi.*,*</Import-Package>
+            <Bundle-Version>4</Bundle-Version>
+            <Bundle-Copyright>Copyright (c) OSGi Alliance (2000, 2006). All Rights Reserved.</Bundle-Copyright>
+            <Bundle-Category>osgi</Bundle-Category>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.foundation/1.0.0/org.osgi.foundation-1.0.0.jar.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.foundation/1.0.0/org.osgi.foundation-1.0.0.jar.sha1
new file mode 100644
index 0000000..0c4711e
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.foundation/1.0.0/org.osgi.foundation-1.0.0.jar.sha1
@@ -0,0 +1 @@
+458c4a8b1168c8f19812b50ff7d9fdd78b6582d5
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.foundation/1.0.0/org.osgi.foundation-1.0.0.pom b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.foundation/1.0.0/org.osgi.foundation-1.0.0.pom
new file mode 100644
index 0000000..094aff3
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.foundation/1.0.0/org.osgi.foundation-1.0.0.pom
@@ -0,0 +1,39 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>felix</artifactId>
+    <version>1.0.1</version>
+    <relativePath>../pom/pom.xml</relativePath>
+  </parent>
+  <organization>
+    <name>OSGi Alliance</name>
+    <url>http://www.osgi.org/</url>
+  </organization>
+  <modelVersion>4.0.0</modelVersion>
+  <name>OSGi R4 Foundation EE</name>
+  <artifactId>org.osgi.foundation</artifactId>
+  <version>1.0.0</version>
+
+  <scm>
+    <connection>scm:svn:https://svn.apache.org/repos/asf/felix/releases/org.osgi.foundation-1.0.0</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/felix/releases/org.osgi.foundation-1.0.0</developerConnection>
+    <url>scm:svn:https://svn.apache.org/repos/asf/felix/releases/org.osgi.foundation-1.0.0</url>
+  </scm>
+</project>
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.foundation/1.0.0/org.osgi.foundation-1.0.0.pom.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.foundation/1.0.0/org.osgi.foundation-1.0.0.pom.sha1
new file mode 100644
index 0000000..265872e
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.foundation/1.0.0/org.osgi.foundation-1.0.0.pom.sha1
@@ -0,0 +1 @@
+34ca68b2f8af7023b232ad04a5e6aefd9f2876ee
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.service.obr/1.0.0/org.osgi.service.obr-1.0.0.jar.md5 b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.service.obr/1.0.0/org.osgi.service.obr-1.0.0.jar.md5
new file mode 100644
index 0000000..1c891a8
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.service.obr/1.0.0/org.osgi.service.obr-1.0.0.jar.md5
@@ -0,0 +1 @@
+b4f7bb71b5fee9bc66f5f821c4ea840a
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.service.obr/1.0.0/org.osgi.service.obr-1.0.0.pom b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.service.obr/1.0.0/org.osgi.service.obr-1.0.0.pom
new file mode 100644
index 0000000..a9bbb9e
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.service.obr/1.0.0/org.osgi.service.obr-1.0.0.pom
@@ -0,0 +1,49 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>felix</artifactId>
+    <version>1.0.1</version>
+    <relativePath>../pom/pom.xml</relativePath>
+  </parent>
+  <organization>
+    <name>OSGi Alliance</name>
+    <url>http://www.osgi.org/</url>
+  </organization>
+  <modelVersion>4.0.0</modelVersion>
+  <name>OSGi OBR Service API</name>
+  <description>OSGi OBR Service API</description>
+  <artifactId>org.osgi.service.obr</artifactId>
+  <version>1.0.0</version>
+  <packaging>jar</packaging>
+  <dependencies>
+    <dependency>
+      <groupId>${pom.groupId}</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <version>1.0.0</version>
+    </dependency>
+  </dependencies>
+
+  <scm>
+    <connection>scm:svn:https://svn.apache.org/repos/asf/felix/releases/org.osgi.service.obr-1.0.0</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/felix/releases/org.osgi.service.obr-1.0.0</developerConnection>
+    <url>scm:svn:https://svn.apache.org/repos/asf/felix/releases/org.osgi.service.obr-1.0.0</url>
+  </scm>
+</project>
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.service.obr/1.0.0/org.osgi.service.obr-1.0.0.pom.md5 b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.service.obr/1.0.0/org.osgi.service.obr-1.0.0.pom.md5
new file mode 100644
index 0000000..5930bc9
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.service.obr/1.0.0/org.osgi.service.obr-1.0.0.pom.md5
@@ -0,0 +1 @@
+7ec1a770c5c72925fd1f48fc35e612d6
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.service.obr/1.0.1/org.osgi.service.obr-1.0.1.jar.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.service.obr/1.0.1/org.osgi.service.obr-1.0.1.jar.sha1
new file mode 100644
index 0000000..6b6bfd8
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.service.obr/1.0.1/org.osgi.service.obr-1.0.1.jar.sha1
@@ -0,0 +1 @@
+7e8c734cd0676baf4dc4f863b3ba34824dd9d45f  org.osgi.service.obr-1.0.1.jar
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.service.obr/1.0.1/org.osgi.service.obr-1.0.1.pom b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.service.obr/1.0.1/org.osgi.service.obr-1.0.1.pom
new file mode 100644
index 0000000..f402630
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.service.obr/1.0.1/org.osgi.service.obr-1.0.1.pom
@@ -0,0 +1,49 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>felix</artifactId>
+    <version>1.0.2</version>
+    <relativePath>../pom/pom.xml</relativePath>
+  </parent>
+  <organization>
+    <name>OSGi Alliance</name>
+    <url>http://www.osgi.org/</url>
+  </organization>
+  <modelVersion>4.0.0</modelVersion>
+  <name>OSGi OBR Service API</name>
+  <description>OSGi OBR Service API</description>
+  <artifactId>org.osgi.service.obr</artifactId>
+  <version>1.0.1</version>
+  <packaging>jar</packaging>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <version>1.0.0</version>
+    </dependency>
+  </dependencies>
+
+  <scm>
+    <connection>scm:svn:https://svn.apache.org/repos/asf/felix/releases/org.osgi.service.obr-1.0.1</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/felix/releases/org.osgi.service.obr-1.0.1</developerConnection>
+    <url>scm:svn:https://svn.apache.org/repos/asf/felix/releases/org.osgi.service.obr-1.0.1</url>
+  </scm>
+</project>
diff --git a/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.service.obr/1.0.1/org.osgi.service.obr-1.0.1.pom.sha1 b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.service.obr/1.0.1/org.osgi.service.obr-1.0.1.pom.sha1
new file mode 100644
index 0000000..5f4e7ba
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/maven-repo/org/apache/felix/org.osgi.service.obr/1.0.1/org.osgi.service.obr-1.0.1.pom.sha1
@@ -0,0 +1 @@
+ab4cc38f95ad6bc2793f7cf6c71a0c69b82f5e3c  org.osgi.service.obr-1.0.1.pom
diff --git a/biz.aQute.bndlib/test/redirectws/bnd/build.bnd b/biz.aQute.bndlib.tests/test/redirectws/bnd/build.bnd
similarity index 100%
rename from biz.aQute.bndlib/test/redirectws/bnd/build.bnd
rename to biz.aQute.bndlib.tests/test/redirectws/bnd/build.bnd
diff --git a/biz.aQute.bndlib/test/redirectws/bnd/ext/test.bnd b/biz.aQute.bndlib.tests/test/redirectws/bnd/ext/test.bnd
similarity index 100%
rename from biz.aQute.bndlib/test/redirectws/bnd/ext/test.bnd
rename to biz.aQute.bndlib.tests/test/redirectws/bnd/ext/test.bnd
diff --git a/biz.aQute.bndlib/test/redirectws/wss/ws/cnf b/biz.aQute.bndlib.tests/test/redirectws/wss/ws/cnf
similarity index 100%
rename from biz.aQute.bndlib/test/redirectws/wss/ws/cnf
rename to biz.aQute.bndlib.tests/test/redirectws/wss/ws/cnf
diff --git a/biz.aQute.bndlib.tests/test/w o r k s p a c e/cnf/build.bnd b/biz.aQute.bndlib.tests/test/w o r k s p a c e/cnf/build.bnd
new file mode 100644
index 0000000..2d9eb9a
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/w o r k s p a c e/cnf/build.bnd	
@@ -0,0 +1,3 @@
+test=abcdef
+override=parent
+-plugin: ${ext.extension.-plugin},ParentPlugin
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/w o r k s p a c e/cnf/ext/extension.bnd b/biz.aQute.bndlib.tests/test/w o r k s p a c e/cnf/ext/extension.bnd
new file mode 100644
index 0000000..7b34db3
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/w o r k s p a c e/cnf/ext/extension.bnd	
@@ -0,0 +1,3 @@
+ext = true
+override = extension
+-plugin: ExtPlugin
\ No newline at end of file
diff --git a/biz.aQute.bndlib/test/w o r k s p a c e/p r o j e c t/bnd.bnd b/biz.aQute.bndlib.tests/test/w o r k s p a c e/p r o j e c t/bnd.bnd
similarity index 100%
copy from biz.aQute.bndlib/test/w o r k s p a c e/p r o j e c t/bnd.bnd
copy to biz.aQute.bndlib.tests/test/w o r k s p a c e/p r o j e c t/bnd.bnd
diff --git a/biz.aQute.bndlib.tests/test/ws-repo-test/cnf/build.bnd b/biz.aQute.bndlib.tests/test/ws-repo-test/cnf/build.bnd
new file mode 100644
index 0000000..f0e7872
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/ws-repo-test/cnf/build.bnd
@@ -0,0 +1,9 @@
+build = sometime
+
+-plugin	            	= \
+						aQute.lib.deployer.FileRepo; \
+                                location=${workspace}/cnf/releaserepo; \
+                                readonly=false;name=Release, \
+                        aQute.lib.deployer.FileRepo; \
+                                location=${workspace}/cnf/repo; \
+                                readonly=true
\ No newline at end of file
diff --git a/biz.aQute.bndlib/test/ws/cnf/repo/libtest/libtest-1.0.0.lib b/biz.aQute.bndlib.tests/test/ws-repo-test/cnf/repo/libtest/libtest-1.0.0.lib
similarity index 100%
copy from biz.aQute.bndlib/test/ws/cnf/repo/libtest/libtest-1.0.0.lib
copy to biz.aQute.bndlib.tests/test/ws-repo-test/cnf/repo/libtest/libtest-1.0.0.lib
diff --git a/biz.aQute.bndlib/test/ws/p1/bnd.bnd b/biz.aQute.bndlib.tests/test/ws-repo-test/p1/bnd.bnd
similarity index 100%
copy from biz.aQute.bndlib/test/ws/p1/bnd.bnd
copy to biz.aQute.bndlib.tests/test/ws-repo-test/p1/bnd.bnd
diff --git a/biz.aQute.bndlib/test/ws/p1/p1a.bndrun b/biz.aQute.bndlib.tests/test/ws-repo-test/p1/p1a.bndrun
similarity index 100%
copy from biz.aQute.bndlib/test/ws/p1/p1a.bndrun
copy to biz.aQute.bndlib.tests/test/ws-repo-test/p1/p1a.bndrun
diff --git a/biz.aQute.bndlib/test/ws/p1/p1b.bndrun b/biz.aQute.bndlib.tests/test/ws-repo-test/p1/p1b.bndrun
similarity index 100%
copy from biz.aQute.bndlib/test/ws/p1/p1b.bndrun
copy to biz.aQute.bndlib.tests/test/ws-repo-test/p1/p1b.bndrun
diff --git a/biz.aQute.bndlib/test/ws/p2/Resources/more/resource6.txt b/biz.aQute.bndlib.tests/test/ws-repo-test/p2/Resources/more/resource6.txt
similarity index 100%
copy from biz.aQute.bndlib/test/ws/p2/Resources/more/resource6.txt
copy to biz.aQute.bndlib.tests/test/ws-repo-test/p2/Resources/more/resource6.txt
diff --git a/biz.aQute.bndlib/test/ws/p2/Resources/more/resource7.txt b/biz.aQute.bndlib.tests/test/ws-repo-test/p2/Resources/more/resource7.txt
similarity index 100%
copy from biz.aQute.bndlib/test/ws/p2/Resources/more/resource7.txt
copy to biz.aQute.bndlib.tests/test/ws-repo-test/p2/Resources/more/resource7.txt
diff --git a/biz.aQute.bndlib/test/ws/p2/Resources/more/resource8.res b/biz.aQute.bndlib.tests/test/ws-repo-test/p2/Resources/more/resource8.res
similarity index 100%
copy from biz.aQute.bndlib/test/ws/p2/Resources/more/resource8.res
copy to biz.aQute.bndlib.tests/test/ws-repo-test/p2/Resources/more/resource8.res
diff --git a/biz.aQute.bndlib/test/ws/p2/Resources/resource1.res b/biz.aQute.bndlib.tests/test/ws-repo-test/p2/Resources/resource1.res
similarity index 100%
copy from biz.aQute.bndlib/test/ws/p2/Resources/resource1.res
copy to biz.aQute.bndlib.tests/test/ws-repo-test/p2/Resources/resource1.res
diff --git a/biz.aQute.bndlib/test/ws/p2/Resources/resource2.res b/biz.aQute.bndlib.tests/test/ws-repo-test/p2/Resources/resource2.res
similarity index 100%
copy from biz.aQute.bndlib/test/ws/p2/Resources/resource2.res
copy to biz.aQute.bndlib.tests/test/ws-repo-test/p2/Resources/resource2.res
diff --git a/biz.aQute.bndlib/test/ws/p2/Resources/resource3.txt b/biz.aQute.bndlib.tests/test/ws-repo-test/p2/Resources/resource3.txt
similarity index 100%
copy from biz.aQute.bndlib/test/ws/p2/Resources/resource3.txt
copy to biz.aQute.bndlib.tests/test/ws-repo-test/p2/Resources/resource3.txt
diff --git a/biz.aQute.bndlib/test/ws/p2/Resources/resource4.txt b/biz.aQute.bndlib.tests/test/ws-repo-test/p2/Resources/resource4.txt
similarity index 100%
copy from biz.aQute.bndlib/test/ws/p2/Resources/resource4.txt
copy to biz.aQute.bndlib.tests/test/ws-repo-test/p2/Resources/resource4.txt
diff --git a/biz.aQute.bndlib/test/ws/p2/Resources/resource5.asc b/biz.aQute.bndlib.tests/test/ws-repo-test/p2/Resources/resource5.asc
similarity index 100%
copy from biz.aQute.bndlib/test/ws/p2/Resources/resource5.asc
copy to biz.aQute.bndlib.tests/test/ws-repo-test/p2/Resources/resource5.asc
diff --git a/biz.aQute.bndlib/test/ws/p2/Resources/stuff/resource9.res b/biz.aQute.bndlib.tests/test/ws-repo-test/p2/Resources/stuff/resource9.res
similarity index 100%
copy from biz.aQute.bndlib/test/ws/p2/Resources/stuff/resource9.res
copy to biz.aQute.bndlib.tests/test/ws-repo-test/p2/Resources/stuff/resource9.res
diff --git a/biz.aQute.bndlib/test/ws/p2/Resources/text.txt b/biz.aQute.bndlib.tests/test/ws-repo-test/p2/Resources/text.txt
similarity index 100%
copy from biz.aQute.bndlib/test/ws/p2/Resources/text.txt
copy to biz.aQute.bndlib.tests/test/ws-repo-test/p2/Resources/text.txt
diff --git a/biz.aQute.bndlib/test/ws/p2/bnd.bnd b/biz.aQute.bndlib.tests/test/ws-repo-test/p2/bnd.bnd
similarity index 100%
copy from biz.aQute.bndlib/test/ws/p2/bnd.bnd
copy to biz.aQute.bndlib.tests/test/ws-repo-test/p2/bnd.bnd
diff --git a/biz.aQute.bndlib/test/ws/p3/bnd.bnd b/biz.aQute.bndlib.tests/test/ws-repo-test/p3/bnd.bnd
similarity index 100%
copy from biz.aQute.bndlib/test/ws/p3/bnd.bnd
copy to biz.aQute.bndlib.tests/test/ws-repo-test/p3/bnd.bnd
diff --git a/biz.aQute.bndlib/test/ws/p4-sub/a.bnd b/biz.aQute.bndlib.tests/test/ws-repo-test/p4-sub/a.bnd
similarity index 100%
copy from biz.aQute.bndlib/test/ws/p4-sub/a.bnd
copy to biz.aQute.bndlib.tests/test/ws-repo-test/p4-sub/a.bnd
diff --git a/biz.aQute.bndlib/test/ws/p4-sub/b.bnd b/biz.aQute.bndlib.tests/test/ws-repo-test/p4-sub/b.bnd
similarity index 100%
copy from biz.aQute.bndlib/test/ws/p4-sub/b.bnd
copy to biz.aQute.bndlib.tests/test/ws-repo-test/p4-sub/b.bnd
diff --git a/biz.aQute.bndlib/test/ws/p4-sub/bnd.bnd b/biz.aQute.bndlib.tests/test/ws-repo-test/p4-sub/bnd.bnd
similarity index 100%
copy from biz.aQute.bndlib/test/ws/p4-sub/bnd.bnd
copy to biz.aQute.bndlib.tests/test/ws-repo-test/p4-sub/bnd.bnd
diff --git a/biz.aQute.bndlib/test/ws/p4-sub/c.bnd b/biz.aQute.bndlib.tests/test/ws-repo-test/p4-sub/c.bnd
similarity index 100%
copy from biz.aQute.bndlib/test/ws/p4-sub/c.bnd
copy to biz.aQute.bndlib.tests/test/ws-repo-test/p4-sub/c.bnd
diff --git a/biz.aQute.bndlib.tests/test/ws-repo-test/p5/bnd.bnd b/biz.aQute.bndlib.tests/test/ws-repo-test/p5/bnd.bnd
new file mode 100644
index 0000000..9fdbe41
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/ws-repo-test/p5/bnd.bnd
@@ -0,0 +1 @@
+Bundle-Version: 1.0.0-FOOBAR
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/ws/bug194/bnd.bnd b/biz.aQute.bndlib.tests/test/ws/bug194/bnd.bnd
new file mode 100644
index 0000000..b8bc74e
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/ws/bug194/bnd.bnd
@@ -0,0 +1 @@
+-runbundles: bug194;version=latest
diff --git a/biz.aQute.bndlib/test/w o r k s p a c e/p r o j e c t/bnd.bnd b/biz.aQute.bndlib.tests/test/ws/build-all/bnd.bnd
similarity index 100%
rename from biz.aQute.bndlib/test/w o r k s p a c e/p r o j e c t/bnd.bnd
rename to biz.aQute.bndlib.tests/test/ws/build-all/bnd.bnd
diff --git a/biz.aQute.bndlib.tests/test/ws/bump-included/bnd.bnd b/biz.aQute.bndlib.tests/test/ws/bump-included/bnd.bnd
new file mode 100644
index 0000000..e4ace50
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/ws/bump-included/bnd.bnd
@@ -0,0 +1 @@
+-include: include.txt
diff --git a/biz.aQute.bndlib.tests/test/ws/bump-included/include.txt b/biz.aQute.bndlib.tests/test/ws/bump-included/include.txt
new file mode 100644
index 0000000..ea46fde
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/ws/bump-included/include.txt
@@ -0,0 +1,3 @@
+# Heullo
+
+Bundle-Version: 1.0
diff --git a/biz.aQute.bndlib.tests/test/ws/bump-sub/a.bnd b/biz.aQute.bndlib.tests/test/ws/bump-sub/a.bnd
new file mode 100644
index 0000000..ea46fde
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/ws/bump-sub/a.bnd
@@ -0,0 +1,3 @@
+# Heullo
+
+Bundle-Version: 1.0
diff --git a/biz.aQute.bndlib.tests/test/ws/bump-sub/b.bnd b/biz.aQute.bndlib.tests/test/ws/bump-sub/b.bnd
new file mode 100644
index 0000000..ea46fde
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/ws/bump-sub/b.bnd
@@ -0,0 +1,3 @@
+# Heullo
+
+Bundle-Version: 1.0
diff --git a/biz.aQute.bndlib.tests/test/ws/bump-sub/bnd.bnd b/biz.aQute.bndlib.tests/test/ws/bump-sub/bnd.bnd
new file mode 100644
index 0000000..a1eecfd
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/ws/bump-sub/bnd.bnd
@@ -0,0 +1 @@
+-sub: *.bnd
diff --git a/biz.aQute.bndlib.tests/test/ws/cnf/build.bnd b/biz.aQute.bndlib.tests/test/ws/cnf/build.bnd
new file mode 100644
index 0000000..b78063a
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/ws/cnf/build.bnd
@@ -0,0 +1,9 @@
+build = sometime
+
+-plugin	            	= \
+						aQute.lib.deployer.FileRepo; \
+                                location=${workspace}/cnf/releaserepo; \
+                                readonly=false;name=Release, \
+                        aQute.lib.deployer.FileRepo; \
+                                location=${workspace}/cnf/repo; \
+                                readonly=true;name=Repo
\ No newline at end of file
diff --git a/biz.aQute.bndlib/test/ws/cnf/repo/libtest/libtest-1.0.0.lib b/biz.aQute.bndlib.tests/test/ws/cnf/repo/libtest/libtest-1.0.0.lib
similarity index 100%
rename from biz.aQute.bndlib/test/ws/cnf/repo/libtest/libtest-1.0.0.lib
rename to biz.aQute.bndlib.tests/test/ws/cnf/repo/libtest/libtest-1.0.0.lib
diff --git a/biz.aQute.bndlib/test/ws/maven1/bnd.bnd b/biz.aQute.bndlib.tests/test/ws/maven1/bnd.bnd
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/bnd.bnd
rename to biz.aQute.bndlib.tests/test/ws/maven1/bnd.bnd
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.6.1/_maven.repositories b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.6.1/_maven.repositories
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.6.1/_maven.repositories
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.6.1/_maven.repositories
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.6.1/com.springsource.org.apache.commons.beanutils-1.6.1.jar.sha1 b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.6.1/com.springsource.org.apache.commons.beanutils-1.6.1.jar.sha1
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.6.1/com.springsource.org.apache.commons.beanutils-1.6.1.jar.sha1
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.6.1/com.springsource.org.apache.commons.beanutils-1.6.1.jar.sha1
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.6.1/com.springsource.org.apache.commons.beanutils-1.6.1.pom b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.6.1/com.springsource.org.apache.commons.beanutils-1.6.1.pom
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.6.1/com.springsource.org.apache.commons.beanutils-1.6.1.pom
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.6.1/com.springsource.org.apache.commons.beanutils-1.6.1.pom
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.6.1/com.springsource.org.apache.commons.beanutils-1.6.1.pom.sha1 b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.6.1/com.springsource.org.apache.commons.beanutils-1.6.1.pom.sha1
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.6.1/com.springsource.org.apache.commons.beanutils-1.6.1.pom.sha1
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.6.1/com.springsource.org.apache.commons.beanutils-1.6.1.pom.sha1
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.7.0/_maven.repositories b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.7.0/_maven.repositories
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.7.0/_maven.repositories
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.7.0/_maven.repositories
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.7.0/com.springsource.org.apache.commons.beanutils-1.7.0.pom b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.7.0/com.springsource.org.apache.commons.beanutils-1.7.0.pom
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.7.0/com.springsource.org.apache.commons.beanutils-1.7.0.pom
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.7.0/com.springsource.org.apache.commons.beanutils-1.7.0.pom
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.7.0/com.springsource.org.apache.commons.beanutils-1.7.0.pom.lastUpdated b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.7.0/com.springsource.org.apache.commons.beanutils-1.7.0.pom.lastUpdated
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.7.0/com.springsource.org.apache.commons.beanutils-1.7.0.pom.lastUpdated
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.7.0/com.springsource.org.apache.commons.beanutils-1.7.0.pom.lastUpdated
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.7.0/com.springsource.org.apache.commons.beanutils-1.7.0.pom.sha1 b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.7.0/com.springsource.org.apache.commons.beanutils-1.7.0.pom.sha1
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.7.0/com.springsource.org.apache.commons.beanutils-1.7.0.pom.sha1
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.beanutils/1.7.0/com.springsource.org.apache.commons.beanutils-1.7.0.pom.sha1
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.codec/1.3.0/_maven.repositories b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.codec/1.3.0/_maven.repositories
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.codec/1.3.0/_maven.repositories
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.codec/1.3.0/_maven.repositories
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.codec/1.3.0/com.springsource.org.apache.commons.codec-1.3.0.pom b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.codec/1.3.0/com.springsource.org.apache.commons.codec-1.3.0.pom
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.codec/1.3.0/com.springsource.org.apache.commons.codec-1.3.0.pom
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.codec/1.3.0/com.springsource.org.apache.commons.codec-1.3.0.pom
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.codec/1.3.0/com.springsource.org.apache.commons.codec-1.3.0.pom.lastUpdated b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.codec/1.3.0/com.springsource.org.apache.commons.codec-1.3.0.pom.lastUpdated
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.codec/1.3.0/com.springsource.org.apache.commons.codec-1.3.0.pom.lastUpdated
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.codec/1.3.0/com.springsource.org.apache.commons.codec-1.3.0.pom.lastUpdated
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.codec/1.3.0/com.springsource.org.apache.commons.codec-1.3.0.pom.sha1 b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.codec/1.3.0/com.springsource.org.apache.commons.codec-1.3.0.pom.sha1
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.codec/1.3.0/com.springsource.org.apache.commons.codec-1.3.0.pom.sha1
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.codec/1.3.0/com.springsource.org.apache.commons.codec-1.3.0.pom.sha1
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/_maven.repositories b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/_maven.repositories
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/_maven.repositories
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/_maven.repositories
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/com.springsource.org.apache.commons.collections-2.1.1.jar.lastUpdated b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/com.springsource.org.apache.commons.collections-2.1.1.jar.lastUpdated
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/com.springsource.org.apache.commons.collections-2.1.1.jar.lastUpdated
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/com.springsource.org.apache.commons.collections-2.1.1.jar.lastUpdated
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/com.springsource.org.apache.commons.collections-2.1.1.jar.sha1 b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/com.springsource.org.apache.commons.collections-2.1.1.jar.sha1
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/com.springsource.org.apache.commons.collections-2.1.1.jar.sha1
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/com.springsource.org.apache.commons.collections-2.1.1.jar.sha1
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/com.springsource.org.apache.commons.collections-2.1.1.pom b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/com.springsource.org.apache.commons.collections-2.1.1.pom
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/com.springsource.org.apache.commons.collections-2.1.1.pom
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/com.springsource.org.apache.commons.collections-2.1.1.pom
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/com.springsource.org.apache.commons.collections-2.1.1.pom.lastUpdated b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/com.springsource.org.apache.commons.collections-2.1.1.pom.lastUpdated
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/com.springsource.org.apache.commons.collections-2.1.1.pom.lastUpdated
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/com.springsource.org.apache.commons.collections-2.1.1.pom.lastUpdated
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/com.springsource.org.apache.commons.collections-2.1.1.pom.sha1 b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/com.springsource.org.apache.commons.collections-2.1.1.pom.sha1
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/com.springsource.org.apache.commons.collections-2.1.1.pom.sha1
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/2.1.1/com.springsource.org.apache.commons.collections-2.1.1.pom.sha1
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/3.2.0/com.springsource.org.apache.commons.collections-3.2.0.jar.sha1 b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/3.2.0/com.springsource.org.apache.commons.collections-3.2.0.jar.sha1
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/3.2.0/com.springsource.org.apache.commons.collections-3.2.0.jar.sha1
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/3.2.0/com.springsource.org.apache.commons.collections-3.2.0.jar.sha1
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/3.2.0/com.springsource.org.apache.commons.collections-3.2.0.pom b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/3.2.0/com.springsource.org.apache.commons.collections-3.2.0.pom
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/3.2.0/com.springsource.org.apache.commons.collections-3.2.0.pom
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/3.2.0/com.springsource.org.apache.commons.collections-3.2.0.pom
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/3.2.0/com.springsource.org.apache.commons.collections-3.2.0.pom.sha1 b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/3.2.0/com.springsource.org.apache.commons.collections-3.2.0.pom.sha1
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/3.2.0/com.springsource.org.apache.commons.collections-3.2.0.pom.sha1
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.collections/3.2.0/com.springsource.org.apache.commons.collections-3.2.0.pom.sha1
diff --git a/biz.aQute.bndlib/com.springsource.org.apache.commons.logging/1.0.4/_maven.repositories b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/_maven.repositories
similarity index 100%
rename from biz.aQute.bndlib/com.springsource.org.apache.commons.logging/1.0.4/_maven.repositories
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/_maven.repositories
diff --git a/biz.aQute.bndlib/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.jar.lastUpdated b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.jar.lastUpdated
similarity index 100%
rename from biz.aQute.bndlib/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.jar.lastUpdated
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.jar.lastUpdated
diff --git a/biz.aQute.bndlib/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.jar.sha1 b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.jar.sha1
similarity index 100%
rename from biz.aQute.bndlib/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.jar.sha1
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.jar.sha1
diff --git a/biz.aQute.bndlib/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.pom b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.pom
similarity index 100%
rename from biz.aQute.bndlib/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.pom
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.pom
diff --git a/biz.aQute.bndlib/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.pom.lastUpdated b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.pom.lastUpdated
similarity index 100%
rename from biz.aQute.bndlib/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.pom.lastUpdated
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.pom.lastUpdated
diff --git a/biz.aQute.bndlib/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.pom.sha1 b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.pom.sha1
similarity index 100%
rename from biz.aQute.bndlib/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.pom.sha1
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.pom.sha1
diff --git a/biz.aQute.bndlib/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar.sha1 b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar.sha1
similarity index 100%
rename from biz.aQute.bndlib/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar.sha1
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar.sha1
diff --git a/biz.aQute.bndlib/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.pom b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.pom
similarity index 100%
rename from biz.aQute.bndlib/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.pom
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.pom
diff --git a/biz.aQute.bndlib/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.pom.sha1 b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.pom.sha1
similarity index 100%
rename from biz.aQute.bndlib/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.pom.sha1
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.pom.sha1
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.jar.sha1 b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.jar.sha1
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.jar.sha1
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.jar.sha1
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.pom b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.pom
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.pom
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.pom
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.pom.sha1 b/biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.pom.sha1
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/m2/org/apache/log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.pom.sha1
rename to biz.aQute.bndlib.tests/test/ws/maven1/m2/org/apache/log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.pom.sha1
diff --git a/biz.aQute.bndlib/test/ws/maven1/maven-dependencies.txt b/biz.aQute.bndlib.tests/test/ws/maven1/maven-dependencies.txt
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/maven-dependencies.txt
rename to biz.aQute.bndlib.tests/test/ws/maven1/maven-dependencies.txt
diff --git a/biz.aQute.bndlib/test/ws/maven1/mvndeploy b/biz.aQute.bndlib.tests/test/ws/maven1/mvndeploy
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/mvndeploy
rename to biz.aQute.bndlib.tests/test/ws/maven1/mvndeploy
diff --git a/biz.aQute.bndlib/test/ws/maven1/parentpom.xml b/biz.aQute.bndlib.tests/test/ws/maven1/parentpom.xml
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/parentpom.xml
rename to biz.aQute.bndlib.tests/test/ws/maven1/parentpom.xml
diff --git a/biz.aQute.bndlib/test/ws/maven1/pom.xml b/biz.aQute.bndlib.tests/test/ws/maven1/pom.xml
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/pom.xml
rename to biz.aQute.bndlib.tests/test/ws/maven1/pom.xml
diff --git a/biz.aQute.bndlib/test/ws/maven1/testparentpom.xml b/biz.aQute.bndlib.tests/test/ws/maven1/testparentpom.xml
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/testparentpom.xml
rename to biz.aQute.bndlib.tests/test/ws/maven1/testparentpom.xml
diff --git a/biz.aQute.bndlib/test/ws/maven1/testpom.xml b/biz.aQute.bndlib.tests/test/ws/maven1/testpom.xml
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven1/testpom.xml
rename to biz.aQute.bndlib.tests/test/ws/maven1/testpom.xml
diff --git a/biz.aQute.bndlib/test/ws/maven2/bnd.bnd b/biz.aQute.bndlib.tests/test/ws/maven2/bnd.bnd
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven2/bnd.bnd
rename to biz.aQute.bndlib.tests/test/ws/maven2/bnd.bnd
diff --git a/biz.aQute.bndlib/test/ws/maven2/parentpom.xml b/biz.aQute.bndlib.tests/test/ws/maven2/parentpom.xml
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven2/parentpom.xml
rename to biz.aQute.bndlib.tests/test/ws/maven2/parentpom.xml
diff --git a/biz.aQute.bndlib/test/ws/maven2/pom.xml b/biz.aQute.bndlib.tests/test/ws/maven2/pom.xml
similarity index 100%
rename from biz.aQute.bndlib/test/ws/maven2/pom.xml
rename to biz.aQute.bndlib.tests/test/ws/maven2/pom.xml
diff --git a/biz.aQute.bndlib/test/ws/p-maven-remote/bnd.bnd b/biz.aQute.bndlib.tests/test/ws/p-maven-remote/bnd.bnd
similarity index 100%
rename from biz.aQute.bndlib/test/ws/p-maven-remote/bnd.bnd
rename to biz.aQute.bndlib.tests/test/ws/p-maven-remote/bnd.bnd
diff --git a/biz.aQute.bndlib.tests/test/ws/p-stale-dep/bnd.bnd b/biz.aQute.bndlib.tests/test/ws/p-stale-dep/bnd.bnd
new file mode 100644
index 0000000..06d1caf
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/ws/p-stale-dep/bnd.bnd
@@ -0,0 +1,3 @@
+Bundle-Version:	1.2.3.${build}
+Include-Resource: p;literal="hello"
+-runbuilds: false 
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/ws/p-stale/bnd.bnd b/biz.aQute.bndlib.tests/test/ws/p-stale/bnd.bnd
new file mode 100644
index 0000000..038d480
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/ws/p-stale/bnd.bnd
@@ -0,0 +1,3 @@
+-resourceonly:
+Include-Resource: p;literal="hello"
+-dependson: p-stale-dep
\ No newline at end of file
diff --git a/biz.aQute.bndlib/test/ws/p1/bnd.bnd b/biz.aQute.bndlib.tests/test/ws/p1/bnd.bnd
similarity index 100%
rename from biz.aQute.bndlib/test/ws/p1/bnd.bnd
rename to biz.aQute.bndlib.tests/test/ws/p1/bnd.bnd
diff --git a/biz.aQute.bndlib/test/ws/p1/p1a.bndrun b/biz.aQute.bndlib.tests/test/ws/p1/p1a.bndrun
similarity index 100%
rename from biz.aQute.bndlib/test/ws/p1/p1a.bndrun
rename to biz.aQute.bndlib.tests/test/ws/p1/p1a.bndrun
diff --git a/biz.aQute.bndlib/test/ws/p1/p1b.bndrun b/biz.aQute.bndlib.tests/test/ws/p1/p1b.bndrun
similarity index 100%
rename from biz.aQute.bndlib/test/ws/p1/p1b.bndrun
rename to biz.aQute.bndlib.tests/test/ws/p1/p1b.bndrun
diff --git a/biz.aQute.bndlib/test/ws/p2/Resources/more/resource6.txt b/biz.aQute.bndlib.tests/test/ws/p2/Resources/more/resource6.txt
similarity index 100%
rename from biz.aQute.bndlib/test/ws/p2/Resources/more/resource6.txt
rename to biz.aQute.bndlib.tests/test/ws/p2/Resources/more/resource6.txt
diff --git a/biz.aQute.bndlib/test/ws/p2/Resources/more/resource7.txt b/biz.aQute.bndlib.tests/test/ws/p2/Resources/more/resource7.txt
similarity index 100%
rename from biz.aQute.bndlib/test/ws/p2/Resources/more/resource7.txt
rename to biz.aQute.bndlib.tests/test/ws/p2/Resources/more/resource7.txt
diff --git a/biz.aQute.bndlib/test/ws/p2/Resources/more/resource8.res b/biz.aQute.bndlib.tests/test/ws/p2/Resources/more/resource8.res
similarity index 100%
rename from biz.aQute.bndlib/test/ws/p2/Resources/more/resource8.res
rename to biz.aQute.bndlib.tests/test/ws/p2/Resources/more/resource8.res
diff --git a/biz.aQute.bndlib/test/ws/p2/Resources/resource1.res b/biz.aQute.bndlib.tests/test/ws/p2/Resources/resource1.res
similarity index 100%
rename from biz.aQute.bndlib/test/ws/p2/Resources/resource1.res
rename to biz.aQute.bndlib.tests/test/ws/p2/Resources/resource1.res
diff --git a/biz.aQute.bndlib/test/ws/p2/Resources/resource2.res b/biz.aQute.bndlib.tests/test/ws/p2/Resources/resource2.res
similarity index 100%
rename from biz.aQute.bndlib/test/ws/p2/Resources/resource2.res
rename to biz.aQute.bndlib.tests/test/ws/p2/Resources/resource2.res
diff --git a/biz.aQute.bndlib/test/ws/p2/Resources/resource3.txt b/biz.aQute.bndlib.tests/test/ws/p2/Resources/resource3.txt
similarity index 100%
rename from biz.aQute.bndlib/test/ws/p2/Resources/resource3.txt
rename to biz.aQute.bndlib.tests/test/ws/p2/Resources/resource3.txt
diff --git a/biz.aQute.bndlib/test/ws/p2/Resources/resource4.txt b/biz.aQute.bndlib.tests/test/ws/p2/Resources/resource4.txt
similarity index 100%
rename from biz.aQute.bndlib/test/ws/p2/Resources/resource4.txt
rename to biz.aQute.bndlib.tests/test/ws/p2/Resources/resource4.txt
diff --git a/biz.aQute.bndlib/test/ws/p2/Resources/resource5.asc b/biz.aQute.bndlib.tests/test/ws/p2/Resources/resource5.asc
similarity index 100%
rename from biz.aQute.bndlib/test/ws/p2/Resources/resource5.asc
rename to biz.aQute.bndlib.tests/test/ws/p2/Resources/resource5.asc
diff --git a/biz.aQute.bndlib/test/ws/p2/Resources/stuff/resource9.res b/biz.aQute.bndlib.tests/test/ws/p2/Resources/stuff/resource9.res
similarity index 100%
rename from biz.aQute.bndlib/test/ws/p2/Resources/stuff/resource9.res
rename to biz.aQute.bndlib.tests/test/ws/p2/Resources/stuff/resource9.res
diff --git a/biz.aQute.bndlib/test/ws/p2/Resources/text.txt b/biz.aQute.bndlib.tests/test/ws/p2/Resources/text.txt
similarity index 100%
rename from biz.aQute.bndlib/test/ws/p2/Resources/text.txt
rename to biz.aQute.bndlib.tests/test/ws/p2/Resources/text.txt
diff --git a/biz.aQute.bndlib/test/ws/p2/bnd.bnd b/biz.aQute.bndlib.tests/test/ws/p2/bnd.bnd
similarity index 100%
rename from biz.aQute.bndlib/test/ws/p2/bnd.bnd
rename to biz.aQute.bndlib.tests/test/ws/p2/bnd.bnd
diff --git a/biz.aQute.bndlib/test/ws/p3/bnd.bnd b/biz.aQute.bndlib.tests/test/ws/p3/bnd.bnd
similarity index 100%
rename from biz.aQute.bndlib/test/ws/p3/bnd.bnd
rename to biz.aQute.bndlib.tests/test/ws/p3/bnd.bnd
diff --git a/biz.aQute.bndlib/test/ws/p4-sub/a.bnd b/biz.aQute.bndlib.tests/test/ws/p4-sub/a.bnd
similarity index 100%
rename from biz.aQute.bndlib/test/ws/p4-sub/a.bnd
rename to biz.aQute.bndlib.tests/test/ws/p4-sub/a.bnd
diff --git a/biz.aQute.bndlib/test/ws/p4-sub/b.bnd b/biz.aQute.bndlib.tests/test/ws/p4-sub/b.bnd
similarity index 100%
rename from biz.aQute.bndlib/test/ws/p4-sub/b.bnd
rename to biz.aQute.bndlib.tests/test/ws/p4-sub/b.bnd
diff --git a/biz.aQute.bndlib/test/ws/p4-sub/bnd.bnd b/biz.aQute.bndlib.tests/test/ws/p4-sub/bnd.bnd
similarity index 100%
rename from biz.aQute.bndlib/test/ws/p4-sub/bnd.bnd
rename to biz.aQute.bndlib.tests/test/ws/p4-sub/bnd.bnd
diff --git a/biz.aQute.bndlib/test/ws/p4-sub/c.bnd b/biz.aQute.bndlib.tests/test/ws/p4-sub/c.bnd
similarity index 100%
rename from biz.aQute.bndlib/test/ws/p4-sub/c.bnd
rename to biz.aQute.bndlib.tests/test/ws/p4-sub/c.bnd
diff --git a/biz.aQute.bndlib.tests/test/ws/p5/bnd.bnd b/biz.aQute.bndlib.tests/test/ws/p5/bnd.bnd
new file mode 100644
index 0000000..0cb9e1e
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/ws/p5/bnd.bnd
@@ -0,0 +1,3 @@
+Export-Package: *
+
+src:src
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/ws/p5/src/pkg1/.keep b/biz.aQute.bndlib.tests/test/ws/p5/src/pkg1/.keep
new file mode 100644
index 0000000..c693f13
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/ws/p5/src/pkg1/.keep
@@ -0,0 +1 @@
+keep
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/ws/p5/src/pkg2/package-info.java b/biz.aQute.bndlib.tests/test/ws/p5/src/pkg2/package-info.java
new file mode 100644
index 0000000..acf214c
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/ws/p5/src/pkg2/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Package Description
+ */
+ at Version("1.0.0")
+package pkg2;
+import aQute.bnd.annotation.Version;
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/ws/p5/src/pkg3/package-info.java b/biz.aQute.bndlib.tests/test/ws/p5/src/pkg3/package-info.java
new file mode 100644
index 0000000..0af7680
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/ws/p5/src/pkg3/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * Package Description
+ */
+ at aQute.bnd.annotation.Version("1.0.0")
+package pkg3;
diff --git a/biz.aQute.bndlib.tests/test/ws/p5/src/pkg4/package-info.java b/biz.aQute.bndlib.tests/test/ws/p5/src/pkg4/package-info.java
new file mode 100644
index 0000000..ab59c9b
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/ws/p5/src/pkg4/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * Package Description
+ */
+ at aQute.bnd.annotation.Version(value="1.0.0")
+package pkg4;
diff --git a/biz.aQute.bndlib.tests/test/ws/p5/src/pkg5/package-info.java b/biz.aQute.bndlib.tests/test/ws/p5/src/pkg5/package-info.java
new file mode 100644
index 0000000..3f0c390
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/ws/p5/src/pkg5/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Package Description
+ */
+ at Version("1.0.0")
+package pkg5;
+import aQute.bnd.annotation.Version;
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/ws/p5/src/pkg5/packageinfo b/biz.aQute.bndlib.tests/test/ws/p5/src/pkg5/packageinfo
new file mode 100644
index 0000000..e252556
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/ws/p5/src/pkg5/packageinfo
@@ -0,0 +1 @@
+version 1.0.0
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/ws/p5/src/pkg6/package-info.java b/biz.aQute.bndlib.tests/test/ws/p5/src/pkg6/package-info.java
new file mode 100644
index 0000000..cd295f7
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/ws/p5/src/pkg6/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Package Description
+ */
+package pkg6;
diff --git a/biz.aQute.bndlib.tests/test/ws/p5/src/pkg6/packageinfo b/biz.aQute.bndlib.tests/test/ws/p5/src/pkg6/packageinfo
new file mode 100644
index 0000000..e252556
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/ws/p5/src/pkg6/packageinfo
@@ -0,0 +1 @@
+version 1.0.0
\ No newline at end of file
diff --git a/biz.aQute.bndlib.tests/test/ws/p5/src/pkg7/package-info.java b/biz.aQute.bndlib.tests/test/ws/p5/src/pkg7/package-info.java
new file mode 100644
index 0000000..dc3b1b6
--- /dev/null
+++ b/biz.aQute.bndlib.tests/test/ws/p5/src/pkg7/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Package Description
+ */
+package pkg7;
diff --git a/biz.aQute.bndlib/.project b/biz.aQute.bndlib/.project
index c90014e..8c1fb12 100755
--- a/biz.aQute.bndlib/.project
+++ b/biz.aQute.bndlib/.project
@@ -10,8 +10,14 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>bndtools.core.bndbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>bndtools.core.bndnature</nature>
 	</natures>
 </projectDescription>
diff --git a/biz.aQute.bndlib/.settings/org.eclipse.jdt.core.prefs b/biz.aQute.bndlib/.settings/org.eclipse.jdt.core.prefs
old mode 100755
new mode 100644
index 8d2e2af..2301ac5
--- a/biz.aQute.bndlib/.settings/org.eclipse.jdt.core.prefs
+++ b/biz.aQute.bndlib/.settings/org.eclipse.jdt.core.prefs
@@ -1,4 +1,4 @@
-#Mon Jul 14 16:25:03 CEST 2008
+#Fri Aug 10 13:46:22 CEST 2012
 eclipse.preferences.version=1
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
@@ -7,6 +7,355 @@ org.eclipse.jdt.core.compiler.compliance=1.5
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
 org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=ignore
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=true
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/biz.aQute.bndlib/.settings/org.eclipse.jdt.ui.prefs b/biz.aQute.bndlib/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..f5e8897
--- /dev/null
+++ b/biz.aQute.bndlib/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,61 @@
+#Fri Aug 10 13:48:46 CEST 2012
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=false
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=false
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=false
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
+cleanup_settings_version=2
+eclipse.preferences.version=1
+formatter_profile=_bnd(tools)
+formatter_settings_version=12
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=1
+org.eclipse.jdt.ui.staticondemandthreshold=1
diff --git a/biz.aQute.bndlib/bnd.bnd b/biz.aQute.bndlib/bnd.bnd
index 7c15a65..e583927 100644
--- a/biz.aQute.bndlib/bnd.bnd
+++ b/biz.aQute.bndlib/bnd.bnd
@@ -7,34 +7,52 @@ Bundle-License: 				http://www.opensource.org/licenses/apache2.0.php; \
 									description="Apache Software License 2.0"; \
 									link=http://www.apache.org/licenses/LICENSE-2.0.html
 Bundle-DocURL:          		http://www.aQute.biz/Code/Bnd
-Bundle-Name: 					bnd - Bundle Tool
+Bundle-Name: 					bndlib
 Bundle-Description:				A Swiss Army Knife for OSGi
 Bundle-SymbolicName: 	        biz.aQute.bndlib
-Private-Package: 				aQute.bnd.*, aQute.lib.*, org.osgi.service.component.annotations
+
+Private-Package: 				\
+	aQute.bnd.*, \
+	aQute.lib.*;-split-package:=first, \
+	aQute.libg.*;-split-package:=first, \
+	org.osgi.service.component.annotations
+
 Export-Package: aQute.bnd.annotation.*,\
-	aQute.lib.osgi,\
+	aQute.bnd.osgi,\
+	aQute.bnd.osgi.resource,\
 	aQute.bnd.build,\
+	aQute.bnd.differ,\
 	aQute.bnd.service.*,\
 	aQute.bnd.help.*,\
-	aQute.libg.reporter,\
-	aQute.libg.version,\
-	aQute.libg.sed,\
-	aQute.libg.header,\
-	aQute.libg.qtokens,\
-	aQute.libg.sax,\
-	org.osgi.service.bindex
-#Workaround, bnd should be adding this automatically:
-Import-Package: org.osgi.service.bindex,*
+	org.osgi.service.repository,\
+	org.osgi.resource,\
+	aQute.bnd.header,\
+	aQute.bnd.version,\
+	aQute.bnd.filerepo,\
+	aQute.bnd.properties,\
+	aQute.bnd.build.model,\
+	aQute.bnd.build.model.clauses,\
+	aQute.service.reporter,\
+	aQute.bnd.maven.support
 
-Conditional-Package:	        aQute.libg.*, aQute.lib.*, aQute.service.*
-Include-Resource: 				LICENSE
+Conditional-Package:	        aQute.service.*, aQute.configurable
+Include-Resource: 				LICENSE, img/=img/
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
 
 -buildpath: com.springsource.junit,\
 	osgi.cmpn;version=4.3,\
 	aQute.libg;version=project,\
-	osgi.core;version=4.1, \
-	ee.j2se; version=1.5, \
-	org.osgi.impl.bundle.bindex
+	osgi.core;version=4.1,\
+	osgi.r5;version=1.0.1,\
+	ee.j2se;version=${javac.ee}
+
+Bundle-Version: 2.1.0.${tstamp;yyyyMMdd-HHmmss}
+Import-Package: junit.framework;resolution:=optional,\
+	org.osgi.resource;resolution:=optional,\
+	org.osgi.framework;version='[1.5,2)',\
+	*
 
-Bundle-Version: 1.49.0
+Bundle-Icon: img/bnd-64.png;size=64
+Bundle-Developers: peter.kriens at aQute.biz, njbartlett at gmail.com
+Bundle-Contributors: per.kristian.soreide at comactivity.net, ferry.huberts at pelagic.nl, bj at bjhargrave.com
+Bundle-SCM: git at github.com:bndtools/bnd.git
diff --git a/biz.aQute.bndlib/bnd/ondemand.bnd b/biz.aQute.bndlib/bnd/ondemand.bnd
deleted file mode 100644
index 979d4e3..0000000
--- a/biz.aQute.bndlib/bnd/ondemand.bnd
+++ /dev/null
@@ -1 +0,0 @@
-Export-Package: aQute.bnd.make
diff --git a/biz.aQute.bndlib/img/bnd-64.png b/biz.aQute.bndlib/img/bnd-64.png
new file mode 100644
index 0000000..4eadaff
Binary files /dev/null and b/biz.aQute.bndlib/img/bnd-64.png differ
diff --git a/biz.aQute.bndlib/src/DefaultPackage.java b/biz.aQute.bndlib/src/DefaultPackage.java
deleted file mode 100644
index 11ba69f..0000000
--- a/biz.aQute.bndlib/src/DefaultPackage.java
+++ /dev/null
@@ -1,4 +0,0 @@
-
-public class DefaultPackage {
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/annotation/ConsumerType.java b/biz.aQute.bndlib/src/aQute/bnd/annotation/ConsumerType.java
index cbbc17b..1909410 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/annotation/ConsumerType.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/annotation/ConsumerType.java
@@ -3,12 +3,19 @@ package aQute.bnd.annotation;
 import java.lang.annotation.*;
 
 /**
- * Adding this annotation to a type in an API package indicates the the owner of
+ * <p>
+ * Adding this annotation to a type in an API package indicates that the owner of
  * that package will not change this interface in a minor update. Any backward
- * compatible change to this interface requires a major update of the version of
- * this package.
- * 
+ * incompatible change to this interface requires a major update of the version
+ * of this package. This annotation is provided for convenience because it is the default. 
+ * </p>
+ * <p>
+ * For an elaborate and simple explanation, see {@link ProviderType}.
+ * </p>
  */
- at Retention(RetentionPolicy.CLASS) @Target(ElementType.TYPE) public @interface ConsumerType {
+ at Documented
+ at Retention(RetentionPolicy.CLASS)
+ at Target(ElementType.TYPE)
+public @interface ConsumerType {
 
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/annotation/Export.java b/biz.aQute.bndlib/src/aQute/bnd/annotation/Export.java
index 27ea389..4389c77 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/annotation/Export.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/annotation/Export.java
@@ -2,29 +2,21 @@ package aQute.bnd.annotation;
 
 import java.lang.annotation.*;
 
+ at Documented
 @Retention(RetentionPolicy.CLASS)
 @Target(ElementType.PACKAGE)
 public @interface Export {
-    String MANDATORY = "mandatory";
-    String OPTIONAL  = "optional";
-    String USES      = "uses";
-    String EXCLUDE   = "exclude";
-    String INCLUDE   = "include";
+	String	MANDATORY	= "mandatory";
+	String	OPTIONAL	= "optional";
+	String	USES		= "uses";
+	String	EXCLUDE		= "exclude";
+	String	INCLUDE		= "include";
 
-    String[] mandatory() default "";
+	String[] mandatory() default "";
 
-    String[] optional() default "";
+	String[] optional() default "";
 
-    Class<?>[] exclude() default Object.class;
+	Class< ? >[] exclude() default Object.class;
 
-    Class<?>[] include() default Object.class;
-    
-    /**
-     * Use {@link @Version} annotation instead
-     * @return
-     */
-    @Deprecated()
-    String version() default "";
-    
-    
+	Class< ? >[] include() default Object.class;
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/annotation/ProviderType.java b/biz.aQute.bndlib/src/aQute/bnd/annotation/ProviderType.java
index 15ee17e..926fe93 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/annotation/ProviderType.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/annotation/ProviderType.java
@@ -3,15 +3,63 @@ package aQute.bnd.annotation;
 import java.lang.annotation.*;
 
 /**
- * This type is provided for convenience because it is the default. A change 
- * in a provider type (that is all except Consumer types) can be changed with
- * only a minor update to the package API version number.
- * 
- * This interface is similar to the Eclipse @noextend and @noimplement annotations.
- * 
- * 
- * 
+ * <p>
+ * A change in
+ * a provider type (that is all except Consumer types) can be changed with only
+ * (at minimum) a minor update to the package API version number. This interface
+ * is similar to the Eclipse @noextend and @noimplement annotations. OSGi
+ * specifications use the @noimplement annotation, see below.
+ * </p>
+ * <h2>Elaborate and Simple Explanation</h2>
+ * <p>
+ * There is a distinction between "provider implemented" and
+ * "consumer implemented" interfaces, which is reflected in the
+ * {@link ProviderType} and {@link ConsumerType} annotations respectively.
+ * </p>
+ * <p>
+ * These annotations can be placed on an interface to enable the tooling to
+ * detect the role of the interface and generate the correct import range.
+ * </p>
+ * <p>
+ * Usually - to a developer - the role of the interface is clear: interfaces
+ * that are merely call-backs or listeners are generally "consumer implemented".
+ * </p>
+ * <h2>Thought Experiment with ConfigurationAdmin</h2>
+ * <p>
+ * In the case of the ConfigurationAdmin specification: implementing
+ * ManagedService or ManagedServiceFactory does not make you a provider. You
+ * would have to implement ConfigurationAdmin in order to be a provider.
+ * </p>
+ * <p>
+ * <b>Rule of thumb:</b> suppose a method would be added to
+ * ManagedServiceFactory. How many bundles would be broken as a result? The
+ * answer is "lots" and therefore ManagedServiceFactory is a consumer type.
+ * However, if a method would be added to ConfigurationAdmin then only a very
+ * small number of bundles would be broken; these are the providers of the
+ * ConfigurationAdmin API, e.g. org.apache.felix.configadmin and so on.
+ * </p>
+ * <h2>Relation to OSGi Specifications and Javadoc</h2>
+ * <p>
+ * At OSGi, the javadoc tag @noimplement is used to mark "provider implemented"
+ * interfaces. Interfaces not marked @noimplement are "consumer implemented"
+ * interfaces.
+ * </p>
+ * <p>
+ * So, for example, the ConfigurationAdmin interface is marked @noimplement
+ * while the ManagedService and ManagedServiceFactory interfaces are not.
+ * </p>
+ * <p>
+ * In the specification, you will see
+ * "No Implement  Consumers of this API must not implement this interface" for @noimplement
+ * marked interfaces.
+ * </p>
+ * <p>
+ * In the html javadoc, you will see
+ * "Consumers of this API must not implement this interface" for @noimplement
+ * marked interfaces.
+ * </p>
  */
+ at Documented
 @Retention(RetentionPolicy.CLASS)
 @Target(ElementType.TYPE)
 public @interface ProviderType {
diff --git a/biz.aQute.bndlib/src/aQute/bnd/annotation/UsePolicy.java b/biz.aQute.bndlib/src/aQute/bnd/annotation/UsePolicy.java
deleted file mode 100644
index 36f0eaf..0000000
--- a/biz.aQute.bndlib/src/aQute/bnd/annotation/UsePolicy.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package aQute.bnd.annotation;
-
-import java.lang.annotation.*;
-
-/**
- * This annotation can be applied to interface where an implementation should be
- * treated as a use policy, not an implementation policy. Many package have
- * interfaces that are very stable and can be maintained backward compatible for
- * implementers during minor changes. For example, in Event Admin, the
- * EventAdmin implementers should follow the minor version, e.g. [1.1,1.2), however,
- * an implementer of EventHandler should not require such a small range. Therefore
- * an interface like EventHandler should use this anotation.
- */
- at Retention(RetentionPolicy.CLASS)
- at Target(ElementType.TYPE)
- at Deprecated
-public @interface UsePolicy {
-    String RNAME = "LaQute/bnd/annotation/UsePolicy;";
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/annotation/Version.java b/biz.aQute.bndlib/src/aQute/bnd/annotation/Version.java
index fae42b1..a90c250 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/annotation/Version.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/annotation/Version.java
@@ -2,8 +2,11 @@ package aQute.bnd.annotation;
 
 import java.lang.annotation.*;
 
+ at Documented
 @Retention(RetentionPolicy.CLASS)
- at Target({ElementType.PACKAGE})
+ at Target({
+	ElementType.PACKAGE
+})
 public @interface Version {
 	String value();
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Activate.java b/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Activate.java
index 52284a0..e731669 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Activate.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Activate.java
@@ -5,6 +5,6 @@ import java.lang.annotation.*;
 @Retention(RetentionPolicy.CLASS)
 @Target(ElementType.METHOD)
 public @interface Activate {
-    String RNAME = "LaQute/bnd/annotation/component/Activate;";
-    
+	String	RNAME	= "LaQute/bnd/annotation/component/Activate;";
+
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Attribute.java b/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Attribute.java
deleted file mode 100644
index f089b75..0000000
--- a/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Attribute.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package aQute.bnd.annotation.component;
-
-public @interface Attribute {
-	class C {}
-	
-	String name() default "";
-	String description() default "";
-	String[] options();
-	
-}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Component.java b/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Component.java
index 1fb39d6..1d733ac 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Component.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Component.java
@@ -2,7 +2,9 @@ package aQute.bnd.annotation.component;
 
 import java.lang.annotation.*;
 
- at Retention(RetentionPolicy.CLASS) @Target(ElementType.TYPE) public @interface Component {
+ at Retention(RetentionPolicy.CLASS)
+ at Target(ElementType.TYPE)
+public @interface Component {
 	String	RNAME					= "LaQute/bnd/annotation/component/Component;";
 	String	PROVIDE					= "provide";
 	String	NAME					= "name";
@@ -18,7 +20,7 @@ import java.lang.annotation.*;
 
 	String name() default "";
 
-	Class<?>[] provide() default Object.class;
+	Class< ? >[] provide() default Object.class;
 
 	String factory() default "";
 
@@ -32,7 +34,7 @@ import java.lang.annotation.*;
 
 	String[] properties() default {};
 
-	Class<?> designate() default Object.class;
+	Class< ? > designate() default Object.class;
 
-	Class<?> designateFactory() default Object.class;
+	Class< ? > designateFactory() default Object.class;
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/annotation/component/ConfigurationPolicy.java b/biz.aQute.bndlib/src/aQute/bnd/annotation/component/ConfigurationPolicy.java
index 7651557..9e10951 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/annotation/component/ConfigurationPolicy.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/annotation/component/ConfigurationPolicy.java
@@ -1,5 +1,5 @@
 package aQute.bnd.annotation.component;
 
 public enum ConfigurationPolicy {
-    optional, require, ignore;
+	optional, require, ignore;
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Deactivate.java b/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Deactivate.java
index 5858ea0..60c7be4 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Deactivate.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Deactivate.java
@@ -5,6 +5,6 @@ import java.lang.annotation.*;
 @Retention(RetentionPolicy.CLASS)
 @Target(ElementType.METHOD)
 public @interface Deactivate {
-    String RNAME = "LaQute/bnd/annotation/component/Deactivate;";
+	String	RNAME	= "LaQute/bnd/annotation/component/Deactivate;";
 
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Modified.java b/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Modified.java
index 655a535..ae36b7f 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Modified.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Modified.java
@@ -5,6 +5,6 @@ import java.lang.annotation.*;
 @Retention(RetentionPolicy.CLASS)
 @Target(ElementType.METHOD)
 public @interface Modified {
-    String RNAME = "LaQute/bnd/annotation/component/Modified;";
+	String	RNAME	= "LaQute/bnd/annotation/component/Modified;";
 
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Reference.java b/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Reference.java
index 58894dd..2a71bac 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Reference.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/annotation/component/Reference.java
@@ -5,29 +5,29 @@ import java.lang.annotation.*;
 @Retention(RetentionPolicy.CLASS)
 @Target(ElementType.METHOD)
 public @interface Reference {
-    String RNAME    = "LaQute/bnd/annotation/component/Reference;";
-    String NAME     = "name";
-    String SERVICE  = "service";
-    String OPTIONAL = "optional";
-    String MULTIPLE = "multiple";
-    String DYNAMIC  = "dynamic";
-    String TARGET   = "target";
-    String TYPE     = "type";
-    String UNBIND   = "unbind";
+	String	RNAME		= "LaQute/bnd/annotation/component/Reference;";
+	String	NAME		= "name";
+	String	SERVICE		= "service";
+	String	OPTIONAL	= "optional";
+	String	MULTIPLE	= "multiple";
+	String	DYNAMIC		= "dynamic";
+	String	TARGET		= "target";
+	String	TYPE		= "type";
+	String	UNBIND		= "unbind";
 
-    String name() default "";
+	String name() default "";
 
-    Class<?> service() default Object.class;
+	Class< ? > service() default Object.class;
 
-    boolean optional() default false;
+	boolean optional() default false;
 
-    boolean multiple() default false;
+	boolean multiple() default false;
 
-    boolean dynamic() default false;
+	boolean dynamic() default false;
 
-    String target() default "";
-    
-    String unbind() default "";
+	String target() default "";
 
-    char type() default 0;
+	String unbind() default "";
+
+	char type() default 0;
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/annotation/metatype/Configurable.java b/biz.aQute.bndlib/src/aQute/bnd/annotation/metatype/Configurable.java
index 6dcf614..9a08c4a 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/annotation/metatype/Configurable.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/annotation/metatype/Configurable.java
@@ -4,20 +4,21 @@ import java.lang.reflect.*;
 import java.util.*;
 import java.util.regex.*;
 
+ at SuppressWarnings({
+		"unchecked", "rawtypes"
+})
 public class Configurable<T> {
 
-	
-	
-	
-	public static <T> T createConfigurable(Class<T> c, Map<?, ?> properties) {
-		Object o = Proxy.newProxyInstance(c.getClassLoader(), new Class<?>[] { c },
-				new ConfigurableHandler(properties, c.getClassLoader()));
+	public static <T> T createConfigurable(Class<T> c, Map< ? , ? > properties) {
+		Object o = Proxy.newProxyInstance(c.getClassLoader(), new Class< ? >[] {
+			c
+		}, new ConfigurableHandler(properties, c.getClassLoader()));
 		return c.cast(o);
 	}
 
-	public static <T> T createConfigurable(Class<T> c, Dictionary<?, ?> properties) {
+	public static <T> T createConfigurable(Class<T> c, Dictionary< ? , ? > properties) {
 		Map<Object,Object> alt = new HashMap<Object,Object>();
-		for( Enumeration<?> e = properties.keys(); e.hasMoreElements(); ) {
+		for (Enumeration< ? > e = properties.keys(); e.hasMoreElements();) {
 			Object key = e.nextElement();
 			alt.put(key, properties.get(key));
 		}
@@ -25,10 +26,10 @@ public class Configurable<T> {
 	}
 
 	static class ConfigurableHandler implements InvocationHandler {
-		final Map<?, ?>	properties;
-		final ClassLoader			loader;
+		final Map< ? , ? >	properties;
+		final ClassLoader	loader;
 
-		ConfigurableHandler(Map<?, ?> properties, ClassLoader loader) {
+		ConfigurableHandler(Map< ? , ? > properties, ClassLoader loader) {
 			this.properties = properties;
 			this.loader = loader;
 		}
@@ -45,8 +46,7 @@ public class Configurable<T> {
 			if (o == null) {
 				if (ad != null) {
 					if (ad.required())
-						throw new IllegalStateException("Attribute is required but not set "
-								+ method.getName());
+						throw new IllegalStateException("Attribute is required but not set " + method.getName());
 
 					o = ad.deflt();
 					if (o.equals(Meta.NULL))
@@ -54,8 +54,11 @@ public class Configurable<T> {
 				}
 			}
 			if (o == null) {
-				if (method.getReturnType().isPrimitive()
-						|| Number.class.isAssignableFrom(method.getReturnType())) {
+				Class< ? > rt = method.getReturnType();
+				if (rt == boolean.class )
+					return false;
+				
+				if (method.getReturnType().isPrimitive()) {
 
 					o = "0";
 				} else
@@ -65,8 +68,7 @@ public class Configurable<T> {
 			return convert(method.getGenericReturnType(), o);
 		}
 
-		@SuppressWarnings( { "unchecked" }) public Object convert(Type type, Object o)
-				throws Exception {
+		public Object convert(Type type, Object o) throws Exception {
 			if (type instanceof ParameterizedType) {
 				ParameterizedType pType = (ParameterizedType) type;
 				return convert(pType, o);
@@ -77,29 +79,31 @@ public class Configurable<T> {
 				return convertArray(gType.getGenericComponentType(), o);
 			}
 
-			Class<?> resultType = (Class<?>) type;
+			Class< ? > resultType = (Class< ? >) type;
 
 			if (resultType.isArray()) {
 				return convertArray(resultType.getComponentType(), o);
 			}
 
-			Class<?> actualType = o.getClass();
+			Class< ? > actualType = o.getClass();
 			if (actualType.isAssignableFrom(resultType))
 				return o;
 
 			if (resultType == boolean.class || resultType == Boolean.class) {
-				if ( actualType == boolean.class || actualType == Boolean.class)
+				if (actualType == boolean.class || actualType == Boolean.class)
 					return o;
-				
+
 				if (Number.class.isAssignableFrom(actualType)) {
 					double b = ((Number) o).doubleValue();
 					if (b == 0)
 						return false;
-					else
-						return true;
+					return true;
+				}
+				if ( o instanceof String) {
+					return Boolean.parseBoolean((String) o);
 				}
 				return true;
-				
+
 			} else if (resultType == byte.class || resultType == Byte.class) {
 				if (Number.class.isAssignableFrom(actualType))
 					return ((Number) o).byteValue();
@@ -148,37 +152,41 @@ public class Configurable<T> {
 			}
 
 			try {
-				Constructor<?> c = resultType.getConstructor(String.class);
+				Constructor< ? > c = resultType.getConstructor(String.class);
 				return c.newInstance(o.toString());
-			} catch (Throwable t) {
+			}
+			catch (Throwable t) {
 				// handled on next line
 			}
-			throw new IllegalArgumentException("No conversion to " + resultType + " from "
-					+ actualType + " value " + o);
+			throw new IllegalArgumentException("No conversion to " + resultType + " from " + actualType + " value " + o);
 		}
 
 		private Object convert(ParameterizedType pType, Object o) throws InstantiationException,
 				IllegalAccessException, Exception {
-			Class<?> resultType = (Class<?>) pType.getRawType();
+			Class< ? > resultType = (Class< ? >) pType.getRawType();
 			if (Collection.class.isAssignableFrom(resultType)) {
-				Collection<?> input = toCollection(o);
+				Collection< ? > input = toCollection(o);
 				if (resultType.isInterface()) {
 					if (resultType == Collection.class || resultType == List.class)
 						resultType = ArrayList.class;
 					else if (resultType == Set.class || resultType == SortedSet.class)
 						resultType = TreeSet.class;
-					else if (resultType == Queue.class /*|| resultType == Deque.class*/)
+					else if (resultType == Queue.class /*
+														 * || resultType ==
+														 * Deque.class
+														 */)
 						resultType = LinkedList.class;
-					else if (resultType == Queue.class /*|| resultType == Deque.class*/)
+					else if (resultType == Queue.class /*
+														 * || resultType ==
+														 * Deque.class
+														 */)
 						resultType = LinkedList.class;
 					else
 						throw new IllegalArgumentException(
-								"Unknown interface for a collection, no concrete class found: "
-										+ resultType);
+								"Unknown interface for a collection, no concrete class found: " + resultType);
 				}
-				
-				@SuppressWarnings("unchecked") Collection<Object> result = (Collection<Object>) resultType
-						.newInstance();
+
+				Collection<Object> result = (Collection<Object>) resultType.newInstance();
 				Type componentType = pType.getActualTypeArguments()[0];
 
 				for (Object i : input) {
@@ -188,13 +196,33 @@ public class Configurable<T> {
 			} else if (pType.getRawType() == Class.class) {
 				return loader.loadClass(o.toString());
 			}
+			if (Map.class.isAssignableFrom(resultType)) {
+				Map< ? , ? > input = toMap(o);
+				if (resultType.isInterface()) {
+					if (resultType == SortedMap.class)
+						resultType = TreeMap.class;
+					else if (resultType == Map.class)
+						resultType = LinkedHashMap.class;
+					else
+						throw new IllegalArgumentException(
+								"Unknown interface for a collection, no concrete class found: " + resultType);
+				}
+				Map<Object,Object> result = (Map<Object,Object>) resultType.newInstance();
+				Type keyType = pType.getActualTypeArguments()[0];
+				Type valueType = pType.getActualTypeArguments()[1];
+
+				for (Map.Entry< ? , ? > entry : input.entrySet()) {
+					result.put(convert(keyType, entry.getKey()), convert(valueType, entry.getValue()));
+				}
+				return result;
+			}
 			throw new IllegalArgumentException("cannot convert to " + pType
-					+ " because it uses generics and is not a Collection");
+					+ " because it uses generics and is not a Collection or a map");
 		}
 
 		Object convertArray(Type componentType, Object o) throws Exception {
-			Collection<?> input = toCollection(o);
-			Class<?> componentClass = getRawClass(componentType);
+			Collection< ? > input = toCollection(o);
+			Class< ? > componentClass = getRawClass(componentType);
 			Object array = Array.newInstance(componentClass, input.size());
 
 			int i = 0;
@@ -204,58 +232,63 @@ public class Configurable<T> {
 			return array;
 		}
 
-		private Class<?> getRawClass(Type type) {
+		private Class< ? > getRawClass(Type type) {
 			if (type instanceof Class)
-				return (Class<?>) type;
+				return (Class< ? >) type;
 
 			if (type instanceof ParameterizedType)
-				return (Class<?>) ((ParameterizedType) type).getRawType();
+				return (Class< ? >) ((ParameterizedType) type).getRawType();
 
-			throw new IllegalArgumentException(
-					"For the raw type, type must be ParamaterizedType or Class but is " + type);
+			throw new IllegalArgumentException("For the raw type, type must be ParamaterizedType or Class but is "
+					+ type);
 		}
 
-		private Collection<?> toCollection(Object o) {
+		private Collection< ? > toCollection(Object o) {
 			if (o instanceof Collection)
-				return (Collection<?>) o;
+				return (Collection< ? >) o;
 
 			if (o.getClass().isArray()) {
-				if ( o.getClass().getComponentType().isPrimitive()) {
+				if (o.getClass().getComponentType().isPrimitive()) {
 					int length = Array.getLength(o);
 					List<Object> result = new ArrayList<Object>(length);
-					for ( int i=0; i<length; i++) {
-						result.add( Array.get(o, i));
+					for (int i = 0; i < length; i++) {
+						result.add(Array.get(o, i));
 					}
 					return result;
-				} else
-					return Arrays.asList((Object[]) o);
+				}
+				return Arrays.asList((Object[]) o);
 			}
 
-			if ( o instanceof String) {
-				String s = (String)o;
-				if (s.indexOf('|')>0)
-					return Arrays.asList(s.split("\\|"));					
+			if (o instanceof String) {
+				String s = (String) o;
+				if (s.indexOf('|') > 0)
+					return Arrays.asList(s.split("\\|"));
 			}
 			return Arrays.asList(o);
 		}
 
+		private Map< ? , ? > toMap(Object o) {
+			if (o instanceof Map)
+				return (Map< ? , ? >) o;
+
+			throw new IllegalArgumentException("Cannot convert " + o + " to a map as requested");
+		}
+
 	}
-	
-	
+
 	public static String mangleMethodName(String id) {
 		StringBuilder sb = new StringBuilder(id);
-		for ( int i =0; i<sb.length(); i++) {
-			char c  = sb.charAt(i);
-			boolean twice = i < sb.length()-1 && sb.charAt(i+1) ==c;
-			if ( c == '$' || c == '_') {
-				if ( twice )
-					sb.deleteCharAt(i+1);
-				else 
-					if ( c == '$')
-						sb.deleteCharAt(i--); // Remove dollars
-					else
-						sb.setCharAt(i, '.'); // Make _ into .
-			}				
+		for (int i = 0; i < sb.length(); i++) {
+			char c = sb.charAt(i);
+			boolean twice = i < sb.length() - 1 && sb.charAt(i + 1) == c;
+			if (c == '$' || c == '_') {
+				if (twice)
+					sb.deleteCharAt(i + 1);
+				else if (c == '$')
+					sb.deleteCharAt(i--); // Remove dollars
+				else
+					sb.setCharAt(i, '.'); // Make _ into .
+			}
 		}
 		return sb.toString();
 	}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/annotation/metatype/Meta.java b/biz.aQute.bndlib/src/aQute/bnd/annotation/metatype/Meta.java
index a2686e5..d7b6745 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/annotation/metatype/Meta.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/annotation/metatype/Meta.java
@@ -13,16 +13,7 @@ import java.lang.annotation.*;
 
 public interface Meta {
 	enum Type {
-		Boolean,
-		Byte,
-		Character,
-		Short,
-		Integer,
-		Long,
-		Float,
-		Double,
-		String,
-		Password
+		Boolean, Byte, Character, Short, Integer, Long, Float, Double, String, Password
 	}
 
 	/**
@@ -34,9 +25,10 @@ public interface Meta {
 	 * The OCD Annotation maps to the OCD element in the Metatype specification.
 	 * The only difference is that it is possible to create a Designate element
 	 * as well.
-	 * 
 	 */
-	@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface OCD {
+	@Target(ElementType.TYPE)
+	@Retention(RetentionPolicy.RUNTIME)
+	@interface OCD {
 		/**
 		 * The name for this component. The default name is a the short class
 		 * name that us un-camel cased to make it more readable.
@@ -48,7 +40,6 @@ public interface Meta {
 		/**
 		 * The id of the component. Default the name of the class in FQN
 		 * notation but with nested classes using the $ as separator (not .).
-		 * 
 		 * The Felix webconsole always uses this id as the PID and not the pid
 		 * in the Designate element. Reported as an error.
 		 * 
@@ -79,9 +70,10 @@ public interface Meta {
 
 	/**
 	 * The AD element in the Metatype specification.
-	 * 
 	 */
-	@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @interface AD {
+	@Target(ElementType.METHOD)
+	@Retention(RetentionPolicy.RUNTIME)
+	@interface AD {
 		/**
 		 * A description of the attribute. Default is empty.
 		 * 
@@ -119,10 +111,9 @@ public interface Meta {
 		/**
 		 * The cardinality of the attribute. If not explicitly set it will be
 		 * derived from the attributes return type. Collections return
-		 * Integer.MIN_VALUE and arrays use Integer.MAX_VALUE.
-		 * 
-		 * If a single string needs to be converted to a Collection or array
-		 * then the | will be used as a separator to split the line.
+		 * Integer.MIN_VALUE and arrays use Integer.MAX_VALUE. If a single
+		 * string needs to be converted to a Collection or array then the | will
+		 * be used as a separator to split the line.
 		 * 
 		 * @return the cardinality of the attribute
 		 */
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/CircularDependencyException.java b/biz.aQute.bndlib/src/aQute/bnd/build/CircularDependencyException.java
index f08255b..c56a8eb 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/build/CircularDependencyException.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/CircularDependencyException.java
@@ -1,10 +1,10 @@
 package aQute.bnd.build;
 
 public class CircularDependencyException extends Exception {
-    public CircularDependencyException(String string) {
-        super(string);
-    }
+	public CircularDependencyException(String string) {
+		super(string);
+	}
 
-    private static final long serialVersionUID = 1L;
+	private static final long	serialVersionUID	= 1L;
 
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/Container.java b/biz.aQute.bndlib/src/aQute/bnd/build/Container.java
index a18472d..f693ddb 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/build/Container.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/Container.java
@@ -4,47 +4,55 @@ import java.io.*;
 import java.util.*;
 import java.util.jar.*;
 
-import aQute.bnd.service.RepositoryPlugin.Strategy;
-import aQute.lib.osgi.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.*;
 
 public class Container {
 	public enum TYPE {
-		REPO, PROJECT, PROJECT_BUNDLE, EXTERNAL, LIBRARY, ERROR
+		REPO, PROJECT, EXTERNAL, LIBRARY, ERROR
 	}
 
-	final File					file;
+	private final File			file;
+	private final String		path;
 	final TYPE					type;
 	final String				bsn;
 	final String				version;
 	final String				error;
 	final Project				project;
-	volatile Map<String, String>	attributes;
+	final DownloadBlocker		db;
+	volatile Map<String,String>	attributes;
 	private long				manifestTime;
 	private Manifest			manifest;
 
 	Container(Project project, String bsn, String version, TYPE type, File source, String error,
-			Map<String, String> attributes) {
+			Map<String,String> attributes, DownloadBlocker db) {
 		this.bsn = bsn;
 		this.version = version;
 		this.type = type;
 		this.file = source != null ? source : new File("/" + bsn + ":" + version + ":" + type);
+		this.path = file.getAbsolutePath();
+		
 		this.project = project;
 		this.error = error;
 		if (attributes == null || attributes.isEmpty())
 			this.attributes = Collections.emptyMap();
 		else
 			this.attributes = attributes;
+		this.db = db;
 	}
 
 	public Container(Project project, File file) {
-		this(project, file.getName(), "project", TYPE.PROJECT, file, null, null);
+		this(project, file.getName(), "project", TYPE.PROJECT, file, null, null, null);
 	}
 
-	public Container(File file) {
-		this(null, file.getName(), "project", TYPE.EXTERNAL, file, null, null);
+	public Container(File file, DownloadBlocker db) {
+		this(null, file.getName(), "project", TYPE.EXTERNAL, file, null, null, db);
 	}
 
 	public File getFile() {
+		if (db != null && db.getReason() != null) {
+			return new File(db.getReason() + ": " + file);
+		}
 		return file;
 	}
 
@@ -57,32 +65,32 @@ public class Container {
 	 */
 	public boolean contributeFiles(List<File> files, Processor reporter) throws Exception {
 		switch (type) {
-		case EXTERNAL:
-		case REPO:
-			files.add(file);
-			return true;
-
-		case PROJECT:
-			File[] fs = project.build();
-			reporter.getInfo(project);
-			if (fs == null)
-				return false;
+			case EXTERNAL :
+			case REPO :
+				files.add(getFile());
+				return true;
+
+			case PROJECT :
+				File[] fs = project.build();
+				reporter.getInfo(project);
+				if (fs == null)
+					return false;
 
-			for (File f : fs)
-				files.add(f);
-			return true;
+				for (File f : fs)
+					files.add(f);
+				return true;
 
-		case LIBRARY:
-			List<Container> containers = getMembers();
-			for (Container container : containers) {
-				if (!container.contributeFiles(files, reporter))
-					return false;
-			}
-			return true;
+			case LIBRARY :
+				List<Container> containers = getMembers();
+				for (Container container : containers) {
+					if (!container.contributeFiles(files, reporter))
+						return false;
+				}
+				return true;
 
-		case ERROR:
-			reporter.error(error);
-			return false;
+			case ERROR :
+				reporter.error(error);
+				return false;
 		}
 		return false;
 	}
@@ -103,15 +111,16 @@ public class Container {
 		return error;
 	}
 
+	@Override
 	public boolean equals(Object other) {
 		if (other instanceof Container)
-			return file.equals(((Container) other).file);
-		else
-			return false;
+			return path.equals(((Container) other).path);
+		return false;
 	}
 
+	@Override
 	public int hashCode() {
-		return file.hashCode();
+		return path.hashCode();
 	}
 
 	public Project getProject() {
@@ -123,20 +132,20 @@ public class Container {
 	 * 
 	 * @return
 	 */
+	@Override
 	public String toString() {
 		if (getError() != null)
 			return "/error/" + getError();
-		else
-			return getFile().getAbsolutePath();
+		return getFile().getAbsolutePath();
 	}
 
-	public Map<String, String> getAttributes() {
+	public Map<String,String> getAttributes() {
 		return attributes;
 	}
-	
+
 	public void putAttribute(String name, String value) {
-		if (attributes == Collections.<String,String>emptyMap())
-			attributes = new HashMap<String, String>(1);
+		if (attributes == Collections.<String, String> emptyMap())
+			attributes = new HashMap<String,String>(1);
 		attributes.put(name, value);
 	}
 
@@ -157,11 +166,12 @@ public class Container {
 			// basically a specification clause per line.
 			// I.e. you can do bsn; version, bsn2; version. But also
 			// spread it out over lines.
-			InputStream in = new FileInputStream(file);
-			BufferedReader rd = new BufferedReader(new InputStreamReader(in,
-					Constants.DEFAULT_CHARSET));
+			InputStream in = null;
+			BufferedReader rd = null;
+			String line;
 			try {
-				String line;
+				in = new FileInputStream(getFile());
+				rd = new BufferedReader(new InputStreamReader(in, Constants.DEFAULT_CHARSET));
 				while ((line = rd.readLine()) != null) {
 					line = line.trim();
 					if (!line.startsWith("#") && line.length() > 0) {
@@ -169,8 +179,14 @@ public class Container {
 						result.addAll(list);
 					}
 				}
-			} finally {
-				in.close();
+			}
+			finally {
+				if (rd != null) {
+					rd.close();
+				}
+				if (in != null) {
+					in.close();
+				}
 			}
 		} else
 			result.add(this);
@@ -194,7 +210,8 @@ public class Container {
 				manifest = jin.getManifest();
 				jin.close();
 				manifestTime = getFile().lastModified();
-			} finally {
+			}
+			finally {
 				in.close();
 			}
 		}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/DownloadBlocker.java b/biz.aQute.bndlib/src/aQute/bnd/build/DownloadBlocker.java
new file mode 100644
index 0000000..5b9b785
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/DownloadBlocker.java
@@ -0,0 +1,111 @@
+package aQute.bnd.build;
+
+import java.io.*;
+
+import aQute.bnd.service.*;
+import aQute.service.reporter.*;
+
+/**
+ * This class is intended to be used by the users of a {@link RepositoryPlugin}.
+ * The
+ * {@link RepositoryPlugin#get(String, aQute.bnd.version.Version, java.util.Map, aQute.bnd.service.RepositoryPlugin.DownloadListener...)}
+ * method takes one or more Download Listeners. These are called back with the
+ * success or failure of a download. This class is a simple implementation of
+ * this model, just call {@link #getReason()} and it blocks until success or
+ * failure is called.
+ */
+public class DownloadBlocker implements RepositoryPlugin.DownloadListener {
+	public enum Stage {
+		INIT, SUCCESS, FAILURE
+	};
+
+	private volatile Stage	stage	= Stage.INIT;
+	private String			failure;
+	private File			file;
+	private final Reporter	reporter;
+
+	public DownloadBlocker(Reporter reporter) {
+		this.reporter = reporter;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see
+	 * aQute.bnd.service.RepositoryPlugin.DownloadListener#success(java.io.File)
+	 */
+	public void success(File file) throws Exception {
+		synchronized (this) {
+			assert stage == Stage.INIT;
+			stage = Stage.SUCCESS;
+			this.file = file;
+			notifyAll();
+		}
+		if (reporter != null)
+			reporter.trace("successfully downloaded %s", file);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see
+	 * aQute.bnd.service.RepositoryPlugin.DownloadListener#failure(java.io.File,
+	 * java.lang.String)
+	 */
+	public void failure(File file, String reason) throws Exception {
+		synchronized (this) {
+			assert stage == Stage.INIT;
+			stage = Stage.FAILURE;
+			this.failure = reason;
+			this.file = file;
+			notifyAll();
+		}
+		if (reporter != null)
+			reporter.error("Download %s %s", reason, file);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see
+	 * aQute.bnd.service.RepositoryPlugin.DownloadListener#progress(java.io.
+	 * File, int)
+	 */
+	public boolean progress(File file, int percentage) throws Exception {
+		assert stage == Stage.INIT;
+		return true;
+	}
+
+	/**
+	 * Return a failure reason or null. This method will block until either
+	 * {@link #success(File)} or {@link #failure(File, String)} has been called.
+	 * It can be called many times.
+	 * 
+	 * @return null or a reason for a failure
+	 */
+	public synchronized String getReason() {
+		try {
+			while (stage == Stage.INIT)
+				wait();
+		}
+		catch (InterruptedException e) {
+			return "Interrupted";
+		}
+
+		return failure;
+	}
+
+	/**
+	 * Return the stage we're in
+	 * 
+	 * @return the current stage
+	 */
+	public Stage getStage() {
+		return stage;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString() {
+		return "DownloadBlocker(" + stage + "," + file + ", " + failure + ")";
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/Project.java b/biz.aQute.bndlib/src/aQute/bnd/build/Project.java
index 4b85527..954da2e 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/build/Project.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/Project.java
@@ -5,38 +5,38 @@ import java.lang.reflect.*;
 import java.net.*;
 import java.util.*;
 import java.util.Map.Entry;
-import java.util.concurrent.*;
 import java.util.concurrent.locks.*;
 import java.util.jar.*;
+import java.util.regex.*;
 
+import aQute.bnd.header.*;
 import aQute.bnd.help.*;
 import aQute.bnd.maven.support.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.eclipse.*;
 import aQute.bnd.service.*;
-import aQute.bnd.service.RepositoryPlugin.Strategy;
+import aQute.bnd.service.RepositoryPlugin.PutResult;
 import aQute.bnd.service.action.*;
+import aQute.bnd.version.*;
 import aQute.lib.io.*;
-import aQute.lib.osgi.*;
-import aQute.lib.osgi.eclipse.*;
 import aQute.libg.generics.*;
-import aQute.libg.header.*;
+import aQute.libg.reporter.*;
 import aQute.libg.sed.*;
-import aQute.libg.version.*;
 
 /**
  * This class is NOT threadsafe
- * 
- * @author aqute
- * 
  */
 
 public class Project extends Processor {
 
+	final static Pattern		VERSION_ANNOTATION		= Pattern.compile("@\\s*(:?aQute\\.bnd\\.annotation\\.)?Version\\s*\\(\\s*(:?value\\s*=\\s*)?\"(\\d+(:?\\.\\d+(:?\\.\\d+(:?\\.[\\d\\w-_]+)?)?)?)\"\\s*\\)");
 	final static String			DEFAULT_ACTIONS			= "build; label='Build', test; label='Test', run; label='Run', clean; label='Clean', release; label='Release', refreshAll; label=Refresh, deploy;label=Deploy";
 	public final static String	BNDFILE					= "bnd.bnd";
 	public final static String	BNDCNF					= "cnf";
 	final Workspace				workspace;
 	boolean						preparedPaths;
 	final Collection<Project>	dependson				= new LinkedHashSet<Project>();
+	final Collection<Container>	classpath				= new LinkedHashSet<Container>();
 	final Collection<Container>	buildpath				= new LinkedHashSet<Container>();
 	final Collection<Container>	testpath				= new LinkedHashSet<Container>();
 	final Collection<Container>	runpath					= new LinkedHashSet<Container>();
@@ -53,9 +53,9 @@ public class Project extends Processor {
 	boolean						inPrepare;
 	int							revision;
 	File						files[];
-	private long				buildtime;
 	static List<Project>		trail					= new ArrayList<Project>();
 	boolean						delayRunDependencies	= false;
+	final ProjectMessages		msgs					= ReporterMessages.base(this, ProjectMessages.class);
 
 	public Project(Workspace workspace, File projectDir, File buildFile) throws Exception {
 		super(workspace);
@@ -76,7 +76,7 @@ public class Project extends Processor {
 			File f = getFile("build.properties");
 			if (f.isFile()) {
 				Properties p = loadProperties(f);
-				for (Enumeration<?> e = p.propertyNames(); e.hasMoreElements();) {
+				for (Enumeration< ? > e = p.propertyNames(); e.hasMoreElements();) {
 					String key = (String) e.nextElement();
 					String newkey = key;
 					if (key.indexOf('$') >= 0) {
@@ -85,7 +85,8 @@ public class Project extends Processor {
 					setProperty(newkey, p.getProperty(key));
 				}
 			}
-		} catch (Exception e) {
+		}
+		catch (Exception e) {
 			e.printStackTrace();
 		}
 	}
@@ -122,7 +123,8 @@ public class Project extends Processor {
 			builder = new ProjectBuilder(parent);
 
 		builder.setBase(getBase());
-
+		builder.setPedantic(isPedantic());
+		builder.setTrace(isTrace());
 		return builder;
 	}
 
@@ -146,6 +148,7 @@ public class Project extends Processor {
 		return workspace;
 	}
 
+	@Override
 	public String toString() {
 		return getBase().getName();
 	}
@@ -200,22 +203,23 @@ public class Project extends Processor {
 						sourcepath.add(getBase());
 
 					// Set default bin directory
-					output = getFile(getProperty("bin", "bin")).getAbsoluteFile();
+					output = getOutput0();
 					if (!output.exists()) {
-						output.mkdirs();
+						if (!output.mkdirs()) {
+							throw new IOException("Could not create directory " + output);
+						}
 						getWorkspace().changedFile(output);
 					}
 					if (!output.isDirectory())
-						error("Can not find output directory: " + output);
-					else if (!buildpath.contains(output))
-						buildpath.add(new Container(this, output));
+						msgs.NoOutputDirectory_(output);
+					else {
+						Container c = new Container(this, output);
+						if (!buildpath.contains(c))
+							buildpath.add(c);
+					}
 
 					// Where we store all our generated stuff.
-					target = getFile(getProperty("target", "generated"));
-					if (!target.exists()) {
-						target.mkdirs();
-						getWorkspace().changedFile(target);
-					}
+					target = getTarget0();
 
 					// Where the launched OSGi framework stores stuff
 					String runStorageStr = getProperty(Constants.RUNSTORAGE);
@@ -224,26 +228,27 @@ public class Project extends Processor {
 					// We might have some other projects we want build
 					// before we do anything, but these projects are not in
 					// our path. The -dependson allows you to build them before.
+					// The values are possibly negated globbing patterns.
 
-					List<Project> dependencies = new ArrayList<Project>();
 					// dependencies.add( getWorkspace().getProject("cnf"));
 
 					String dp = getProperty(Constants.DEPENDSON);
-					Set<String> requiredProjectNames = parseHeader(dp).keySet();
+					Set<String> requiredProjectNames = new LinkedHashSet<String>(new Parameters(dp).keySet());
+					
+					//Allow DependencyConstributors to modify requiredProjectNames
 					List<DependencyContributor> dcs = getPlugins(DependencyContributor.class);
 					for (DependencyContributor dc : dcs)
 						dc.addDependencies(this, requiredProjectNames);
-
-					for (String p : requiredProjectNames) {
-						Project required = getWorkspace().getProject(p);
-						if (required == null)
-							error("No such project " + required + " on " + Constants.DEPENDSON);
-						else {
-							dependencies.add(required);
-						}
-
-					}
-
+					
+					Instructions is = new Instructions(requiredProjectNames);
+					
+					Set<Instruction> unused = new HashSet<Instruction>();
+					Collection<Project> projects = getWorkspace().getAllProjects();
+					Collection<Project> dependencies = is.select(projects, unused, false);
+					
+					for (Instruction u: unused) 
+						msgs.MissingDependson_(u.getInput());							
+						
 					// We have two paths that consists of repo files, projects,
 					// or some other stuff. The doPath routine adds them to the
 					// path and extracts the projects so we can build them
@@ -276,15 +281,38 @@ public class Project extends Processor {
 					}
 					if (isOk())
 						preparedPaths = true;
-				} finally {
+				}
+				finally {
 					inPrepare = false;
 				}
 			}
-		} finally {
+		}
+		finally {
 			trail.remove(this);
 		}
 	}
 
+	/**
+	 * @return
+	 */
+	private File getOutput0() {
+		return getFile(getProperty("bin", "bin")).getAbsoluteFile();
+	}
+
+	/**
+	 * 
+	 */
+	private File getTarget0() throws IOException {
+		File target = getFile(getProperty("target", "generated"));
+		if (!target.exists()) {
+			if (!target.mkdirs()) {
+				throw new IOException("Could not create directory " + target);
+			}
+			getWorkspace().changedFile(target);
+		}
+		return target;
+	}
+
 	public File getSrc() {
 		return new File(getBase(), getProperty("src", "src"));
 	}
@@ -312,8 +340,8 @@ public class Project extends Processor {
 	 * @param entries
 	 *            The input list of classpath entries
 	 */
-	private void doPath(Collection<Container> resultpath, Collection<Project> projects,
-			Collection<Container> entries, Collection<Container> bootclasspath) {
+	private void doPath(Collection<Container> resultpath, Collection<Project> projects, Collection<Container> entries,
+			Collection<Container> bootclasspath) {
 		for (Container cpe : entries) {
 			if (cpe.getError() != null)
 				error(cpe.getError());
@@ -321,8 +349,8 @@ public class Project extends Processor {
 				if (cpe.getType() == Container.TYPE.PROJECT) {
 					projects.add(cpe.getProject());
 				}
-				if (bootclasspath != null && cpe.getBundleSymbolicName().startsWith("ee.")
-						|| cpe.getAttributes().containsKey("boot"))
+				if (bootclasspath != null
+						&& (cpe.getBundleSymbolicName().startsWith("ee.") || cpe.getAttributes().containsKey("boot")))
 					bootclasspath.add(cpe);
 				else
 					resultpath.add(cpe);
@@ -332,7 +360,6 @@ public class Project extends Processor {
 
 	/**
 	 * Parse the list of bundles that are a prerequisite to this project.
-	 * 
 	 * Bundles are listed in repo specific names. So we just let our repo
 	 * plugins iterate over the list of bundles and we get the highest version
 	 * from them.
@@ -341,10 +368,7 @@ public class Project extends Processor {
 	 */
 
 	private List<Container> parseBuildpath() throws Exception {
-		List<Container> bundles = getBundles(Strategy.LOWEST, getProperty(Constants.BUILDPATH),
-				Constants.BUILDPATH);
-		appendPackages(Strategy.LOWEST, getProperty(Constants.BUILDPACKAGES), bundles,
-				ResolverMode.build);
+		List<Container> bundles = getBundles(Strategy.LOWEST, getProperty(Constants.BUILDPATH), Constants.BUILDPATH);
 		return bundles;
 	}
 
@@ -375,26 +399,18 @@ public class Project extends Processor {
 	 * @return
 	 */
 
-	public List<Container> getBundles(Strategy strategyx, String spec, String source)
-			throws Exception {
+	public List<Container> getBundles(Strategy strategyx, String spec, String source) throws Exception {
 		List<Container> result = new ArrayList<Container>();
-		Map<String, Map<String, String>> bundles = parseHeader(spec);
+		Parameters bundles = new Parameters(spec);
 
 		try {
-			for (Iterator<Map.Entry<String, Map<String, String>>> i = bundles.entrySet().iterator(); i
-					.hasNext();) {
-				Map.Entry<String, Map<String, String>> entry = i.next();
-				String bsn = entry.getKey();
-				Map<String, String> attrs = entry.getValue();
+			for (Iterator<Entry<String,Attrs>> i = bundles.entrySet().iterator(); i.hasNext();) {
+				Entry<String,Attrs> entry = i.next();
+				String bsn = removeDuplicateMarker(entry.getKey());
+				Map<String,String> attrs = entry.getValue();
 
 				Container found = null;
 
-				// Check if we have to use the maven pom ...
-				if (bsn.equals("pom")) {
-					doMavenPom(strategyx, result, attrs.get("scope"));
-					continue;
-				}
-
 				String versionRange = attrs.get("version");
 
 				if (versionRange != null) {
@@ -403,16 +419,13 @@ public class Project extends Processor {
 					}
 				}
 				if (found == null) {
-					if (versionRange != null
-							&& (versionRange.equals("project") || versionRange.equals("latest"))) {
+					if (versionRange != null && (versionRange.equals("project") || versionRange.equals("latest"))) {
 						Project project = getWorkspace().getProject(bsn);
 						if (project != null && project.exists()) {
 							File f = project.getOutput();
-							found = new Container(project, bsn, versionRange,
-									Container.TYPE.PROJECT, f, null, attrs);
+							found = new Container(project, bsn, versionRange, Container.TYPE.PROJECT, f, null, attrs, null);
 						} else {
-							error("Reference to project that does not exist in workspace\n"
-									+ "  Project       %s\n" + "  Specification %s", bsn, spec);
+							msgs.NoSuchProject(bsn, spec);
 							continue;
 						}
 					} else if (versionRange != null && versionRange.equals("file")) {
@@ -421,11 +434,9 @@ public class Project extends Processor {
 						if (!f.exists())
 							error = "File does not exist: " + f.getAbsolutePath();
 						if (f.getName().endsWith(".lib")) {
-							found = new Container(this, bsn, "file", Container.TYPE.LIBRARY, f,
-									error, attrs);
+							found = new Container(this, bsn, "file", Container.TYPE.LIBRARY, f, error, attrs, null);
 						} else {
-							found = new Container(this, bsn, "file", Container.TYPE.EXTERNAL, f,
-									error, attrs);
+							found = new Container(this, bsn, "file", Container.TYPE.EXTERNAL, f, error, attrs, null);
 						}
 					} else {
 						found = getBundle(bsn, versionRange, strategyx, attrs);
@@ -436,26 +447,27 @@ public class Project extends Processor {
 					List<Container> libs = found.getMembers();
 					for (Container cc : libs) {
 						if (result.contains(cc))
-							warning("Multiple bundles with the same final URL: " + cc);
-
-						result.add(cc);
+							warning("Multiple bundles with the same final URL: %s, dropped duplicate", cc);
+						else
+							result.add(cc);
 					}
 				} else {
 					// Oops, not a bundle in sight :-(
-					Container x = new Container(this, bsn, versionRange, Container.TYPE.ERROR,
-							null, bsn + ";version=" + versionRange + " not found", attrs);
+					Container x = new Container(this, bsn, versionRange, Container.TYPE.ERROR, null, bsn + ";version="
+							+ versionRange + " not found", attrs, null);
 					result.add(x);
 					warning("Can not find URL for bsn " + bsn);
 				}
 			}
-		} catch (CircularDependencyException e) {
+		}
+		catch (CircularDependencyException e) {
 			String message = e.getMessage();
 			if (source != null)
 				message = String.format("%s (from property: %s)", message, source);
-			error("Circular dependency detected from project %s: %s", e, getName(), message);
-		} catch (Exception e) {
-			error("Unexpected error while trying to get the bundles from " + spec, e);
-			e.printStackTrace();
+			msgs.CircularDependencyContext_Message_(getName(), message);
+		}
+		catch (Exception e) {
+			msgs.Unexpected_Error_(spec, e);
 		}
 		return result;
 	}
@@ -464,78 +476,11 @@ public class Project extends Processor {
 	 * Just calls a new method with a default parm.
 	 * 
 	 * @throws Exception
-	 * 
 	 */
 	Collection<Container> getBundles(Strategy strategy, String spec) throws Exception {
 		return getBundles(strategy, spec, null);
 	}
 
-	/**
-	 * Calculates the containers required to fulfil the {@code -buildpackages}
-	 * instruction, and appends them to the existing list of containers.
-	 * 
-	 * @param strategyx
-	 *            The package-version disambiguation strategy.
-	 * @param spec
-	 *            The value of the @{code -buildpackages} instruction.
-	 * @throws Exception
-	 */
-	public void appendPackages(Strategy strategyx, String spec, List<Container> resolvedBundles,
-			ResolverMode mode) throws Exception {
-		Map<File, Container> pkgResolvedBundles = new HashMap<File, Container>();
-
-		List<Entry<String, Map<String, String>>> queue = new LinkedList<Map.Entry<String, Map<String, String>>>();
-		queue.addAll(parseHeader(spec).entrySet());
-
-		while (!queue.isEmpty()) {
-			Entry<String, Map<String, String>> entry = queue.remove(0);
-
-			String pkgName = entry.getKey();
-			Map<String, String> attrs = entry.getValue();
-
-			Container found = null;
-
-			String versionRange = attrs.get(Constants.VERSION_ATTRIBUTE);
-			if ("latest".equals(versionRange) || "snapshot".equals(versionRange))
-				found = getPackage(pkgName, versionRange, strategyx, attrs, mode);
-
-			if (found == null)
-				found = getPackage(pkgName, versionRange, strategyx, attrs, mode);
-
-			if (found != null) {
-				if (resolvedBundles.contains(found)) {
-					// Don't add his bundle because it was already included
-					// using -buildpath
-				} else {
-					List<Container> libs = found.getMembers();
-					for (Container cc : libs) {
-						Container existing = pkgResolvedBundles.get(cc.file);
-						if (existing != null)
-							addToPackageList(existing, attrs.get("packages"));
-						else {
-							addToPackageList(cc, attrs.get("packages"));
-							pkgResolvedBundles.put(cc.file, cc);
-						}
-
-						String importUses = cc.getAttributes().get("import-uses");
-						if (importUses != null)
-							queue.addAll(0, parseHeader(importUses).entrySet());
-					}
-				}
-			} else {
-				// Unable to resolve
-				Container x = new Container(this, "X", versionRange, Container.TYPE.ERROR, null,
-						"package " + pkgName + ";version=" + versionRange + " not found", attrs);
-				resolvedBundles.add(x);
-				warning("Can not find URL for package " + pkgName);
-			}
-		}
-
-		for (Container container : pkgResolvedBundles.values()) {
-			resolvedBundles.add(container);
-		}
-	}
-
 	static void mergeNames(String names, Set<String> set) {
 		StringTokenizer tokenizer = new StringTokenizer(names, ",");
 		while (tokenizer.hasMoreTokens())
@@ -567,71 +512,6 @@ public class Project extends Processor {
 	}
 
 	/**
-	 * Find a container to fulfil a package requirement
-	 * 
-	 * @param packageName
-	 *            The package required
-	 * @param range
-	 *            The package version range required
-	 * @param strategyx
-	 *            The package-version disambiguation strategy
-	 * @param attrs
-	 *            Other attributes specified by the search.
-	 * @return
-	 * @throws Exception
-	 */
-	public Container getPackage(String packageName, String range, Strategy strategyx,
-			Map<String, String> attrs, ResolverMode mode) throws Exception {
-		if ("snapshot".equals(range))
-			return new Container(this, "", range, Container.TYPE.ERROR, null,
-					"snapshot not supported for package lookups", null);
-
-		if (attrs == null)
-			attrs = new HashMap<String, String>(2);
-		attrs.put("package", packageName);
-		attrs.put("mode", mode.name());
-
-		Strategy useStrategy = findStrategy(attrs, strategyx, range);
-
-		List<RepositoryPlugin> plugins = getPlugins(RepositoryPlugin.class);
-		for (RepositoryPlugin plugin : plugins) {
-			try {
-				File result = plugin.get(null, range, useStrategy, attrs);
-				if (result != null) {
-					if (result.getName().endsWith("lib"))
-						return new Container(this, result.getName(), range, Container.TYPE.LIBRARY,
-								result, null, attrs);
-					else
-						return new Container(this, result.getName(), range, Container.TYPE.REPO,
-								result, null, attrs);
-				}
-			} catch (Exception e) {
-				// Ignore... lots of repos will fail here
-			}
-		}
-
-		return new Container(this, "X", range, Container.TYPE.ERROR, null, "package " + packageName
-				+ ";version=" + range + " Not found in " + plugins, null);
-	}
-
-	private Strategy findStrategy(Map<String, String> attrs, Strategy defaultStrategy,
-			String versionRange) {
-		Strategy useStrategy = defaultStrategy;
-		String overrideStrategy = attrs.get("strategy");
-		if (overrideStrategy != null) {
-			if ("highest".equalsIgnoreCase(overrideStrategy))
-				useStrategy = Strategy.HIGHEST;
-			else if ("lowest".equalsIgnoreCase(overrideStrategy))
-				useStrategy = Strategy.LOWEST;
-			else if ("exact".equalsIgnoreCase(overrideStrategy))
-				useStrategy = Strategy.EXACT;
-		}
-		if ("latest".equals(versionRange))
-			useStrategy = Strategy.HIGHEST;
-		return useStrategy;
-	}
-
-	/**
 	 * The user selected pom in a path. This will place the pom as well as its
 	 * dependencies on the list
 	 * 
@@ -644,11 +524,10 @@ public class Project extends Processor {
 	 * @throws Exception
 	 *             anything goes wrong
 	 */
-	public void doMavenPom(Strategy strategyx, List<Container> result, String action)
-			throws Exception {
+	public void doMavenPom(Strategy strategyx, List<Container> result, String action) throws Exception {
 		File pomFile = getFile("pom.xml");
 		if (!pomFile.isFile())
-			error("Specified to use pom.xml but the project directory does not contain a pom.xml file");
+			msgs.MissingPom();
 		else {
 			ProjectPom pom = getWorkspace().getMaven().createProjectModel(pomFile);
 			if (action == null)
@@ -657,7 +536,7 @@ public class Project extends Processor {
 			Set<Pom> dependencies = pom.getDependencies(act);
 			for (Pom sub : dependencies) {
 				File artifact = sub.getArtifact();
-				Container container = new Container(artifact);
+				Container container = new Container(artifact, null);
 				result.add(container);
 			}
 		}
@@ -710,8 +589,7 @@ public class Project extends Processor {
 		boolean result;
 		String runBuildsStr = getProperty(Constants.RUNBUILDS);
 		if (runBuildsStr == null)
-			result = !getPropertiesFile().getName().toLowerCase()
-					.endsWith(Constants.DEFAULT_BNDRUN_EXTENSION);
+			result = !getPropertiesFile().getName().toLowerCase().endsWith(Constants.DEFAULT_BNDRUN_EXTENSION);
 		else
 			result = Boolean.parseBoolean(runBuildsStr);
 		return result;
@@ -748,10 +626,10 @@ public class Project extends Processor {
 			dependson.add(required);
 		}
 		for (File f : eclipse.getClasspath()) {
-			buildpath.add(new Container(f));
+			buildpath.add(new Container(f, null));
 		}
 		for (File f : eclipse.getBootclasspath()) {
-			bootclasspath.add(new Container(f));
+			bootclasspath.add(new Container(f, null));
 		}
 		sourcepath.addAll(eclipse.getSourcepath());
 		allsourcepath.addAll(eclipse.getAllSources());
@@ -762,7 +640,7 @@ public class Project extends Processor {
 		return list(args, toFiles(getDependson()));
 	}
 
-	private Collection<?> toFiles(Collection<Project> projects) {
+	private Collection< ? > toFiles(Collection<Project> projects) {
 		List<File> files = new ArrayList<File>();
 		for (Project p : projects) {
 			files.add(p.getBase());
@@ -796,11 +674,10 @@ public class Project extends Processor {
 		return getOutput().getAbsolutePath();
 	}
 
-	private String list(String[] args, Collection<?> list) {
+	private String list(String[] args, Collection< ? > list) {
 		if (args.length > 3)
 			throw new IllegalArgumentException("${" + args[0]
-					+ "[;<separator>]} can only take a separator as argument, has "
-					+ Arrays.toString(args));
+					+ "[;<separator>]} can only take a separator as argument, has " + Arrays.toString(args));
 
 		String separator = ",";
 
@@ -811,13 +688,21 @@ public class Project extends Processor {
 		return join(list, separator);
 	}
 
+	@Override
 	protected Object[] getMacroDomains() {
-		return new Object[] { workspace };
+		return new Object[] {
+			workspace
+		};
+	}
+
+	public File release(String jarName, InputStream jarStream) throws Exception {
+		String name = getProperty(Constants.RELEASEREPO);
+		return release(name, jarName, jarStream);
 	}
 
-	public File release(Jar jar) throws Exception {
+	public URI releaseURI(String jarName, InputStream jarStream) throws Exception {
 		String name = getProperty(Constants.RELEASEREPO);
-		return release(name, jar);
+		return releaseURI(name, jarName, jarStream);
 	}
 
 	/**
@@ -825,46 +710,62 @@ public class Project extends Processor {
 	 * 
 	 * @param name
 	 *            The repository name
-	 * @param jar
+	 * @param jarName
+	 * @param jarStream
 	 * @return
 	 * @throws Exception
 	 */
-	public File release(String name, Jar jar) throws Exception {
-		trace("release %s", name);
-		List<RepositoryPlugin> plugins = getPlugins(RepositoryPlugin.class);
-		RepositoryPlugin rp = null;
-		for (RepositoryPlugin plugin : plugins) {
-			if (!plugin.canWrite()) {
-				continue;
-			}
-			if (name == null) {
-				rp = plugin;
-				break;
-			} else if (name.equals(plugin.getName())) {
-				rp = plugin;
-				break;
-			}
+	public File release(String name, String jarName, InputStream jarStream) throws Exception {
+		URI uri = releaseURI(name, jarName, jarStream);
+		if (uri != null) {
+			return new File(uri);
 		}
+		return null;
+	}
 
-		if (rp != null) {
-			try {
-				File file = rp.put(jar);
-				trace("Released %s to file %s in repository %s", jar.getName(), file, rp);
-			} catch (Exception e) {
-				error("Deploying " + jar.getName() + " on " + rp.getName(), e);
-			} finally {
-				jar.close();
-			}
-		} else if (name == null)
-			error("There is no writable repository (no repo name specified)");
-		else
-			error("Cannot find a writeable repository with the name %s from the repositiories %s",
-					name, plugins);
+	public URI releaseURI(String name, String jarName, InputStream jarStream) throws Exception {
+		
+		trace("release to %s", name);
+		RepositoryPlugin repo = getReleaseRepo(name);
 
-		return null;
+		if (repo == null) {
+			if (name == null)
+				msgs.NoNameForReleaseRepository();
+			else
+				msgs.ReleaseRepository_NotFoundIn_(name, getPlugins(RepositoryPlugin.class));
+			return null;
+		}
 
+		try {
+			PutResult r = repo.put(jarStream, new RepositoryPlugin.PutOptions());
+			trace("Released %s to %s in repository %s", jarName, r.artifact, repo);
+			return r.artifact;
+		}
+		catch (Exception e) {
+			msgs.Release_Into_Exception_(jarName, repo, e);
+			return null;
+		}
 	}
 
+	RepositoryPlugin getReleaseRepo(String releaserepo) {
+		String name = releaserepo == null ? 
+			name = getProperty(RELEASEREPO) : releaserepo;
+		
+		List<RepositoryPlugin> plugins = getPlugins(RepositoryPlugin.class);
+		
+		for (RepositoryPlugin plugin : plugins) {
+			if (!plugin.canWrite())
+				continue;
+
+			if (name == null)
+				return plugin;
+				
+			if (name.equals(plugin.getName()))
+				return plugin;
+		}
+		return null;
+	}
+	
 	public void release(boolean test) throws Exception {
 		String name = getProperty(Constants.RELEASEREPO);
 		release(name, test);
@@ -889,14 +790,8 @@ public class Project extends Processor {
 		}
 		trace("build ", Arrays.toString(jars));
 		for (File jar : jars) {
-			Jar j = new Jar(jar);
-			try {
-				release(name, j);
-			} finally {
-				j.close();
-			}
+			release(name, jar.getName(), new BufferedInputStream(new FileInputStream(jar)));
 		}
-
 	}
 
 	/**
@@ -915,8 +810,7 @@ public class Project extends Processor {
 	 *             when something goes wrong
 	 */
 
-	public Container getBundle(String bsn, String range, Strategy strategy,
-			Map<String, String> attrs) throws Exception {
+	public Container getBundle(String bsn, String range, Strategy strategy, Map<String,String> attrs) throws Exception {
 
 		if (range == null)
 			range = "0";
@@ -937,48 +831,55 @@ public class Project extends Processor {
 
 		useStrategy = overrideStrategy(attrs, useStrategy);
 
-		List<RepositoryPlugin> plugins = getPlugins(RepositoryPlugin.class);
+		List<RepositoryPlugin> plugins = workspace.getRepositories();
 
 		if (useStrategy == Strategy.EXACT) {
+			if (!Verifier.isVersion(range))
+				return new Container(this, bsn, range, Container.TYPE.ERROR, null, bsn + ";version=" + range
+						+ " Invalid version", null, null);
 
 			// For an exact range we just iterate over the repos
 			// and return the first we find.
-
+			Version version = new Version(range);
 			for (RepositoryPlugin plugin : plugins) {
-				File result = plugin.get(bsn, range, Strategy.EXACT, attrs);
+				DownloadBlocker blocker = new DownloadBlocker(this);
+				File result = plugin.get(bsn, version, attrs, blocker);
 				if (result != null)
-					return toContainer(bsn, range, attrs, result);
+					return toContainer(bsn, range, attrs, result, blocker);
 			}
 		} else {
-			VersionRange versionRange = "latest".equals(range) ? new VersionRange("0")
-					: new VersionRange(range);
+			VersionRange versionRange = "latest".equals(range) ? new VersionRange("0") : new VersionRange(range);
 
 			// We have a range search. Gather all the versions in all the repos
 			// and make a decision on that choice. If the same version is found
 			// in
 			// multiple repos we take the first
 
-			SortedMap<Version, RepositoryPlugin> versions = new TreeMap<Version, RepositoryPlugin>();
+			SortedMap<Version,RepositoryPlugin> versions = new TreeMap<Version,RepositoryPlugin>();
 			for (RepositoryPlugin plugin : plugins) {
 				try {
-					List<Version> vs = plugin.versions(bsn);
+					SortedSet<Version> vs = plugin.versions(bsn);
 					if (vs != null) {
 						for (Version v : vs) {
 							if (!versions.containsKey(v) && versionRange.includes(v))
 								versions.put(v, plugin);
 						}
 					}
-				} catch (UnsupportedOperationException ose) {
+				}
+				catch (UnsupportedOperationException ose) {
 					// We have a plugin that cannot list versions, try
 					// if it has this specific version
-					// The main reaosn for this code was the Maven Remote Repository
+					// The main reaosn for this code was the Maven Remote
+					// Repository
 					// To query, we must have a real version
 					if (!versions.isEmpty() && Verifier.isVersion(range)) {
-						File file = plugin.get(bsn, range, useStrategy, attrs);
+						Version version = new Version(range);
+						DownloadBlocker blocker = new DownloadBlocker(this);
+						File file = plugin.get(bsn, version, attrs, blocker);
 						// and the entry must exist
 						// if it does, return this as a result
 						if (file != null)
-							return toContainer(bsn, range, attrs, file);
+							return toContainer(bsn, range, attrs, file, blocker);
 					}
 				}
 			}
@@ -990,30 +891,34 @@ public class Project extends Processor {
 				Version provider = null;
 
 				switch (useStrategy) {
-				case HIGHEST:
-					provider = versions.lastKey();
-					break;
-
-				case LOWEST:
-					provider = versions.firstKey();
-					break;
+					case HIGHEST :
+						provider = versions.lastKey();
+						break;
+
+					case LOWEST :
+						provider = versions.firstKey();
+						break;
+					case EXACT :
+						// TODO need to handle exact better
+						break;
 				}
 				if (provider != null) {
 					RepositoryPlugin repo = versions.get(provider);
 					String version = provider.toString();
-					File result = repo.get(bsn, version, Strategy.EXACT, attrs);
-					return toContainer(bsn, version, attrs, result);
+					DownloadBlocker blocker = new DownloadBlocker(this);
+					File result = repo.get(bsn, provider, attrs, blocker);
+					if (result != null)
+						return toContainer(bsn, version, attrs, result, blocker);
 				} else
-					error("Unexpected, found versions %s but then not provider for startegy %s?",
-							versions, useStrategy);
+					msgs.FoundVersions_ForStrategy_ButNoProvider(versions, useStrategy);
 			}
 		}
 
 		//
 		// If we get this far we ran into an error somewhere
 
-		return new Container(this, bsn, range, Container.TYPE.ERROR, null, bsn + ";version="
-				+ range + " Not found in " + plugins, null);
+		return new Container(this, bsn, range, Container.TYPE.ERROR, null, bsn + ";version=" + range + " Not found in "
+				+ plugins, null, null);
 
 	}
 
@@ -1022,7 +927,7 @@ public class Project extends Processor {
 	 * @param useStrategy
 	 * @return
 	 */
-	protected Strategy overrideStrategy(Map<String, String> attrs, Strategy useStrategy) {
+	protected Strategy overrideStrategy(Map<String,String> attrs, Strategy useStrategy) {
 		if (attrs != null) {
 			String overrideStrategy = attrs.get("strategy");
 
@@ -1045,14 +950,19 @@ public class Project extends Processor {
 	 * @param result
 	 * @return
 	 */
-	protected Container toContainer(String bsn, String range, Map<String, String> attrs, File result) {
-		if (result == null) {
-			System.out.println("Huh?");
+	protected Container toContainer(String bsn, String range, Map<String,String> attrs, File result, DownloadBlocker db) {
+		File f = result;
+		if (f == null) {
+			msgs.ConfusedNoContainerFile();
+			f = new File("was null");
 		}
-		if (result.getName().endsWith("lib"))
-			return new Container(this, bsn, range, Container.TYPE.LIBRARY, result, null, attrs);
+		Container container;
+		if (f.getName().endsWith("lib"))
+			container = new Container(this, bsn, range, Container.TYPE.LIBRARY, f, null, attrs, db);
 		else
-			return new Container(this, bsn, range, Container.TYPE.REPO, result, null, attrs);
+			container = new Container(this, bsn, range, Container.TYPE.REPO, f, null, attrs, db);
+		
+		return container;
 	}
 
 	/**
@@ -1066,7 +976,7 @@ public class Project extends Processor {
 	 * @return
 	 * @throws Exception
 	 */
-	private Container getBundleFromProject(String bsn, Map<String, String> attrs) throws Exception {
+	private Container getBundleFromProject(String bsn, Map<String,String> attrs) throws Exception {
 		String pname = bsn;
 		while (true) {
 			Project p = getWorkspace().getProject(pname);
@@ -1092,7 +1002,7 @@ public class Project extends Processor {
 	 */
 	public void deploy(String name, File file) throws Exception {
 		List<RepositoryPlugin> plugins = getPlugins(RepositoryPlugin.class);
-		;
+
 		RepositoryPlugin rp = null;
 		for (RepositoryPlugin plugin : plugins) {
 			if (!plugin.canWrite()) {
@@ -1108,14 +1018,12 @@ public class Project extends Processor {
 		}
 
 		if (rp != null) {
-			Jar jar = new Jar(file);
 			try {
-				rp.put(jar);
+				rp.put(new BufferedInputStream(new FileInputStream(file)), new RepositoryPlugin.PutOptions());
 				return;
-			} catch (Exception e) {
-				error("Deploying " + file + " on " + rp.getName(), e);
-			} finally {
-				jar.close();
+			}
+			catch (Exception e) {
+				msgs.DeployingFile_On_Exception_(file, rp.getName(), e);
 			}
 			return;
 		}
@@ -1140,41 +1048,37 @@ public class Project extends Processor {
 	 * @throws Exception
 	 */
 	public void deploy() throws Exception {
-		Map<String, Map<String, String>> deploy = parseHeader(getProperty(DEPLOY));
+		Parameters deploy = new Parameters(getProperty(DEPLOY));
 		if (deploy.isEmpty()) {
 			warning("Deploying but %s is not set to any repo", DEPLOY);
 			return;
 		}
 		File[] outputs = getBuildFiles();
 		for (File output : outputs) {
-			Jar jar = new Jar(output);
-			try {
-				for (Deploy d : getPlugins(Deploy.class)) {
-					trace("Deploying %s to: %s", jar, d);
-					try {
-						if (d.deploy(this, jar))
-							trace("deployed %s successfully to %s", output, d);
-					} catch (Exception e) {
-						error("Error while deploying %s, %s", this, e);
-						e.printStackTrace();
-					}
+			for (Deploy d : getPlugins(Deploy.class)) {
+				trace("Deploying %s to: %s", output.getName(), d);
+				try {
+					if (d.deploy(this, output.getName(), new BufferedInputStream(new FileInputStream(output))))
+						trace("deployed %s successfully to %s", output, d);
+				}
+				catch (Exception e) {
+					msgs.Deploying(e);
 				}
-			} finally {
-				jar.close();
 			}
 		}
 	}
 
 	/**
-	 * Macro access to the repository
-	 * 
-	 * ${repo;<bsn>[;<version>[;<low|high>]]}
+	 * Macro access to the repository ${repo;<bsn>[;<version>[;<low|high>]]}
 	 */
 
+	static String	_repoHelp	= "${repo ';'<bsn> [ ; <version> [; ('HIGHEST'|'LOWEST')]}";
+
 	public String _repo(String args[]) throws Exception {
-		if (args.length < 2)
-			throw new IllegalArgumentException(
-					"Too few arguments for repo, syntax=: ${repo ';'<bsn> [ ; <version> [; ('HIGHEST'|'LOWEST')]}");
+		if (args.length < 2) {
+			msgs.RepoTooFewArguments(_repoHelp, args);
+			return null;
+		}
 
 		String bsns = args[1];
 		String version = null;
@@ -1190,8 +1094,7 @@ public class Project extends Processor {
 				else if (args[3].equalsIgnoreCase("EXACT"))
 					strategy = Strategy.EXACT;
 				else
-					error("${repo;<bsn>;<version>;<'highest'|'lowest'|'exact'>} macro requires a strategy of 'highest' or 'lowest', and is "
-							+ args[3]);
+					msgs.InvalidStrategy(_repoHelp, args);
 			}
 		}
 
@@ -1215,8 +1118,8 @@ public class Project extends Processor {
 			if (container.getError() == null)
 				paths.add(container.getFile().getAbsolutePath());
 			else {
-				paths.add("<<${repo} = " + container.getBundleSymbolicName() + "-"
-						+ container.getVersion() + " : " + container.getError() + ">>");
+				paths.add("<<${repo} = " + container.getBundleSymbolicName() + "-" + container.getVersion() + " : "
+						+ container.getError() + ">>");
 
 				if (isPedantic()) {
 					warning("Could not expand repo path request: %s ", container);
@@ -1240,7 +1143,7 @@ public class Project extends Processor {
 	 * @throws Exception
 	 */
 	public File[] build(boolean underTest) throws Exception {
-		if (getProperty(NOBUNDLES) != null)
+		if (isNoBundles())
 			return null;
 
 		if (getProperty("-nope") != null) {
@@ -1249,7 +1152,7 @@ public class Project extends Processor {
 		}
 
 		if (isStale()) {
-			trace("Building " + this);
+			trace("building " + this);
 			files = buildLocal(underTest);
 		}
 
@@ -1265,36 +1168,69 @@ public class Project extends Processor {
 	}
 
 	/**
-	 * Check if this project needs building
+	 * Check if this project needs building. This is defined as:
 	 */
 	public boolean isStale() throws Exception {
-		if (files == null)
+		if (workspace.isOffline()) {
+			trace("working %s offline, so always stale", this);
 			return true;
+		}
+
+		Set<Project> visited = new HashSet<Project>();
+		return isStale(visited);
+	}
+
+	boolean isStale(Set<Project> visited) throws Exception {
+		// When we do not generate anything ...
+		if (isNoBundles())
+			return false;
 
-		long localTime = getBuildTime();
-		if (lastModified() > localTime)
+		if (visited.contains(this)) {
+			msgs.CircularDependencyContext_Message_(this.getName(), visited.toString());
+			return false;
+		}
+
+		visited.add(this);
+
+		long buildTime = 0;
+
+		files = getBuildFiles(false);
+		if (files == null)
 			return true;
 
-		for (Project dependency : getDependson()) {
-			if (dependency.isStale())
+		for (File f : files) {
+			if (f.lastModified() < lastModified())
 				return true;
 
-			if (dependency.getBuildTime() > localTime)
-				return true;
+			if (buildTime < f.lastModified())
+				buildTime = f.lastModified();
+		}
+
+		for (Project dependency : getDependson()) {
+			if (dependency == this)
+				continue;
 
-			if (dependency.lastModified() > localTime)
+			if (dependency.isStale())
 				return true;
 
+			if (dependency.isNoBundles())
+				continue;
+
+			File[] deps = dependency.getBuildFiles();
+			for (File f : deps) {
+				if (f.lastModified() >= buildTime)
+					return true;
+			}
 		}
+
 		return false;
 	}
 
 	/**
 	 * This method must only be called when it is sure that the project has been
-	 * build before in the same session.
-	 * 
-	 * It is a bit yucky, but ant creates different class spaces which makes it
-	 * hard to detect we already build it.
+	 * build before in the same session. It is a bit yucky, but ant creates
+	 * different class spaces which makes it hard to detect we already build it.
+	 * This method remembers the files in the appropriate instance vars.
 	 * 
 	 * @return
 	 */
@@ -1304,29 +1240,38 @@ public class Project extends Processor {
 	}
 
 	public File[] getBuildFiles(boolean buildIfAbsent) throws Exception {
+		if (files != null)
+			return files;
+
 		File f = new File(getTarget(), BUILDFILES);
 		if (f.isFile()) {
-			FileReader fin = new FileReader(f);
-			BufferedReader rdr = new BufferedReader(fin);
+			BufferedReader rdr = IO.reader(f);
 			try {
 				List<File> files = newList();
 				for (String s = rdr.readLine(); s != null; s = rdr.readLine()) {
 					s = s.trim();
 					File ff = new File(s);
 					if (!ff.isFile()) {
-						error("buildfile lists file but the file does not exist %s", ff);
-					} else
-						files.add(ff);
+						// Originally we warned the user
+						// but lets just rebuild. That way
+						// the error is not noticed but
+						// it seems better to correct,
+						// See #154
+						rdr.close();
+						f.delete();
+						break;
+					}
+					files.add(ff);
 				}
-				return files.toArray(new File[files.size()]);
-			} finally {
-				fin.close();
+				return this.files = files.toArray(new File[files.size()]);
+			}
+			finally {
+				rdr.close();
 			}
 		}
 		if (buildIfAbsent)
-			return buildLocal(false);
-		else
-			return null;
+			return files = buildLocal(false);
+		return files = null;
 	}
 
 	/**
@@ -1338,45 +1283,59 @@ public class Project extends Processor {
 	 * @throws Exception
 	 */
 	public File[] buildLocal(boolean underTest) throws Exception {
-		if (getProperty(NOBUNDLES) != null)
+		if (isNoBundles())
 			return null;
 
-		long buildtime = System.currentTimeMillis();
 		File bfs = new File(getTarget(), BUILDFILES);
 		bfs.delete();
 
 		files = null;
 		ProjectBuilder builder = getBuilder(null);
-		if (underTest)
-			builder.setProperty(Constants.UNDERTEST, "true");
-		Jar jars[] = builder.builds();
-		File[] files = new File[jars.length];
-
-		for (int i = 0; i < jars.length; i++) {
-			Jar jar = jars[i];
-			files[i] = saveBuild(jar);
-		}
-		getInfo(builder);
-		builder.close();
-		if (isOk()) {
-			this.files = files;
-
-			// Write out the filenames in the buildfiles file
-			// so we can get them later evenin another process
-			FileWriter fw = new FileWriter(bfs);
-			try {
-				for (File f : files) {
-					fw.append(f.getAbsolutePath());
-					fw.append("\n");
+		try {
+			if (underTest)
+				builder.setProperty(Constants.UNDERTEST, "true");
+			Jar jars[] = builder.builds();
+			File[] files = new File[jars.length];
+
+			getInfo(builder);
+
+			if (isOk()) {
+				this.files = files;
+
+				for (int i = 0; i < jars.length; i++) {
+					Jar jar = jars[i];
+					files[i] = saveBuild(jar);
+				}
+
+				// Write out the filenames in the buildfiles file
+				// so we can get them later evenin another process
+				Writer fw = IO.writer(bfs);
+				try {
+					for (File f : files) {
+						fw.append(f.getAbsolutePath());
+						fw.append("\n");
+					}
+				}
+				finally {
+					fw.close();
 				}
-			} finally {
-				fw.close();
+				getWorkspace().changedFile(bfs);
+				return files;
 			}
-			getWorkspace().changedFile(bfs);
-			this.buildtime = buildtime;
-			return files;
-		} else
 			return null;
+		}
+		finally {
+			builder.close();
+		}
+	}
+
+	/**
+	 * Answer if this project does not have any output
+	 * 
+	 * @return
+	 */
+	public boolean isNoBundles() {
+		return getProperty(NOBUNDLES) != null;
 	}
 
 	public File saveBuild(Jar jar) throws Exception {
@@ -1387,8 +1346,12 @@ public class Project extends Processor {
 			if (!f.exists() || f.lastModified() < jar.lastModified()) {
 				reportNewer(f.lastModified(), jar);
 				f.delete();
-				if (!f.getParentFile().isDirectory())
-					f.getParentFile().mkdirs();
+				File fp = f.getParentFile();
+				if (!fp.isDirectory()) {
+					if (!fp.exists() && !fp.mkdirs()) {
+						throw new IOException("Could not create directory " + fp);
+					}
+				}
 				jar.write(f);
 
 				getWorkspace().changedFile(f);
@@ -1397,7 +1360,8 @@ public class Project extends Processor {
 			}
 			trace(jar.getName() + " (" + f.getName() + ") " + jar.getResources().size() + " " + msg);
 			return f;
-		} finally {
+		}
+		finally {
 			jar.close();
 		}
 	}
@@ -1410,7 +1374,7 @@ public class Project extends Processor {
 		if (isTrue(getProperty(Constants.REPORTNEWER))) {
 			StringBuilder sb = new StringBuilder();
 			String del = "Newer than " + new Date(lastModified);
-			for (Map.Entry<String, Resource> entry : jar.getResources().entrySet()) {
+			for (Map.Entry<String,Resource> entry : jar.getResources().entrySet()) {
 				if (entry.getValue().lastModified() > lastModified) {
 					sb.append(del);
 					del = ", \n     ";
@@ -1425,6 +1389,7 @@ public class Project extends Processor {
 	/**
 	 * Refresh if we are based on stale data. This also implies our workspace.
 	 */
+	@Override
 	public boolean refresh() {
 		boolean changed = false;
 		if (isCnf()) {
@@ -1437,6 +1402,7 @@ public class Project extends Processor {
 		return getBase().getName().equals(Workspace.CNFDIR);
 	}
 
+	@Override
 	public void propertiesChanged() {
 		super.propertiesChanged();
 		preparedPaths = false;
@@ -1448,13 +1414,13 @@ public class Project extends Processor {
 		return getBase().getName();
 	}
 
-	public Map<String, Action> getActions() {
-		Map<String, Action> all = newMap();
-		Map<String, Action> actions = newMap();
+	public Map<String,Action> getActions() {
+		Map<String,Action> all = newMap();
+		Map<String,Action> actions = newMap();
 		fillActions(all);
 		getWorkspace().fillActions(all);
 
-		for (Map.Entry<String, Action> action : all.entrySet()) {
+		for (Map.Entry<String,Action> action : all.entrySet()) {
 			String key = getReplacer().process(action.getKey());
 			if (key != null && key.trim().length() != 0)
 				actions.put(key, action.getValue());
@@ -1462,21 +1428,19 @@ public class Project extends Processor {
 		return actions;
 	}
 
-	public void fillActions(Map<String, Action> all) {
+	public void fillActions(Map<String,Action> all) {
 		List<NamedAction> plugins = getPlugins(NamedAction.class);
 		for (NamedAction a : plugins)
 			all.put(a.getName(), a);
 
-		Map<String, Map<String, String>> actions = parseHeader(getProperty("-actions",
-				DEFAULT_ACTIONS));
-		for (Map.Entry<String, Map<String, String>> entry : actions.entrySet()) {
+		Parameters actions = new Parameters(getProperty("-actions", DEFAULT_ACTIONS));
+		for (Entry<String,Attrs> entry : actions.entrySet()) {
 			String key = Processor.removeDuplicateMarker(entry.getKey());
 			Action action;
 
 			if (entry.getValue().get("script") != null) {
 				// TODO check for the type
-				action = new ScriptAction(entry.getValue().get("type"), entry.getValue().get(
-						"script"));
+				action = new ScriptAction(entry.getValue().get("type"), entry.getValue().get("script"));
 			} else {
 				action = new ReflectAction(key);
 			}
@@ -1501,14 +1465,19 @@ public class Project extends Processor {
 	}
 
 	public void clean() throws Exception {
-		File target = getTarget();
+		File target = getTarget0();
 		if (target.isDirectory() && target.getParentFile() != null) {
 			IO.delete(target);
-			target.mkdirs();
+			if (!target.exists() && !target.mkdirs()) {
+				throw new IOException("Could not create directory " + target);
+			}
 		}
+		File output = getOutput0();
 		if (getOutput().isDirectory())
-			IO.delete(getOutput());
-		getOutput().mkdirs();
+			IO.delete(output);
+		if (!output.exists() && !output.mkdirs()) {
+			throw new IOException("Could not create directory " + output);
+		}
 	}
 
 	public File[] build() throws Exception {
@@ -1522,7 +1491,14 @@ public class Project extends Processor {
 	}
 
 	public void test() throws Exception {
+		
+		String testcases = get(Constants.TESTCASES);
+		if ( testcases == null) {
+			warning("No %s set", Constants.TESTCASES);
+			return;
+		}
 		clear();
+		
 		ProjectTester tester = getProjectTester();
 		tester.setContinuous(isTrue(getProperty(Constants.TESTCONTINUOUS)));
 		tester.prepare();
@@ -1532,13 +1508,13 @@ public class Project extends Processor {
 		}
 		int errors = tester.test();
 		if (errors == 0) {
-			System.out.println("No Errors");
+			System.err.println("No Errors");
 		} else {
 			if (errors > 0) {
-				System.out.println(errors + " Error(s)");
+				System.err.println(errors + " Error(s)");
 
 			} else
-				System.out.println("Error " + errors);
+				System.err.println("Error " + errors);
 		}
 	}
 
@@ -1562,7 +1538,8 @@ public class Project extends Processor {
 		try {
 			Jar jar = new Jar(url.getFile().replace('/', '.'), in, System.currentTimeMillis());
 			return getValidJar(jar, url.toString());
-		} finally {
+		}
+		finally {
 			in.close();
 		}
 	}
@@ -1597,24 +1574,83 @@ public class Project extends Processor {
 		return jar;
 	}
 
-	public String _project(String args[]) {
+	public String _project(@SuppressWarnings("unused")
+	String args[]) {
 		return getBase().getAbsolutePath();
 	}
 
-	public void bump(String mask) throws IOException {
-		Sed sed = new Sed(getReplacer(), getPropertiesFile());
-		sed.replace("(Bundle-Version\\s*(:|=)\\s*)(([0-9]+(\\.[0-9]+(\\.[0-9]+)?)?))",
-				"$1${version;" + mask + ";$3}");
-		sed.doIt();
-		forceRefresh();
+	/**
+	 * Bump the version of this project. First check the main bnd file. If this
+	 * does not contain a version, check the include files. If they still do not
+	 * contain a version, then check ALL the sub builders. If not, add a version
+	 * to the main bnd file.
+	 * 
+	 * @param mask
+	 *            the mask for bumping, see {@link Macro#_version(String[])}
+	 * @throws Exception
+	 */
+	public void bump(String mask) throws Exception {
+		String pattern = "(Bundle-Version\\s*(:|=)\\s*)(([0-9]+(\\.[0-9]+(\\.[0-9]+)?)?))";
+		String replace = "$1${version;" + mask + ";$3}";
+		try {
+			// First try our main bnd file
+			if (replace(getPropertiesFile(), pattern, replace))
+				return;
+
+			trace("no version in bnd.bnd");
+
+			// Try the included filed in reverse order (last has highest
+			// priority)
+			List<File> included = getIncluded();
+			if (included != null) {
+				List<File> copy = new ArrayList<File>(included);
+				Collections.reverse(copy);
+
+				for (File file : copy) {
+					if (replace(file, pattern, replace)) {
+						trace("replaced version in file %s", file);
+						return;
+					}
+				}
+			}
+			trace("no version in included files");
+
+			boolean found = false;
+
+			// Replace in all sub builders.
+			for (Builder sub : getSubBuilders()) {
+				found |= replace(sub.getPropertiesFile(), pattern, replace);
+			}
+
+			if (!found) {
+				trace("no version in sub builders, add it to bnd.bnd");
+				String bndfile = IO.collect(getPropertiesFile());
+				bndfile += "\n# Added by by bump\nBundle-Version: 0.0.0\n";
+				IO.store(bndfile, getPropertiesFile());
+			}
+		}
+		finally {
+			forceRefresh();
+		}
 	}
 
-	public void bump() throws IOException {
+	boolean replace(File f, String pattern, String replacement) throws IOException {
+		final Macro macro = getReplacer();
+		Sed sed = new Sed(new Replacer() {
+			public String process(String line) {
+				return macro.process(line);
+			}
+		}, f);
+		sed.replace(pattern, replacement);
+		return sed.doIt() > 0;
+	}
+
+	public void bump() throws Exception {
 		bump(getProperty(BUMPPOLICY, "=+0"));
 	}
 
 	public void action(String command) throws Throwable {
-		Map<String, Action> actions = getActions();
+		Map<String,Action> actions = getActions();
 
 		Action a = actions.get(command);
 		if (a == null)
@@ -1623,7 +1659,8 @@ public class Project extends Processor {
 		before(this, command);
 		try {
 			a.execute(this, command);
-		} catch (Throwable t) {
+		}
+		catch (Throwable t) {
 			after(this, command, t);
 			throw t;
 		}
@@ -1631,9 +1668,9 @@ public class Project extends Processor {
 
 	/**
 	 * Run all before command plugins
-	 * 
 	 */
-	void before(Project p, String a) {
+	void before(@SuppressWarnings("unused")
+	Project p, String a) {
 		List<CommandPlugin> testPlugins = getPlugins(CommandPlugin.class);
 		for (CommandPlugin testPlugin : testPlugins) {
 			testPlugin.before(this, a);
@@ -1643,7 +1680,8 @@ public class Project extends Processor {
 	/**
 	 * Run all after command plugins
 	 */
-	void after(Project p, String a, Throwable t) {
+	void after(@SuppressWarnings("unused")
+	Project p, String a, Throwable t) {
 		List<CommandPlugin> testPlugins = getPlugins(CommandPlugin.class);
 		for (int i = testPlugins.size() - 1; i >= 0; i--) {
 			testPlugins.get(i).after(this, a, t);
@@ -1653,7 +1691,7 @@ public class Project extends Processor {
 	public String _findfile(String args[]) {
 		File f = getFile(args[1]);
 		List<String> files = new ArrayList<String>();
-		tree(files, f, "", Instruction.getPattern(args[2]));
+		tree(files, f, "", new Instruction(args[2]));
 		return join(files);
 	}
 
@@ -1679,18 +1717,22 @@ public class Project extends Processor {
 		refresh();
 	}
 
-	@SuppressWarnings("unchecked") public void script(String type, String script) throws Exception {
+	@SuppressWarnings("unchecked")
+	public void script(@SuppressWarnings("unused")
+	String type, String script) throws Exception {
 		// TODO check tyiping
 		List<Scripter> scripters = getPlugins(Scripter.class);
 		if (scripters.isEmpty()) {
-			error("Can not execute script because there are no scripters registered: %s", script);
+			msgs.NoScripters_(script);
 			return;
 		}
-		@SuppressWarnings("rawtypes") Map x = (Map) getProperties();
-		scripters.get(0).eval((Map<String, Object>) x, new StringReader(script));
+		@SuppressWarnings("rawtypes")
+		Map x = getProperties();
+		scripters.get(0).eval(x, new StringReader(script));
 	}
 
-	public String _repos(String args[]) throws Exception {
+	public String _repos(@SuppressWarnings("unused")
+	String args[]) throws Exception {
 		List<RepositoryPlugin> repos = getPlugins(RepositoryPlugin.class);
 		List<String> names = new ArrayList<String>();
 		for (RepositoryPlugin rp : repos)
@@ -1712,11 +1754,11 @@ public class Project extends Processor {
 
 		if (what == null || what.equals("lead"))
 			return syntax.getLead();
-		if (what == null || what.equals("example"))
+		if (what.equals("example"))
 			return syntax.getExample();
-		if (what == null || what.equals("pattern"))
+		if (what.equals("pattern"))
 			return syntax.getPattern();
-		if (what == null || what.equals("values"))
+		if (what.equals("values"))
 			return syntax.getValues();
 
 		return "Invalid type specified for help: lead, example, pattern, values";
@@ -1728,16 +1770,15 @@ public class Project extends Processor {
 	 * Otherwise it contains all the sub bnd files.
 	 * 
 	 * @return A collection of containers
-	 * 
 	 * @throws Exception
 	 */
 	public Collection<Container> getDeliverables() throws Exception {
 		List<Container> result = new ArrayList<Container>();
-		Collection<? extends Builder> builders = getSubBuilders();
+		Collection< ? extends Builder> builders = getSubBuilders();
 
 		for (Builder builder : builders) {
-			Container c = new Container(this, builder.getBsn(), builder.getVersion(),
-					Container.TYPE.PROJECT, getOutputFile(builder.getBsn()), null, null);
+			Container c = new Container(this, builder.getBsn(), builder.getVersion(), Container.TYPE.PROJECT,
+					getOutputFile(builder.getBsn()), null, null, null);
 			result.add(c);
 		}
 		return result;
@@ -1764,7 +1805,7 @@ public class Project extends Processor {
 		if (!bndFile.getAbsolutePath().startsWith(base.getAbsolutePath()))
 			return null;
 
-		Collection<? extends Builder> builders = getSubBuilders();
+		Collection< ? extends Builder> builders = getSubBuilders();
 		for (Builder sub : builders) {
 			File propertiesFile = sub.getPropertiesFile();
 			if (propertiesFile != null) {
@@ -1785,8 +1826,9 @@ public class Project extends Processor {
 	 * @return null or the builder for a sub file.
 	 * @throws Exception
 	 */
-	public Container getDeliverable(String bsn, Map<String, String> attrs) throws Exception {
-		Collection<? extends Builder> builders = getSubBuilders();
+	public Container getDeliverable(String bsn, @SuppressWarnings("unused")
+	Map<String,String> attrs) throws Exception {
+		Collection< ? extends Builder> builders = getSubBuilders();
 		for (Builder sub : builders) {
 			if (sub.getBsn().equals(bsn))
 				return new Container(this, getOutputFile(bsn));
@@ -1803,7 +1845,7 @@ public class Project extends Processor {
 	 * @return A list of builders.
 	 * @throws Exception
 	 */
-	public Collection<? extends Builder> getSubBuilders() throws Exception {
+	public Collection< ? extends Builder> getSubBuilders() throws Exception {
 		return getBuilder(null).getSubBuilders();
 	}
 
@@ -1823,11 +1865,16 @@ public class Project extends Processor {
 	}
 
 	public Collection<String> getRunVM() {
-		Map<String, Map<String, String>> hdr = parseHeader(getProperty(RUNVM));
+		Parameters hdr = getParameters(RUNVM);
+		return hdr.keySet();
+	}
+
+	public Collection<String> getRunProgramArgs() {
+		Parameters hdr = getParameters(RUNPROGRAMARGS);
 		return hdr.keySet();
 	}
 
-	public Map<String, String> getRunProperties() {
+	public Map<String,String> getRunProperties() {
 		return OSGiHeader.parseProperties(getProperty(RUNPROPERTIES));
 	}
 
@@ -1838,23 +1885,23 @@ public class Project extends Processor {
 	 * @throws Exception
 	 */
 	public ProjectLauncher getProjectLauncher() throws Exception {
-		return getHandler(ProjectLauncher.class, getRunpath(), LAUNCHER_PLUGIN,
-				"biz.aQute.launcher");
+		return getHandler(ProjectLauncher.class, getRunpath(), LAUNCHER_PLUGIN, "biz.aQute.launcher");
 	}
 
 	public ProjectTester getProjectTester() throws Exception {
 		return getHandler(ProjectTester.class, getTestpath(), TESTER_PLUGIN, "biz.aQute.junit");
 	}
 
-	private <T> T getHandler(Class<T> target, Collection<Container> containers, String header,
-			String defaultHandler) throws Exception {
-		Class<? extends T> handlerClass = target;
+	private <T> T getHandler(Class<T> target, Collection<Container> containers, String header, String defaultHandler)
+			throws Exception {
+		Class< ? extends T> handlerClass = target;
 
 		// Make sure we find at least one handler, but hope to find an earlier
 		// one
 		List<Container> withDefault = Create.list();
 		withDefault.addAll(containers);
 		withDefault.addAll(getBundles(Strategy.HIGHEST, defaultHandler, null));
+		trace("candidates for tester %s", withDefault);
 
 		for (Container c : withDefault) {
 			Manifest manifest = c.getManifest();
@@ -1862,62 +1909,216 @@ public class Project extends Processor {
 			if (manifest != null) {
 				String launcher = manifest.getMainAttributes().getValue(header);
 				if (launcher != null) {
-					Class<?> clz = getClass(launcher, c.getFile());
+					Class< ? > clz = getClass(launcher, c.getFile());
 					if (clz != null) {
 						if (!target.isAssignableFrom(clz)) {
-							error("Found a %s class in %s but it is not compatible with: %s", clz,
-									c, target);
+							msgs.IncompatibleHandler_For_(launcher, defaultHandler);
 						} else {
 							handlerClass = clz.asSubclass(target);
-							Constructor<? extends T> constructor = handlerClass
-									.getConstructor(Project.class);
+							Constructor< ? extends T> constructor = handlerClass.getConstructor(Project.class);
 							return constructor.newInstance(this);
 						}
 					}
 				}
 			}
 		}
-		throw new IllegalArgumentException("Default handler for " + header + " not found in "
-				+ defaultHandler);
+
+		throw new IllegalArgumentException("Default handler for " + header + " not found in " + defaultHandler);
 	}
 
-	public synchronized boolean lock(String reason) throws InterruptedException {
-		if (!lock.tryLock(5, TimeUnit.SECONDS)) {
-			error("Could not acquire lock for %s, was locked by %s for %s", reason, lockingThread,
-					lockingReason);
-			System.out.printf("Could not acquire lock for %s, was locked by %s for %s\n", reason,
-					lockingThread, lockingReason);
-			System.out.flush();
-			return false;
+	/**
+	 * Make this project delay the calculation of the run dependencies. The run
+	 * dependencies calculation can be done in prepare or until the dependencies
+	 * are actually needed.
+	 */
+	public void setDelayRunDependencies(boolean x) {
+		delayRunDependencies = x;
+	}
+
+	/**
+	 * Sets the package version on an exported package
+	 * 
+	 * @param packageName
+	 *            The package name
+	 * @param version
+	 *            The new package version
+	 */
+	public void setPackageInfo(String packageName, Version version) {
+		try {
+			Version current = getPackageInfoJavaVersion(packageName);
+			boolean packageInfoJava = false;
+			if (current != null) {
+				updatePackageInfoJavaFile(packageName, version);
+				packageInfoJava = true;
+			}
+			if (!packageInfoJava || getPackageInfoFile(packageName).exists()) {
+				updatePackageInfoFile(packageName, version);
+			}
+		}
+		catch (Exception e) {
+			msgs.SettingPackageInfoException_(e);
+		}
+	}
+
+	void updatePackageInfoJavaFile(String packageName, final Version newVersion) throws Exception {
+		File file = getPackageInfoJavaFile(packageName);
+
+		if (!file.exists()) {
+			return;
+		}
+
+		// If package/classes are copied into the bundle through Private-Package
+		// etc, there will be no source
+		if (!file.getParentFile().exists()) {
+			return;
+		}
+
+		Version oldVersion = getPackageInfo(packageName);
+
+		if (newVersion.compareTo(oldVersion) == 0) {
+			return;
+		}
+
+		Sed sed = new Sed(new Replacer() {
+			public String process(String line) {
+				Matcher m = VERSION_ANNOTATION.matcher(line);
+				if (m.find()) {
+					return line.substring(0, m.start(3)) + newVersion.toString() + line.substring(m.end(3));
+				}
+				return line;
+			}
+		}, file);
+
+		sed.replace(VERSION_ANNOTATION.pattern(), "$0");
+		sed.setBackup(false);
+		sed.doIt();
+	}
+
+	void updatePackageInfoFile(String packageName, Version newVersion) throws Exception {
+
+		File file = getPackageInfoFile(packageName);
+
+		// If package/classes are copied into the bundle through Private-Package
+		// etc, there will be no source
+		if (!file.getParentFile().exists()) {
+			return;
+		}
+
+		Version oldVersion = getPackageInfoVersion(packageName);
+		if (oldVersion == null) {
+			oldVersion = Version.emptyVersion;
+		}
+
+		if (newVersion.compareTo(oldVersion) == 0) {
+			return;
+		}
+		PrintWriter pw = IO.writer(file);
+		pw.println("version " + newVersion);
+		pw.flush();
+		pw.close();
+
+		String path = packageName.replace('.', '/') + "/packageinfo";
+		File binary = IO.getFile(getOutput(), path);
+		File bp = binary.getParentFile();
+		if (!bp.exists() && !bp.mkdirs()) {
+			throw new IOException("Could not create directory " + bp);
 		}
-		this.lockingReason = reason;
-		this.lockingThread = Thread.currentThread();
-		return true;
+		IO.copy(file, binary);
+	}
+
+	File getPackageInfoFile(String packageName) {
+		String path = packageName.replace('.', '/') + "/packageinfo";
+		return IO.getFile(getSrc(), path);
+
 	}
 
-	public void unlock() {
-		lockingReason = null;
-		lock.unlock();
+	File getPackageInfoJavaFile(String packageName) {
+		String path = packageName.replace('.', '/') + "/package-info.java";
+		return IO.getFile(getSrc(), path);
+
 	}
 
-	public long getBuildTime() throws Exception {
-		if (buildtime == 0) {
+	public Version getPackageInfo(String packageName) throws IOException {
+
+		Version version = getPackageInfoJavaVersion(packageName);
+		if (version != null) {
+			return version;
+		}
+		
+		version = getPackageInfoVersion(packageName);
+		if (version != null) {
+			return version;
+		}
+
+		return Version.emptyVersion;
+	}
 
-			files = getBuildFiles();
-			if (files != null && files.length >= 1)
-				buildtime = files[0].lastModified();
+	Version getPackageInfoVersion(String packageName) throws IOException {
+		File packageInfoFile = getPackageInfoFile(packageName);
+		if (!packageInfoFile.exists()) {
+			return null;
+		}
+		BufferedReader reader = null;
+		try {
+			reader = IO.reader(packageInfoFile);
+			String line;
+			while ((line = reader.readLine()) != null) {
+				line = line.trim();
+				if (line.startsWith("version ")) {
+					return Version.parseVersion(line.substring(8));
+				}
+			}
 		}
-		return buildtime;
+		finally {
+			if (reader != null) {
+				IO.close(reader);
+			}
+		}
+		return null;
+	}
+
+	Version getPackageInfoJavaVersion(String packageName) throws IOException {
+		File packageInfoJavaFile = getPackageInfoJavaFile(packageName);
+		if (!packageInfoJavaFile.exists()) {
+			return null;
+		}
+		BufferedReader reader = null;
+		try {
+			reader = IO.reader(packageInfoJavaFile);
+			String line;
+			while ((line = reader.readLine()) != null) {
+				Matcher matcher = VERSION_ANNOTATION.matcher(line);
+				if (matcher.find()) {
+					return Version.parseVersion(matcher.group(3));
+				}
+			}
+		}
+		finally {
+			if (reader != null) {
+				IO.close(reader);
+			}
+		}
+		return null;
 	}
 
 	/**
-	 * Make this project delay the calculation of the run dependencies.
-	 * 
-	 * The run dependencies calculation can be done in prepare or until the
-	 * dependencies are actually needed.
+	 * bnd maintains a class path that is set by the environment, i.e. bnd is
+	 * not in charge of it.
 	 */
-	public void setDelayRunDependencies(boolean x) {
-		delayRunDependencies = x;
+
+	public void addClasspath(File f) {
+		if (!f.isFile() && !f.isDirectory()) {
+			msgs.AddingNonExistentFileToClassPath_(f);
+		}
+		Container container = new Container(f, null);
+		classpath.add(container);
+	}
+
+	public void clearClasspath() {
+		classpath.clear();
 	}
 
+	public Collection<Container> getClasspath() {
+		return classpath;
+	}
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/ProjectBuilder.java b/biz.aQute.bndlib/src/aQute/bnd/build/ProjectBuilder.java
index d9cccda..e551c9c 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/build/ProjectBuilder.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/ProjectBuilder.java
@@ -3,71 +3,187 @@ package aQute.bnd.build;
 import java.io.*;
 import java.util.*;
 
-import aQute.lib.osgi.*;
+import aQute.bnd.differ.*;
+import aQute.bnd.differ.Baseline.Info;
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.*;
+import aQute.bnd.version.*;
 
 public class ProjectBuilder extends Builder {
-    Project project;
-    boolean initialized;
-
-    public ProjectBuilder(Project project) {
-        super(project);
-        this.project = project;
-    }
-
-    public ProjectBuilder(ProjectBuilder builder) {
-        super(builder);
-        this.project = builder.project;
-    }
-
-    @Override
-    public long lastModified() {
-        return Math.max(project.lastModified(), super.lastModified());
-    }
-
-    /**
-     * We put our project and our workspace on the macro path.
-     */
-    protected Object[] getMacroDomains() {
-        return new Object[] { project, project.getWorkspace() };
-    }
-
-    public Builder getSubBuilder() throws Exception {
-        return project.getBuilder(this);
-    }
-
-    public Project getProject() {
-        return project;
-    }
-
-    public void init() {
-        try {
-            if (!initialized) {
-                initialized = true;
-                for (Container file : project.getBuildpath()) {
-                    addClasspath(file.getFile());
-                }
-
-                for (Container file : project.getBootclasspath()) {
-                    addClasspath(file.getFile());
-                }
-
-                for (File file : project.getAllsourcepath()) {
-                    addSourcepath(file);
-                }
-
-            }
-        } catch (Exception e) {
-            error("init project builder fails", e);
-        }
-    }
-
-    public List<Jar> getClasspath() {
-        init();
-        return super.getClasspath();
-    }
-
-    @Override
-    protected void changedFile(File f) {
-        project.getWorkspace().changedFile(f);
-    }
+	private final DiffPluginImpl	differ	= new DiffPluginImpl();
+	Project							project;
+	boolean							initialized;
+
+	public ProjectBuilder(Project project) {
+		super(project);
+		this.project = project;
+	}
+
+	public ProjectBuilder(ProjectBuilder builder) {
+		super(builder);
+		this.project = builder.project;
+	}
+
+	@Override
+	public long lastModified() {
+		return Math.max(project.lastModified(), super.lastModified());
+	}
+
+	/**
+	 * We put our project and our workspace on the macro path.
+	 */
+	@Override
+	protected Object[] getMacroDomains() {
+		return new Object[] {
+				project, project.getWorkspace()
+		};
+	}
+
+	@Override
+	public Builder getSubBuilder() throws Exception {
+		return project.getBuilder(this);
+	}
+
+	public Project getProject() {
+		return project;
+	}
+
+	@Override
+	public void init() {
+		try {
+			if (!initialized) {
+				initialized = true;
+				for (Container file : project.getClasspath()) {
+					addClasspath(file.getFile());
+				}
+
+				for (Container file : project.getBuildpath()) {
+					addClasspath(file.getFile());
+				}
+
+				for (Container file : project.getBootclasspath()) {
+					addClasspath(file.getFile());
+				}
+
+				for (File file : project.getAllsourcepath()) {
+					addSourcepath(file);
+				}
+
+			}
+		}
+		catch (Exception e) {
+			msgs.Unexpected_Error_("ProjectBuilder init", e);
+		}
+	}
+
+	@Override
+	public List<Jar> getClasspath() {
+		init();
+		return super.getClasspath();
+	}
+
+	@Override
+	protected void changedFile(File f) {
+		project.getWorkspace().changedFile(f);
+	}
+
+	/**
+	 * Compare this builder's JAR with a baseline
+	 * 
+	 * @throws Exception
+	 */
+	@Override
+	protected void doBaseline(Jar dot) throws Exception {
+
+		Jar jar = getBaselineJar(false);
+		if (jar == null) {
+			return;
+		}
+		try {
+			Baseline baseline = new Baseline(this, differ);
+
+			Set<Info> infos = baseline.baseline(dot, jar, null);
+			for (Info info : infos) {
+				if (info.mismatch) {
+					error("%s %-50s %-10s %-10s %-10s %-10s %-10s\n", info.mismatch ? '*' : ' ', info.packageName,
+							info.packageDiff.getDelta(), info.newerVersion, info.olderVersion, info.suggestedVersion,
+							info.suggestedIfProviders == null ? "-" : info.suggestedIfProviders);
+				}
+			}
+		}
+		finally {
+			jar.close();
+		}
+	}
+
+	public Jar getBaselineJar(boolean fallback) throws Exception {
+
+		String baseline = getProperty(Constants.BASELINE);
+		String baselineRepo = getProperty(Constants.BASELINEREPO);
+		if ((baseline == null || baseline.trim().length() == 0) 
+				&& (baselineRepo == null || baselineRepo.trim().length() == 0) && !fallback)
+			return null;
+
+		File baselineFile = null;
+		if ((baseline == null || baseline.trim().length() == 0)) {
+			baselineFile = getBaselineFromRepo(fallback);
+			if (baselineFile != null)
+				trace("baseline %s", baselineFile.getName());
+		} else {
+
+			trace("baseline %s", baseline);
+
+			Collection<Container> bundles = project.getBundles(Strategy.LOWEST, baseline);
+			for (Container c : bundles) {
+
+				if (c.getError() != null || c.getFile() == null) {
+					error("Erroneous baseline bundle %s", c);
+					continue;
+				}
+
+				baselineFile = c.getFile();
+				break;
+			}
+		}
+		if (fallback && baselineFile == null) {
+			return new Jar(".");
+		}
+		return new Jar(baselineFile);
+	}
+
+	private File getBaselineFromRepo(boolean fallback) throws Exception {
+		String repoName = getProperty(Constants.BASELINEREPO);
+		if (repoName == null && !fallback)
+			return null;
+
+		if (repoName == null) {
+			repoName = getProperty(Constants.RELEASEREPO);
+			if (repoName == null) {
+				return null;
+			}
+		}
+
+		List<RepositoryPlugin> repos = getPlugins(RepositoryPlugin.class);
+		for (RepositoryPlugin repo : repos) {
+			if (repoName.equals(repo.getName())) {
+				SortedSet<Version> versions = repo.versions(getBsn());
+				if (!versions.isEmpty()) {
+					return repo.get(getBsn(), versions.last(), null);
+				}
+				break;
+			}
+		}
+		return null;
+
+	}
+
+	/** 
+	 * Gets the baseline Jar. 
+	 * 
+	 * @return the baseline jar
+	 * @throws Exception
+	 */
+	public Jar getBaselineJar() throws Exception {
+		return getBaselineJar(true);
+	}
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/ProjectLauncher.java b/biz.aQute.bndlib/src/aQute/bnd/build/ProjectLauncher.java
index fc1dfdb..3d729a8 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/build/ProjectLauncher.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/ProjectLauncher.java
@@ -2,11 +2,13 @@ package aQute.bnd.build;
 
 import java.io.*;
 import java.util.*;
+import java.util.Map.Entry;
 import java.util.concurrent.*;
 import java.util.jar.*;
 
-import aQute.bnd.service.RepositoryPlugin.Strategy;
-import aQute.lib.osgi.*;
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.*;
 import aQute.libg.command.*;
 import aQute.libg.generics.*;
 
@@ -17,42 +19,44 @@ import aQute.libg.generics.*;
  * class is instantiated and cast to a LauncherPlugin. This plug in is then
  * asked to provide a ProjectLauncher. This project launcher is then used by the
  * project to run the code. Launchers must extend this class.
- * 
  */
 public abstract class ProjectLauncher {
-	private final Project						project;
-	private long								timeout				= 0;
-	private final Collection<String>			classpath			= new ArrayList<String>();
-	private List<String>						runbundles			= Create.list();
-	private final List<String>					runvm				= new ArrayList<String>();
-	private Map<String, String>					runproperties;
-	private Command								java;
-	private Map<String, Map<String, String>>	runsystempackages;
-	private final List<String>					activators			= Create.list();
-	private File								storageDir;
-	private final List<String>					warnings			= Create.list();
-	private final List<String>					errors				= Create.list();
-
-	private boolean								trace;
-	private boolean								keep;
-	private int									framework;
-
-	public final static int						SERVICES			= 10111;
-	public final static int						NONE				= 20123;
+	private final Project		project;
+	private long				timeout				= 0;
+	private final List<String>	classpath			= new ArrayList<String>();
+	private List<String>		runbundles			= Create.list();
+	private final List<String>	runvm				= new ArrayList<String>();
+	private final List<String>	runprogramargs		= new ArrayList<String>();
+	private Map<String,String>	runproperties;
+	private Command				java;
+	private Parameters			runsystempackages;
+	private String				runsystemcapabilities;
+	private final List<String>	activators			= Create.list();
+	private File				storageDir;
+	private final List<String>	warnings			= Create.list();
+	private final List<String>	errors				= Create.list();
+
+	private boolean				trace;
+	private boolean				keep;
+	private int					framework;
+	private File				cwd;
+
+	public final static int		SERVICES			= 10111;
+	public final static int		NONE				= 20123;
 
 	// MUST BE ALIGNED WITH LAUNCHER
-	public final static int						OK					= 0;
-	public final static int						WARNING				= -1;
-	public final static int						ERROR				= -2;
-	public final static int						TIMEDOUT			= -3;
-	public final static int						UPDATE_NEEDED		= -4;
-	public final static int						CANCELED			= -5;
-	public final static int						DUPLICATE_BUNDLE	= -6;
-	public final static int						RESOLVE_ERROR		= -7;
-	public final static int						ACTIVATOR_ERROR		= -8;
-	public final static int						CUSTOM_LAUNCHER		= -128;
-
-	public final static String					EMBEDDED_ACTIVATOR	= "Embedded-Activator";
+	public final static int		OK					= 0;
+	public final static int		WARNING				= -1;
+	public final static int		ERROR				= -2;
+	public final static int		TIMEDOUT			= -3;
+	public final static int		UPDATE_NEEDED		= -4;
+	public final static int		CANCELED			= -5;
+	public final static int		DUPLICATE_BUNDLE	= -6;
+	public final static int		RESOLVE_ERROR		= -7;
+	public final static int		ACTIVATOR_ERROR		= -8;
+	public final static int		CUSTOM_LAUNCHER		= -128;
+
+	public final static String	EMBEDDED_ACTIVATOR	= "Embedded-Activator";
 
 	public ProjectLauncher(Project project) throws Exception {
 		this.project = project;
@@ -71,13 +75,13 @@ public abstract class ProjectLauncher {
 		// project.refresh();
 		runbundles.clear();
 		Collection<Container> run = project.getRunbundles();
-		
+
 		for (Container container : run) {
 			File file = container.getFile();
 			if (file != null && (file.isFile() || file.isDirectory())) {
 				runbundles.add(file.getAbsolutePath());
 			} else {
-				warning("Bundle file \"%s\" does not exist", file.getAbsolutePath());
+				warning("Bundle file \"%s\" does not exist", file);
 			}
 		}
 
@@ -89,15 +93,15 @@ public abstract class ProjectLauncher {
 		}
 
 		Collection<Container> runpath = project.getRunpath();
-		runsystempackages = project.parseHeader(project.getProperty(Constants.RUNSYSTEMPACKAGES));
+		runsystempackages = project.getParameters(Constants.RUNSYSTEMPACKAGES);
+		runsystemcapabilities = project.getProperty(Constants.RUNSYSTEMCAPABILITIES);
 		framework = getRunframework(project.getProperty(Constants.RUNFRAMEWORK));
 		trace = Processor.isTrue(project.getProperty(Constants.RUNTRACE));
 
 		timeout = Processor.getDuration(project.getProperty(Constants.RUNTIMEOUT), 0);
 		trace = Processor.isTrue(project.getProperty(Constants.RUNTRACE));
 
-		// For backward compatibility with bndtools launcher
-		List<Container> fws = project.getBundles(Strategy.HIGHEST, project.getProperty("-runfw"), "-runfw");
+		List<Container> fws = project.getBundles(Strategy.HIGHEST, project.getProperty(Constants.RUNFW), Constants.RUNFW);
 		runpath.addAll(fws);
 
 		for (Container c : runpath) {
@@ -105,6 +109,7 @@ public abstract class ProjectLauncher {
 		}
 
 		runvm.addAll(project.getRunVM());
+		runprogramargs.addAll(project.getRunProgramArgs());
 		runproperties = project.getRunProperties();
 
 		storageDir = project.getRunStorage();
@@ -124,8 +129,7 @@ public abstract class ProjectLauncher {
 
 	public void addClasspath(Container container) throws Exception {
 		if (container.getError() != null) {
-			project.error("Cannot launch because %s has reported %s", container.getProject(),
-					container.getError());
+			project.error("Cannot launch because %s has reported %s", container.getProject(), container.getError());
 		} else {
 			Collection<Container> members = container.getMembers();
 			for (Container m : members) {
@@ -134,10 +138,11 @@ public abstract class ProjectLauncher {
 					classpath.add(path);
 
 					Manifest manifest = m.getManifest();
+
 					if (manifest != null) {
-						Map<String, Map<String, String>> exports = project.parseHeader(manifest
-								.getMainAttributes().getValue(Constants.EXPORT_PACKAGE));
-						for (Map.Entry<String, Map<String, String>> e : exports.entrySet()) {
+						Parameters exports = project.parseHeader(manifest.getMainAttributes().getValue(
+								Constants.EXPORT_PACKAGE));
+						for (Entry<String,Attrs> e : exports.entrySet()) {
 							if (!runsystempackages.containsKey(e.getKey()))
 								runsystempackages.put(e.getKey(), e.getValue());
 						}
@@ -147,8 +152,7 @@ public abstract class ProjectLauncher {
 						// the framework is completely initialized wit the
 						// system
 						// context.
-						String activator = manifest.getMainAttributes()
-								.getValue(EMBEDDED_ACTIVATOR);
+						String activator = manifest.getMainAttributes().getValue(EMBEDDED_ACTIVATOR);
 						if (activator != null)
 							activators.add(activator);
 					}
@@ -169,7 +173,11 @@ public abstract class ProjectLauncher {
 		runvm.add(arg);
 	}
 
-	public Collection<String> getRunpath() {
+	public void addRunProgramArgs(String arg) {
+		runprogramargs.add(arg);
+	}
+
+	public List<String> getRunpath() {
 		return classpath;
 	}
 
@@ -181,14 +189,19 @@ public abstract class ProjectLauncher {
 		return runvm;
 	}
 
+	@Deprecated
 	public Collection<String> getArguments() {
-		return Collections.emptySet();
+		return getRunProgramArgs();
+	}
+
+	public Collection<String> getRunProgramArgs() {
+		return runprogramargs;
 	}
 
-	public Map<String, String> getRunProperties() {
+	public Map<String,String> getRunProperties() {
 		return runproperties;
 	}
-	
+
 	public File getStorageDir() {
 		return storageDir;
 	}
@@ -205,37 +218,53 @@ public abstract class ProjectLauncher {
 		java.add(Processor.join(getClasspath(), File.pathSeparator));
 		java.addAll(getRunVM());
 		java.add(getMainTypeName());
-		java.addAll(getArguments());
+		java.addAll(getRunProgramArgs());
 		if (timeout != 0)
 			java.setTimeout(timeout + 1000, TimeUnit.MILLISECONDS);
+		
+		File cwd = getCwd();
+		if (cwd != null) java.setCwd(cwd);
+
+		try {
+			int result = java.execute(System.in, System.err, System.err);
+			if (result == Integer.MIN_VALUE)
+				return TIMEDOUT;
+			reportResult(result);
+			return result;
+		}
+		finally {
+			cleanup();
+		}
+	}
 
-		int result = java.execute(System.in, System.out, System.err);
-		if (result == Integer.MIN_VALUE)
-			return TIMEDOUT;
+	/**
+	 * Is called after the process exists. Can you be used to cleanup the
+	 * properties file.
+	 */
 
-		reportResult(result);
-		return result;
+	public void cleanup() {
+		// do nothing by default
 	}
 
 	protected void reportResult(int result) {
 		switch (result) {
-		case OK:
-			project.trace("Command terminated normal %s", java);
-			break;
-		case TIMEDOUT:
-			project.error("Launch timedout: %s", java);
-			break;
-
-		case ERROR:
-			project.error("Launch errored: %s", java);
-			break;
-
-		case WARNING:
-			project.warning("Launch had a warning %s", java);
-			break;
-		default:
-			project.warning("Unknown code %d from launcher: %s", result, java);
-			break;
+			case OK :
+				project.trace("Command terminated normal %s", java);
+				break;
+			case TIMEDOUT :
+				project.error("Launch timedout: %s", java);
+				break;
+
+			case ERROR :
+				project.error("Launch errored: %s", java);
+				break;
+
+			case WARNING :
+				project.warning("Launch had a warning %s", java);
+				break;
+			default :
+				project.error("Exit code remote process %d: %s", result, java);
+				break;
 		}
 	}
 
@@ -251,8 +280,12 @@ public abstract class ProjectLauncher {
 		java.cancel();
 	}
 
-	public Map<String, Map<String, String>> getSystemPackages() {
-		return runsystempackages;
+	public Map<String, ? extends Map<String,String>> getSystemPackages() {
+		return runsystempackages.asMapMap();
+	}
+	
+	public String getSystemCapabilities() {
+		return runsystemcapabilities;
 	}
 
 	public void setKeep(boolean keep) {
@@ -329,20 +362,20 @@ public abstract class ProjectLauncher {
 	public Jar executable() throws Exception {
 		throw new UnsupportedOperationException();
 	}
-	
+
 	public void clear() {
 		errors.clear();
 		warnings.clear();
 	}
-	
+
 	public List<String> getErrors() {
 		return Collections.unmodifiableList(errors);
 	}
-	
+
 	public List<String> getWarnings() {
 		return Collections.unmodifiableList(warnings);
 	}
-	
+
 	protected void error(String message, Object... args) {
 		String formatted = String.format(message, args);
 		errors.add(formatted);
@@ -352,4 +385,12 @@ public abstract class ProjectLauncher {
 		String formatted = String.format(message, args);
 		warnings.add(formatted);
 	}
+	
+	public File getCwd() {
+		return cwd;
+	}
+
+	public void setCwd(File cwd) {
+		this.cwd = cwd;
+	}
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/ProjectMessages.java b/biz.aQute.bndlib/src/aQute/bnd/build/ProjectMessages.java
new file mode 100644
index 0000000..c2908a4
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/ProjectMessages.java
@@ -0,0 +1,48 @@
+package aQute.bnd.build;
+
+import java.io.*;
+import java.util.*;
+
+import aQute.bnd.service.*;
+import aQute.bnd.version.*;
+import aQute.service.reporter.*;
+
+public interface ProjectMessages extends Messages {
+
+	ERROR InvalidStrategy(String help, String[] args);
+
+	ERROR RepoTooFewArguments(String help, String[] args);
+
+	ERROR AddingNonExistentFileToClassPath_(File f);
+
+	ERROR Deploying(Exception e);
+
+	ERROR DeployingFile_On_Exception_(File file, String name, Exception e);
+
+	ERROR MissingPom();
+
+	ERROR FoundVersions_ForStrategy_ButNoProvider(SortedMap<Version,RepositoryPlugin> versions, Strategy useStrategy);
+
+	ERROR NoSuchProject(String bsn, String spec);
+
+	ERROR CircularDependencyContext_Message_(String name, String message);
+
+	ERROR IncompatibleHandler_For_(String launcher, String defaultHandler);
+
+	ERROR NoOutputDirectory_(File output);
+
+	ERROR MissingDependson_(String p);
+
+	ERROR NoNameForReleaseRepository();
+
+	ERROR ReleaseRepository_NotFoundIn_(String name, List<RepositoryPlugin> plugins);
+
+	ERROR Release_Into_Exception_(String jar, RepositoryPlugin rp, Exception e);
+
+	ERROR NoScripters_(String script);
+
+	ERROR SettingPackageInfoException_(Exception e);
+
+	ERROR ConfusedNoContainerFile();
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/ProjectTester.java b/biz.aQute.bndlib/src/aQute/bnd/build/ProjectTester.java
index 5060d2f..a765a2e 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/build/ProjectTester.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/ProjectTester.java
@@ -10,7 +10,8 @@ public abstract class ProjectTester {
 	final List<String>			tests		= new ArrayList<String>();
 	File						reportDir;
 	boolean						continuous	= true;
-	
+	File						cwd;
+
 	public ProjectTester(Project project) throws Exception {
 		this.project = project;
 		launcher = project.getProjectLauncher();
@@ -18,8 +19,7 @@ public abstract class ProjectTester {
 		for (Container c : testbundles) {
 			launcher.addClasspath(c);
 		}
-		reportDir = new File(project.getTarget(), project.getProperty("test-reports",
-				"test-reports"));
+		reportDir = new File(project.getTarget(), project.getProperty("test-reports", "test-reports"));
 	}
 
 	public ProjectLauncher getProjectLauncher() {
@@ -37,7 +37,7 @@ public abstract class ProjectTester {
 	public Collection<File> getReports() {
 		List<File> reports = new ArrayList<File>();
 		for (File report : reportDir.listFiles()) {
-			if (report.isFile() )
+			if (report.isFile())
 				reports.add(report);
 		}
 		return reports;
@@ -62,10 +62,20 @@ public abstract class ProjectTester {
 	public void setContinuous(boolean b) {
 		this.continuous = b;
 	}
+	
+	public File getCwd() {
+		return cwd;
+	}
+	
+	public void setCwd(File dir) {
+		this.cwd = dir;
+	}
 
 	public boolean prepare() throws Exception {
-		reportDir.mkdirs();
-		for ( File file : reportDir.listFiles() ) {
+		if (!reportDir.exists() && !reportDir.mkdirs()) {
+			throw new IOException("Could not create directory " + reportDir);
+		}
+		for (File file : reportDir.listFiles()) {
 			file.delete();
 		}
 		return true;
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/ReflectAction.java b/biz.aQute.bndlib/src/aQute/bnd/build/ReflectAction.java
index 55c2861..7a0f855 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/build/ReflectAction.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/ReflectAction.java
@@ -5,18 +5,19 @@ import java.lang.reflect.*;
 import aQute.bnd.service.action.*;
 
 public class ReflectAction implements Action {
-    String  what;
-    
-    public ReflectAction(String what) {
-        this.what = what;
-    }
-    
-    public void execute(Project project, String action) throws Exception {
-        Method m = project.getClass().getMethod(what);
-        m.invoke(project);
-    }
+	String	what;
 
-    public String toString() {
-        return "ra:" + what;
-    }
+	public ReflectAction(String what) {
+		this.what = what;
+	}
+
+	public void execute(Project project, String action) throws Exception {
+		Method m = project.getClass().getMethod(what);
+		m.invoke(project);
+	}
+
+	@Override
+	public String toString() {
+		return "ra:" + what;
+	}
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/ScriptAction.java b/biz.aQute.bndlib/src/aQute/bnd/build/ScriptAction.java
index 8ca55fd..cba37e6 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/build/ScriptAction.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/ScriptAction.java
@@ -3,16 +3,16 @@ package aQute.bnd.build;
 import aQute.bnd.service.action.*;
 
 public class ScriptAction implements Action {
-    final String script;
-    final String type;
-    
-    public ScriptAction(String type, String script) {
-        this.script = script;
-        this.type = type;
-    }
+	final String	script;
+	final String	type;
 
-    public void execute(Project project, String action) throws Exception {
-        project.script(type, script);
-    }
+	public ScriptAction(String type, String script) {
+		this.script = script;
+		this.type = type;
+	}
+
+	public void execute(Project project, String action) throws Exception {
+		project.script(type, script);
+	}
 
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/Workspace.java b/biz.aQute.bndlib/src/aQute/bnd/build/Workspace.java
index ba731ce..be7a71c 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/build/Workspace.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/Workspace.java
@@ -2,6 +2,7 @@ package aQute.bnd.build;
 
 import java.io.*;
 import java.lang.ref.*;
+import java.net.*;
 import java.util.*;
 import java.util.concurrent.*;
 import java.util.concurrent.locks.*;
@@ -10,12 +11,14 @@ import java.util.jar.*;
 import javax.naming.*;
 
 import aQute.bnd.maven.support.*;
+import aQute.bnd.osgi.*;
 import aQute.bnd.service.*;
 import aQute.bnd.service.action.*;
 import aQute.lib.deployer.*;
+import aQute.lib.hex.*;
 import aQute.lib.io.*;
-import aQute.lib.osgi.*;
-import aQute.libg.reporter.*;
+import aQute.lib.settings.*;
+import aQute.service.reporter.*;
 
 public class Workspace extends Processor {
 	public static final String					BUILDFILE	= "build.bnd";
@@ -23,13 +26,13 @@ public class Workspace extends Processor {
 	public static final String					BNDDIR		= "bnd";
 	public static final String					CACHEDIR	= "cache";
 
-	static Map<File, WeakReference<Workspace>>	cache		= newHashMap();
-	final Map<String, Project>					models		= newHashMap();
-	final Map<String, Action>					commands	= newMap();
-	final CachedFileRepo						cachedRepo;
+	static Map<File,WeakReference<Workspace>>	cache		= newHashMap();
+	final Map<String,Project>					models		= newHashMap();
+	final Map<String,Action>					commands	= newMap();
 	final File									buildDir;
 	final Maven									maven		= new Maven(Processor.getExecutor());
-	private boolean								postpone;
+	private boolean								offline		= true;
+	Settings									settings	= new Settings();
 
 	/**
 	 * This static method finds the workspace and creates a project (or returns
@@ -82,7 +85,9 @@ public class Workspace extends Processor {
 
 	public Workspace(File dir) throws Exception {
 		dir = dir.getAbsoluteFile();
-		dir.mkdirs();
+		if (!dir.exists() && !dir.mkdirs()) {
+			throw new IOException("Could not create directory " + dir);
+		}
 		assert dir.isDirectory();
 
 		File buildDir = new File(dir, BNDDIR).getAbsoluteFile();
@@ -98,7 +103,6 @@ public class Workspace extends Processor {
 		setProperties(buildFile, dir);
 		propertiesChanged();
 
-		cachedRepo = new CachedFileRepo();
 	}
 
 	public Project getProject(String bsn) throws Exception {
@@ -125,6 +129,7 @@ public class Workspace extends Processor {
 		return models.values();
 	}
 
+	@Override
 	public boolean refresh() {
 		if (super.refresh()) {
 			for (Project project : getCurrentProjects()) {
@@ -135,16 +140,20 @@ public class Workspace extends Processor {
 		return false;
 	}
 
-	@Override public void propertiesChanged() {
+	@Override
+	public void propertiesChanged() {
 		super.propertiesChanged();
 		File extDir = new File(this.buildDir, "ext");
 		File[] extensions = extDir.listFiles();
 		if (extensions != null) {
 			for (File extension : extensions) {
-				if (extension.getName().endsWith(".bnd")) {
+				String extensionName = extension.getName();
+				if (extensionName.endsWith(".bnd")) {
+					extensionName = extensionName.substring(0, extensionName.length() - ".bnd".length());
 					try {
-						doIncludeFile(extension, false, getProperties());
-					} catch (Exception e) {
+						doIncludeFile(extension, false, getProperties(), "ext." + extensionName);
+					}
+					catch (Exception e) {
 						error("PropertiesChanged: " + e.getMessage());
 					}
 				}
@@ -152,7 +161,8 @@ public class Workspace extends Processor {
 		}
 	}
 
-	public String _workspace(String args[]) {
+	public String _workspace(@SuppressWarnings("unused")
+	String args[]) {
 		return getBase().getAbsolutePath();
 	}
 
@@ -164,7 +174,7 @@ public class Workspace extends Processor {
 		commands.remove(menu);
 	}
 
-	public void fillActions(Map<String, Action> all) {
+	public void fillActions(Map<String,Action> all) {
 		all.putAll(commands);
 	}
 
@@ -187,8 +197,10 @@ public class Workspace extends Processor {
 		List<BndListener> listeners = getPlugins(BndListener.class);
 		for (BndListener l : listeners)
 			try {
+				offline = false;
 				l.changed(f);
-			} catch (Exception e) {
+			}
+			catch (Exception e) {
 				e.printStackTrace();
 			}
 	}
@@ -201,42 +213,46 @@ public class Workspace extends Processor {
 					l.begin();
 				else
 					l.end();
-			} catch (Exception e) {
+			}
+			catch (Exception e) {
 				// who cares?
 			}
 	}
 
-	
 	/**
-	 * Signal a BndListener plugin.
-	 * We ran an infinite bug loop :-( 
+	 * Signal a BndListener plugin. We ran an infinite bug loop :-(
 	 */
-	final ThreadLocal<Reporter> signalBusy = new ThreadLocal<Reporter>();
+	final ThreadLocal<Reporter>	signalBusy	= new ThreadLocal<Reporter>();
+
 	public void signal(Reporter reporter) {
-		if ( signalBusy.get() != null)
+		if (signalBusy.get() != null)
 			return;
-		
+
 		signalBusy.set(reporter);
 		try {
 			List<BndListener> listeners = getPlugins(BndListener.class);
 			for (BndListener l : listeners)
 				try {
 					l.signal(this);
-				} catch (Exception e) {
+				}
+				catch (Exception e) {
 					// who cares?
 				}
-		} catch (Exception e) {
+		}
+		catch (Exception e) {
 			// Ignore
-		} finally {
+		}
+		finally {
 			signalBusy.set(null);
 		}
 	}
 
-	@Override public void signal() {
+	@Override
+	public void signal() {
 		signal(this);
 	}
 
-	private void copy(InputStream in, OutputStream out) throws Exception {
+	void copy(InputStream in, OutputStream out) throws Exception {
 		byte data[] = new byte[10000];
 		int size = in.read(data);
 		while (size > 0) {
@@ -253,26 +269,35 @@ public class Workspace extends Processor {
 			super("cache", getFile(buildDir, CACHEDIR), false);
 		}
 
-		protected void init() throws Exception {
+		@Override
+		public String toString() {
+			return "bnd-cache";
+		}
+
+		@Override
+		protected boolean init() throws Exception {
 			if (lock.tryLock(50, TimeUnit.SECONDS) == false)
-				throw new TimeLimitExceededException(
-						"Cached File Repo is locked and can't acquire it");
+				throw new TimeLimitExceededException("Cached File Repo is locked and can't acquire it");
 			try {
-				if (!inited) {
+				if (super.init()) {
 					inited = true;
-					root.mkdirs();
+					if (!root.exists() && !root.mkdirs()) {
+						throw new IOException("Could not create cache directory " + root);
+					}
 					if (!root.isDirectory())
-						throw new IllegalArgumentException("Cannot create cache dir " + root);
+						throw new IllegalArgumentException("Cache directory " + root + " not a directory");
 
 					InputStream in = getClass().getResourceAsStream(EMBEDDED_REPO);
 					if (in != null)
 						unzip(in, root);
 					else {
-						System.out.println("!!!! Couldn't find embedded-repo.jar in bundle ");
 						error("Couldn't find embedded-repo.jar in bundle ");
 					}
-				}
-			} finally {
+					return true;
+				} else
+					return false;
+			}
+			finally {
 				lock.unlock();
 			}
 		}
@@ -284,20 +309,24 @@ public class Workspace extends Processor {
 				while (jentry != null) {
 					if (!jentry.isDirectory()) {
 						File dest = Processor.getFile(dir, jentry.getName());
-						if (!dest.isFile() || dest.lastModified() < jentry.getTime()
-								|| jentry.getTime() == 0) {
-							dest.getParentFile().mkdirs();
+						if (!dest.isFile() || dest.lastModified() < jentry.getTime() || jentry.getTime() == 0) {
+							File dp = dest.getParentFile();
+							if (!dp.exists() && !dp.mkdirs()) {
+								throw new IOException("Could not create directory " + dp);
+							}
 							FileOutputStream out = new FileOutputStream(dest);
 							try {
 								copy(jin, out);
-							} finally {
+							}
+							finally {
 								out.close();
 							}
 						}
 					}
 					jentry = jin.getNextJarEntry();
 				}
-			} finally {
+			}
+			finally {
 				in.close();
 			}
 		}
@@ -307,6 +336,32 @@ public class Workspace extends Processor {
 		return getPlugins(RepositoryPlugin.class);
 	}
 
+	public Collection<Project> getBuildOrder() throws Exception {
+		List<Project> result = new ArrayList<Project>();
+		for (Project project : getAllProjects()) {
+			Collection<Project> dependsOn = project.getDependson();
+			getBuildOrder(dependsOn, result);
+			if (!result.contains(project)) {
+				result.add(project);
+			}
+		}
+		return result;
+	}
+
+	private void getBuildOrder(Collection<Project> dependsOn, List<Project> result) throws Exception {
+		for (Project project : dependsOn) {
+			Collection<Project> subProjects = project.getDependson();
+			for (Project subProject : subProjects) {
+				if (!result.contains(subProject)) {
+					result.add(subProject);
+				}
+			}
+			if (!result.contains(project)) {
+				result.add(project);
+			}
+		}
+	}
+
 	public static Workspace getWorkspace(String path) throws Exception {
 		File file = IO.getFile(new File(""), path);
 		return getWorkspace(file);
@@ -316,10 +371,53 @@ public class Workspace extends Processor {
 		return maven;
 	}
 
-	@Override protected void setTypeSpecificPlugins(Set<Object> list) {
+	@Override
+	protected void setTypeSpecificPlugins(Set<Object> list) {
 		super.setTypeSpecificPlugins(list);
 		list.add(maven);
-		list.add(cachedRepo);
+		list.add(new CachedFileRepo());
+	}
+
+	/**
+	 * Return if we're in offline mode. Offline mode is defined as an
+	 * environment where nobody tells us the resources are out of date (refresh
+	 * or changed). This is currently defined as having bndlisteners.
+	 * 
+	 * @return
+	 */
+	public boolean isOffline() {
+		return offline;
 	}
 
+	public Workspace setOffline(boolean on) {
+		this.offline = on;
+		return this;
+	}
+
+	/**
+	 * Provide access to the global settings of this machine.
+	 * 
+	 * @throws Exception
+	 * @throws UnknownHostException
+	 */
+
+	public String _global(String[] args) throws Exception {
+		Macro.verifyCommand(args, "${global;<name>[;<default>]}, get a global setting from ~/.bnd/settings.json", null,
+				2, 3);
+
+		String key = args[1];
+		if (key.equals("key.public"))
+			return Hex.toHexString(settings.getPublicKey());
+		if (key.equals("key.private"))
+			return Hex.toHexString(settings.getPrivateKey());
+
+		String s = settings.get(key);
+		if (s != null)
+			return s;
+
+		if (args.length == 3)
+			return args[2];
+		
+		return null;
+	}
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/WorkspaceRepository.java b/biz.aQute.bndlib/src/aQute/bnd/build/WorkspaceRepository.java
new file mode 100644
index 0000000..a5e2467
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/WorkspaceRepository.java
@@ -0,0 +1,191 @@
+package aQute.bnd.build;
+
+import java.io.*;
+import java.util.*;
+import java.util.regex.*;
+
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.*;
+import aQute.bnd.version.*;
+import aQute.lib.collections.*;
+import aQute.libg.glob.*;
+
+public class WorkspaceRepository implements RepositoryPlugin, Actionable {
+	private final Workspace	workspace;
+
+	public WorkspaceRepository(Workspace workspace) {
+		this.workspace = workspace;
+	}
+
+	private File[] get(String bsn, String range) throws Exception {
+		Collection<Project> projects = workspace.getAllProjects();
+		SortedMap<Version,File> foundVersion = new TreeMap<Version,File>();
+		for (Project project : projects) {
+			for (Builder builder : project.getSubBuilders()) {	
+				if (!bsn.equals(builder.getBsn())) {
+					continue;
+				}
+				Version version = new Version(builder.getVersion());
+				boolean exact = range.matches("[0-9]+\\.[0-9]+\\.[0-9]+\\..*");
+				if ("latest".equals(range) || matchVersion(range, version, exact)) {
+					File file = project.getOutputFile(bsn);
+					if (!file.exists()) {
+						Jar jar = builder.build();
+						if (jar == null) {
+							project.getInfo(builder);
+							continue;
+						}
+						file = project.saveBuild(jar);
+						jar.close();
+					}
+					foundVersion.put(version, file);
+				}
+			}
+		}
+
+		File[] result = new File[foundVersion.size()];
+		result = foundVersion.values().toArray(result);
+		if (!"latest".equals(range)) {
+			return result;
+		}
+		if (result.length > 0) {
+			return new File[] {
+				result[0]
+			};
+		}
+		return new File[0];
+	}
+
+	private File get(String bsn, String range, Strategy strategy, Map<String,String> properties) throws Exception {
+		File[] files = get(bsn, range);
+
+		if (files.length == 0) {
+			return null;
+		}
+
+		if (strategy == Strategy.EXACT) {
+			return files[0];
+		} else if (strategy == Strategy.HIGHEST) {
+			return files[files.length - 1];
+		} else if (strategy == Strategy.LOWEST) {
+			return files[0];
+		}
+
+		return null;
+	}
+
+	private boolean matchVersion(String range, Version version, boolean exact) {
+		if (range == null || range.trim().length() == 0)
+			return true;
+		VersionRange vr = new VersionRange(range);
+
+		boolean result;
+		if (exact) {
+			if (vr.isRange())
+				result = false;
+			else
+				result = vr.getHigh().equals(version);
+		} else {
+			result = vr.includes(version);
+		}
+		return result;
+	}
+
+	public boolean canWrite() {
+		return false;
+	}
+
+	public PutResult put(InputStream stream, PutOptions options) throws Exception {
+		throw new UnsupportedOperationException("Read only repository");
+	}
+
+	public List<String> list(String pattern) throws Exception {
+		List<String> names = new ArrayList<String>();
+		Collection<Project> projects = workspace.getAllProjects();
+		for (Project project : projects) {
+			for (Builder builder : project.getSubBuilders()) {	
+				String bsn = builder.getBsn();
+				if (pattern != null) {
+					Glob glob = new Glob(pattern);
+					Matcher matcher = glob.matcher(bsn);
+					if (matcher.matches()) {
+						if (!names.contains(bsn)) {
+							names.add(bsn);
+						}
+					}
+				} else {
+					if (!names.contains(bsn)) {
+						names.add(bsn);
+					}
+				}
+			}
+		}
+
+		return names;
+	}
+
+	public SortedSet<Version> versions(String bsn) throws Exception {
+		List<Version> versions = new ArrayList<Version>();
+		Collection<Project> projects = workspace.getAllProjects();
+		for (Project project : projects) {
+			for (Builder builder : project.getSubBuilders()) {
+				if (bsn.equals(builder.getBsn())) {
+					String v  = builder.getVersion();
+					if (v == null)
+						v = "0";
+					else {
+						v = Analyzer.cleanupVersion(v);
+						if (!Verifier.isVersion(v))
+							continue; // skip
+					}
+					
+					versions.add(new Version(v));
+				}
+			}
+		}
+		if ( versions.isEmpty())
+			return SortedList.empty();
+		
+		return new SortedList<Version>(versions);
+	}
+
+	public String getName() {
+		return "Workspace " + workspace.getBase().getName();
+	}
+
+	public String getLocation() {
+		return workspace.getBase().getAbsolutePath();
+	}
+
+	public File get(String bsn, Version version, Map<String,String> properties, DownloadListener ... listeners) throws Exception {
+		File file = get(bsn, version.toString(), Strategy.EXACT, properties);
+		if ( file == null)
+			return null;
+		for (DownloadListener l : listeners) {
+			try {
+				l.success(file);
+			}
+			catch (Exception e) {
+				workspace.exception(e, "Workspace repo listener callback for %s" ,file);
+			}
+		}
+		return file;
+	}
+
+	
+	public Map<String,Runnable> actions(Object... target) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public String tooltip(Object... target) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public String title(Object... target) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/BndEditModel.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/BndEditModel.java
new file mode 100644
index 0000000..ab357fc
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/BndEditModel.java
@@ -0,0 +1,828 @@
+package aQute.bnd.build.model;
+
+import java.beans.*;
+import java.io.*;
+import java.util.*;
+import java.util.Map.Entry;
+
+import org.osgi.resource.*;
+
+import aQute.bnd.build.*;
+import aQute.bnd.build.model.clauses.*;
+import aQute.bnd.build.model.conversions.*;
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.properties.*;
+import aQute.bnd.version.*;
+import aQute.libg.tuple.*;
+
+/**
+ * A model for a Bnd file. In the first iteration, use a simple Properties
+ * object; this will need to be enhanced to additionally record formatting, e.g.
+ * line breaks and empty lines, and comments.
+ * 
+ * @author Neil Bartlett
+ */
+public class BndEditModel {
+
+	public static final String										NEWLINE_LINE_SEPARATOR		= "\\n\\\n\t";
+	public static final String										LIST_SEPARATOR				= ",\\\n\t";
+
+	private static final String									ISO_8859_1					= "ISO-8859-1";												//$NON-NLS-1$
+
+	private static String[]										KNOWN_PROPERTIES			= new String[] {
+			Constants.BUNDLE_LICENSE, Constants.BUNDLE_CATEGORY,
+			Constants.BUNDLE_NAME, Constants.BUNDLE_DESCRIPTION, Constants.BUNDLE_COPYRIGHT, Constants.BUNDLE_UPDATELOCATION,
+			Constants.BUNDLE_VENDOR, Constants.BUNDLE_CONTACTADDRESS, Constants.BUNDLE_DOCURL,
+			Constants.BUNDLE_SYMBOLICNAME, Constants.BUNDLE_VERSION, Constants.BUNDLE_ACTIVATOR,
+			Constants.EXPORT_PACKAGE, Constants.IMPORT_PACKAGE, aQute.bnd.osgi.Constants.PRIVATE_PACKAGE,
+			aQute.bnd.osgi.Constants.SOURCES,
+			aQute.bnd.osgi.Constants.SERVICE_COMPONENT, aQute.bnd.osgi.Constants.CLASSPATH,
+			aQute.bnd.osgi.Constants.BUILDPATH, aQute.bnd.osgi.Constants.BUILDPACKAGES,
+			aQute.bnd.osgi.Constants.RUNBUNDLES, aQute.bnd.osgi.Constants.RUNPROPERTIES, aQute.bnd.osgi.Constants.SUB,
+			aQute.bnd.osgi.Constants.RUNFRAMEWORK, aQute.bnd.osgi.Constants.RUNFW,
+			aQute.bnd.osgi.Constants.RUNVM, aQute.bnd.osgi.Constants.RUNPROGRAMARGS,
+			// BndConstants.RUNVMARGS,
+			// BndConstants.TESTSUITES,
+			aQute.bnd.osgi.Constants.TESTCASES, aQute.bnd.osgi.Constants.PLUGIN, aQute.bnd.osgi.Constants.PLUGINPATH,
+			aQute.bnd.osgi.Constants.RUNREPOS, aQute.bnd.osgi.Constants.RUNREQUIRES, aQute.bnd.osgi.Constants.RUNEE};
+
+	public static final String										BUNDLE_VERSION_MACRO		= "${"
+																										+ Constants.BUNDLE_VERSION
+																										+ "}";
+
+	private final Map<String,Converter< ? extends Object,String>>	converters					= new HashMap<String,Converter< ? extends Object,String>>();
+	private final Map<String,Converter<String, ? extends Object>>	formatters					= new HashMap<String,Converter<String, ? extends Object>>();
+	// private final DataModelHelper obrModelHelper = new DataModelHelperImpl();
+
+	private final PropertyChangeSupport								propChangeSupport			= new PropertyChangeSupport(
+																										this);
+	private final Properties										properties					= new Properties();
+
+	private File													bndResource;
+	private String													bndResourceName;
+	private final Map<String,Object>								objectProperties			= new HashMap<String,Object>();
+	private final Map<String,String>								changesToSave				= new HashMap<String,String>();
+
+	// CONVERTERS
+	private Converter<List<VersionedClause>,String>				buildPathConverter			= new ClauseListConverter<VersionedClause>(
+																										new Converter<VersionedClause,Pair<String,Attrs>>() {
+																											public VersionedClause convert(
+																													Pair<String,Attrs> input)
+																													throws IllegalArgumentException {
+																												return new VersionedClause(
+																														input.getFirst(),
+																														input.getSecond());
+																											}
+																										});
+	private Converter<List<VersionedClause>,String>				buildPackagesConverter		= new ClauseListConverter<VersionedClause>(
+																										new Converter<VersionedClause,Pair<String,Attrs>>() {
+																											public VersionedClause convert(
+																													Pair<String,Attrs> input)
+																													throws IllegalArgumentException {
+																												return new VersionedClause(
+																														input.getFirst(),
+																														input.getSecond());
+																											}
+																										});
+	private Converter<List<VersionedClause>,String>				clauseListConverter			= new ClauseListConverter<VersionedClause>(
+																										new VersionedClauseConverter());
+	private Converter<String,String>								stringConverter				= new NoopConverter<String>();
+	private Converter<Boolean,String>								includedSourcesConverter	= new Converter<Boolean,String>() {
+																									public Boolean convert(
+																											String string)
+																											throws IllegalArgumentException {
+																										return Boolean
+																												.valueOf(string);
+																									}
+																								};
+	private Converter<List<String>,String>						listConverter				= SimpleListConverter
+																										.create();
+	private Converter<List<HeaderClause>,String>					headerClauseListConverter	= new HeaderClauseListConverter();
+	private ClauseListConverter<ExportedPackage>					exportPackageConverter		= new ClauseListConverter<ExportedPackage>(
+																										new Converter<ExportedPackage,Pair<String,Attrs>>() {
+																											public ExportedPackage convert(
+																													Pair<String,Attrs> input) {
+																												return new ExportedPackage(
+																														input.getFirst(),
+																														input.getSecond());
+																											}
+																										});
+	private Converter<List<ServiceComponent>,String>				serviceComponentConverter	= new ClauseListConverter<ServiceComponent>(
+																										new Converter<ServiceComponent,Pair<String,Attrs>>() {
+																											public ServiceComponent convert(
+																													Pair<String,Attrs> input)
+																													throws IllegalArgumentException {
+																												return new ServiceComponent(
+																														input.getFirst(),
+																														input.getSecond());
+																											}
+																										});
+	private Converter<List<ImportPattern>,String>					importPatternConverter		= new ClauseListConverter<ImportPattern>(
+																										new Converter<ImportPattern,Pair<String,Attrs>>() {
+																											public ImportPattern convert(
+																													Pair<String,Attrs> input)
+																													throws IllegalArgumentException {
+																												return new ImportPattern(
+																														input.getFirst(),
+																														input.getSecond());
+																											}
+																										});
+
+	private Converter<Map<String,String>,String>					propertiesConverter			= new PropertiesConverter();
+	
+	private Converter<List<Requirement>,String>					requirementListConverter	= new RequirementListConverter();
+	private Converter<EE,String>									eeConverter					= new EEConverter();
+
+	// Converter<ResolveMode, String> resolveModeConverter =
+	// EnumConverter.create(ResolveMode.class, ResolveMode.manual);
+
+	// FORMATTERS
+	private Converter<String,String>								newlineEscapeFormatter		= new NewlineEscapedStringFormatter();
+	private Converter<String,Boolean>								defaultFalseBoolFormatter	= new DefaultBooleanFormatter(
+																										false);
+	private Converter<String,Collection< ? >>						stringListFormatter			= new CollectionFormatter<Object>(
+																										LIST_SEPARATOR,
+																										(String) null);
+	private Converter<String,Collection< ? extends HeaderClause>>	headerClauseListFormatter	= new CollectionFormatter<HeaderClause>(
+																										LIST_SEPARATOR,
+																										new HeaderClauseFormatter(),
+																										null);
+	private Converter<String,Map<String,String>>					propertiesFormatter			= new MapFormatter(
+																										LIST_SEPARATOR,
+																										new PropertiesEntryFormatter(),
+																										null);
+	
+	private Converter<String,Collection< ? extends Requirement>>	requirementListFormatter	= new CollectionFormatter<Requirement>(
+																										LIST_SEPARATOR,
+																										new RequirementFormatter(),
+																										null);
+
+	private Converter<String,EE>									eeFormatter					= new EEFormatter();
+	private Converter<String,Collection< ? extends String>>			runReposFormatter			= new CollectionFormatter<String>(
+																										LIST_SEPARATOR,
+																										aQute.bnd.osgi.Constants.EMPTY_HEADER);
+
+	// Converter<String, ResolveMode> resolveModeFormatter =
+	// EnumFormatter.create(ResolveMode.class, ResolveMode.manual);
+
+	@SuppressWarnings("deprecation")
+	public BndEditModel() {
+		// register converters
+		converters.put(aQute.bnd.osgi.Constants.BUNDLE_LICENSE, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.BUNDLE_CATEGORY, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.BUNDLE_NAME, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.BUNDLE_DESCRIPTION, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.BUNDLE_COPYRIGHT, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.BUNDLE_UPDATELOCATION, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.BUNDLE_VENDOR, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.BUNDLE_CONTACTADDRESS, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.BUNDLE_DOCURL, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.BUILDPATH, buildPathConverter);
+		converters.put(aQute.bnd.osgi.Constants.BUILDPACKAGES, buildPackagesConverter);
+		converters.put(aQute.bnd.osgi.Constants.RUNBUNDLES, clauseListConverter);
+		converters.put(Constants.BUNDLE_SYMBOLICNAME, stringConverter);
+		converters.put(Constants.BUNDLE_VERSION, stringConverter);
+		converters.put(Constants.BUNDLE_ACTIVATOR, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.OUTPUT, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.SOURCES, includedSourcesConverter);
+		converters.put(aQute.bnd.osgi.Constants.PRIVATE_PACKAGE, listConverter);
+		converters.put(aQute.bnd.osgi.Constants.CLASSPATH, listConverter);
+		converters.put(Constants.EXPORT_PACKAGE, exportPackageConverter);
+		converters.put(aQute.bnd.osgi.Constants.SERVICE_COMPONENT, serviceComponentConverter);
+		converters.put(Constants.IMPORT_PACKAGE, importPatternConverter);
+		converters.put(aQute.bnd.osgi.Constants.RUNFRAMEWORK, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.RUNFW, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.SUB, listConverter);
+		converters.put(aQute.bnd.osgi.Constants.RUNPROPERTIES, propertiesConverter);
+		converters.put(aQute.bnd.osgi.Constants.RUNVM, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.RUNPROGRAMARGS, stringConverter);
+		// converters.put(BndConstants.RUNVMARGS, stringConverter);
+		converters.put(aQute.bnd.osgi.Constants.TESTSUITES, listConverter);
+		converters.put(aQute.bnd.osgi.Constants.TESTCASES, listConverter);
+		converters.put(aQute.bnd.osgi.Constants.PLUGIN, headerClauseListConverter);
+		converters.put(aQute.bnd.osgi.Constants.RUNREQUIRES, requirementListConverter);
+		converters.put(aQute.bnd.osgi.Constants.RUNEE, eeConverter);
+		converters.put(aQute.bnd.osgi.Constants.RUNREPOS, listConverter);
+		// converters.put(BndConstants.RESOLVE_MODE, resolveModeConverter);
+
+		formatters.put(aQute.bnd.osgi.Constants.BUNDLE_LICENSE, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.BUNDLE_CATEGORY, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.BUNDLE_NAME, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.BUNDLE_DESCRIPTION, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.BUNDLE_COPYRIGHT, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.BUNDLE_UPDATELOCATION, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.BUNDLE_VENDOR, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.BUNDLE_CONTACTADDRESS, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.BUNDLE_DOCURL, newlineEscapeFormatter);
+
+		formatters.put(aQute.bnd.osgi.Constants.BUILDPATH, headerClauseListFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.BUILDPACKAGES, headerClauseListFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.RUNBUNDLES, headerClauseListFormatter);
+		formatters.put(Constants.BUNDLE_SYMBOLICNAME, newlineEscapeFormatter);
+		formatters.put(Constants.BUNDLE_VERSION, newlineEscapeFormatter);
+		formatters.put(Constants.BUNDLE_ACTIVATOR, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.OUTPUT, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.SOURCES, defaultFalseBoolFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.PRIVATE_PACKAGE, stringListFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.CLASSPATH, stringListFormatter);
+		formatters.put(Constants.EXPORT_PACKAGE, headerClauseListFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.SERVICE_COMPONENT, headerClauseListFormatter);
+		formatters.put(Constants.IMPORT_PACKAGE, headerClauseListFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.RUNFRAMEWORK, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.RUNFW, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.SUB, stringListFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.RUNPROPERTIES, propertiesFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.RUNVM, newlineEscapeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.RUNPROGRAMARGS, newlineEscapeFormatter);
+		// formatters.put(BndConstants.RUNVMARGS, newlineEscapeFormatter);
+		// formatters.put(BndConstants.TESTSUITES, stringListFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.TESTCASES, stringListFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.PLUGIN, headerClauseListFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.RUNREQUIRES, requirementListFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.RUNEE, eeFormatter);
+		formatters.put(aQute.bnd.osgi.Constants.RUNREPOS, runReposFormatter);
+		// formatters.put(BndConstants.RESOLVE_MODE, resolveModeFormatter);
+	}
+
+	public void loadFrom(IDocument document) throws IOException {
+		InputStream inputStream = new ByteArrayInputStream(document.get().getBytes(ISO_8859_1));
+		loadFrom(inputStream);
+	}
+
+	public void loadFrom(File file) throws IOException {
+		loadFrom(new BufferedInputStream(new FileInputStream(file)));
+	}
+
+	public void loadFrom(InputStream inputStream) throws IOException {
+		try {
+			// Clear and load
+			properties.clear();
+			properties.load(inputStream);
+			objectProperties.clear();
+			changesToSave.clear();
+
+			// Fire property changes on all known property names
+			for (String prop : KNOWN_PROPERTIES) {
+				// null values for old and new forced the change to be fired
+				propChangeSupport.firePropertyChange(prop, null, null);
+			}
+		}
+		finally {
+			inputStream.close();
+		}
+
+	}
+
+	public void saveChangesTo(IDocument document) {
+		for (Iterator<Entry<String,String>> iter = changesToSave.entrySet().iterator(); iter.hasNext();) {
+			Entry<String,String> entry = iter.next();
+			iter.remove();
+
+			String propertyName = entry.getKey();
+			String stringValue = entry.getValue();
+
+			updateDocument(document, propertyName, stringValue);
+		}
+	}
+
+	private static IRegion findEntry(IDocument document, String name) throws Exception {
+		PropertiesLineReader reader = new PropertiesLineReader(document);
+		LineType type = reader.next();
+		while (type != LineType.eof) {
+			if (type == LineType.entry) {
+				String key = reader.key();
+				if (name.equals(key))
+					return reader.region();
+			}
+			type = reader.next();
+		}
+		return null;
+	}
+
+	private static void updateDocument(IDocument document, String name, String value) {
+		String newEntry;
+		if (value != null) {
+			StringBuilder buffer = new StringBuilder();
+			buffer.append(name).append(": ").append(value);
+			newEntry = buffer.toString();
+		} else {
+			newEntry = "";
+		}
+
+		try {
+			IRegion region = findEntry(document, name);
+			if (region != null) {
+				// Replace an existing entry
+				int offset = region.getOffset();
+				int length = region.getLength();
+
+				// If the replacement is empty, remove one extra character to
+				// the right, i.e. the following newline,
+				// unless this would take us past the end of the document
+				if (newEntry.length() == 0 && offset + length + 1 < document.getLength()) {
+					length++;
+				}
+				document.replace(offset, length, newEntry);
+			} else if (newEntry.length() > 0) {
+				// This is a new entry, put it at the end of the file
+
+				// Does the last line of the document have a newline? If not,
+				// we need to add one.
+				if (document.getLength() > 0 && document.getChar(document.getLength() - 1) != '\n')
+					newEntry = "\n" + newEntry;
+				document.replace(document.getLength(), 0, newEntry);
+			}
+		}
+		catch (Exception e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+	}
+
+	public List<String> getAllPropertyNames() {
+		List<String> result = new ArrayList<String>(properties.size());
+
+		Enumeration<String> names = (Enumeration<String>) properties.propertyNames();
+
+		while (names.hasMoreElements()) {
+			result.add(names.nextElement());
+		}
+		return result;
+	}
+
+	public Object genericGet(String propertyName) {
+		Converter< ? extends Object,String> converter = converters.get(propertyName);
+		if (converter == null)
+			converter = new NoopConverter<String>();
+		return doGetObject(propertyName, converter);
+	}
+
+	public void genericSet(String propertyName, Object value) {
+		Object oldValue = genericGet(propertyName);
+		Converter<String,Object> formatter = (Converter<String,Object>) formatters.get(propertyName);
+		if (formatter == null)
+			formatter = new DefaultFormatter();
+		doSetObject(propertyName, oldValue, value, formatter);
+	}
+
+	public String getBundleLicense() {
+		return doGetObject(Constants.BUNDLE_LICENSE, stringConverter);
+	}
+
+	public void setBundleLicense(String bundleLicense) {
+		doSetObject(Constants.BUNDLE_LICENSE, getBundleLicense(), bundleLicense, newlineEscapeFormatter);
+	}
+
+	public String getBundleCategory() {
+		return doGetObject(Constants.BUNDLE_CATEGORY, stringConverter);
+	}
+
+	public void setBundleCategory(String bundleCategory) {
+		doSetObject(Constants.BUNDLE_CATEGORY, getBundleCategory(), bundleCategory, newlineEscapeFormatter);
+	}
+
+	public String getBundleName() {
+		return doGetObject(Constants.BUNDLE_NAME, stringConverter);
+	}
+
+	public void setBundleName(String bundleName) {
+		doSetObject(Constants.BUNDLE_NAME, getBundleName(), bundleName, newlineEscapeFormatter);
+	}
+
+	public String getBundleDescription() {
+		return doGetObject(Constants.BUNDLE_DESCRIPTION, stringConverter);
+	}
+
+	public void setBundleDescription(String bundleDescription) {
+		doSetObject(Constants.BUNDLE_DESCRIPTION, getBundleDescription(), bundleDescription, newlineEscapeFormatter);
+	}
+
+	public String getBundleCopyright() {
+		return doGetObject(Constants.BUNDLE_COPYRIGHT, stringConverter);
+	}
+
+	public void setBundleCopyright(String bundleCopyright) {
+		doSetObject(Constants.BUNDLE_COPYRIGHT, getBundleCopyright(), bundleCopyright, newlineEscapeFormatter);
+	}
+
+	public String getBundleUpdateLocation() {
+		return doGetObject(Constants.BUNDLE_UPDATELOCATION, stringConverter);
+	}
+
+	public void setBundleUpdateLocation(String bundleUpdateLocation) {
+		doSetObject(Constants.BUNDLE_UPDATELOCATION, getBundleUpdateLocation(), bundleUpdateLocation, newlineEscapeFormatter);
+	}
+
+	public String getBundleVendor() {
+		return doGetObject(Constants.BUNDLE_VENDOR, stringConverter);
+	}
+
+	public void setBundleVendor(String bundleVendor) {
+		doSetObject(Constants.BUNDLE_VENDOR, getBundleVendor(), bundleVendor, newlineEscapeFormatter);
+	}
+
+	public String getBundleContactAddress() {
+		return doGetObject(Constants.BUNDLE_CONTACTADDRESS, stringConverter);
+	}
+
+	public void setBundleContactAddress(String bundleContactAddress) {
+		doSetObject(Constants.BUNDLE_CONTACTADDRESS, getBundleContactAddress(), bundleContactAddress, newlineEscapeFormatter);
+	}
+
+	public String getBundleDocUrl() {
+		return doGetObject(Constants.BUNDLE_DOCURL, stringConverter);
+	}
+
+	public void setBundleDocUrl(String bundleDocUrl) {
+		doSetObject(Constants.BUNDLE_DOCURL, getBundleDocUrl(), bundleDocUrl, newlineEscapeFormatter);
+	}
+
+	public String getBundleSymbolicName() {
+		return doGetObject(Constants.BUNDLE_SYMBOLICNAME, stringConverter);
+	}
+
+	public void setBundleSymbolicName(String bundleSymbolicName) {
+		doSetObject(Constants.BUNDLE_SYMBOLICNAME, getBundleSymbolicName(), bundleSymbolicName, newlineEscapeFormatter);
+	}
+
+	public String getBundleVersionString() {
+		return doGetObject(Constants.BUNDLE_VERSION, stringConverter);
+	}
+
+	public void setBundleVersion(String bundleVersion) {
+		doSetObject(Constants.BUNDLE_VERSION, getBundleVersionString(), bundleVersion, newlineEscapeFormatter);
+	}
+
+	public String getBundleActivator() {
+		return doGetObject(Constants.BUNDLE_ACTIVATOR, stringConverter);
+	}
+
+	public void setBundleActivator(String bundleActivator) {
+		doSetObject(Constants.BUNDLE_ACTIVATOR, getBundleActivator(), bundleActivator, newlineEscapeFormatter);
+	}
+
+	public String getOutputFile() {
+		return doGetObject(aQute.bnd.osgi.Constants.OUTPUT, stringConverter);
+	}
+
+	public void setOutputFile(String name) {
+		doSetObject(aQute.bnd.osgi.Constants.OUTPUT, getOutputFile(), name, newlineEscapeFormatter);
+	}
+
+	public boolean isIncludeSources() {
+		return doGetObject(aQute.bnd.osgi.Constants.SOURCES, includedSourcesConverter);
+	}
+
+	public void setIncludeSources(boolean includeSources) {
+		boolean oldValue = isIncludeSources();
+		doSetObject(aQute.bnd.osgi.Constants.SOURCES, oldValue, includeSources, defaultFalseBoolFormatter);
+	}
+
+	public List<String> getPrivatePackages() {
+		return doGetObject(aQute.bnd.osgi.Constants.PRIVATE_PACKAGE, listConverter);
+	}
+
+	public void setPrivatePackages(List< ? extends String> packages) {
+		List<String> oldPackages = getPrivatePackages();
+		doSetObject(aQute.bnd.osgi.Constants.PRIVATE_PACKAGE, oldPackages, packages, stringListFormatter);
+	}
+
+	public List<ExportedPackage> getSystemPackages() {
+		return doGetObject(aQute.bnd.osgi.Constants.RUNSYSTEMPACKAGES, exportPackageConverter);
+	}
+
+	public void setSystemPackages(List< ? extends ExportedPackage> packages) {
+		List<ExportedPackage> oldPackages = getSystemPackages();
+		doSetObject(aQute.bnd.osgi.Constants.RUNSYSTEMPACKAGES, oldPackages, packages, headerClauseListFormatter);
+	}
+
+	public List<String> getClassPath() {
+		return doGetObject(aQute.bnd.osgi.Constants.CLASSPATH, listConverter);
+	}
+
+	public void addPrivatePackage(String packageName) {
+		List<String> packages = getPrivatePackages();
+		if (packages == null)
+			packages = new ArrayList<String>();
+		else
+			packages = new ArrayList<String>(packages);
+		packages.add(packageName);
+		setPrivatePackages(packages);
+	}
+
+	public void setClassPath(List< ? extends String> classPath) {
+		List<String> oldClassPath = getClassPath();
+		doSetObject(aQute.bnd.osgi.Constants.CLASSPATH, oldClassPath, classPath, stringListFormatter);
+	}
+
+	public List<ExportedPackage> getExportedPackages() {
+		return doGetObject(Constants.EXPORT_PACKAGE, exportPackageConverter);
+	}
+
+	public void setExportedPackages(List< ? extends ExportedPackage> exports) {
+		boolean referencesBundleVersion = false;
+
+		if (exports != null) {
+			for (ExportedPackage pkg : exports) {
+				String versionString = pkg.getVersionString();
+				if (versionString != null && versionString.indexOf(BUNDLE_VERSION_MACRO) > -1) {
+					referencesBundleVersion = true;
+				}
+			}
+		}
+		List<ExportedPackage> oldValue = getExportedPackages();
+		doSetObject(Constants.EXPORT_PACKAGE, oldValue, exports, headerClauseListFormatter);
+
+		if (referencesBundleVersion && getBundleVersionString() == null) {
+			setBundleVersion(Version.emptyVersion.toString());
+		}
+	}
+
+	public void addExportedPackage(ExportedPackage export) {
+		List<ExportedPackage> exports = getExportedPackages();
+		exports = (exports == null) ? new ArrayList<ExportedPackage>() : new ArrayList<ExportedPackage>(exports);
+		exports.add(export);
+		setExportedPackages(exports);
+	}
+
+	public List<String> getDSAnnotationPatterns() {
+		return doGetObject(aQute.bnd.osgi.Constants.DSANNOTATIONS, listConverter);
+	}
+
+	public void setDSAnnotationPatterns(List< ? extends String> patterns) {
+		List<String> oldValue = getDSAnnotationPatterns();
+		doSetObject(aQute.bnd.osgi.Constants.DSANNOTATIONS, oldValue, patterns, stringListFormatter);
+	}
+
+	public List<ServiceComponent> getServiceComponents() {
+		return doGetObject(aQute.bnd.osgi.Constants.SERVICE_COMPONENT, serviceComponentConverter);
+	}
+
+	public void setServiceComponents(List< ? extends ServiceComponent> components) {
+		List<ServiceComponent> oldValue = getServiceComponents();
+		doSetObject(aQute.bnd.osgi.Constants.SERVICE_COMPONENT, oldValue, components, headerClauseListFormatter);
+	}
+
+	public List<ImportPattern> getImportPatterns() {
+		return doGetObject(Constants.IMPORT_PACKAGE, importPatternConverter);
+	}
+
+	public void setImportPatterns(List< ? extends ImportPattern> patterns) {
+		List<ImportPattern> oldValue = getImportPatterns();
+		doSetObject(Constants.IMPORT_PACKAGE, oldValue, patterns, headerClauseListFormatter);
+	}
+
+	public List<VersionedClause> getBuildPath() {
+		return doGetObject(aQute.bnd.osgi.Constants.BUILDPATH, buildPathConverter);
+	}
+
+	public void setBuildPath(List< ? extends VersionedClause> paths) {
+		List<VersionedClause> oldValue = getBuildPath();
+		doSetObject(aQute.bnd.osgi.Constants.BUILDPATH, oldValue, paths, headerClauseListFormatter);
+	}
+
+	public List<VersionedClause> getBuildPackages() {
+		return doGetObject(aQute.bnd.osgi.Constants.BUILDPACKAGES, buildPackagesConverter);
+	}
+
+	public void setBuildPackages(List< ? extends VersionedClause> paths) {
+		List<VersionedClause> oldValue = getBuildPackages();
+		doSetObject(aQute.bnd.osgi.Constants.BUILDPACKAGES, oldValue, paths, headerClauseListFormatter);
+	}
+
+	public List<VersionedClause> getRunBundles() {
+		return doGetObject(aQute.bnd.osgi.Constants.RUNBUNDLES, clauseListConverter);
+	}
+
+	public void setRunBundles(List< ? extends VersionedClause> paths) {
+		List<VersionedClause> oldValue = getRunBundles();
+		doSetObject(aQute.bnd.osgi.Constants.RUNBUNDLES, oldValue, paths, headerClauseListFormatter);
+	}
+
+	public boolean isIncludedPackage(String packageName) {
+		final Collection<String> privatePackages = getPrivatePackages();
+		if (privatePackages != null) {
+			if (privatePackages.contains(packageName))
+				return true;
+		}
+		final Collection<ExportedPackage> exportedPackages = getExportedPackages();
+		if (exportedPackages != null) {
+			for (ExportedPackage pkg : exportedPackages) {
+				if (packageName.equals(pkg.getName())) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	public List<String> getSubBndFiles() {
+		return doGetObject(aQute.bnd.osgi.Constants.SUB, listConverter);
+	}
+
+	public void setSubBndFiles(List<String> subBndFiles) {
+		List<String> oldValue = getSubBndFiles();
+		doSetObject(aQute.bnd.osgi.Constants.SUB, oldValue, subBndFiles, stringListFormatter);
+	}
+
+	public Map<String,String> getRunProperties() {
+		return doGetObject(aQute.bnd.osgi.Constants.RUNPROPERTIES, propertiesConverter);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see bndtools.editor.model.IBndModel#setRunProperties(java.util.Map)
+	 */
+	public void setRunProperties(Map<String,String> props) {
+		Map<String,String> old = getRunProperties();
+		doSetObject(aQute.bnd.osgi.Constants.RUNPROPERTIES, old, props, propertiesFormatter);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see bndtools.editor.model.IBndModel#getRunVMArgs()
+	 */
+	public String getRunVMArgs() {
+		return doGetObject(aQute.bnd.osgi.Constants.RUNVM, stringConverter);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see bndtools.editor.model.IBndModel#setRunVMArgs(java.lang.String)
+	 */
+	public void setRunVMArgs(String args) {
+		String old = getRunVMArgs();
+		doSetObject(aQute.bnd.osgi.Constants.RUNVM, old, args, newlineEscapeFormatter);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see bndtools.editor.model.IBndModel#getRunProgramArgs()
+	 */
+	public String getRunProgramArgs() {
+		return doGetObject(aQute.bnd.osgi.Constants.RUNPROGRAMARGS, stringConverter);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see bndtools.editor.model.IBndModel#setRunProgramArgs(java.lang.String)
+	 */
+	public void setRunProgramArgs(String args) {
+		String old = getRunProgramArgs();
+		doSetObject(aQute.bnd.osgi.Constants.RUNPROGRAMARGS, old, args, newlineEscapeFormatter);
+	}
+
+	@SuppressWarnings("deprecation")
+	public List<String> getTestSuites() {
+		List<String> testCases = doGetObject(aQute.bnd.osgi.Constants.TESTCASES, listConverter);
+		testCases = testCases != null ? testCases : Collections.<String> emptyList();
+
+		List<String> testSuites = doGetObject(aQute.bnd.osgi.Constants.TESTSUITES, listConverter);
+		testSuites = testSuites != null ? testSuites : Collections.<String> emptyList();
+
+		List<String> result = new ArrayList<String>(testCases.size() + testSuites.size());
+		result.addAll(testCases);
+		result.addAll(testSuites);
+		return result;
+	}
+
+	@SuppressWarnings("deprecation")
+	public void setTestSuites(List<String> suites) {
+		List<String> old = getTestSuites();
+		doSetObject(aQute.bnd.osgi.Constants.TESTCASES, old, suites, stringListFormatter);
+		doSetObject(aQute.bnd.osgi.Constants.TESTSUITES, null, null, stringListFormatter);
+	}
+
+	public List<HeaderClause> getPlugins() {
+		return doGetObject(aQute.bnd.osgi.Constants.PLUGIN, headerClauseListConverter);
+	}
+
+	public void setPlugins(List<HeaderClause> plugins) {
+		List<HeaderClause> old = getPlugins();
+		doSetObject(aQute.bnd.osgi.Constants.PLUGIN, old, plugins, headerClauseListFormatter);
+	}
+
+	public List<String> getPluginPath() {
+		return doGetObject(aQute.bnd.osgi.Constants.PLUGINPATH, listConverter);
+	}
+
+	public void setPluginPath(List<String> pluginPath) {
+		List<String> old = getPluginPath();
+		doSetObject(aQute.bnd.osgi.Constants.PLUGINPATH, old, pluginPath, stringListFormatter);
+	}
+	
+    public List<String> getRunRepos() {
+        return doGetObject(aQute.bnd.osgi.Constants.RUNREPOS, listConverter);
+    }
+
+    public void setRunRepos(List<String> repos) {
+        List<String> old = getRunRepos();
+        doSetObject(aQute.bnd.osgi.Constants.RUNREPOS, old, repos, runReposFormatter);
+    }
+    
+    public String getRunFramework() {
+        return doGetObject(aQute.bnd.osgi.Constants.RUNFRAMEWORK, stringConverter);
+    }
+
+    public String getRunFw() {
+        return doGetObject(aQute.bnd.osgi.Constants.RUNFW, stringConverter);
+    }
+
+    public EE getEE() {
+        return doGetObject(aQute.bnd.osgi.Constants.RUNEE, eeConverter);
+    }
+
+    public void setEE(EE ee) {
+        EE old = getEE();
+        doSetObject(aQute.bnd.osgi.Constants.RUNEE, old, ee, eeFormatter);
+    }
+
+    
+    public void setRunFramework(String clause) {
+        assert (Constants.RUNFRAMEWORK_SERVICES.equals(clause.toLowerCase().trim()) ||
+                Constants.RUNFRAMEWORK_NONE.equals(clause.toLowerCase().trim()));
+        String oldValue = getRunFramework();
+        doSetObject(aQute.bnd.osgi.Constants.RUNFRAMEWORK, oldValue, clause, newlineEscapeFormatter);
+    }
+    
+    public void setRunFw(String clause) {
+        String oldValue = getRunFw();
+        doSetObject(aQute.bnd.osgi.Constants.RUNFW, oldValue, clause, newlineEscapeFormatter);
+    }
+
+    public List<Requirement> getRunRequires() {
+    	return doGetObject(aQute.bnd.osgi.Constants.RUNREQUIRES, requirementListConverter);
+    }
+    
+    public void setRunRequires(List<Requirement> requires) {
+    	List<Requirement> oldValue = getRunRequires();
+    	doSetObject(aQute.bnd.osgi.Constants.RUNREQUIRES, oldValue, requires, requirementListFormatter);
+    }
+
+
+	private <R> R doGetObject(String name, Converter< ? extends R, ? super String> converter) {
+		R result;
+		if (objectProperties.containsKey(name)) {
+			R temp = (R) objectProperties.get(name);
+			result = temp;
+		} else if (changesToSave.containsKey(name)) {
+			result = converter.convert(changesToSave.get(name));
+			objectProperties.put(name, result);
+		} else if (properties.containsKey(name)) {
+			result = converter.convert(properties.getProperty(name));
+			objectProperties.put(name, result);
+		} else {
+			result = null;
+		}
+		return result;
+	}
+
+	private <T> void doSetObject(String name, T oldValue, T newValue, Converter<String, ? super T> formatter) {
+		objectProperties.put(name, newValue);
+		changesToSave.put(name, formatter.convert(newValue));
+		propChangeSupport.firePropertyChange(name, oldValue, newValue);
+	}
+
+	public boolean isProjectFile() {
+		return Project.BNDFILE.equals(getBndResourceName());
+	}
+
+	public boolean isBndrun() {
+		return getBndResourceName().endsWith(Constants.DEFAULT_BNDRUN_EXTENSION);
+	}
+
+	public void addPropertyChangeListener(PropertyChangeListener listener) {
+		propChangeSupport.addPropertyChangeListener(listener);
+	}
+
+	public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
+		propChangeSupport.addPropertyChangeListener(propertyName, listener);
+	}
+
+	public void removePropertyChangeListener(PropertyChangeListener listener) {
+		propChangeSupport.removePropertyChangeListener(listener);
+	}
+
+	public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
+		propChangeSupport.removePropertyChangeListener(propertyName, listener);
+	}
+
+	public void setBndResource(File bndResource) {
+		this.bndResource = bndResource;
+	}
+
+	public File getBndResource() {
+		return bndResource;
+	}
+
+	public String getBndResourceName() {
+		if (bndResourceName == null)
+			return "";
+		return bndResourceName;
+	}
+
+	public void setBndResourceName(String bndResourceName) {
+		this.bndResourceName = bndResourceName;
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/EE.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/EE.java
new file mode 100644
index 0000000..5bb8c45
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/EE.java
@@ -0,0 +1,61 @@
+package aQute.bnd.build.model;
+
+import aQute.bnd.version.*;
+
+public enum EE {
+
+    OSGI_Minimum_1_0("OSGi/Minimum-1.0", "OSGi/Minimum", new Version("1.0")),
+    OSGI_Minimum_1_1("OSGi/Minimum-1.1", "OSGi/Minimum", new Version("1.1"), OSGI_Minimum_1_0),
+    OSGI_Minimum_1_2("OSGi/Minimum-1.2", "OSGi/Minimum", new Version("1.2"), OSGI_Minimum_1_0, OSGI_Minimum_1_1),
+
+    JRE_1_1("JRE-1.1", "JRE", new Version("1.1")),
+
+    J2SE_1_2("J2SE-1.2", "JavaSE", new Version("1.2"), JRE_1_1),
+    J2SE_1_3("J2SE-1.3", "JavaSE", new Version("1.3"), JRE_1_1, J2SE_1_2, OSGI_Minimum_1_0, OSGI_Minimum_1_1),
+    J2SE_1_4("J2SE-1.4", "JavaSE", new Version("1.4"), JRE_1_1, J2SE_1_2, J2SE_1_3, OSGI_Minimum_1_0, OSGI_Minimum_1_1, OSGI_Minimum_1_2),
+    J2SE_1_5("J2SE-1.5", "JavaSE", new Version("1.5"), JRE_1_1, J2SE_1_2, J2SE_1_3, J2SE_1_4, OSGI_Minimum_1_0, OSGI_Minimum_1_1, OSGI_Minimum_1_2),
+
+    JavaSE_1_6("JavaSE-1.6", "JavaSE", new Version("1.6"), JRE_1_1, J2SE_1_2, J2SE_1_3, J2SE_1_4, J2SE_1_5, OSGI_Minimum_1_0, OSGI_Minimum_1_1, OSGI_Minimum_1_2),
+    JavaSE_1_7("JavaSE-1.7", "JavaSE", new Version("1.7"), JRE_1_1, J2SE_1_2, J2SE_1_3, J2SE_1_4, J2SE_1_5, JavaSE_1_6, OSGI_Minimum_1_0, OSGI_Minimum_1_1, OSGI_Minimum_1_2),
+    JavaSE_1_8("JavaSE-1.8", "JavaSE", new Version("1.8"), JRE_1_1, J2SE_1_2, J2SE_1_3, J2SE_1_4, J2SE_1_5, JavaSE_1_6, JavaSE_1_7, OSGI_Minimum_1_0, OSGI_Minimum_1_1, OSGI_Minimum_1_2),
+    JavaSE_1_9("JavaSE-1.9", "JavaSE", new Version("1.9"), JRE_1_1, J2SE_1_2, J2SE_1_3, J2SE_1_4, J2SE_1_5, JavaSE_1_6, JavaSE_1_7, JavaSE_1_8, OSGI_Minimum_1_0, OSGI_Minimum_1_1, OSGI_Minimum_1_2);
+
+    private final String eeName;
+    private final String capabilityName;
+    private final Version capabilityVersion;
+    private final EE[] compatible;
+
+    EE(String name, String capabilityName, Version capabilityVersion, EE... compatible) {
+        this.eeName = name;
+        this.capabilityName = capabilityName;
+        this.capabilityVersion = capabilityVersion;
+        this.compatible = compatible;
+    }
+
+    public String getEEName() {
+        return eeName;
+    }
+
+    /**
+     * @return An array of EEs that this EE implicitly offers, through backwards compatibility.
+     */
+    public EE[] getCompatible() {
+        return compatible != null ? compatible : new EE[0];
+    }
+    
+	public String getCapabilityName() {
+		return capabilityName;
+	}
+
+	public Version getCapabilityVersion() {
+		return capabilityVersion;
+	}
+
+    public static EE parse(String str) {
+        for (EE ee : values()) {
+            if (ee.eeName.equals(str))
+                return ee;
+        }
+        throw new IllegalArgumentException("Unrecognised execution environment name: " + str);
+    }
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/clauses/ComponentSvcReference.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/clauses/ComponentSvcReference.java
new file mode 100644
index 0000000..66272d6
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/clauses/ComponentSvcReference.java
@@ -0,0 +1,102 @@
+package aQute.bnd.build.model.clauses;
+
+public class ComponentSvcReference implements Cloneable {
+
+	private String	name;
+	private String	bind;
+	private String	unbind;
+	private String	serviceClass;
+	private boolean	optional;
+	private boolean	multiple;
+	private boolean	dynamic;
+	private String	targetFilter;
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getBind() {
+		return bind;
+	}
+
+	public void setBind(String bind) {
+		this.bind = bind;
+	}
+
+	public String getUnbind() {
+		return unbind;
+	}
+
+	public void setUnbind(String unbind) {
+		this.unbind = unbind;
+	}
+
+	public String getServiceClass() {
+		return serviceClass;
+	}
+
+	public void setServiceClass(String serviceClass) {
+		this.serviceClass = serviceClass;
+	}
+
+	public boolean isOptional() {
+		return optional;
+	}
+
+	public void setOptional(boolean optional) {
+		this.optional = optional;
+	}
+
+	public boolean isMultiple() {
+		return multiple;
+	}
+
+	public void setMultiple(boolean multiple) {
+		this.multiple = multiple;
+	}
+
+	public boolean isDynamic() {
+		return dynamic;
+	}
+
+	public void setDynamic(boolean dynamic) {
+		this.dynamic = dynamic;
+	}
+
+	public String getTargetFilter() {
+		return targetFilter;
+	}
+
+	public void setTargetFilter(String targetFilter) {
+		this.targetFilter = targetFilter;
+	}
+
+	@Override
+	public ComponentSvcReference clone() {
+		ComponentSvcReference copy = new ComponentSvcReference();
+		copy.name = this.name;
+		copy.serviceClass = this.serviceClass;
+		copy.bind = this.bind;
+		copy.unbind = this.unbind;
+		copy.optional = this.optional;
+		copy.multiple = this.multiple;
+		copy.dynamic = this.dynamic;
+		copy.targetFilter = this.targetFilter;
+		return copy;
+	}
+
+	public void copyFrom(ComponentSvcReference other) {
+		this.name = other.name;
+		this.serviceClass = other.serviceClass;
+		this.bind = other.bind;
+		this.unbind = other.unbind;
+		this.optional = other.optional;
+		this.multiple = other.multiple;
+		this.dynamic = other.dynamic;
+		this.targetFilter = other.targetFilter;
+	}
+}
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/clauses/ExportedPackage.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/clauses/ExportedPackage.java
new file mode 100644
index 0000000..47b37bd
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/clauses/ExportedPackage.java
@@ -0,0 +1,41 @@
+package aQute.bnd.build.model.clauses;
+
+import org.osgi.framework.*;
+
+import aQute.bnd.header.*;
+
+public class ExportedPackage extends HeaderClause {
+
+	public ExportedPackage(String packageName, Attrs attribs) {
+		super(packageName, attribs);
+	}
+
+	@Override
+	protected boolean newlinesBetweenAttributes() {
+		return false;
+	}
+
+	public void setVersionString(String version) {
+		attribs.put(Constants.VERSION_ATTRIBUTE, version);
+	}
+
+	public String getVersionString() {
+		return attribs.get(Constants.VERSION_ATTRIBUTE);
+	}
+
+	public boolean isProvided() {
+		return Boolean.valueOf(attribs.get(aQute.bnd.osgi.Constants.PROVIDE_DIRECTIVE));
+	}
+
+	public void setProvided(boolean provided) {
+		if (provided)
+			attribs.put(aQute.bnd.osgi.Constants.PROVIDE_DIRECTIVE, Boolean.toString(true));
+		else
+			attribs.remove(aQute.bnd.osgi.Constants.PROVIDE_DIRECTIVE);
+	}
+
+	@Override
+	public ExportedPackage clone() {
+		return new ExportedPackage(this.name, new Attrs(this.attribs));
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/clauses/HeaderClause.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/clauses/HeaderClause.java
new file mode 100644
index 0000000..4af4dde
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/clauses/HeaderClause.java
@@ -0,0 +1,153 @@
+package aQute.bnd.build.model.clauses;
+
+import java.util.*;
+import java.util.Map.Entry;
+
+import aQute.bnd.header.*;
+
+public class HeaderClause implements Cloneable, Comparable<HeaderClause> {
+
+	private static final String	INTERNAL_LIST_SEPARATOR				= ";";
+	private static final String	INTERNAL_LIST_SEPARATOR_NEWLINES	= INTERNAL_LIST_SEPARATOR + "\\\n\t\t";
+
+	protected String			name;
+	protected Attrs				attribs;
+
+	public HeaderClause(String name, Attrs attribs) {
+		assert name != null;
+		assert attribs != null;
+
+		this.name = name;
+		this.attribs = attribs;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public Attrs getAttribs() {
+		return attribs;
+	}
+
+	public List<String> getListAttrib(String attrib) {
+		String string = attribs.get(attrib);
+		if (string == null)
+			return null;
+
+		List<String> result = new ArrayList<String>();
+		StringTokenizer tokenizer = new StringTokenizer(string, ",");
+		while (tokenizer.hasMoreTokens()) {
+			result.add(tokenizer.nextToken().trim());
+		}
+
+		return result;
+	}
+
+	public void setListAttrib(String attrib, Collection< ? extends String> value) {
+		if (value == null || value.isEmpty())
+			attribs.remove(attrib);
+		else {
+			StringBuilder buffer = new StringBuilder();
+			boolean first = true;
+			for (String string : value) {
+				if (!first)
+					buffer.append(',');
+				buffer.append(string);
+				first = false;
+			}
+			attribs.put(attrib, buffer.toString());
+		}
+	}
+
+	public void formatTo(StringBuilder buffer) {
+		formatTo(buffer, null);
+	}
+
+	public void formatTo(StringBuilder buffer, Comparator<Entry<String,String>> sorter) {
+		String separator = newlinesBetweenAttributes() ? INTERNAL_LIST_SEPARATOR_NEWLINES : INTERNAL_LIST_SEPARATOR;
+		buffer.append(name);
+		if (attribs != null) {
+			Set<Entry<String,String>> set;
+			if (sorter != null) {
+				set = new TreeSet<Map.Entry<String,String>>(sorter);
+				set.addAll(attribs.entrySet());
+			} else {
+				set = attribs.entrySet();
+			}
+
+			for (Iterator<Entry<String,String>> iter = set.iterator(); iter.hasNext();) {
+				Entry<String,String> entry = iter.next();
+				String name = entry.getKey();
+				String value = entry.getValue();
+
+				if (value != null && value.length() > 0) {
+					buffer.append(separator);
+
+					// If the value contains any comma or equals, then quote the
+					// whole thing
+					if (value.indexOf(',') > -1 || value.indexOf('=') > -1)
+						value = "'" + value + "'";
+
+					buffer.append(name).append('=').append(value);
+				}
+			}
+		}
+	}
+
+	protected boolean newlinesBetweenAttributes() {
+		return false;
+	}
+
+	@Override
+	public HeaderClause clone() {
+		try {
+			HeaderClause clone = (HeaderClause) super.clone();
+			clone.name = this.name;
+			clone.attribs = new Attrs(this.attribs);
+			return clone;
+		}
+		catch (CloneNotSupportedException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	public int compareTo(HeaderClause other) {
+		return this.name.compareTo(other.name);
+	}
+
+	@SuppressWarnings("deprecation")
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((attribs == null) ? 0 : attribs.hashCode());
+		result = prime * result + ((name == null) ? 0 : name.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		HeaderClause other = (HeaderClause) obj;
+		if (attribs == null) {
+			if (other.attribs != null)
+				return false;
+		} else if (!attribs.isEqual(other.attribs))
+			return false;
+		if (name == null) {
+			if (other.name != null)
+				return false;
+		} else if (!name.equals(other.name))
+			return false;
+		return true;
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/clauses/ImportPattern.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/clauses/ImportPattern.java
new file mode 100644
index 0000000..bdca772
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/clauses/ImportPattern.java
@@ -0,0 +1,29 @@
+package aQute.bnd.build.model.clauses;
+
+import org.osgi.framework.*;
+
+import aQute.bnd.header.*;
+
+public class ImportPattern extends VersionedClause implements Cloneable {
+
+	public ImportPattern(String pattern, Attrs attributes) {
+		super(pattern, attributes);
+	}
+
+	public boolean isOptional() {
+		String resolution = attribs.get(aQute.bnd.osgi.Constants.RESOLUTION_DIRECTIVE);
+		return Constants.RESOLUTION_OPTIONAL.equals(resolution);
+	}
+
+	public void setOptional(boolean optional) {
+		if (optional)
+			attribs.put(aQute.bnd.osgi.Constants.RESOLUTION_DIRECTIVE, Constants.RESOLUTION_OPTIONAL);
+		else
+			attribs.remove(aQute.bnd.osgi.Constants.RESOLUTION_DIRECTIVE);
+	}
+
+	@Override
+	public ImportPattern clone() {
+		return new ImportPattern(this.name, new Attrs(this.attribs));
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/clauses/ServiceComponent.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/clauses/ServiceComponent.java
new file mode 100644
index 0000000..d8e4c6b
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/clauses/ServiceComponent.java
@@ -0,0 +1,249 @@
+package aQute.bnd.build.model.clauses;
+
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.regex.*;
+
+import aQute.bnd.header.*;
+
+public class ServiceComponent extends HeaderClause implements Cloneable {
+
+	// v1.0.0 attributes
+	// public final static String COMPONENT_NAME = "name:";
+	public final static String		COMPONENT_FACTORY				= "factory:";
+	public final static String		COMPONENT_SERVICEFACTORY		= "servicefactory:";
+	public final static String		COMPONENT_IMMEDIATE				= "immediate:";
+	public final static String		COMPONENT_ENABLED				= "enabled:";
+
+	public final static String		COMPONENT_DYNAMIC				= "dynamic:";
+	public final static String		COMPONENT_MULTIPLE				= "multiple:";
+	public final static String		COMPONENT_PROVIDE				= "provide:";
+	public final static String		COMPONENT_OPTIONAL				= "optional:";
+	public final static String		COMPONENT_PROPERTIES			= "properties:";
+	// public final static String COMPONENT_IMPLEMENTATION = "implementation:";
+
+	// v1.1.0 attributes
+	public final static String		COMPONENT_VERSION				= "version:";
+	public final static String		COMPONENT_CONFIGURATION_POLICY	= "configuration-policy:";
+	public final static String		COMPONENT_MODIFIED				= "modified:";
+	public final static String		COMPONENT_ACTIVATE				= "activate:";
+	public final static String		COMPONENT_DEACTIVATE			= "deactivate:";
+
+	private final static Pattern	REFERENCE_PATTERN				= Pattern.compile("([^(]+)(\\(.+\\))?");
+
+	public ServiceComponent(String name, Attrs attribs) {
+		super(name, attribs);
+	}
+
+	public boolean isPath() {
+		return name.indexOf('/') >= 0 || name.endsWith(".xml");
+	}
+
+	private Set<String> getStringSet(String attrib) {
+		List<String> list = getListAttrib(attrib);
+		return list != null ? new HashSet<String>(list) : new HashSet<String>();
+	}
+
+	public void setPropertiesMap(Map<String,String> properties) {
+		List<String> strings = new ArrayList<String>(properties.size());
+		for (Entry<String,String> entry : properties.entrySet()) {
+			String line = new StringBuilder().append(entry.getKey()).append("=").append(entry.getValue()).toString();
+			strings.add(line);
+		}
+		setListAttrib(COMPONENT_PROPERTIES, strings);
+	}
+
+	public Map<String,String> getPropertiesMap() {
+		Map<String,String> result = new LinkedHashMap<String,String>();
+
+		List<String> list = getListAttrib(COMPONENT_PROPERTIES);
+		if (list != null) {
+			for (String entryStr : list) {
+				String name;
+				String value;
+
+				int index = entryStr.lastIndexOf('=');
+				if (index == -1) {
+					name = entryStr;
+					value = null;
+				} else {
+					name = entryStr.substring(0, index);
+					value = entryStr.substring(index + 1);
+				}
+
+				result.put(name, value);
+			}
+		}
+
+		return result;
+	}
+
+	public void setSvcRefs(List< ? extends ComponentSvcReference> refs) {
+		// First remove all existing references, i.e. non-directives
+		for (Iterator<String> iter = attribs.keySet().iterator(); iter.hasNext();) {
+			String name = iter.next();
+			if (!name.endsWith(":")) {
+				iter.remove();
+			}
+		}
+
+		// Add in the references
+		Set<String> dynamic = new HashSet<String>();
+		Set<String> optional = new HashSet<String>();
+		Set<String> multiple = new HashSet<String>();
+		for (ComponentSvcReference ref : refs) {
+			// Build the reference name with bind and unbind
+			String expandedRefName = ref.getName();
+			if (ref.getBind() != null) {
+				expandedRefName += "/" + ref.getBind();
+				if (ref.getUnbind() != null) {
+					expandedRefName += "/" + ref.getUnbind();
+				}
+			}
+
+			// Start building the map value
+			StringBuilder buffer = new StringBuilder();
+			buffer.append(ref.getServiceClass());
+
+			// Add the target filter
+			if (ref.getTargetFilter() != null) {
+				buffer.append('(').append(ref.getTargetFilter()).append(')');
+			}
+
+			// Work out the cardinality suffix (i.e. *, +, ? org ~).
+			// Adding to the dynamic/multiple/optional lists for non-standard
+			// cases
+			String cardinalitySuffix;
+			if (ref.isDynamic()) {
+				if (ref.isOptional()) {
+					if (ref.isMultiple()) // 0..n dynamic
+						cardinalitySuffix = "*";
+					else
+						// 0..1 dynamic
+						cardinalitySuffix = "?";
+				} else {
+					if (ref.isMultiple()) // 1..n dynamic
+						cardinalitySuffix = "+";
+					else { // 1..1 dynamic, not a normal combination
+						cardinalitySuffix = null;
+						dynamic.add(ref.getName());
+					}
+				}
+			} else {
+				if (ref.isOptional()) {
+					if (ref.isMultiple()) { // 0..n static, not a normal
+											// combination
+						cardinalitySuffix = null;
+						optional.add(ref.getName());
+						multiple.add(ref.getName());
+					} else { // 0..1 static
+						cardinalitySuffix = "~";
+					}
+				} else {
+					if (ref.isMultiple()) { // 1..n static, not a normal
+											// combination
+						multiple.add(ref.getName());
+						cardinalitySuffix = null;
+					} else { // 1..1 static
+						cardinalitySuffix = null;
+					}
+				}
+			}
+
+			if (cardinalitySuffix != null)
+				buffer.append(cardinalitySuffix);
+
+			// Write to the map
+			attribs.put(expandedRefName, buffer.toString());
+		}
+		setListAttrib(COMPONENT_OPTIONAL, optional);
+		setListAttrib(COMPONENT_MULTIPLE, multiple);
+		setListAttrib(COMPONENT_DYNAMIC, dynamic);
+	}
+
+	public List<ComponentSvcReference> getSvcRefs() {
+		List<ComponentSvcReference> result = new ArrayList<ComponentSvcReference>();
+
+		Set<String> dynamicSet = getStringSet(COMPONENT_DYNAMIC);
+		Set<String> optionalSet = getStringSet(COMPONENT_OPTIONAL);
+		Set<String> multipleSet = getStringSet(COMPONENT_MULTIPLE);
+
+		for (Entry<String,String> entry : attribs.entrySet()) {
+			String referenceName = entry.getKey();
+
+			// Skip directives
+			if (referenceName.endsWith(":"))//$NON-NLS-1$
+				continue;
+
+			ComponentSvcReference svcRef = new ComponentSvcReference();
+
+			String bind = null;
+			String unbind = null;
+
+			if (referenceName.indexOf('/') >= 0) {
+				String parts[] = referenceName.split("/");
+				referenceName = parts[0];
+				bind = parts[1];
+				if (parts.length > 2)
+					unbind = parts[2];
+				/*
+				 * else if (bind.startsWith("add")) unbind =
+				 * bind.replaceAll("add(.+)", "remove$1"); else unbind = "un" +
+				 * bind; } else if
+				 * (Character.isLowerCase(referenceName.charAt(0))) { bind =
+				 * "set" + Character.toUpperCase(referenceName.charAt(0)) +
+				 * referenceName.substring(1); unbind = "un" + bind;
+				 */
+			}
+			svcRef.setName(referenceName);
+			svcRef.setBind(bind);
+			svcRef.setUnbind(unbind);
+
+			String interfaceName = entry.getValue();
+			if (interfaceName == null || interfaceName.length() == 0) {
+				continue;
+			}
+			svcRef.setServiceClass(interfaceName);
+
+			// Check the cardinality by looking at the last
+			// character of the value
+			char c = interfaceName.charAt(interfaceName.length() - 1);
+			if ("?+*~".indexOf(c) >= 0) {
+				if (c == '?' || c == '*' || c == '~')
+					optionalSet.add(referenceName);
+				if (c == '+' || c == '*')
+					multipleSet.add(referenceName);
+				if (c == '+' || c == '*' || c == '?')
+					dynamicSet.add(referenceName);
+				interfaceName = interfaceName.substring(0, interfaceName.length() - 1);
+			}
+			svcRef.setOptional(optionalSet.contains(referenceName));
+			svcRef.setMultiple(multipleSet.contains(referenceName));
+			svcRef.setDynamic(dynamicSet.contains(referenceName));
+
+			// Parse the target from the interface name
+			// The target is a filter.
+			String target = null;
+			Matcher m = REFERENCE_PATTERN.matcher(interfaceName);
+			if (m.matches()) {
+				interfaceName = m.group(1);
+				target = m.group(2);
+			}
+			svcRef.setTargetFilter(target);
+
+			result.add(svcRef);
+		}
+
+		return result;
+	}
+
+	@Override
+	public ServiceComponent clone() {
+		return new ServiceComponent(this.name, new Attrs(this.attribs));
+	}
+
+	@Override
+	protected boolean newlinesBetweenAttributes() {
+		return true;
+	}
+}
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/clauses/VersionedClause.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/clauses/VersionedClause.java
new file mode 100644
index 0000000..358ec08
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/clauses/VersionedClause.java
@@ -0,0 +1,27 @@
+package aQute.bnd.build.model.clauses;
+
+import org.osgi.framework.*;
+
+import aQute.bnd.header.*;
+
+public class VersionedClause extends HeaderClause implements Cloneable {
+	public VersionedClause(String name, Attrs attribs) {
+		super(name, attribs);
+	}
+
+	public String getVersionRange() {
+		return attribs.get(Constants.VERSION_ATTRIBUTE);
+	}
+
+	public void setVersionRange(String versionRangeString) {
+		attribs.put(Constants.VERSION_ATTRIBUTE, versionRangeString);
+	}
+
+	@Override
+	public VersionedClause clone() {
+		VersionedClause clone = (VersionedClause) super.clone();
+		clone.name = this.name;
+		clone.attribs = new Attrs(this.attribs);
+		return clone;
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/clauses/packageinfo b/biz.aQute.bndlib/src/aQute/bnd/build/model/clauses/packageinfo
new file mode 100644
index 0000000..55af8e5
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/clauses/packageinfo
@@ -0,0 +1 @@
+version 2
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/ClauseListConverter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/ClauseListConverter.java
new file mode 100644
index 0000000..893a22f
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/ClauseListConverter.java
@@ -0,0 +1,31 @@
+package aQute.bnd.build.model.conversions;
+
+import java.util.*;
+import java.util.Map.Entry;
+
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
+import aQute.libg.tuple.*;
+
+public class ClauseListConverter<R> implements Converter<List<R>,String> {
+
+	private final Converter< ? extends R, ? super Pair<String,Attrs>>	itemConverter;
+
+	public ClauseListConverter(Converter< ? extends R, ? super Pair<String,Attrs>> itemConverter) {
+		this.itemConverter = itemConverter;
+	}
+
+	public List<R> convert(String input) throws IllegalArgumentException {
+		List<R> result = new ArrayList<R>();
+
+		Parameters header = new Parameters(input);
+		for (Entry<String,Attrs> entry : header.entrySet()) {
+			String key = Processor.removeDuplicateMarker(entry.getKey());
+			Pair<String,Attrs> pair = Pair.newInstance(key, entry.getValue());
+			result.add(itemConverter.convert(pair));
+		}
+
+		return result;
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/CollectionFormatter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/CollectionFormatter.java
new file mode 100644
index 0000000..d9f345a
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/CollectionFormatter.java
@@ -0,0 +1,47 @@
+package aQute.bnd.build.model.conversions;
+
+import java.util.*;
+
+public class CollectionFormatter<T> implements Converter<String,Collection< ? extends T>> {
+
+	private final String						separator;
+	private final Converter<String, ? super T>	itemFormatter;
+	private final String						emptyOutput;
+
+	public CollectionFormatter(String separator) {
+		this(separator, (String) null);
+	}
+
+	public CollectionFormatter(String separator, String emptyOutput) {
+		this(separator, new DefaultFormatter(), emptyOutput);
+	}
+
+	public CollectionFormatter(String separator, Converter<String, ? super T> itemFormatter) {
+		this(separator, itemFormatter, null);
+	}
+
+	public CollectionFormatter(String separator, Converter<String, ? super T> itemFormatter, String emptyOutput) {
+		this.separator = separator;
+		this.itemFormatter = itemFormatter;
+		this.emptyOutput = emptyOutput;
+	}
+
+	public String convert(Collection< ? extends T> input) throws IllegalArgumentException {
+		String result = null;
+		if (input != null) {
+			if (input.isEmpty()) {
+				result = emptyOutput;
+			} else {
+				StringBuilder buffer = new StringBuilder();
+				for (Iterator< ? extends T> iter = input.iterator(); iter.hasNext();) {
+					T item = iter.next();
+					buffer.append(itemFormatter.convert(item));
+					if (iter.hasNext())
+						buffer.append(separator);
+				}
+				result = buffer.toString();
+			}
+		}
+		return result;
+	}
+}
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/Converter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/Converter.java
new file mode 100644
index 0000000..8513f52
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/Converter.java
@@ -0,0 +1,5 @@
+package aQute.bnd.build.model.conversions;
+
+public interface Converter<R, T> {
+	R convert(T input) throws IllegalArgumentException;
+}
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/DefaultBooleanFormatter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/DefaultBooleanFormatter.java
new file mode 100644
index 0000000..f188569
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/DefaultBooleanFormatter.java
@@ -0,0 +1,26 @@
+package aQute.bnd.build.model.conversions;
+
+/**
+ * Formatter for booleans with a default value; if the input value matches the
+ * default then it is formatted to <code>null</code>.
+ * 
+ * @author Neil Bartlett
+ */
+public class DefaultBooleanFormatter implements Converter<String,Boolean> {
+
+	private final boolean	defaultValue;
+
+	public DefaultBooleanFormatter(boolean defaultValue) {
+		this.defaultValue = defaultValue;
+	}
+
+	public String convert(Boolean input) throws IllegalArgumentException {
+		String result = null;
+
+		if (input != null && input.booleanValue() != defaultValue)
+			result = input.toString();
+
+		return result;
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/DefaultFormatter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/DefaultFormatter.java
new file mode 100644
index 0000000..a552c0d
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/DefaultFormatter.java
@@ -0,0 +1,9 @@
+package aQute.bnd.build.model.conversions;
+
+public class DefaultFormatter implements Converter<String,Object> {
+
+	public String convert(Object input) throws IllegalArgumentException {
+		return input == null ? null : input.toString();
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/EEConverter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/EEConverter.java
new file mode 100644
index 0000000..a2defbf
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/EEConverter.java
@@ -0,0 +1,11 @@
+package aQute.bnd.build.model.conversions;
+
+import aQute.bnd.build.model.*;
+
+public class EEConverter implements Converter<EE,String> {
+
+	public EE convert(String input) throws IllegalArgumentException {
+		return EE.parse(input);
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/EEFormatter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/EEFormatter.java
new file mode 100644
index 0000000..44a7de6
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/EEFormatter.java
@@ -0,0 +1,9 @@
+package aQute.bnd.build.model.conversions;
+
+import aQute.bnd.build.model.*;
+
+public final class EEFormatter implements Converter<String,EE> {
+	public String convert(EE input) throws IllegalArgumentException {
+		return input != null ? input.getEEName() : null;
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/EnumConverter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/EnumConverter.java
new file mode 100644
index 0000000..4c94d3b
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/EnumConverter.java
@@ -0,0 +1,27 @@
+package aQute.bnd.build.model.conversions;
+
+public class EnumConverter<E extends Enum<E>> implements Converter<E,String> {
+
+	private final Class<E>	enumType;
+	private final E			defaultValue;
+
+	public static <E extends Enum<E>> EnumConverter<E> create(Class<E> enumType) {
+		return new EnumConverter<E>(enumType, null);
+	}
+
+	public static <E extends Enum<E>> EnumConverter<E> create(Class<E> enumType, E defaultValue) {
+		return new EnumConverter<E>(enumType, defaultValue);
+	}
+
+	private EnumConverter(Class<E> enumType, E defaultValue) {
+		this.enumType = enumType;
+		this.defaultValue = defaultValue;
+	}
+
+	public E convert(String input) throws IllegalArgumentException {
+		if (input == null)
+			return defaultValue;
+		return Enum.valueOf(enumType, input);
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/EnumFormatter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/EnumFormatter.java
new file mode 100644
index 0000000..8500a25
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/EnumFormatter.java
@@ -0,0 +1,53 @@
+package aQute.bnd.build.model.conversions;
+
+/**
+ * Formats an enum type. Outputs {@code null} when the value of the enum is
+ * equal to a default value.
+ * 
+ * @param <E>
+ * @author Neil Bartlett
+ */
+public class EnumFormatter<E extends Enum<E>> implements Converter<String,E> {
+
+	private final E			defaultValue;
+
+	/**
+	 * Construct a new formatter with no default value, i.e. any non-null value
+	 * of the enum will print that value.
+	 * 
+	 * @param enumType
+	 *            The enum type.
+	 * @return
+	 */
+	public static <E extends Enum<E>> EnumFormatter<E> create(Class<E> enumType) {
+		return new EnumFormatter<E>(null);
+	}
+
+	/**
+	 * Construct a new formatter with the specified default value.
+	 * 
+	 * @param enumType
+	 *            The enum type.
+	 * @param defaultValue
+	 *            The default value, which will never be output.
+	 * @return
+	 */
+	public static <E extends Enum<E>> EnumFormatter<E> create(Class<E> enumType, E defaultValue) {
+		return new EnumFormatter<E>(defaultValue);
+	}
+
+	private EnumFormatter(E defaultValue) {
+		this.defaultValue = defaultValue;
+	}
+
+	public String convert(E input) throws IllegalArgumentException {
+		String result;
+		if (input == defaultValue || input == null)
+			result = null;
+		else {
+			result = input.toString();
+		}
+		return result;
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/HeaderClauseConverter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/HeaderClauseConverter.java
new file mode 100644
index 0000000..dffd900
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/HeaderClauseConverter.java
@@ -0,0 +1,13 @@
+package aQute.bnd.build.model.conversions;
+
+import aQute.bnd.build.model.clauses.*;
+import aQute.bnd.header.*;
+import aQute.libg.tuple.*;
+
+public class HeaderClauseConverter implements Converter<HeaderClause,Pair<String,Attrs>> {
+
+	public HeaderClause convert(Pair<String,Attrs> input) throws IllegalArgumentException {
+		return new HeaderClause(input.getFirst(), input.getSecond());
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/HeaderClauseFormatter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/HeaderClauseFormatter.java
new file mode 100644
index 0000000..f4161f5
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/HeaderClauseFormatter.java
@@ -0,0 +1,11 @@
+package aQute.bnd.build.model.conversions;
+
+import aQute.bnd.build.model.clauses.*;
+
+public class HeaderClauseFormatter implements Converter<String,HeaderClause> {
+	public String convert(HeaderClause input) throws IllegalArgumentException {
+		StringBuilder buffer = new StringBuilder();
+		input.formatTo(buffer);
+		return buffer.toString();
+	}
+}
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/HeaderClauseListConverter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/HeaderClauseListConverter.java
new file mode 100644
index 0000000..65d8471
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/HeaderClauseListConverter.java
@@ -0,0 +1,11 @@
+package aQute.bnd.build.model.conversions;
+
+import aQute.bnd.build.model.clauses.*;
+
+public class HeaderClauseListConverter extends ClauseListConverter<HeaderClause> {
+
+	public HeaderClauseListConverter() {
+		super(new HeaderClauseConverter());
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/MapFormatter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/MapFormatter.java
new file mode 100644
index 0000000..03d6f71
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/MapFormatter.java
@@ -0,0 +1,18 @@
+package aQute.bnd.build.model.conversions;
+
+import java.util.*;
+import java.util.Map.Entry;
+
+public class MapFormatter implements Converter<String,Map<String,String>> {
+
+	private CollectionFormatter<Entry<String,String>>	entrySetFormatter;
+
+	public MapFormatter(String listSeparator, Converter<String, ? super Entry<String,String>> entryFormatter,
+			String emptyOutput) {
+		entrySetFormatter = new CollectionFormatter<Entry<String,String>>(listSeparator, entryFormatter, emptyOutput);
+	}
+
+	public String convert(Map<String,String> input) throws IllegalArgumentException {
+		return entrySetFormatter.convert(input.entrySet());
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/NewlineEscapedStringFormatter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/NewlineEscapedStringFormatter.java
new file mode 100644
index 0000000..1bf9220
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/NewlineEscapedStringFormatter.java
@@ -0,0 +1,33 @@
+package aQute.bnd.build.model.conversions;
+
+import aQute.bnd.build.model.*;
+
+public class NewlineEscapedStringFormatter implements Converter<String,String> {
+
+	public String convert(String input) throws IllegalArgumentException {
+		if (input == null)
+			return null;
+
+		// Shortcut the result for the majority of cases where there is no
+		// newline
+		if (input.indexOf('\n') == -1)
+			return input;
+
+		// Build a new string with newlines escaped
+		StringBuilder result = new StringBuilder();
+		int position = 0;
+		while (position < input.length()) {
+			int newlineIndex = input.indexOf('\n', position);
+			if (newlineIndex == -1) {
+				result.append(input.substring(position));
+				break;
+			}
+			result.append(input.substring(position, newlineIndex));
+			result.append(BndEditModel.NEWLINE_LINE_SEPARATOR);
+			position = newlineIndex + 1;
+		}
+
+		return result.toString();
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/NoopConverter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/NoopConverter.java
new file mode 100644
index 0000000..7a9f39d
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/NoopConverter.java
@@ -0,0 +1,7 @@
+package aQute.bnd.build.model.conversions;
+
+public class NoopConverter<T> implements Converter<T,T> {
+	public T convert(T input) throws IllegalArgumentException {
+		return input;
+	}
+}
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/PropertiesConverter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/PropertiesConverter.java
new file mode 100644
index 0000000..cd45c60
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/PropertiesConverter.java
@@ -0,0 +1,13 @@
+package aQute.bnd.build.model.conversions;
+
+import java.util.*;
+
+import aQute.bnd.header.*;
+
+public class PropertiesConverter implements Converter<Map<String,String>,String> {
+
+	public Map<String,String> convert(String input) throws IllegalArgumentException {
+		return OSGiHeader.parseProperties(input);
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/PropertiesEntryFormatter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/PropertiesEntryFormatter.java
new file mode 100644
index 0000000..b487190
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/PropertiesEntryFormatter.java
@@ -0,0 +1,26 @@
+package aQute.bnd.build.model.conversions;
+
+import java.util.Map.Entry;
+
+public class PropertiesEntryFormatter implements Converter<String,Entry<String,String>> {
+	public String convert(Entry<String,String> entry) {
+		StringBuilder buffer = new StringBuilder();
+
+		String name = entry.getKey();
+		buffer.append(name).append('=');
+
+		String value = entry.getValue();
+		if (value != null && value.length() > 0) {
+			int quotableIndex = value.indexOf(',');
+			if (quotableIndex == -1)
+				quotableIndex = value.indexOf('=');
+
+			if (quotableIndex >= 0) {
+				buffer.append('\'').append(value).append('\'');
+			} else {
+				buffer.append(value);
+			}
+		}
+		return buffer.toString();
+	}
+}
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/RequirementFormatter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/RequirementFormatter.java
new file mode 100644
index 0000000..2a293ef
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/RequirementFormatter.java
@@ -0,0 +1,25 @@
+package aQute.bnd.build.model.conversions;
+
+import java.util.Map.Entry;
+
+import org.osgi.resource.*;
+
+public class RequirementFormatter implements Converter<String,Requirement> {
+
+	public String convert(Requirement req) throws IllegalArgumentException {
+		StringBuilder builder = new StringBuilder();
+		
+		builder.append(req.getNamespace());
+		
+		for (Entry<String,String> directive : req.getDirectives().entrySet()) {
+			builder.append(';').append(directive.getKey()).append(":='").append(directive.getValue()).append('\'');
+		}
+		
+		for (Entry<String,Object> attribute : req.getAttributes().entrySet()) {
+			builder.append(';').append(attribute.getKey()).append("='").append(attribute.getValue()).append('\'');
+		}
+		
+		return builder.toString();
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/RequirementListConverter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/RequirementListConverter.java
new file mode 100644
index 0000000..dacd6ed
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/RequirementListConverter.java
@@ -0,0 +1,32 @@
+package aQute.bnd.build.model.conversions;
+
+import java.util.Map.Entry;
+
+import org.osgi.resource.*;
+
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.resource.*;
+import aQute.libg.tuple.*;
+
+public class RequirementListConverter extends ClauseListConverter<Requirement> {
+
+	public RequirementListConverter() {
+		super(new Converter<Requirement,Pair<String,Attrs>>() {
+			public Requirement convert(Pair<String,Attrs> input) throws IllegalArgumentException {
+				String namespace = input.getFirst();
+				CapReqBuilder builder = new CapReqBuilder(namespace);
+				for (Entry<String,String> entry : input.getSecond().entrySet()) {
+					String key = entry.getKey();
+					if (key.endsWith(":")) {
+						key = key.substring(0, key.length() - 1);
+						builder.addDirective(key, entry.getValue());
+					} else {
+						builder.addAttribute(key, entry.getValue());
+					}
+				}
+				return builder.buildSyntheticRequirement();
+			}
+		});
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/SimpleListConverter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/SimpleListConverter.java
new file mode 100644
index 0000000..a3a262b
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/SimpleListConverter.java
@@ -0,0 +1,41 @@
+package aQute.bnd.build.model.conversions;
+
+import java.util.*;
+
+import aQute.bnd.osgi.*;
+import aQute.libg.qtokens.*;
+
+public class SimpleListConverter<R> implements Converter<List<R>,String> {
+
+	private Converter< ? extends R, ? super String>	itemConverter;
+
+	public static <R> Converter<List<R>,String> create(Converter<R, ? super String> itemConverter) {
+		return new SimpleListConverter<R>(itemConverter);
+	}
+
+	public static Converter<List<String>,String> create() {
+		return new SimpleListConverter<String>(new NoopConverter<String>());
+	}
+
+	private SimpleListConverter(Converter< ? extends R, ? super String> itemConverter) {
+		this.itemConverter = itemConverter;
+	}
+
+	public List<R> convert(String input) throws IllegalArgumentException {
+		List<R> result = new ArrayList<R>();
+
+		if (Constants.EMPTY_HEADER.equalsIgnoreCase(input.trim()))
+			return result;
+
+		QuotedTokenizer qt = new QuotedTokenizer(input, ",");
+		String token = qt.nextToken();
+
+		while (token != null) {
+			result.add(itemConverter.convert(token.trim()));
+			token = qt.nextToken();
+		}
+
+		return result;
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/StringEntryConverter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/StringEntryConverter.java
new file mode 100644
index 0000000..c857ddc
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/StringEntryConverter.java
@@ -0,0 +1,11 @@
+package aQute.bnd.build.model.conversions;
+
+import java.util.Map.Entry;
+
+public class StringEntryConverter implements Converter<String,Entry<String, ? >> {
+
+	public String convert(Entry<String, ? > input) throws IllegalArgumentException {
+		return input.getKey();
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/VersionedClauseConverter.java b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/VersionedClauseConverter.java
new file mode 100644
index 0000000..31a1663
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/conversions/VersionedClauseConverter.java
@@ -0,0 +1,11 @@
+package aQute.bnd.build.model.conversions;
+
+import aQute.bnd.build.model.clauses.*;
+import aQute.bnd.header.*;
+import aQute.libg.tuple.*;
+
+public class VersionedClauseConverter implements Converter<VersionedClause,Pair<String,Attrs>> {
+	public VersionedClause convert(Pair<String,Attrs> input) throws IllegalArgumentException {
+		return new VersionedClause(input.getFirst(), input.getSecond());
+	}
+}
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/model/packageinfo b/biz.aQute.bndlib/src/aQute/bnd/build/model/packageinfo
new file mode 100644
index 0000000..67281af
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/model/packageinfo
@@ -0,0 +1 @@
+version 2.3
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/packageinfo b/biz.aQute.bndlib/src/aQute/bnd/build/packageinfo
index ec0efd4..a2afe57 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/build/packageinfo
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/packageinfo
@@ -1 +1 @@
-version 1.43.1
+version 2.1.0
diff --git a/biz.aQute.bndlib/src/aQute/bnd/compatibility/Access.java b/biz.aQute.bndlib/src/aQute/bnd/compatibility/Access.java
index ac8bb37..1fcb640 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/compatibility/Access.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/compatibility/Access.java
@@ -19,6 +19,7 @@ public enum Access {
 		return PACKAGE;
 	}
 
+	@Override
 	public String toString() {
 		return super.toString().toLowerCase();
 	}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/compatibility/GenericParameter.java b/biz.aQute.bndlib/src/aQute/bnd/compatibility/GenericParameter.java
index 1eac28c..e801a8a 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/compatibility/GenericParameter.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/compatibility/GenericParameter.java
@@ -1,22 +1,25 @@
 package aQute.bnd.compatibility;
 
 public class GenericParameter {
-	String name;
-	GenericType bounds[];
-	
+	String		name;
+	GenericType	bounds[];
+
 	public GenericParameter(String name, GenericType[] bounds) {
 		this.name = name;
 		this.bounds = bounds;
 		if (bounds == null || bounds.length == 0)
-			bounds = new GenericType[] { new GenericType( Object.class) };
+			this.bounds = new GenericType[] {
+				new GenericType(Object.class)
+			};
 	}
 
+	@Override
 	public String toString() {
 		StringBuilder sb = new StringBuilder();
 		sb.append(name);
-		if ( bounds != null && bounds.length > 0) {
-			for ( GenericType gtype : bounds ) {
-				sb.append( ":");
+		if (bounds != null && bounds.length > 0) {
+			for (GenericType gtype : bounds) {
+				sb.append(":");
 				sb.append(gtype);
 			}
 		}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/compatibility/GenericType.java b/biz.aQute.bndlib/src/aQute/bnd/compatibility/GenericType.java
index 847a358..ce286f2 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/compatibility/GenericType.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/compatibility/GenericType.java
@@ -1,8 +1,7 @@
 package aQute.bnd.compatibility;
 
-
 public class GenericType {
-	public GenericType(Class<Object> class1) {
+	public GenericType(@SuppressWarnings("unused") Class<Object> class1) {
 		// TODO Auto-generated constructor stub
 	}
 
@@ -11,27 +10,25 @@ public class GenericType {
 	GenericType[]				a;
 	GenericType[]				b;
 	int							array;
-	
-	Scope	scope;
-	
-		static public class GenericWildcard extends GenericType{
+
+	Scope						scope;
+
+	static public class GenericWildcard extends GenericType {
 
 		public GenericWildcard(Class<Object> class1) {
 			super(class1);
 			// TODO Auto-generated constructor stub
 		}
-		
+
 	}
-	
+
 	static public class GenericArray extends GenericType {
 
 		public GenericArray(Class<Object> class1) {
 			super(class1);
 			// TODO Auto-generated constructor stub
 		}
-		
+
 	}
-	
-	
 
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/compatibility/Kind.java b/biz.aQute.bndlib/src/aQute/bnd/compatibility/Kind.java
index 1e84030..2e9f5cd 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/compatibility/Kind.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/compatibility/Kind.java
@@ -2,11 +2,11 @@ package aQute.bnd.compatibility;
 
 /**
  * The kind of thing we scope
- * 
  */
 public enum Kind {
 	ROOT, CLASS, FIELD, CONSTRUCTOR, METHOD, UNKNOWN;
 
+	@Override
 	public String toString() {
 		return super.toString().toLowerCase();
 	}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/compatibility/ParseSignatureBuilder.java b/biz.aQute.bndlib/src/aQute/bnd/compatibility/ParseSignatureBuilder.java
index dc578ea..6cb52ce 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/compatibility/ParseSignatureBuilder.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/compatibility/ParseSignatureBuilder.java
@@ -2,108 +2,117 @@ package aQute.bnd.compatibility;
 
 import java.io.*;
 
-import aQute.lib.osgi.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Descriptors.TypeRef;
 
 public class ParseSignatureBuilder {
-	final Scope			root;
-	
+	final Scope	root;
+
 	public ParseSignatureBuilder(Scope root) {
 		this.root = root;
 	}
-	
-	public void add( Jar jar ) throws Exception {
-		for ( Resource r : jar.getResources().values()) {
+
+	public void add(Jar jar) throws Exception {
+		for (Resource r : jar.getResources().values()) {
 			InputStream in = r.openInputStream();
 			try {
 				parse(in);
-			} finally {
+			}
+			finally {
 				in.close();
 			}
 		}
 	}
-	
-	public Scope getRoot() { return root; }
-	
-	
-	public void parse(InputStream in) throws IOException {
-		Clazz clazz = new Clazz("", null);
-		
+
+	public Scope getRoot() {
+		return root;
+	}
+
+	public void parse(InputStream in) throws Exception {
+		Analyzer analyzer = new Analyzer();
+		Clazz clazz = new Clazz(analyzer, "", null);
+
 		clazz.parseClassFile(in, new ClassDataCollector() {
 			Scope	s;
 			Scope	enclosing;
 			Scope	declaring;
 
-			public void classBegin(int access, String name) {
-				s = root.getScope(Scope.classIdentity(name));
+			@Override
+			public void classBegin(int access, TypeRef name) {
+				s = root.getScope(name.getBinary());
 				s.access = Access.modifier(access);
 				s.kind = Kind.CLASS;
 			}
 
-			public void extendsClass(String name) {
-//				s.setBase(new GenericType(name));
+			@Override
+			public void extendsClass(TypeRef name) {
+				// s.setBase(new GenericType(name));
 			}
 
-			public void implementsInterfaces(String names[]) {
+			@Override
+			public void implementsInterfaces(TypeRef names[]) {
 				s.setParameterTypes(convert(names));
 			}
 
-			GenericType[] convert(String names[]) {
+			GenericType[] convert(TypeRef names[]) {
 				GenericType tss[] = new GenericType[names.length];
 				for (int i = 0; i < names.length; i++) {
-//					tss[i] = new GenericType(names[i]);
+					// tss[i] = new GenericType(names[i]);
 				}
 				return tss;
 			}
 
+			@Override
 			public void method(Clazz.MethodDef defined) {
 				String descriptor;
 				Kind kind;
 				if (defined.isConstructor()) {
-					descriptor = ":" + defined.descriptor;
+					descriptor = ":" + defined.getDescriptor();
 					kind = Kind.CONSTRUCTOR;
 				} else {
-					descriptor = defined.name + ":" + defined.descriptor;
+					descriptor = defined.getName() + ":" + defined.getDescriptor();
 					kind = Kind.METHOD;
 				}
 				Scope m = s.getScope(descriptor);
-				m.access = Access.modifier(defined.access);
+				m.access = Access.modifier(defined.getAccess());
 				m.kind = kind;
 				m.declaring = s;
 				s.add(m);
 			}
 
+			@Override
 			public void field(Clazz.FieldDef defined) {
-				String descriptor = defined.name + ":" + defined.descriptor;
+				String descriptor = defined.getName() + ":" + defined.getDescriptor();
 				Kind kind = Kind.FIELD;
 				Scope m = s.getScope(descriptor);
-				m.access = Access.modifier(defined.access);
+				m.access = Access.modifier(defined.getAccess());
 				m.kind = kind;
 				m.declaring = s;
 				s.add(m);
 			}
 
+			@Override
 			public void classEnd() {
 				if (enclosing != null)
-					s.setEnclosing( enclosing );
+					s.setEnclosing(enclosing);
 				if (declaring != null)
-					s.setDeclaring( declaring );				
+					s.setDeclaring(declaring);
 			}
 
-			public void enclosingMethod(String cName, String mName, String mDescriptor) {
-				enclosing = root.getScope(Scope.classIdentity(cName));
+			@Override
+			public void enclosingMethod(TypeRef cName, String mName, String mDescriptor) {
+				enclosing = root.getScope(cName.getBinary());
 				if (mName != null) {
 					enclosing = enclosing.getScope(Scope.methodIdentity(mName, mDescriptor));
 				}
 			}
 
-			public void innerClass(String innerClass, String outerClass, String innerName,
-					int innerClassAccessFlags) {
-				if (outerClass != null && innerClass != null && innerClass.equals(s.name))
-					declaring = root.getScope(Scope.classIdentity(outerClass));
+			@Override
+			public void innerClass(TypeRef innerClass, TypeRef outerClass, String innerName, int innerClassAccessFlags) {
+				if (outerClass != null && innerClass != null && innerClass.getBinary().equals(s.name))
+					declaring = root.getScope(outerClass.getBinary());
 			}
 		});
-		
-		
+
 	}
 }
-
diff --git a/biz.aQute.bndlib/src/aQute/bnd/compatibility/RuntimeSignatureBuilder.java b/biz.aQute.bndlib/src/aQute/bnd/compatibility/RuntimeSignatureBuilder.java
index 7761701..9e6b090 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/compatibility/RuntimeSignatureBuilder.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/compatibility/RuntimeSignatureBuilder.java
@@ -9,16 +9,15 @@ public class RuntimeSignatureBuilder {
 		this.root = root;
 	}
 
-	static public String identity(Class<?> c) {
+	static public String identity(Class< ? > c) {
 		return Scope.classIdentity(c.getName());
 	}
 
 	static public String identity(Method m) {
-		return Scope.methodIdentity(m.getName(), getDescriptor(m.getReturnType(), m
-				.getParameterTypes()));
+		return Scope.methodIdentity(m.getName(), getDescriptor(m.getReturnType(), m.getParameterTypes()));
 	}
 
-	static public String identity(Constructor m) {
+	static public String identity(Constructor< ? > m) {
 		return Scope.constructorIdentity(getDescriptor(void.class, m.getParameterTypes()));
 	}
 
@@ -26,11 +25,11 @@ public class RuntimeSignatureBuilder {
 		return Scope.fieldIdentity(m.getName(), getDescriptor(m.getType(), null));
 	}
 
-	static public String getDescriptor(Class<?> base, Class<?>[] parameters) {
+	static public String getDescriptor(Class< ? > base, Class< ? >[] parameters) {
 		StringBuilder sb = new StringBuilder();
 		if (parameters != null) {
 			sb.append("(");
-			for (Class<?> parameter : parameters) {
+			for (Class< ? > parameter : parameters) {
 				sb.append(getDescriptor(parameter));
 			}
 			sb.append(")");
@@ -39,9 +38,9 @@ public class RuntimeSignatureBuilder {
 		return sb.toString();
 	}
 
-	public Scope add(Class<?> c) {
-		Scope local = add(root, getEnclosingScope(c), c.getModifiers(), c.getTypeParameters(),
-				Kind.CLASS, identity(c), c.getGenericSuperclass(), c.getGenericInterfaces(), null);
+	public Scope add(Class< ? > c) {
+		Scope local = add(root, getEnclosingScope(c), c.getModifiers(), c.getTypeParameters(), Kind.CLASS, identity(c),
+				c.getGenericSuperclass(), c.getGenericInterfaces(), null);
 
 		for (Field f : c.getDeclaredFields()) {
 			add(local, // declaring scope
@@ -56,7 +55,7 @@ public class RuntimeSignatureBuilder {
 			);
 		}
 
-		for (Constructor constr : c.getConstructors()) {
+		for (Constructor< ? > constr : c.getConstructors()) {
 			add(local, // class scope
 					local, // enclosing
 					constr.getModifiers(), // access modifiers
@@ -86,20 +85,20 @@ public class RuntimeSignatureBuilder {
 		return local;
 	}
 
-	private Scope getEnclosingScope(Class<?> c) {
+	private Scope getEnclosingScope(Class< ? > c) {
 		Method m = c.getEnclosingMethod();
 		if (m != null) {
 			Scope s = getGlobalScope(m.getDeclaringClass());
 			return s.getScope(identity(m));
 		}
-// TODO
-//		Constructor cnstr = c.getEnclosingConstructor();
-//		if (m != null) {
-//			Scope s = getGlobalScope(cnstr.getDeclaringClass());
-//			return s.getScope(identity(cnstr));
-//
-//		}
-		Class<?> enclosingClass = c.getEnclosingClass();
+		// TODO
+		// Constructor cnstr = c.getEnclosingConstructor();
+		// if (m != null) {
+		// Scope s = getGlobalScope(cnstr.getDeclaringClass());
+		// return s.getScope(identity(cnstr));
+		//
+		// }
+		Class< ? > enclosingClass = c.getEnclosingClass();
 		if (enclosingClass != null) {
 			return getGlobalScope(enclosingClass);
 		}
@@ -107,23 +106,22 @@ public class RuntimeSignatureBuilder {
 		return null;
 	}
 
-	private Scope getGlobalScope(Class<?> c) {
+	private Scope getGlobalScope(Class< ? > c) {
 		if (c == null)
 			return null;
 		String id = identity(c);
 		return root.getScope(id);
 	}
 
-	private Scope add(Scope declaring, Scope enclosing, int modifiers,
-			TypeVariable<?>[] typeVariables, Kind kind, String id, Type mainType,
-			Type[] parameterTypes, Type exceptionTypes[]) {
+	private Scope add(Scope declaring, Scope enclosing, int modifiers, TypeVariable< ? >[] typeVariables, Kind kind,
+			String id, Type mainType, Type[] parameterTypes, Type exceptionTypes[]) {
 
 		Scope scope = declaring.getScope(id);
 		assert scope.access == Access.UNKNOWN;
 		scope.setAccess(Access.modifier(modifiers));
 		scope.setKind(kind);
 		scope.setGenericParameter(convert(typeVariables));
-		scope.setBase(convert(scope,mainType));
+		scope.setBase(convert(scope, mainType));
 		scope.setParameterTypes(convert(parameterTypes));
 		scope.setExceptionTypes(convert(exceptionTypes));
 		scope.setDeclaring(declaring);
@@ -135,32 +133,32 @@ public class RuntimeSignatureBuilder {
 		if (t instanceof ParameterizedType) {
 			// C<P..>
 			ParameterizedType pt = (ParameterizedType) t;
-			/*Scope reference =*/ root.getScope(identity((Class<?>)pt.getRawType()));			
+			/* Scope reference = */root.getScope(identity((Class< ? >) pt.getRawType()));
 			Type args[] = pt.getActualTypeArguments();
 			GenericType[] arguments = new GenericType[args.length];
 			int n = 0;
 			for (Type arg : args)
-				arguments[n++] = convert(source,arg);
-//			return new GenericType(reference,null,arguments);
-			
+				arguments[n++] = convert(source, arg);
+			// return new GenericType(reference,null,arguments);
+
 		} else if (t instanceof TypeVariable) {
-//			TypeVariable tv = (TypeVariable) t;
-//			return new GenericType(source,tv.getName(), null);
+			// TypeVariable tv = (TypeVariable) t;
+			// return new GenericType(source,tv.getName(), null);
 		} else if (t instanceof WildcardType) {
-//			WildcardType wc = (WildcardType) t;
-//			wc.
+			// WildcardType wc = (WildcardType) t;
+			// wc.
 		} else if (t instanceof GenericArrayType) {
 
 		}
-		if (t instanceof Class<?>) {
-//			raw = ((Class<?>) t).getName() + ";";
+		if (t instanceof Class< ? >) {
+			// raw = ((Class<?>) t).getName() + ";";
 		} else
 			throw new IllegalArgumentException(t.toString());
 
 		return null;
 	}
 
-	private GenericParameter[] convert(TypeVariable vars[]) {
+	private GenericParameter[] convert(TypeVariable< ? > vars[]) {
 		if (vars == null)
 			return null;
 
@@ -178,12 +176,12 @@ public class RuntimeSignatureBuilder {
 
 		GenericType tss[] = new GenericType[parameterTypes.length];
 		for (int i = 0; i < parameterTypes.length; i++) {
-			//tss[i] = new GenericType(parameterTypes[i]);
+			// tss[i] = new GenericType(parameterTypes[i]);
 		}
 		return tss;
 	}
 
-	private static String getDescriptor(Class<?> c) {
+	private static String getDescriptor(Class< ? > c) {
 		StringBuilder sb = new StringBuilder();
 		if (c.isPrimitive()) {
 			if (c == boolean.class)
diff --git a/biz.aQute.bndlib/src/aQute/bnd/compatibility/Scope.java b/biz.aQute.bndlib/src/aQute/bnd/compatibility/Scope.java
index 218a31c..c44f3bf 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/compatibility/Scope.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/compatibility/Scope.java
@@ -4,20 +4,20 @@ import java.io.*;
 import java.util.*;
 
 public class Scope {
-	final Map<String, Scope>	children	= new LinkedHashMap<String, Scope>();
+	final Map<String,Scope>	children	= new LinkedHashMap<String,Scope>();
 
 	// class: slashed name
 	// field: name ":" typed
 	// constructor: ":(" typed* ")" typed
 	// method: name ":(" typed* ")" typed
-	final String				name;
+	final String			name;
 
-	Access						access;
-	Kind						kind;
-	Scope						enclosing;
-	Scope						declaring;
-	GenericParameter						typeVars[];
-	Map<String, String[]>		name2bounds;
+	Access					access;
+	Kind					kind;
+	Scope					enclosing;
+	Scope					declaring;
+	GenericParameter		typeVars[];
+	Map<String,String[]>	name2bounds;
 
 	// class: super
 	// field: type
@@ -28,11 +28,11 @@ public class Scope {
 	// class: interfaces
 	// constructor: args
 	// method: args
-	GenericType[]				parameters;
+	GenericType[]			parameters;
 
 	// constructor: exceptions
 	// method: exceptions
-	GenericType[]				exceptions;
+	GenericType[]			exceptions;
 
 	// class: super interfaces*
 	// field: type
@@ -68,12 +68,13 @@ public class Scope {
 		base = typeSignature;
 	}
 
+	@Override
 	public String toString() {
 		StringBuilder sb = new StringBuilder();
-		
-		if ( typeVars != null && typeVars.length !=0) {
+
+		if (typeVars != null && typeVars.length != 0) {
 			sb.append("<");
-			for ( GenericParameter v : typeVars) {
+			for (GenericParameter v : typeVars) {
 				sb.append(v);
 			}
 			sb.append(">");
@@ -81,8 +82,8 @@ public class Scope {
 		sb.append(access.toString());
 		sb.append(" ");
 		sb.append(kind.toString());
-		sb.append( " ");
-		sb.append( name );
+		sb.append(" ");
+		sb.append(name);
 		return sb.toString();
 	}
 
@@ -123,8 +124,8 @@ public class Scope {
 		this.kind = kind;
 	}
 
-	static public String classIdentity(String name) {
-		return name.replace('.', '/');
+	static public String classIdentity(String name2) {
+		return name2.replace('.', '/');
 	}
 
 	static public String methodIdentity(String name, String descriptor) {
@@ -140,18 +141,18 @@ public class Scope {
 	}
 
 	public void cleanRoot() {
-		Iterator<Map.Entry<String, Scope>> i = children.entrySet().iterator();
+		Iterator<Map.Entry<String,Scope>> i = children.entrySet().iterator();
 		while (i.hasNext()) {
-			Map.Entry<String, Scope> entry = i.next();
+			Map.Entry<String,Scope> entry = i.next();
 			if (!entry.getValue().isTop())
 				i.remove();
 		}
 	}
 
 	public void prune(EnumSet<Access> level) {
-		Iterator<Map.Entry<String, Scope>> i = children.entrySet().iterator();
+		Iterator<Map.Entry<String,Scope>> i = children.entrySet().iterator();
 		while (i.hasNext()) {
-			Map.Entry<String, Scope> entry = i.next();
+			Map.Entry<String,Scope> entry = i.next();
 			if (!level.contains(entry.getValue().access))
 				i.remove();
 			else
diff --git a/biz.aQute.bndlib/src/aQute/bnd/compatibility/SignatureGenerator.java b/biz.aQute.bndlib/src/aQute/bnd/compatibility/SignatureGenerator.java
deleted file mode 100644
index 25177df..0000000
--- a/biz.aQute.bndlib/src/aQute/bnd/compatibility/SignatureGenerator.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package aQute.bnd.compatibility;
-
-
-public class SignatureGenerator {
-//	enum ACCESS {
-////		PUBLIC("+"), PROTECTED("|"), PACKAGE_PRIVATE(""), PRIVATE("-");
-////		final String	repr;
-////
-////		ACCESS(String s) {
-////			repr = s;
-////		}
-////		
-////		public String toString() {
-////			return repr;
-////		}
-//	}
-//
-//	public static void main(String args[]) throws Exception {
-//		final PrintStream out = System.out;
-//
-//		Clazz c = new Clazz("x", new FileResource(new File(
-//				"src/aQute/bnd/compatibility/SignatureGenerator.class")));
-//		c.parseClassFileWithCollector(new ClassDataCollector() {
-//			public void classBegin(int access, String name) {
-//				out.print(name);
-//				out.println(access(access));
-//			}
-//
-//			private ACCESS access(int access) {
-//				if (Modifier.isPublic(access))
-//					return ACCESS.PUBLIC;
-//
-//				throw new IllegalArgumentException();
-//			}
-//
-//			public void extendsClass(String name) {
-//			}
-//
-//			public void implementsInterfaces(String name[]) {
-//			}
-//
-//			public void addReference(String token) {
-//			}
-//
-//			public void annotation(Annotation annotation) {
-//			}
-//
-//			public void parameter(int p) {
-//			}
-//
-//			public void method(Clazz.MethodDef defined) {
-//				if (defined.isConstructor())
-//					constructor(defined.access, defined.descriptor);
-//				else
-//					method(defined.access, defined.name, defined.descriptor);
-//			}
-//
-//			public void field(Clazz.FieldDef defined) {
-//				field(defined.access, defined.name, defined.descriptor);
-//			}
-//
-//			public void reference(Clazz.MethodDef referenced) {
-//			}
-//
-//			public void reference(Clazz.FieldDef referenced) {
-//			}
-//
-//			public void classEnd() {
-//			}
-//
-//			@Deprecated// Will really be removed!
-//			public void field(int access, String name, String descriptor) {
-//			}
-//
-//			@Deprecated// Will really be removed!
-//			public void constructor(int access, String descriptor) {
-//			}
-//
-//			@Deprecated// Will really be removed!
-//			public void method(int access, String name, String descriptor) {
-//			}
-//
-//			/**
-//			 * The EnclosingMethod attribute
-//			 * 
-//			 * @param cName
-//			 *            The name of the enclosing class, never null. Name is
-//			 *            with slashes.
-//			 * @param mName
-//			 *            The name of the enclosing method in the class with
-//			 *            cName or null
-//			 * @param mDescriptor
-//			 *            The descriptor of this type
-//			 */
-//			public void enclosingMethod(String cName, String mName, String mDescriptor) {
-//
-//			}
-//
-//			/**
-//			 * The InnerClass attribute
-//			 * 
-//			 * @param innerClass
-//			 *            The name of the inner class (with slashes). Can be
-//			 *            null.
-//			 * @param outerClass
-//			 *            The name of the outer class (with slashes) Can be
-//			 *            null.
-//			 * @param innerName
-//			 *            The name inside the outer class, can be null.
-//			 * @param modifiers
-//			 *            The access flags
-//			 */
-//			public void innerClass(String innerClass, String outerClass, String innerName,
-//					int innerClassAccessFlags) {
-//			}
-//
-//			public void signature(String signature) {
-//			}
-//
-//			public void constant(Object object) {
-//			}
-//
-//		});
-//	}
-}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/compatibility/Signatures.java b/biz.aQute.bndlib/src/aQute/bnd/compatibility/Signatures.java
index 2dd0e61..9c894ea 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/compatibility/Signatures.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/compatibility/Signatures.java
@@ -1,19 +1,3 @@
-/*
- * Copyright (c) OSGi Alliance (2009, 2010). All Rights Reserved.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
 package aQute.bnd.compatibility;
 
 import java.lang.reflect.*;
@@ -26,33 +10,30 @@ import java.util.*;
  * signatures can be string compared and match even if the type variable names
  * differ.
  * 
- * @version $Id: ec4a5450ad339ea13acb8e684c6db9c154a33662 $
+ * @version $Id: 70abede2d1c976d3e6209b6bc04a94a4ac558faa $
  */
 public class Signatures {
-	
-	
+
 	/**
-	 * Check if the environment has generics, i.e. later than 
-	 * Java 5 VM.
+	 * Check if the environment has generics, i.e. later than Java 5 VM.
 	 * 
 	 * @return true if generics are supported
 	 * @throws Exception
 	 */
 	public boolean hasGenerics() throws Exception {
 		try {
-			call( Signatures.class, "getGenericSuperClass");
+			call(Signatures.class, "getGenericSuperClass");
 			return true;
-		} catch( NoSuchMethodException mnfe ) {
+		}
+		catch (NoSuchMethodException mnfe) {
 			return false;
 		}
 	}
-	
-	
-	
+
 	/**
 	 * Helper class to track an index in a string.
 	 */
-	class Rover {
+	static class Rover {
 		final String	s;
 		int				i;
 
@@ -72,8 +53,7 @@ public class Signatures {
 		char take(char c) {
 			char x = s.charAt(i++);
 			if (c != x)
-				throw new IllegalStateException("get() expected " + c
-						+ " but got + " + x);
+				throw new IllegalStateException("get() expected " + c + " but got + " + x);
 			return x;
 		}
 
@@ -92,20 +72,21 @@ public class Signatures {
 
 	/**
 	 * Calculate the generic signature of a Class,Method,Field, or Constructor.
+	 * 
 	 * @param f
 	 * @return
-	 * @throws Exception 
+	 * @throws Exception
 	 */
 	public String getSignature(Object c) throws Exception {
-		if( c instanceof Class<?>)
-			return getSignature((Class<?>)c);
-		if( c instanceof Constructor<?>)
-			return getSignature((Constructor<?>)c);
-		if( c instanceof Method)
-			return getSignature((Method)c);
-		if( c instanceof Field)
-			return getSignature((Field)c);
-		
+		if (c instanceof Class< ? >)
+			return getSignature((Class< ? >) c);
+		if (c instanceof Constructor< ? >)
+			return getSignature((Constructor< ? >) c);
+		if (c instanceof Method)
+			return getSignature((Method) c);
+		if (c instanceof Field)
+			return getSignature((Field) c);
+
 		throw new IllegalArgumentException(c.toString());
 	}
 
@@ -116,16 +97,15 @@ public class Signatures {
 	 * 	  class        ::= declaration? reference reference*
 	 * </pre>
 	 * 
-	 * 
 	 * @param f
 	 * @return
-	 * @throws Exception 
+	 * @throws Exception
 	 */
 	public String getSignature(Class< ? > c) throws Exception {
-		StringBuffer sb = new StringBuffer();
+		StringBuilder sb = new StringBuilder();
 		declaration(sb, c);
 		reference(sb, call(c, "getGenericSuperclass"));
-		for (Object type : (Object[]) call(c,"getGenericInterfaces")) {
+		for (Object type : (Object[]) call(c, "getGenericInterfaces")) {
 			reference(sb, type);
 		}
 		return sb.toString();
@@ -140,17 +120,17 @@ public class Signatures {
 	 * 
 	 * @param c
 	 * @return
-	 * @throws Exception 
+	 * @throws Exception
 	 */
 	public String getSignature(Method m) throws Exception {
-		StringBuffer sb = new StringBuffer();
+		StringBuilder sb = new StringBuilder();
 		declaration(sb, m);
 		sb.append('(');
-		for (Object type : (Object[]) call(m,"getGenericParameterTypes")) {
+		for (Object type : (Object[]) call(m, "getGenericParameterTypes")) {
 			reference(sb, type);
 		}
 		sb.append(')');
-		reference(sb, call(m,"getGenericReturnType"));
+		reference(sb, call(m, "getGenericReturnType"));
 		return sb.toString();
 	}
 
@@ -164,13 +144,13 @@ public class Signatures {
 	 * 
 	 * @param c
 	 * @return
-	 * @throws Exception 
+	 * @throws Exception
 	 */
 	public String getSignature(Constructor< ? > c) throws Exception {
-		StringBuffer sb = new StringBuffer();
+		StringBuilder sb = new StringBuilder();
 		declaration(sb, c);
 		sb.append('(');
-		for (Object type : (Object[]) call(c,"getGenericParameterTypes")) {
+		for (Object type : (Object[]) call(c, "getGenericParameterTypes")) {
 			reference(sb, type);
 		}
 		sb.append(')');
@@ -187,11 +167,11 @@ public class Signatures {
 	 * 
 	 * @param c
 	 * @return
-	 * @throws Exception 
+	 * @throws Exception
 	 */
 	public String getSignature(Field f) throws Exception {
-		StringBuffer sb = new StringBuffer();
-		Object t = call(f,"getGenericType");
+		StringBuilder sb = new StringBuilder();
+		Object t = call(f, "getGenericType");
 		reference(sb, t);
 		return sb.toString();
 	}
@@ -214,14 +194,14 @@ public class Signatures {
 	 * @param gd
  * @throws Exception 
 	 */
-	private void declaration(StringBuffer sb, Object gd) throws Exception {
-		Object[] typeParameters = (Object[]) call(gd,"getTypeParameters");
+	private void declaration(StringBuilder sb, Object gd) throws Exception {
+		Object[] typeParameters = (Object[]) call(gd, "getTypeParameters");
 		if (typeParameters.length > 0) {
 			sb.append('<');
 			for (Object tv : typeParameters) {
-				sb.append( call(tv,"getName"));
+				sb.append(call(tv, "getName"));
 
-				Object[] bounds = (Object[]) call(tv,"getBounds");
+				Object[] bounds = (Object[]) call(tv, "getBounds");
 				if (bounds.length > 0 && isInterface(bounds[0])) {
 					sb.append(':');
 				}
@@ -237,22 +217,22 @@ public class Signatures {
 	/**
 	 * Verify that the type is an interface.
 	 * 
-	 * @param type the type to check.
+	 * @param type
+	 *            the type to check.
 	 * @return true if this is a class that is an interface or a Parameterized
 	 *         Type that is an interface
-	 * @throws Exception 
+	 * @throws Exception
 	 */
 	private boolean isInterface(Object type) throws Exception {
 		if (type instanceof Class)
 			return (((Class< ? >) type).isInterface());
 
-		if ( isInstance(type.getClass(), "java.lang.reflect.ParameterizedType"))
-			return isInterface(call(type,"getRawType"));
+		if (isInstance(type.getClass(), "java.lang.reflect.ParameterizedType"))
+			return isInterface(call(type, "getRawType"));
 
 		return false;
 	}
 
-
 /**
 	 * This is the heart of the signature builder. A reference is used
 	 * in a lot of places. It referes to another type.
@@ -269,82 +249,67 @@ public class Signatures {
 	 * @param t
  * @throws Exception 
 	 */
-	private void reference(StringBuffer sb, Object t) throws Exception {
+	private void reference(StringBuilder sb, Object t) throws Exception {
 
-		if ( isInstance(t.getClass(),"java.lang.reflect.ParameterizedType")) {
+		if (isInstance(t.getClass(), "java.lang.reflect.ParameterizedType")) {
 			sb.append('L');
 			parameterizedType(sb, t);
 			sb.append(';');
 			return;
-		}
-		else
-			if ( isInstance(t.getClass(), "java.lang.reflect.GenericArrayType")) {
-				sb.append('[');
-				reference(sb, call(t,"getGenericComponentType"));
-			}
-			else
-				if ( isInstance(t.getClass(), "java.lang.reflect.WildcardType")) {
-					Object[] lowerBounds = (Object[]) call(t, "getLowerBounds");
-					Object[] upperBounds = (Object[]) call(t, "getUpperBounds");
-
-					if (upperBounds.length == 1
-							&& upperBounds[0] == Object.class)
-						upperBounds = new Object[0];
-
-					if (upperBounds.length != 0) {
-						// extend
-						for (Object upper : upperBounds) {
-							sb.append('+');
-							reference(sb, upper);
-						}
-					}
-					else
-						if (lowerBounds.length != 0) {
-							// super, can only be one by the language
-							for (Object lower : lowerBounds) {
-								sb.append('-');
-								reference(sb, lower);
-							}
-						}
-						else
-							sb.append('*');
+		} else if (isInstance(t.getClass(), "java.lang.reflect.GenericArrayType")) {
+			sb.append('[');
+			reference(sb, call(t, "getGenericComponentType"));
+		} else if (isInstance(t.getClass(), "java.lang.reflect.WildcardType")) {
+			Object[] lowerBounds = (Object[]) call(t, "getLowerBounds");
+			Object[] upperBounds = (Object[]) call(t, "getUpperBounds");
+
+			if (upperBounds.length == 1 && upperBounds[0] == Object.class)
+				upperBounds = new Object[0];
+
+			if (upperBounds.length != 0) {
+				// extend
+				for (Object upper : upperBounds) {
+					sb.append('+');
+					reference(sb, upper);
 				}
-				else
-					if ( isInstance(t.getClass(),"java.lang.reflect.TypeVariable")) {
-						sb.append('T');
-						sb.append( call(t,"getName"));
-						sb.append(';');
-					}
-					else
-						if (t instanceof Class< ? >) {
-							Class< ? > c = (Class< ? >) t;
-							if (c.isPrimitive()) {
-								sb.append(primitive(c));
-							}
-							else {
-								sb.append('L');
-								String name = c.getName().replace('.', '/');
-								sb.append(name);
-								sb.append(';');
-							}
-						}
+			} else if (lowerBounds.length != 0) {
+				// super, can only be one by the language
+				for (Object lower : lowerBounds) {
+					sb.append('-');
+					reference(sb, lower);
+				}
+			} else
+				sb.append('*');
+		} else if (isInstance(t.getClass(), "java.lang.reflect.TypeVariable")) {
+			sb.append('T');
+			sb.append(call(t, "getName"));
+			sb.append(';');
+		} else if (t instanceof Class< ? >) {
+			Class< ? > c = (Class< ? >) t;
+			if (c.isPrimitive()) {
+				sb.append(primitive(c));
+			} else {
+				sb.append('L');
+				String name = c.getName().replace('.', '/');
+				sb.append(name);
+				sb.append(';');
+			}
+		}
 	}
 
 	/**
-	 * Creates the signature for a Parameterized Type.
-	 * 
-	 * A Parameterized Type has a raw class and a set of type variables.
+	 * Creates the signature for a Parameterized Type. A Parameterized Type has
+	 * a raw class and a set of type variables.
 	 * 
 	 * @param sb
 	 * @param pt
-	 * @throws Exception 
+	 * @throws Exception
 	 */
-	private void parameterizedType(StringBuffer sb, Object pt) throws Exception {
-		Object owner = call(pt,"getOwnerType");
-		String name = ((Class< ? >) call(pt,"getRawType")).getName()
-				.replace('.', '/');
+	private void parameterizedType(StringBuilder sb, Object pt) throws Exception {
+		Object owner = call(pt, "getOwnerType");
+		String name = ((Class< ? >) call(pt, "getRawType")).getName().replace('.', '/');
 		if (owner != null) {
-			if ( isInstance(owner.getClass(), "java.lang.reflect.ParameterizedType"))
+			if (isInstance(owner.getClass(), "java.lang.reflect.ParameterizedType"))
 				parameterizedType(sb, owner);
 			else
 				sb.append(((Class< ? >) owner).getName().replace('.', '/'));
@@ -355,7 +320,7 @@ public class Signatures {
 		sb.append(name);
 
 		sb.append('<');
-		for (Object parameterType : (Object[]) call(pt,"getActualTypeArguments")) {
+		for (Object parameterType : (Object[]) call(pt, "getActualTypeArguments")) {
 			reference(sb, parameterType);
 		}
 		sb.append('>');
@@ -365,40 +330,31 @@ public class Signatures {
 	/**
 	 * Handle primitives, these need to be translated to a single char.
 	 * 
-	 * @param type the primitive class
+	 * @param type
+	 *            the primitive class
 	 * @return the single char associated with the primitive
 	 */
 	private char primitive(Class< ? > type) {
 		if (type == byte.class)
 			return 'B';
+		else if (type == char.class)
+			return 'C';
+		else if (type == double.class)
+			return 'D';
+		else if (type == float.class)
+			return 'F';
+		else if (type == int.class)
+			return 'I';
+		else if (type == long.class)
+			return 'J';
+		else if (type == short.class)
+			return 'S';
+		else if (type == boolean.class)
+			return 'Z';
+		else if (type == void.class)
+			return 'V';
 		else
-			if (type == char.class)
-				return 'C';
-			else
-				if (type == double.class)
-					return 'D';
-				else
-					if (type == float.class)
-						return 'F';
-					else
-						if (type == int.class)
-							return 'I';
-						else
-							if (type == long.class)
-								return 'J';
-							else
-								if (type == short.class)
-									return 'S';
-								else
-									if (type == boolean.class)
-										return 'Z';
-									else
-										if (type == void.class)
-											return 'V';
-										else
-											throw new IllegalArgumentException(
-													"Unknown primitive type "
-															+ type);
+			throw new IllegalArgumentException("Unknown primitive type " + type);
 	}
 
 	/**
@@ -411,8 +367,8 @@ public class Signatures {
 	 */
 
 	public String normalize(String signature) {
-		StringBuffer sb = new StringBuffer();
-		Map<String, String> map = new HashMap<String, String>();
+		StringBuilder sb = new StringBuilder();
+		Map<String,String> map = new HashMap<String,String>();
 		Rover rover = new Rover(signature);
 		declare(sb, map, rover);
 
@@ -424,8 +380,7 @@ public class Signatures {
 			}
 			sb.append(rover.take(')'));
 			reference(sb, map, rover, true); // return type
-		}
-		else {
+		} else {
 			// field or class
 			reference(sb, map, rover, true); // field type or super class
 			while (!rover.isEOF()) {
@@ -436,58 +391,51 @@ public class Signatures {
 	}
 
 	/**
-	 * The heart of the routine. Handle a reference to a type. Can be
-	 * an array, a class, a type variable, or a primitive.
+	 * The heart of the routine. Handle a reference to a type. Can be an array,
+	 * a class, a type variable, or a primitive.
 	 * 
 	 * @param sb
 	 * @param map
 	 * @param rover
 	 * @param primitivesAllowed
 	 */
-	private void reference(StringBuffer sb, Map<String, String> map,
-			Rover rover, boolean primitivesAllowed) {
+	private void reference(StringBuilder sb, Map<String,String> map, Rover rover, boolean primitivesAllowed) {
 
 		char type = rover.take();
 		sb.append(type);
 
 		if (type == '[') {
 			reference(sb, map, rover, true);
-		}
-		else
-			if (type == 'L') {
-				String fqnb = rover.upTo("<;.");
-				sb.append(fqnb);
+		} else if (type == 'L') {
+			String fqnb = rover.upTo("<;.");
+			sb.append(fqnb);
+			body(sb, map, rover);
+			while (rover.peek() == '.') {
+				sb.append(rover.take('.'));
+				sb.append(rover.upTo("<;."));
 				body(sb, map, rover);
-				while (rover.peek() == '.') {
-					sb.append(rover.take('.'));
-					sb.append(rover.upTo("<;."));
-					body(sb, map, rover);
-				}
-				sb.append(rover.take(';'));
 			}
-			else
-				if (type == 'T') {
-					String name = rover.upTo(";");
-					name = assign(map, name);
-					sb.append(name);
-					sb.append(rover.take(';'));
-				}
-				else {
-					if (!primitivesAllowed)
-						throw new IllegalStateException(
-								"Primitives are not allowed without an array");
-				}
+			sb.append(rover.take(';'));
+		} else if (type == 'T') {
+			String name = rover.upTo(";");
+			name = assign(map, name);
+			sb.append(name);
+			sb.append(rover.take(';'));
+		} else {
+			if (!primitivesAllowed)
+				throw new IllegalStateException("Primitives are not allowed without an array");
+		}
 	}
 
 	/**
-	 * Because classes can be nested the body handles the part that can 
-	 * be nested, the reference handles the enclosing L ... ;
+	 * Because classes can be nested the body handles the part that can be
+	 * nested, the reference handles the enclosing L ... ;
 	 * 
 	 * @param sb
 	 * @param map
 	 * @param rover
 	 */
-	private void body(StringBuffer sb, Map<String, String> map, Rover rover) {
+	private void body(StringBuilder sb, Map<String,String> map, Rover rover) {
 		if (rover.peek() == '<') {
 			sb.append(rover.take('<'));
 			while (rover.peek() != '>') {
@@ -528,7 +476,7 @@ public class Signatures {
 	 * @param map
 	 * @param rover
 	 */
-	private void declare(StringBuffer sb, Map<String, String> map, Rover rover) {
+	private void declare(StringBuilder sb, Map<String,String> map, Rover rover) {
 		char c = rover.peek();
 		if (c == '<') {
 			sb.append(rover.take('<'));
@@ -554,40 +502,40 @@ public class Signatures {
 	}
 
 	/**
-	 * Handles the assignment of type variables to index names so that
-	 * we have a normalized name for each type var.
+	 * Handles the assignment of type variables to index names so that we have a
+	 * normalized name for each type var.
 	 * 
-	 * @param map the map with variables.
-	 * @param name The name of the variable
+	 * @param map
+	 *            the map with variables.
+	 * @param name
+	 *            The name of the variable
 	 * @return the index name, like _1
 	 */
-	private String assign(Map<String, String> map, String name) {
+	private String assign(Map<String,String> map, String name) {
 		if (map.containsKey(name))
 			return map.get(name);
-		else {
-			int n = map.size();
-			map.put(name, "_" + n);
-			return "_" + n;
-		}
+		int n = map.size();
+		map.put(name, "_" + n);
+		return "_" + n;
 	}
 
-	private boolean isInstance(Class<?> type, String string) {
-		if ( type == null)
+	private boolean isInstance(Class< ? > type, String string) {
+		if (type == null)
 			return false;
-		
-		if ( type.getName().equals(string))
+
+		if (type.getName().equals(string))
 			return true;
-		
-		if ( isInstance( type.getSuperclass(), string))
+
+		if (isInstance(type.getSuperclass(), string))
 			return true;
-		
-		for ( Class<?> intf : type.getInterfaces()) {
-			if ( isInstance(intf,string))
+
+		for (Class< ? > intf : type.getInterfaces()) {
+			if (isInstance(intf, string))
 				return true;
 		}
 		return false;
 	}
-	
+
 	private Object call(Object gd, String string) throws Exception {
 		Method m = gd.getClass().getMethod(string);
 		return m.invoke(gd);
diff --git a/biz.aQute.bndlib/src/aQute/bnd/component/AnnotationReader.java b/biz.aQute.bndlib/src/aQute/bnd/component/AnnotationReader.java
index af927f4..21ba940 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/component/AnnotationReader.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/component/AnnotationReader.java
@@ -6,105 +6,128 @@ import java.util.regex.*;
 
 import org.osgi.service.component.annotations.*;
 
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Clazz.MethodDef;
+import aQute.bnd.osgi.Descriptors.TypeRef;
+import aQute.bnd.version.*;
 import aQute.lib.collections.*;
-import aQute.lib.osgi.*;
-import aQute.libg.version.*;
 
+/**
+ * fixup any unbind methods To declare no unbind method, the value "-" must be
+ * used. If not specified, the name of the unbind method is derived from the
+ * name of the annotated bind method. If the annotated method name begins with
+ * set, that is replaced with unset to derive the unbind method name. If the
+ * annotated method name begins with add, that is replaced with remove to derive
+ * the unbind method name. Otherwise, un is prefixed to the annotated method
+ * name to derive the unbind method name.
+ * 
+ * @return
+ * @throws Exception
+ */
 public class AnnotationReader extends ClassDataCollector {
-	final static String[]			EMPTY					= new String[0];
-	final static Pattern			PROPERTY_PATTERN		= Pattern
-																	.compile("([^=]+(:(Boolean|Byte|Char|Short|Integer|Long|Float|Double|String))?)\\s*=(.*)");
+	final static TypeRef[]		EMPTY					= new TypeRef[0];
+	final static Pattern		PROPERTY_PATTERN		= Pattern
+																.compile("\\s*([^=\\s:]+)\\s*(?::\\s*(Boolean|Byte|Character|Short|Integer|Long|Float|Double|String)\\s*)?=(.*)");
 
+	public static final Version	V1_0					= new Version("1.0.0");																												// "1.0.0"
 	public static final Version	V1_1					= new Version("1.1.0");																												// "1.1.0"
-	public static final Version	V1_2					= new Version("1.2.0");																												// "1.1.0"
-	static Pattern					BINDDESCRIPTOR			= Pattern
-																	.compile("\\(((L([^;]+);)(Ljava/util/Map;)?|Lorg/osgi/framework/ServiceReference;)\\)V");
-	static Pattern					BINDMETHOD				= Pattern
-																	.compile("(set|bind|add)?(.*)");
-
-	static Pattern					ACTIVATEDESCRIPTOR		= Pattern
-																	.compile("\\(((Lorg/osgi/service/component/ComponentContext;)|(Lorg/osgi/framework/BundleContext;)|(Ljava/util/Map;))*\\)V");
-	static Pattern					REFERENCEBINDDESCRIPTOR	= Pattern
-																	.compile("\\(Lorg/osgi/framework/ServiceReference;\\)V");
-
-	ComponentDef					component				= new ComponentDef();
-
-	Clazz							clazz;
-	String							interfaces[];
-	String							methodDescriptor;
-	String							method;
-	String							className;
-	int								methodAccess;
-	Analyzer						analyzer;
-	MultiMap<String, String>		methods					= new MultiMap<String, String>();
-	String							extendsClass;
-
-	AnnotationReader(Analyzer analyzer, Clazz clazz) {
+	public static final Version	V1_2					= new Version("1.2.0");																												// "1.2.0"
+//	public static final Version	V1_3					= new Version("1.3.0");																												// "1.3.0"
+
+	public static final String FELIX_1_2				= "http://felix.apache.org/xmlns/scr/v1.2.0-felix";
+	
+	static Pattern				BINDNAME				= Pattern.compile("(set|add|bind)?(.*)");
+	
+	static Pattern				BINDDESCRIPTORDS10			= Pattern
+																.compile("\\(((L([^;]+);)|Lorg/osgi/framework/ServiceReference;)\\)V");
+	static Pattern				BINDDESCRIPTORDS11			= Pattern
+																.compile("\\(((L([^;]+);)(Ljava/util/Map;)?|Lorg/osgi/framework/ServiceReference;)\\)V");
+	static Pattern				BINDDESCRIPTORDS13			= Pattern
+																.compile("\\(((L([^;]+);)(Ljava/util/Map;)?|Lorg/osgi/framework/ServiceReference;)\\)Ljava/util/Map;");
+	static Pattern				REFERENCEBINDDESCRIPTOR		= Pattern
+																.compile("\\(Lorg/osgi/framework/ServiceReference;\\)V");
+
+	static Pattern				LIFECYCLEDESCRIPTORDS10		= Pattern
+																.compile("\\((Lorg/osgi/service/component/ComponentContext;)\\)V");
+	static Pattern				LIFECYCLEDESCRIPTORDS11		= Pattern
+																.compile("\\(((Lorg/osgi/service/component/ComponentContext;)|(Lorg/osgi/framework/BundleContext;)|(Ljava/util/Map;))*\\)V");
+	static Pattern				LIFECYCLEDESCRIPTORDS13		= Pattern
+																.compile("\\(((Lorg/osgi/service/component/ComponentContext;)|(Lorg/osgi/framework/BundleContext;)|(Ljava/util/Map;))*\\)Ljava/util/Map;");
+	static Pattern				DEACTIVATEDESCRIPTORDS11	= Pattern
+																.compile("\\(((Lorg/osgi/service/component/ComponentContext;)|(Lorg/osgi/framework/BundleContext;)|(Ljava/util/Map;)|(Ljava/lang/Integer;)|(I))*\\)V");
+	static Pattern				DEACTIVATEDESCRIPTORDS13	= Pattern
+																.compile("\\(((Lorg/osgi/service/component/ComponentContext;)|(Lorg/osgi/framework/BundleContext;)|(Ljava/util/Map;)|(Ljava/lang/Integer;)|(I))*\\)Ljava/util/Map;");
+
+	ComponentDef				component				= new ComponentDef();
+
+	Clazz						clazz;
+	TypeRef						interfaces[];
+	MethodDef					method;
+	TypeRef						className;
+	Analyzer					analyzer;
+	MultiMap<String,String>		methods					= new MultiMap<String,String>();
+	TypeRef						extendsClass;
+	final boolean						inherit;
+	boolean						baseclass				= true;
+	
+	final boolean						felixExtensions;
+
+	AnnotationReader(Analyzer analyzer, Clazz clazz, boolean inherit, boolean felixExtensions) {
 		this.analyzer = analyzer;
 		this.clazz = clazz;
+		this.inherit = inherit;
+		this.felixExtensions = felixExtensions;
 	}
 
 	public static ComponentDef getDefinition(Clazz c, Analyzer analyzer) throws Exception {
-		AnnotationReader r = new AnnotationReader(analyzer, c);
-
-		return r.getDef(c, analyzer);
+		boolean inherit = Processor.isTrue(analyzer.getProperty("-dsannotations-inherit"));
+		boolean felixExtensions = Processor.isTrue(analyzer.getProperty("-ds-felix-extensions"));
+		AnnotationReader r = new AnnotationReader(analyzer, c, inherit, felixExtensions);
+		return r.getDef();
 	}
 
-	/**
-	 * fixup any unbind methods To declare no unbind method, the value "-" must
-	 * be used. If not specified, the name of the unbind method is derived from
-	 * the name of the annotated bind method. If the annotated method name
-	 * begins with set, that is replaced with unset to derive the unbind method
-	 * name. If the annotated method name begins with add, that is replaced with
-	 * remove to derive the unbind method name. Otherwise, un is prefixed to the
-	 * annotated method name to derive the unbind method name.
-	 * 
-	 * @return
-	 * @throws Exception
-	 */
-	private ComponentDef getDef(Clazz c, Analyzer analyzer) throws Exception {
-		c.parseClassFileWithCollector(this);
+	private ComponentDef getDef() throws Exception {
+		clazz.parseClassFileWithCollector(this);
 		if (component.implementation == null)
 			return null;
 
-		while (extendsClass != null) {
-			if (extendsClass.startsWith("java/"))
-				break;
+		if (inherit) {
+			baseclass = false;
+			while (extendsClass != null) {
+				if (extendsClass.isJava())
+					break;
 
-			Clazz ec = analyzer.findClass(extendsClass);
-			if (ec == null) {
-				analyzer.error("Missing super class for DS annotations: "
-						+ Clazz.pathToFqn(extendsClass) + " from " + c.getFQN());
-			} else {
-				c.parseClassFileWithCollector(this);
+				Clazz ec = analyzer.findClass(extendsClass);
+				if (ec == null) {
+					analyzer.error("Missing super class for DS annotations: " + extendsClass + " from "
+							+ clazz.getClassName());
+				} else {
+					ec.parseClassFileWithCollector(this);
+				}
 			}
 		}
-
-		if (component.implementation != null) {
-			for (ReferenceDef rdef : component.references.values()) {
-				rdef.unbind = referredMethod(analyzer, rdef, rdef.unbind, "add(.*)", "remove$1", "(.*)",
-						"un$1");
-				rdef.modified = referredMethod(analyzer, rdef, rdef.modified, "(add|set)(.*)", "modified$2",
-						"(.*)", "modified$1");
-			}
-			return component;
-		} else
-			return null;
+		for (ReferenceDef rdef : component.references.values()) {
+			rdef.unbind = referredMethod(analyzer, rdef, rdef.unbind, "add(.*)", "remove$1", "(.*)", "un$1");
+			rdef.updated = referredMethod(analyzer, rdef, rdef.updated, "(add|set|bind)(.*)", "updated$2", "(.*)",
+					"updated$1");
+			
+			if (rdef.policy == ReferencePolicy.DYNAMIC && rdef.unbind == null)
+				analyzer.error("In component %s, reference %s is dynamic but has no unbind method.", component.name, rdef.name);
+		}
+		return component;
 	}
 
 	/**
-	 * 
 	 * @param analyzer
 	 * @param rdef
 	 */
-	protected String referredMethod(Analyzer analyzer, ReferenceDef rdef, String value,
-			String... matches) {
+	protected String referredMethod(Analyzer analyzer, ReferenceDef rdef, String value, String... matches) {
 		if (value == null) {
 			String bind = rdef.bind;
 			for (int i = 0; i < matches.length; i += 2) {
 				Matcher m = Pattern.compile(matches[i]).matcher(bind);
 				if (m.matches()) {
-					value = m.replaceFirst(matches[i+1]);
+					value = m.replaceFirst(matches[i + 1]);
 					break;
 				}
 			}
@@ -113,28 +136,48 @@ public class AnnotationReader extends ClassDataCollector {
 
 		if (methods.containsKey(value)) {
 			for (String descriptor : methods.get(value)) {
-				Matcher matcher = BINDDESCRIPTOR.matcher(descriptor);
+				Matcher matcher = BINDDESCRIPTORDS10.matcher(descriptor);
 				if (matcher.matches()) {
 					String type = matcher.group(2);
-					if (rdef.interfce.equals(Clazz.objectDescriptorToFQN(type))
-							|| type.equals("Ljava/util/Map;")
+					if (rdef.service.equals(Clazz.objectDescriptorToFQN(type)) 
 							|| type.equals("Lorg/osgi/framework/ServiceReference;")) {
 
 						return value;
 					}
 				}
+				matcher = BINDDESCRIPTORDS11.matcher(descriptor);
+				if (matcher.matches()) {
+					String type = matcher.group(2);
+					if (rdef.service.equals(Clazz.objectDescriptorToFQN(type)) 
+							|| type.equals("Lorg/osgi/framework/ServiceReference;")) {
+						rdef.updateVersion(V1_1);
+						return value;
+					}
+				}
+				matcher = BINDDESCRIPTORDS13.matcher(descriptor);
+				if (felixExtensions && matcher.matches()) {
+					String type = matcher.group(2);
+					if (rdef.service.equals(Clazz.objectDescriptorToFQN(type)) 
+							|| type.equals("Lorg/osgi/framework/ServiceReference;")) {
+						rdef.updateVersion(V1_2);
+						if (component.xmlns == null) {
+							component.xmlns = FELIX_1_2;
+						}
+						return value;
+					}
+				}
 			}
 			analyzer.error(
 					"A related method to %s from the reference %s has no proper prototype for class %s. Expected void %s(%s s [,Map m] | ServiceReference r)",
-					rdef.bind, value, component.implementation, value, rdef.interfce);
+					rdef.bind, value, component.implementation, value, rdef.service);
 		}
 		return null;
 	}
 
+	@Override
 	public void annotation(Annotation annotation) {
 		try {
 			java.lang.annotation.Annotation a = annotation.getAnnotation();
-
 			if (a instanceof Component)
 				doComponent((Component) a, annotation);
 			else if (a instanceof Activate)
@@ -145,8 +188,8 @@ public class AnnotationReader extends ClassDataCollector {
 				doModified();
 			else if (a instanceof Reference)
 				doReference((Reference) a, annotation);
-
-		} catch (Exception e) {
+		}
+		catch (Exception e) {
 			e.printStackTrace();
 			analyzer.error("During generation of a component on class %s, exception %s", clazz, e);
 		}
@@ -155,28 +198,68 @@ public class AnnotationReader extends ClassDataCollector {
 	/**
 	 * 
 	 */
+	protected void doActivate() {
+		String methodDescriptor = method.getDescriptor().toString();
+		if ("activate".equals(method.getName()) && LIFECYCLEDESCRIPTORDS10.matcher(methodDescriptor).matches()) {
+			component.activate = method.getName();			
+		} else if (LIFECYCLEDESCRIPTORDS11.matcher(methodDescriptor).matches()) {
+			component.activate = method.getName();	
+			component.updateVersion(V1_1);
+		} else if (felixExtensions && LIFECYCLEDESCRIPTORDS13.matcher(methodDescriptor).matches()) {
+			component.activate = method.getName();	
+			component.updateVersion(V1_2);
+			if (component.xmlns == null) {
+				component.xmlns = FELIX_1_2;
+			}
+		} else 
+			analyzer.error(
+					"Activate method for %s does not have an acceptable prototype, only Map, ComponentContext, or BundleContext is allowed. Found: %s",
+					clazz, method.getDescriptor());
+		
+	}
+
+	/**
+	 * 
+	 */
 	protected void doDeactivate() {
-		if (!ACTIVATEDESCRIPTOR.matcher(methodDescriptor).matches())
+		String methodDescriptor = method.getDescriptor().toString();
+		if ( "deactivate".equals(method.getName()) && LIFECYCLEDESCRIPTORDS10.matcher(methodDescriptor).matches()) {
+			component.deactivate = method.getName();			
+		} else if (DEACTIVATEDESCRIPTORDS11.matcher(methodDescriptor).matches()) {
+			component.deactivate = method.getName();
+			component.updateVersion(V1_1);
+		} else if (felixExtensions && DEACTIVATEDESCRIPTORDS13.matcher(methodDescriptor).matches()) {
+			component.deactivate = method.getName();
+			component.updateVersion(V1_2);
+			if (component.xmlns == null) {
+				component.xmlns = FELIX_1_2;
+			}
+		} else
 			analyzer.error(
-					"Deactivate method for %s does not have an acceptable prototype, only Map, ComponentContext, or BundleContext is allowed. Found: %s",
-					clazz, methodDescriptor);
-		else {
-			component.deactivate = method;
-		}
+					"Deactivate method for %s does not have an acceptable prototype, only Map, ComponentContext, BundleContext, int, or Integer is allowed. Found: %s",
+					clazz, method.getDescriptor());
 	}
 
 	/**
 	 * 
 	 */
 	protected void doModified() {
-		if (!ACTIVATEDESCRIPTOR.matcher(methodDescriptor).matches())
+		if (LIFECYCLEDESCRIPTORDS11.matcher(method.getDescriptor().toString()).matches()) {
+			component.modified = method.getName();
+			component.updateVersion(V1_1);
+		} else if (felixExtensions && LIFECYCLEDESCRIPTORDS13.matcher(method.getDescriptor().toString()).matches()) {
+			component.modified = method.getName();
+			component.updateVersion(V1_2);
+			if (component.xmlns == null) {
+				component.xmlns = FELIX_1_2;
+			}
+		} else
+
 			analyzer.error(
 					"Modified method for %s does not have an acceptable prototype, only Map, ComponentContext, or BundleContext is allowed. Found: %s",
-					clazz, methodDescriptor);
-		else {
-			component.modified = method;
-		}
+					clazz, method.getDescriptor());
 	}
+
 	/**
 	 * @param annotation
 	 * @throws Exception
@@ -186,60 +269,61 @@ public class AnnotationReader extends ClassDataCollector {
 		def.name = reference.name();
 
 		if (def.name == null) {
-			Matcher m = BINDMETHOD.matcher(method);
-			if (m.matches()) {
+			Matcher m = BINDNAME.matcher(method.getName());
+			if (m.matches())
 				def.name = m.group(2);
-			} else {
-				def.name = method;
-			}
+			else
+				analyzer.error("Invalid name for bind method %s", method.getName());
 		}
 
 		def.unbind = reference.unbind();
-		def.bind = method;
+		def.updated = reference.updated();
+		def.bind = method.getName();
 
-		def.interfce = raw.get("service");
-		if (def.interfce != null) {
-			def.interfce = Clazz.objectDescriptorToFQN(def.interfce);
+		def.service = raw.get("service");
+		if (def.service != null) {
+			def.service = Clazz.objectDescriptorToFQN(def.service);
 		} else {
 			// We have to find the type of the current method to
 			// link it to the referenced service.
-			Matcher m = BINDDESCRIPTOR.matcher(methodDescriptor);
+			String methodDescriptor = method.getDescriptor().toString();
+			Matcher m = BINDDESCRIPTORDS10.matcher(methodDescriptor);
 			if (m.matches()) {
-				def.interfce = Clazz.internalToFqn(m.group(3));
-			} else
-				throw new IllegalArgumentException(
-						"Cannot detect the type of a Component Reference from the descriptor: "
-								+ methodDescriptor);
+				def.service = Descriptors.binaryToFQN(m.group(3));
+			} else {
+				m = BINDDESCRIPTORDS11.matcher(methodDescriptor);
+				if (m.matches()) {
+					def.service = Descriptors.binaryToFQN(m.group(3));
+					def.updateVersion(V1_1);
+				} else {
+					m = BINDDESCRIPTORDS13.matcher(methodDescriptor);
+					if (felixExtensions && m.matches()) {
+						def.service = Descriptors.binaryToFQN(m.group(3));
+						def.updateVersion(V1_2);
+						if (component.xmlns == null) {
+							component.xmlns = FELIX_1_2;
+						}
+					} else 
+						throw new IllegalArgumentException(
+							"Cannot detect the type of a Component Reference from the descriptor: "
+									+ method.getDescriptor());
+				}
+			}
 		}
 
 		// Check if we have a target, this must be a filter
 		def.target = reference.target();
-		if (def.target != null) {
-			Verifier.verifyFilter(def.target, 0);
-		}
 
 		if (component.references.containsKey(def.name))
 			analyzer.error(
 					"In component %s, multiple references with the same name: %s. Previous def: %s, this def: %s",
-					component.implementation, component.references.get(def.name), def.interfce, "");
+					component.implementation, component.references.get(def.name), def.service, "");
 		else
 			component.references.put(def.name, def);
 
 		def.cardinality = reference.cardinality();
 		def.policy = reference.policy();
-	}
-
-	/**
-	 * 
-	 */
-	protected void doActivate() {
-		if (!ACTIVATEDESCRIPTOR.matcher(methodDescriptor).matches())
-			analyzer.error(
-					"Activate method for %s does not have an acceptable prototype, only Map, ComponentContext, or BundleContext is allowed. Found: %s",
-					clazz, methodDescriptor);
-		else {
-			component.activate = method;
-		}
+		def.policyOption = reference.policyOption();
 	}
 
 	/**
@@ -252,8 +336,7 @@ public class AnnotationReader extends ClassDataCollector {
 		if (component.implementation != null)
 			return;
 
-		component.version = V1_1;
-		component.implementation = clazz.getFQN();
+		component.implementation = clazz.getClassName();
 		component.name = comp.name();
 		component.factory = comp.factory();
 		component.configurationPolicy = comp.configurationPolicy();
@@ -266,30 +349,40 @@ public class AnnotationReader extends ClassDataCollector {
 		if (annotation.get("servicefactory") != null)
 			component.servicefactory = comp.servicefactory();
 
+		if (annotation.get("configurationPid") != null) {
+			component.configurationPid = comp.configurationPid();
+			component.updateVersion(V1_2);
+		}
+
+		if (annotation.get("xmlns") != null)
+			component.xmlns = comp.xmlns();
+
 		String properties[] = comp.properties();
 		if (properties != null)
 			for (String entry : properties)
 				component.properties.add(entry);
 
 		doProperties(comp.property());
-		Object [] x = annotation.get("service");
-		
+		Object[] x = annotation.get("service");
+
 		if (x == null) {
 			// Use the found interfaces, but convert from internal to
 			// fqn.
 			if (interfaces != null) {
-				List<String> result = new ArrayList<String>();
+				List<TypeRef> result = new ArrayList<TypeRef>();
 				for (int i = 0; i < interfaces.length; i++) {
-					if (!interfaces[i].equals("scala/ScalaObject"))
-						result.add(Clazz.internalToFqn(interfaces[i]));
+					if (!interfaces[i].equals(analyzer.getTypeRef("scala/ScalaObject")))
+						result.add(interfaces[i]);
 				}
 				component.service = result.toArray(EMPTY);
 			}
 		} else {
 			// We have explicit interfaces set
-			component.service= new String[x.length];
+			component.service = new TypeRef[x.length];
 			for (int i = 0; i < x.length; i++) {
-				component.service[i] = Clazz.objectDescriptorToFQN(x[i].toString());
+				String s = (String) x[i];
+				TypeRef ref = analyzer.getTypeRefFromFQN(s);
+				component.service[i] = ref;
 			}
 		}
 
@@ -306,11 +399,14 @@ public class AnnotationReader extends ClassDataCollector {
 
 				if (m.matches()) {
 					String key = m.group(1);
-					String value = m.group(4);
+					String type = m.group(2);
+					if ( type != null)
+						key += ":" + type;
+					
+					String value = m.group(3);
 					component.property.add(key, value);
 				} else
-					throw new IllegalArgumentException("Malformed property '" + p
-							+ "' on component: " + className);
+					throw new IllegalArgumentException("Malformed property '" + p + "' on component: " + className);
 			}
 		}
 	}
@@ -319,25 +415,32 @@ public class AnnotationReader extends ClassDataCollector {
 	 * Are called during class parsing
 	 */
 
-	@Override public void classBegin(int access, String name) {
+	@Override
+	public void classBegin(int access, TypeRef name) {
 		className = name;
 	}
 
-	@Override public void implementsInterfaces(String[] interfaces) {
+	@Override
+	public void implementsInterfaces(TypeRef[] interfaces) {
 		this.interfaces = interfaces;
 	}
 
-	@Override public void method(int access, String name, String descriptor) {
-		if (Modifier.isPrivate(access) || Modifier.isAbstract(access) || Modifier.isStatic(access))
+	@Override
+	public void method(Clazz.MethodDef method) {
+		int access = method.getAccess();
+
+		if (Modifier.isAbstract(access) || Modifier.isStatic(access))
+			return;
+
+		if (!baseclass && Modifier.isPrivate(access))
 			return;
 
-		this.method = name;
-		this.methodDescriptor = descriptor;
-		this.methodAccess = access;
-		methods.add(name, descriptor);
+		this.method = method;
+		methods.add(method.getName(), method.getDescriptor().toString());
 	}
 
-	@Override public void extendsClass(String name) {
+	@Override
+	public void extendsClass(TypeRef name) {
 		this.extendsClass = name;
 	}
 
diff --git a/biz.aQute.bndlib/src/aQute/bnd/component/ComponentDef.java b/biz.aQute.bndlib/src/aQute/bnd/component/ComponentDef.java
index 30268a7..8c4b090 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/component/ComponentDef.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/component/ComponentDef.java
@@ -1,126 +1,192 @@
 package aQute.bnd.component;
 
+import java.lang.reflect.*;
 import java.util.*;
 
 import org.osgi.service.component.annotations.*;
 
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Descriptors.TypeRef;
+import aQute.bnd.version.*;
 import aQute.lib.collections.*;
-import aQute.lib.osgi.*;
 import aQute.lib.tag.*;
-import aQute.libg.version.*;
 
+/**
+ * This class just holds the information for the component, implementation, and
+ * service/provide elements. The {@link #prepare(Analyzer)} method will check if
+ * things are ok and the {@link #getTag()} method returns a tag if the prepare
+ * method returns without any errors. The class uses {@link ReferenceDef} to
+ * hold the references.
+ */
 class ComponentDef {
 	final static String				NAMESPACE_STEM	= "http://www.osgi.org/xmlns/scr";
-	Version							version			= new Version("1.1.0");
+	final List<String>				properties		= new ArrayList<String>();
+	final MultiMap<String,String>	property		= new MultiMap<String,String>();
+	final Map<String,ReferenceDef>	references		= new LinkedHashMap<String,ReferenceDef>();
+
+	Version							version			= AnnotationReader.V1_0;
 	String							name;
 	String							factory;
 	Boolean							immediate;
 	Boolean							servicefactory;
 	ConfigurationPolicy				configurationPolicy;
-	String							implementation;
-	String							service[];
+	TypeRef							implementation;
+	TypeRef							service[];
 	String							activate;
 	String							deactivate;
 	String							modified;
 	Boolean							enabled;
-	final List<String>				properties		= new ArrayList<String>();
-	final MultiMap<String, String>	property		= new MultiMap<String, String>();
-	final Map<String, ReferenceDef>	references		= new TreeMap<String, ReferenceDef>();
+	String							xmlns;
+	String							configurationPid;
+	List<Tag>						propertyTags	= new ArrayList<Tag>();
 
-	void prepare(Analyzer analyzer) {
+	/**
+	 * Called to prepare. If will look for any errors or inconsistencies in the
+	 * setup.
+	 * 
+	 * @param analyzer
+	 *            the analyzer to report errors and create references
+	 * @throws Exception
+	 */
+	void prepare(Analyzer analyzer) throws Exception {
 
-		for (ReferenceDef ref : references.values()) {
-			ref.prepare(analyzer);
-			if (ref.version.compareTo(version) > 0)
-				version = ref.version;
-		}
+		prepareVersion(analyzer);
 
-		if (implementation == null)
+
+		if (implementation == null) {
 			analyzer.error("No Implementation defined for component " + name);
-		else
-			analyzer.referTo(implementation);
+			return;
+		}
 
-		name = implementation;
+		analyzer.referTo(implementation);
+
+		if (name == null)
+			name = implementation.getFQN();
 
 		if (service != null && service.length > 0) {
-			for (String interfaceName : service)
+			for (TypeRef interfaceName : service)
 				analyzer.referTo(interfaceName);
 		} else if (servicefactory != null && servicefactory)
 			analyzer.warning("The servicefactory:=true directive is set but no service is provided, ignoring it");
+
+		for (Map.Entry<String,List<String>> kvs : property.entrySet()) {
+			Tag property = new Tag("property");
+			String name = kvs.getKey();
+			String type = null;
+			int n = name.indexOf(':');
+			if (n > 0) {
+				type = name.substring(n + 1);
+				name = name.substring(0, n);
+			}
+
+			property.addAttribute("name", name);
+			if (type != null) {
+				property.addAttribute("type", type);
+			}
+			if (kvs.getValue().size() == 1) {
+				String value = kvs.getValue().get(0);
+				value = check(type, value, analyzer);
+				property.addAttribute("value", value);
+			} else {
+				StringBuilder sb = new StringBuilder();
+
+				String del = "";
+				for (String v : kvs.getValue()) {
+					sb.append(del);
+					v = check(type, v, analyzer);
+					sb.append(v);
+					del = "\n";
+				}
+				property.addContent(sb.toString());
+			}
+			propertyTags.add(property);
+		}
 	}
 
+	private void prepareVersion(Analyzer analyzer) throws Exception {
+		
+		for (ReferenceDef ref : references.values()) {
+			ref.prepare(analyzer);
+			updateVersion(ref.version);
+		}
+		if (configurationPolicy != null)
+			updateVersion(AnnotationReader.V1_1);
+		if (configurationPid != null)
+			updateVersion(AnnotationReader.V1_2);
+		if (modified != null)
+			updateVersion(AnnotationReader.V1_1);
+			
+	}
+	
+	void sortReferences() {
+		Map<String, ReferenceDef> temp = new TreeMap<String,ReferenceDef>(references);
+		references.clear();
+		references.putAll(temp);
+	}
+
+	/**
+	 * Returns a tag describing the component element.
+	 * 
+	 * @return a component element
+	 */
 	Tag getTag() {
-		Tag component = new Tag("scr:component");
-		component.addAttribute("xmlns:scr", NAMESPACE_STEM + "/" + version);
+		String xmlns = this.xmlns;
+		if (xmlns == null && version != AnnotationReader.V1_0)
+			xmlns = NAMESPACE_STEM + "/v" + version;
+		Tag component = new Tag(xmlns == null? "component": "scr:component");
+		if (xmlns != null)
+			component.addAttribute("xmlns:scr", xmlns);
+
 		component.addAttribute("name", name);
 
 		if (servicefactory != null)
 			component.addAttribute("servicefactory", servicefactory);
 
 		if (configurationPolicy != null)
-			component.addAttribute("configuration-policy", configurationPolicy.toString()
-					.toLowerCase());
+			component.addAttribute("configuration-policy", configurationPolicy.toString().toLowerCase());
+
 		if (enabled != null)
 			component.addAttribute("enabled", enabled);
+
 		if (immediate != null)
 			component.addAttribute("immediate", immediate);
 
 		if (factory != null)
 			component.addAttribute("factory", factory);
 
-		if (activate != null)
+		if (activate != null && version != AnnotationReader.V1_0)
 			component.addAttribute("activate", activate);
 
-		if (deactivate != null)
+		if (deactivate != null && version != AnnotationReader.V1_0)
 			component.addAttribute("deactivate", deactivate);
 
 		if (modified != null)
 			component.addAttribute("modified", modified);
 
+		if (configurationPid != null)
+			component.addAttribute("configuration-pid", configurationPid);
+
 		Tag impl = new Tag(component, "implementation");
-		impl.addAttribute("class", implementation);
+		impl.addAttribute("class", implementation.getFQN());
 
 		if (service != null && service.length != 0) {
 			Tag s = new Tag(component, "service");
 			if (servicefactory != null && servicefactory)
 				s.addAttribute("servicefactory", true);
 
-			for (String ss : service) {
+			for (TypeRef ss : service) {
 				Tag provide = new Tag(s, "provide");
-				provide.addAttribute("interface", ss);
+				provide.addAttribute("interface", ss.getFQN());
 			}
 		}
 
 		for (ReferenceDef ref : references.values()) {
 			Tag refTag = ref.getTag();
 			component.addContent(refTag);
-
 		}
 
-		for (Map.Entry<String, Set<String>> kvs : property.entrySet()) {
-			Tag property = new Tag(component, "property");
-			String name = kvs.getKey();
-			String type = null;
-			int n = name.indexOf(':');
-			if (n > 0) {
-				type = name.substring(n + 1);
-				name = name.substring(0, n);
-			}
-
-			property.addAttribute("name", name);
-			if (type != null) {
-				property.addAttribute("type", type);
-			}
-			StringBuffer sb = new StringBuffer();
-
-			String del = "";
-			for (String v : kvs.getValue()) {
-				sb.append(del);
-				sb.append(v);
-				del = "\n";
-			}
-			property.addContent(sb.toString());
-		}
+		for (Tag tag : propertyTags)
+			component.addContent(tag);
 
 		for (String entry : properties) {
 			Tag properties = new Tag(component, "properties");
@@ -129,4 +195,48 @@ class ComponentDef {
 		return component;
 	}
 
+	private String check(String type, String v, Analyzer analyzer) {
+		if (type == null)
+			return v;
+
+		try {
+			if ( type.equals("Char"))
+				type = "Character";
+			
+			Class< ? > c = Class.forName("java.lang." + type);
+			if (c == String.class)
+				return v;
+
+			v = v.trim();
+			if (c == Character.class)
+				c = Integer.class;
+			Method m = c.getMethod("valueOf", String.class);
+			m.invoke(null, v);
+		}
+		catch (ClassNotFoundException e) {
+			analyzer.error("Invalid data type %s", type);
+		}
+		catch (NoSuchMethodException e) {
+			analyzer.error("Cannot convert data %s to type %s", v, type);
+		}
+		catch (NumberFormatException e) {
+			analyzer.error("Not a valid number %s for %s, %s", v, type, e.getMessage());
+		}
+		catch (Exception e) {
+			analyzer.error("Cannot convert data %s to type %s", v, type);
+		}
+		return v;
+	}
+	
+	void updateVersion(Version version) {
+		this.version = max(this.version, version);
+	}
+	
+	static <T extends Comparable<T>> T max(T a, T b) {
+		int n = a.compareTo(b);
+		if (n >= 0)
+			return a;
+		return b;
+	}
+
 }
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/aQute/bnd/component/DSAnnotations.java b/biz.aQute.bndlib/src/aQute/bnd/component/DSAnnotations.java
index b5c60dd..f3840f3 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/component/DSAnnotations.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/component/DSAnnotations.java
@@ -2,45 +2,40 @@ package aQute.bnd.component;
 
 import java.util.*;
 
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
 import aQute.bnd.service.*;
-import aQute.lib.osgi.*;
-import aQute.libg.header.*;
 
 /**
  * Analyze the class space for any classes that have an OSGi annotation for DS.
- * 
  */
 public class DSAnnotations implements AnalyzerPlugin {
 
 	public boolean analyzeJar(Analyzer analyzer) throws Exception {
-		Map<String, Map<String, String>> header = OSGiHeader.parseHeader(analyzer
-				.getProperty("-dsannotations"));
-		if ( header.size()==0)
+		Parameters header = OSGiHeader.parseHeader(analyzer.getProperty(Constants.DSANNOTATIONS));
+		if (header.size() == 0)
 			return false;
-		
-		Set<Instruction> instructions = Instruction.replaceWithInstruction(header).keySet();
+
+		Instructions instructions = new Instructions(header);
 		Set<Clazz> list = new HashSet<Clazz>(analyzer.getClassspace().values());
 		String sc = analyzer.getProperty(Constants.SERVICE_COMPONENT);
 		List<String> names = new ArrayList<String>();
-		if ( sc != null && sc.trim().length() > 0)
+		if (sc != null && sc.trim().length() > 0)
 			names.add(sc);
-		
-		for (Iterator<Clazz> i = list.iterator(); i.hasNext();) {
-			for (Instruction instruction : instructions) {
-				Clazz c = i.next();
-				System.out.println("fqn " + c.getFQN() + " " + instruction);
+
+		for (Clazz c: list) {
+			for (Instruction instruction : instructions.keySet()) {
+
 				if (instruction.matches(c.getFQN())) {
 					if (instruction.isNegated())
-						i.remove();
-					else {
-						ComponentDef definition = AnnotationReader.getDefinition(c, analyzer);
-						if (definition != null) {
-							definition.prepare(analyzer);
-							String name = "OSGI-INF/" + definition.name + ".xml";
-							names.add(name);
-							analyzer.getJar().putResource(name,
-									new TagResource(definition.getTag()));
-						}
+						break;
+					ComponentDef definition = AnnotationReader.getDefinition(c, analyzer);
+					if (definition != null) {
+						definition.sortReferences();
+						definition.prepare(analyzer);
+						String name = "OSGI-INF/" + definition.name + ".xml";
+						names.add(name);
+						analyzer.getJar().putResource(name, new TagResource(definition.getTag()));
 					}
 				}
 			}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/component/HeaderReader.java b/biz.aQute.bndlib/src/aQute/bnd/component/HeaderReader.java
new file mode 100644
index 0000000..aa74aac
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/component/HeaderReader.java
@@ -0,0 +1,504 @@
+package aQute.bnd.component;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.osgi.service.component.annotations.ConfigurationPolicy;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
+
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Clazz.MethodDef;
+import aQute.bnd.osgi.Descriptors.TypeRef;
+import aQute.lib.tag.Tag;
+import aQute.bnd.version.Version;
+
+public class HeaderReader extends Processor {
+	final static Pattern		PROPERTY_PATTERN		= Pattern
+	.compile("([^=]+([:@](Boolean|Byte|Char|Short|Integer|Long|Float|Double|String))?)\\s*=(.*)");
+	private final static Set<String> LIFECYCLE_METHODS = new HashSet<String>(Arrays.asList("activate", "deactivate", "modified"));
+	
+    private final Analyzer analyzer;
+
+	private final static String ComponentContextTR = "org.osgi.service.component.ComponentContext";
+	private final static String BundleContextTR = "org.osgi.framework.BundleContext";
+	private final static String MapTR = Map.class.getName();
+	private final static String IntTR = int.class.getName();
+	final static Set<String> allowed = new HashSet<String>(Arrays.asList(ComponentContextTR, BundleContextTR, MapTR));
+	final static Set<String> allowedDeactivate = new HashSet<String>(Arrays.asList(ComponentContextTR, BundleContextTR, MapTR, IntTR));
+	
+	private final static String ServiceReferenceTR = "org.osgi.framework.ServiceReference";
+
+    public HeaderReader(Analyzer analyzer) {
+    	this.analyzer = analyzer;
+    }
+    
+	public Tag createComponentTag(String name, String impl, Map<String, String> info)
+	throws Exception {
+		final ComponentDef cd = new ComponentDef();
+		cd.name = name;
+		if (info.get(COMPONENT_ENABLED) != null)
+			cd.enabled = Boolean.valueOf(info.get(COMPONENT_ENABLED));
+		cd.factory = info.get(COMPONENT_FACTORY);
+		if (info.get(COMPONENT_IMMEDIATE) != null) 
+		    cd.immediate = Boolean.valueOf(info.get(COMPONENT_IMMEDIATE));
+		if (info.get(COMPONENT_CONFIGURATION_POLICY) != null)
+		    cd.configurationPolicy = ConfigurationPolicy.valueOf(info.get(COMPONENT_CONFIGURATION_POLICY).toUpperCase());
+		cd.activate = checkIdentifier(COMPONENT_ACTIVATE, info.get(COMPONENT_ACTIVATE));
+		cd.deactivate = checkIdentifier(COMPONENT_DEACTIVATE, info.get(COMPONENT_DEACTIVATE));
+		cd.modified = checkIdentifier(COMPONENT_MODIFIED, info.get(COMPONENT_MODIFIED));
+		
+		cd.implementation = analyzer.getTypeRefFromFQN(impl == null? name: impl);
+		
+
+		String provides = info.get(COMPONENT_PROVIDE);
+		if (info.get(COMPONENT_SERVICEFACTORY) != null) {
+			if (provides != null)
+			    cd.servicefactory = Boolean.valueOf(info.get(COMPONENT_SERVICEFACTORY));
+			else
+				warning("The servicefactory:=true directive is set but no service is provided, ignoring it");
+		}
+
+		if (cd.servicefactory != null && cd.servicefactory  && cd.immediate != null && cd.immediate) {
+			// TODO can become error() if it is up to me
+			warning("For a Service Component, the immediate option and the servicefactory option are mutually exclusive for %(%s)",
+					name, impl);
+		}
+		
+		//analyze the class for suitable methods.
+		final Map<String, MethodDef> lifecycleMethods = new HashMap<String, MethodDef>();
+		final Map<String, MethodDef> bindmethods = new HashMap<String, MethodDef>();
+		TypeRef typeRef = analyzer.getTypeRefFromFQN(impl);
+		Clazz clazz = analyzer.findClass(typeRef);
+		boolean privateAllowed = true;
+		boolean defaultAllowed = true; 
+		String topPackage = typeRef.getPackageRef().getFQN();
+		while (clazz != null) {
+			final boolean pa = privateAllowed;
+			final boolean da = defaultAllowed;
+			final Map<String, MethodDef> classLifecyclemethods = new HashMap<String, MethodDef>();
+			final Map<String, MethodDef> classBindmethods = new HashMap<String, MethodDef>();
+			
+			clazz.parseClassFileWithCollector(new ClassDataCollector() {
+				
+				@Override
+				public void method(MethodDef md) {
+					Set<String> allowedParams = allowed;
+					String lifecycleName = null;
+					
+					boolean isLifecycle = (cd.activate == null? "activate": cd.activate).equals(md.getName()) ||
+						md.getName().equals(cd.modified);	
+					if (!isLifecycle && (cd.deactivate == null? "deactivate": cd.deactivate).equals(md.getName())) {
+						isLifecycle = true;
+						allowedParams = allowedDeactivate;
+					}
+					if (isLifecycle && !lifecycleMethods.containsKey(md.getName()) &&
+							(md.isPublic() ||
+									md.isProtected() ||
+									(md.isPrivate() && pa) ||
+									(!md.isPrivate()) && da) &&
+							isBetter(md, classLifecyclemethods.get(md.getName()), allowedParams)) {
+						classLifecyclemethods.put(md.getName(), md);
+					}
+					if (!bindmethods.containsKey(md.getName()) &&
+							(md.isPublic() ||
+									md.isProtected() ||
+									(md.isPrivate() && pa) ||
+									(!md.isPrivate()) && da) &&
+							isBetterBind(md, classBindmethods.get(md.getName()))) {
+						classBindmethods.put(md.getName(), md);
+					}
+				}
+
+				private boolean isBetter(MethodDef test, MethodDef existing, Set<String> allowedParams) {
+					int testRating = rateLifecycle(test, allowedParams);
+					if (existing == null)
+						return testRating < 6;// ignore invalid methods
+					if (testRating < rateLifecycle(existing, allowedParams))
+						return true;
+					
+					return false;
+				}
+
+				private boolean isBetterBind(MethodDef test, MethodDef existing) {
+					int testRating = rateBind(test);
+					if (existing == null)
+						return testRating < 6;// ignore invalid methods
+					if (testRating < rateBind(existing))
+						return true;
+					
+					return false;
+				}
+
+			});
+			lifecycleMethods.putAll(classLifecyclemethods);
+			bindmethods.putAll(classBindmethods);
+			typeRef = clazz.getSuper();
+			if (typeRef == null)
+				break;
+			clazz = analyzer.findClass(typeRef);
+			privateAllowed = false;
+			defaultAllowed = defaultAllowed && topPackage.equals(typeRef.getPackageRef().getFQN());
+		}
+		
+		
+		if (cd.activate != null && !lifecycleMethods.containsKey(cd.activate)) {
+			error("in component %s, activate method %s specified but not found", cd.implementation.getFQN(), cd.activate);
+			cd.activate = null;
+		}
+		if (cd.deactivate != null && !lifecycleMethods.containsKey(cd.deactivate)) {
+			error("in component %s, deactivate method %s specified but not found", cd.implementation.getFQN(), cd.deactivate);
+			cd.activate = null;
+		}
+		if (cd.modified != null && !lifecycleMethods.containsKey(cd.modified)) {
+			error("in component %s, modified method %s specified but not found", cd.implementation.getFQN(), cd.modified);
+			cd.activate = null;
+		}
+		
+		provide(cd, provides, impl);
+		properties(cd, info, name);
+		reference(info, impl, cd, bindmethods);
+		//compute namespace after references, an updated method means ds 1.2.
+		getNamespace(info, cd, lifecycleMethods);
+		cd.prepare(analyzer);
+		return cd.getTag();
+
+	}
+
+	private String checkIdentifier(String name, String value) {
+		if (value != null) {
+			if (!Verifier.isIdentifier(value)) {
+				error("Component attribute %s has value %s but is not a Java identifier",
+						name, value);
+				return null;
+			}
+		}
+		return value;
+	}
+
+	/**
+	 * Check if we need to use the v1.1 namespace (or later).
+	 * 
+	 * @param info
+	 * @param cd TODO
+	 * @param descriptors TODO
+	 * @return
+	 */
+	private void getNamespace(Map<String, String> info, ComponentDef cd, Map<String,MethodDef> descriptors) {
+		String namespace = info.get(COMPONENT_NAMESPACE);
+		if (namespace != null) {
+			cd.xmlns = namespace;
+		}
+		String version = info.get(COMPONENT_VERSION);
+		if (version != null) {
+			try {
+				Version v = new Version(version);
+				cd.updateVersion(v);
+			} catch (Exception e) {
+				error("version: specified on component header but not a valid version: "
+						+ version);
+				return;
+			}
+		}
+		for (String key : info.keySet()) {
+			if (SET_COMPONENT_DIRECTIVES_1_2.contains(key)) {
+				cd.updateVersion(AnnotationReader.V1_2);
+				return;
+			}
+		}
+		for (ReferenceDef rd: cd.references.values()) {
+			if (rd.updated != null) {
+				cd.updateVersion(AnnotationReader.V1_2);
+				return;
+			}
+		}
+		//among other things this picks up any specified lifecycle methods
+		for (String key : info.keySet()) {
+			if (SET_COMPONENT_DIRECTIVES_1_1.contains(key)) {
+				cd.updateVersion(AnnotationReader.V1_1);
+				return;
+			}
+		}
+		for (String lifecycle: LIFECYCLE_METHODS) {
+			//lifecycle methods were not specified.... check for non 1.0 signatures.
+			MethodDef test = descriptors.get(lifecycle);
+			if (descriptors.containsKey(lifecycle) && (!(test.isPublic() || test.isProtected()) || 
+					rateLifecycle(test, "deactivate".equals(lifecycle)? allowedDeactivate: allowed) > 1)) {
+				cd.updateVersion(AnnotationReader.V1_1);
+				return;
+			}
+		}
+	}
+
+	/**
+	 * Print the Service-Component properties element
+	 * 
+	 * @param cd
+	 * @param info
+	 */
+	void properties(ComponentDef cd, Map<String, String> info, String name) {
+		Collection<String> properties = split(info.get(COMPONENT_PROPERTIES));
+		for (String p : properties) {
+			Matcher m = PROPERTY_PATTERN.matcher(p);
+
+			if (m.matches()) {
+				String key = m.group(1).replaceAll("@", ":");
+				String value = m.group(4);
+				String parts[] = value.split("\\s*(\\||\\n)\\s*");
+				for (String part: parts) {
+					cd.property.add(key, part);
+				}
+			} else
+				throw new IllegalArgumentException("Malformed property '" + p
+						+ "' on component: " + name);
+		}
+	}
+
+	/**
+	 * @param cd
+	 * @param provides
+	 */
+	void provide(ComponentDef cd, String provides, String impl) {
+		if (provides != null) {
+			StringTokenizer st = new StringTokenizer(provides, ",");
+			List<TypeRef> provide = new ArrayList<TypeRef>();
+			while (st.hasMoreTokens()) {
+				String interfaceName = st.nextToken();
+				TypeRef ref = analyzer.getTypeRefFromFQN(interfaceName);
+				provide.add(ref);
+				analyzer.referTo(ref);
+
+				// TODO verifies the impl. class extends or implements the
+				// interface
+			}
+			cd.service = provide.toArray(new TypeRef[provide.size()]);
+		} 
+	}
+
+	public final static Pattern	REFERENCE	= Pattern.compile("([^(]+)(\\(.+\\))?");
+
+	/**
+	 * rates the methods according to the scale in 112.5.8 (compendium 4.3, ds 1.2), also returning "6" for invalid methods
+	 * We don't look at return values yet due to proposal to all them for setting service properties.
+	 * @param test methodDef to examine for suitability as a DS lifecycle method
+	 * @param allowedParams TODO
+	 * @return rating; 6 if invalid, lower is better
+	 */
+	int rateLifecycle(MethodDef test, Set<String> allowedParams) {
+		TypeRef[] prototype = test.getDescriptor().getPrototype();
+		if (prototype.length == 1 && ComponentContextTR.equals(prototype[0].getFQN()))
+			    return 1;
+		if (prototype.length == 1 && BundleContextTR.equals(prototype[0].getFQN()))
+			return 2;
+		if (prototype.length == 1 && MapTR.equals(prototype[0].getFQN()))
+			return 3;
+		if (prototype.length > 1) {
+			for (TypeRef tr: prototype) {
+				if (!allowedParams.contains(tr.getFQN()))
+					return 6;
+			}
+			return 5;
+		}
+		if (prototype.length == 0)
+			return 5;
+
+		return 6;
+	}
+
+	/**
+	 * see 112.3.2.  We can't distinguish the bind type, so we just accept anything.
+	 * @param test
+	 * @return
+	 */
+	int rateBind(MethodDef test) {
+		TypeRef[] prototype = test.getDescriptor().getPrototype();
+		if (prototype.length == 1 && ServiceReferenceTR.equals(prototype[0].getFQN()))
+			return 1;
+		if (prototype.length == 1)
+			return 2;
+		if (prototype.length == 2 && MapTR.equals(prototype[1].getFQN()))
+			return 3;
+		return 6;
+	}
+
+	/**
+	 * @param info
+	 * @param impl TODO
+	 * @param descriptors TODO
+	 * @param pw
+	 * @throws Exception 
+	 */
+	void reference(Map<String, String> info, String impl, ComponentDef cd, Map<String,MethodDef> descriptors) throws Exception {
+		Collection<String> dynamic = new ArrayList<String>(split(info.get(COMPONENT_DYNAMIC)));
+		Collection<String> optional = new ArrayList<String>(split(info.get(COMPONENT_OPTIONAL)));
+		Collection<String> multiple = new ArrayList<String>(split(info.get(COMPONENT_MULTIPLE)));
+		Collection<String> greedy = new ArrayList<String>(split(info.get(COMPONENT_GREEDY)));
+
+
+		for (Map.Entry<String, String> entry : info.entrySet()) {
+
+			// Skip directives
+			String referenceName = entry.getKey();
+			if (referenceName.endsWith(":")) {
+				if (!SET_COMPONENT_DIRECTIVES.contains(referenceName))
+					error("Unrecognized directive in Service-Component header: "
+							+ referenceName);
+				continue;
+			}
+
+			// Parse the bind/unbind methods from the name
+			// if set. They are separated by '/'
+			String bind = null;
+			String unbind = null;
+			String updated = null;
+
+			boolean bindCalculated = true;
+			boolean unbindCalculated = true;
+			boolean updatedCalculated = true;
+
+			if (referenceName.indexOf('/') >= 0) {
+				String parts[] = referenceName.split("/");
+				referenceName = parts[0];
+				if (parts[1].length() > 0) {
+					bind = parts[1];
+					bindCalculated = false;
+				} else {
+					bind = calculateBind(referenceName);
+				}
+				bind = parts[1].length() == 0? calculateBind(referenceName): parts[1];
+				if (parts.length > 2 && parts[2].length() > 0) {
+					unbind = parts[2] ;
+					unbindCalculated = false;
+				} else {
+					if (bind.startsWith("add"))
+						unbind = bind.replaceAll("add(.+)", "remove$1");
+					else
+						unbind = "un" + bind;
+				}
+				if (parts.length > 3) {
+					updated = parts[3];
+					updatedCalculated = false;
+				}
+			} else if (Character.isLowerCase(referenceName.charAt(0))) {
+				bind = calculateBind(referenceName);
+				unbind = "un" + bind;
+				updated = "updated" + Character.toUpperCase(referenceName.charAt(0))
+				+ referenceName.substring(1);
+			}
+
+			String interfaceName = entry.getValue();
+			if (interfaceName == null || interfaceName.length() == 0) {
+				error("Invalid Interface Name for references in Service Component: "
+						+ referenceName + "=" + interfaceName);
+				continue;
+			}
+
+			// If we have descriptors, we have analyzed the component.
+			// So why not check the methods
+			if (descriptors.size() > 0) {
+				// Verify that the bind method exists
+				if (!descriptors.containsKey(bind))
+					if (bindCalculated)
+						bind = null;
+					else
+						error("In component %s, the bind method %s for %s not defined", cd.name, bind, referenceName);
+
+				// Check if the unbind method exists
+				if (!descriptors.containsKey(unbind)) {
+					if (unbindCalculated)
+						// remove it
+						unbind = null;
+					else
+						error("In component %s, the unbind method %s for %s not defined", cd.name, unbind, referenceName);
+				}
+				if (!descriptors.containsKey(updated)) {
+					if (updatedCalculated)
+						//remove it
+						updated = null;
+					else 
+						error("In component %s, the updated method %s for %s is not defined", cd.name, updated, referenceName);
+				}
+			}
+			// Check the cardinality by looking at the last
+			// character of the value
+			char c = interfaceName.charAt(interfaceName.length() - 1);
+			if ("?+*~".indexOf(c) >= 0) {
+				if (c == '?' || c == '*' || c == '~')
+					optional.add(referenceName);
+				if (c == '+' || c == '*')
+					multiple.add(referenceName);
+				if (c == '+' || c == '*' || c == '?')
+					dynamic.add(referenceName);
+				interfaceName = interfaceName.substring(0, interfaceName.length() - 1);
+			}
+
+			// Parse the target from the interface name
+			// The target is a filter.
+			String target = null;
+			Matcher m = REFERENCE.matcher(interfaceName);
+			if (m.matches()) {
+				interfaceName = m.group(1);
+				target = m.group(2);
+			}
+			TypeRef ref = analyzer.getTypeRefFromFQN(interfaceName);
+			analyzer.referTo(ref);
+			ReferenceDef rd = new ReferenceDef();
+			rd.name = referenceName;
+			rd.service = interfaceName;
+
+			if (optional.contains(referenceName)) {
+				if (multiple.contains(referenceName)) {
+					rd.cardinality = ReferenceCardinality.MULTIPLE;
+				} else {
+					rd.cardinality = ReferenceCardinality.OPTIONAL;
+				}
+			} else {
+				if (multiple.contains(referenceName)) {
+					rd.cardinality = ReferenceCardinality.AT_LEAST_ONE;
+				} else {
+					rd.cardinality = ReferenceCardinality.MANDATORY;
+				}
+			}
+			if (bind != null) {
+				rd.bind = bind;
+				if (unbind != null) {
+					rd.unbind = unbind;
+				}
+				if (updated != null) {
+					rd.updated = updated;
+				}
+			}
+
+			if (dynamic.contains(referenceName)) {
+				rd.policy = ReferencePolicy.DYNAMIC;
+				if (rd.unbind == null)
+					error("In component %s, reference %s is dynamic but has no unbind method.", cd.name, rd.name);
+			}
+			
+			if (greedy.contains(referenceName)) {
+				rd.policyOption = ReferencePolicyOption.GREEDY;
+			}
+
+			if (target != null) {
+				rd.target = target;
+			}
+			cd.references.put(referenceName, rd);
+		}
+	}
+
+	private String calculateBind(String referenceName) {
+		return "set" + Character.toUpperCase(referenceName.charAt(0))
+		+ referenceName.substring(1);
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/component/ReferenceDef.java b/biz.aQute.bndlib/src/aQute/bnd/component/ReferenceDef.java
index ca810e6..255eef1 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/component/ReferenceDef.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/component/ReferenceDef.java
@@ -2,97 +2,93 @@ package aQute.bnd.component;
 
 import org.osgi.service.component.annotations.*;
 
-import aQute.lib.osgi.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.version.*;
 import aQute.lib.tag.*;
-import aQute.libg.version.*;
+
+/**
+ * Holds the information in the reference element.
+ */
 
 class ReferenceDef {
-	Version					version;
+	Version					version	= AnnotationReader.V1_0;
 	String					name;
-	String					interfce;
+	String					service;
 	ReferenceCardinality	cardinality;
 	ReferencePolicy			policy;
+	ReferencePolicyOption	policyOption;
 	String					target;
 	String					bind;
 	String					unbind;
-	String					modified;
-
-	public void prepare(Analyzer analyzer) {
+	String					updated;
+
+	/**
+	 * Prepare the reference, will check for any errors.
+	 * 
+	 * @param analyzer
+	 *            the analyzer to report errors to.
+	 * @throws Exception
+	 */
+	public void prepare(Analyzer analyzer) throws Exception {
 		if (name == null)
 			analyzer.error("No name for a reference");
 
-		if (version == null)
-			version = AnnotationReader.V1_1;
+		if ((updated != null && !updated.equals("-")) || policyOption != null)
+			updateVersion(AnnotationReader.V1_2);
+
+		if (target != null) {
+			String error = Verifier.validateFilter(target);
+			if (error != null)
+				analyzer.error("Invalid target filter %s for %s", target, name);
+		}
+
+		if (service == null)
+			analyzer.error("No interface specified on %s", name);
 
 	}
 
+	/**
+	 * Calculate the tag.
+	 * 
+	 * @return a tag for the reference element.
+	 */
 	public Tag getTag() {
 		Tag ref = new Tag("reference");
 		ref.addAttribute("name", name);
 		if (cardinality != null)
-			ref.addAttribute("cardinality", p(cardinality));
+			ref.addAttribute("cardinality", cardinality.toString());
+
 		if (policy != null)
-			ref.addAttribute("policy", p(policy));
+			ref.addAttribute("policy", policy.toString());
 
-		if (interfce != null)
-			ref.addAttribute("interface", interfce);
+		ref.addAttribute("interface", service);
 
 		if (target != null)
 			ref.addAttribute("target", target);
 
-		if (bind != null)
+		if (bind != null && !"-".equals(bind))
 			ref.addAttribute("bind", bind);
 
-		if (unbind != null)
+		if (unbind != null && !"-".equals(unbind))
 			ref.addAttribute("unbind", unbind);
 
-		if (modified != null) {
-			ref.addAttribute("modified", modified);
-			version = max(version, AnnotationReader.V1_2);
-		}
-
-		return ref;
-	}
-
-	private String p(ReferencePolicy policy) {
-		switch(policy) {
-		case DYNAMIC:
-			return "dynamic";
-			
-		case STATIC:
-			return "static";
-		}
-		return policy.toString();
-	}
-
-	private String p(ReferenceCardinality crd) {
-		switch (crd) {
-		case AT_LEAST_ONE:
-			return "1..n";
+		if (updated != null && !"-".equals(updated))
+			ref.addAttribute("updated", updated);
 
-		case MANDATORY:
-			return "1..1";
+		if (policyOption != null)
+			ref.addAttribute("policy-option", policyOption.toString());
 
-		case MULTIPLE:
-			return "0..n";
-
-		case OPTIONAL:
-			return "0..1";
-
-		}
-		return crd.toString();
-	}
-
-	private <T extends Comparable<T>> T max(T a, T b) {
-		int n = a.compareTo(b);
-		if (n >= 0)
-			return a;
-		else
-			return b;
+		return ref;
 	}
 
+	@Override
 	public String toString() {
 		return name;
 	}
+	
+	void updateVersion(Version version) {
+		this.version = ComponentDef.max(this.version, version);
+	}
+
 
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/component/TagResource.java b/biz.aQute.bndlib/src/aQute/bnd/component/TagResource.java
new file mode 100644
index 0000000..814a2b6
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/component/TagResource.java
@@ -0,0 +1,33 @@
+package aQute.bnd.component;
+
+import java.io.*;
+
+import aQute.bnd.osgi.*;
+import aQute.lib.tag.*;
+
+public class TagResource extends WriteResource {
+	final Tag	tag;
+
+	public TagResource(Tag tag) {
+		this.tag = tag;
+	}
+
+	@Override
+	public void write(OutputStream out) throws UnsupportedEncodingException {
+		OutputStreamWriter ow = new OutputStreamWriter(out, "UTF-8");
+		PrintWriter pw = new PrintWriter(ow);
+		pw.println("<?xml version='1.1'?>");
+		try {
+			tag.print(0, pw);
+		}
+		finally {
+			pw.flush();
+		}
+	}
+
+	@Override
+	public long lastModified() {
+		return 0;
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/concurrent/MultiBuilder.java b/biz.aQute.bndlib/src/aQute/bnd/concurrent/MultiBuilder.java
deleted file mode 100644
index 9e59607..0000000
--- a/biz.aQute.bndlib/src/aQute/bnd/concurrent/MultiBuilder.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package aQute.bnd.concurrent;
-
-import java.io.*;
-import java.util.*;
-import java.util.concurrent.*;
-
-import aQute.bnd.build.*;
-import aQute.lib.osgi.*;
-import aQute.libg.forker.*;
-
-/**
- * This class implements a concurrent builder. It manages the build process in
- * an environment where many threads can initiate builds. Users should call
- * changed(Project,boolean)
- * 
- */
-public class MultiBuilder {
-	Workspace						workspace;
-	volatile FutureTask<Throwable>	future;
-	final Set<File>					filesChanged	= Collections
-															.synchronizedSet(new HashSet<File>());
-
-	/**
-	 * Constructor
-	 * 
-	 * @param workspace
-	 *            the workspace this MultiBuilder works for.
-	 * 
-	 */
-	public MultiBuilder(Workspace workspace) {
-		this.workspace = workspace;
-	}
-
-	/**
-	 * Return the build result of a project.
-	 * 
-	 * @param p
-	 *            the project
-	 * @return the files build by the project
-	 * 
-	 * @throws Exception
-	 */
-	public File[] build(Project p) throws Exception {
-		if (p.isStale()) {
-			schedule(true);
-		}
-		return p.build();
-	}
-
-	/**
-	 * Indicate that the project has changed. This will start a build.
-	 * 
-	 * @param p
-	 *            the project that is changed
-	 * @throws Exception
-	 */
-	public void changed(Project p) throws Exception {
-		p.setChanged();
-		schedule(false);
-	}
-
-	/**
-	 * Schedule a new build if no build is running otherwise return.
-	 * 
-	 * @throws Exception
-	 */
-	public void schedule(boolean sync) throws Exception {
-		synchronized (this) {
-			if (future != null) {
-				future.cancel(true);
-				future.get();
-				future = null;
-			}
-
-			future = new FutureTask<Throwable>(new Callable<Throwable>() {
-
-				public Throwable call() {
-					Forker<Project> forker = new Forker<Project>(Processor.getExecutor());
-
-					try {
-						Thread.sleep(100);
-						workspace.bracket(true);
-						try {
-							for (final Project p : workspace.getAllProjects()) {
-								forker.doWhen(p.getDependson(), p, new Runnable() {
-
-									public void run() {
-										try {
-											p.build();
-										} catch (Exception e) {
-											e.printStackTrace();
-										}
-									}
-								});
-							}
-							forker.start(0);
-						} catch (InterruptedException e) {
-							forker.cancel(10000);
-						} finally {
-							workspace.bracket(false);
-						}
-					} catch (Exception e) {
-						return e;
-					}
-					return null;
-				}
-
-			});
-			Processor.getExecutor().execute(future);
-			if ( sync )
-				future.get();
-		}
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/differ/Baseline.java b/biz.aQute.bndlib/src/aQute/bnd/differ/Baseline.java
new file mode 100644
index 0000000..cd2d9b6
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/differ/Baseline.java
@@ -0,0 +1,287 @@
+package aQute.bnd.differ;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.diff.*;
+import aQute.bnd.service.diff.Diff.Ignore;
+import aQute.bnd.version.*;
+import aQute.libg.generics.*;
+import aQute.service.reporter.*;
+
+/**
+ * This class maintains
+ */
+public class Baseline {
+
+	public static class Info {
+		public String				packageName;
+		public Diff					packageDiff;
+		public Collection<String>	providers;
+		public Map<String,String>	attributes;
+		public Version				newerVersion;
+		public Version				olderVersion;
+		public Version				suggestedVersion;
+		public Version				suggestedIfProviders;
+		public boolean				mismatch;
+		public String				warning	= "";
+
+	}
+
+	final Differ	differ;
+	final Reporter	bnd;
+	Diff			diff;
+	Set<Info>		infos;
+	String 			bsn;
+	Version			newerVersion;
+	Version			olderVersion;
+	Version			suggestedVersion;
+	String			releaseRepository;
+
+	public Baseline(Reporter bnd, Differ differ) throws IOException {
+		this.differ = differ;
+		this.bnd = bnd;
+	}
+
+	/**
+	 * This method compares a jar to a baseline jar and returns version
+	 * suggestions if the baseline does not agree with the newer jar. The
+	 * returned set contains all the exported packages.
+	 * 
+	 * @param newer
+	 * @param older
+	 * @return null if ok, otherwise a set of suggested versions for all
+	 *         packages (also the ones that were ok).
+	 * @throws Exception
+	 */
+	public Set<Info> baseline(Jar newer, Jar older, Instructions packageFilters) throws Exception {
+		Tree n = differ.tree(newer);
+		Parameters nExports = getExports(newer);
+		Tree o = differ.tree(older);
+		Parameters oExports = getExports(older);
+		if (packageFilters == null)
+			packageFilters = new Instructions();
+
+		return baseline(n, nExports, o, oExports, packageFilters);
+	}
+
+	public Set<Info> baseline(Tree n, Parameters nExports, Tree o, Parameters oExports, Instructions packageFilters)
+			throws Exception {
+		diff = n.diff(o);
+		Diff apiDiff = diff.get("<api>");
+		infos = Create.set();
+
+		bsn = getBsn(n);
+
+		newerVersion = getVersion(n);
+		olderVersion = getVersion(o);
+
+		boolean firstRelease = false;
+		if (o.get("<manifest>") == null) {
+			firstRelease = true;
+			if (newerVersion.equals(Version.emptyVersion)) {
+				newerVersion = Version.ONE;
+			}
+		}
+		Delta highestDelta = Delta.MICRO;
+		for (Diff pdiff : apiDiff.getChildren()) {
+			if (pdiff.getType() != Type.PACKAGE) // Just packages
+				continue;
+
+			if (pdiff.getName().startsWith("java."))
+				continue;
+
+			if (!packageFilters.matches(pdiff.getName()))
+				continue;
+
+			final Info info = new Info();
+			infos.add(info);
+
+			info.packageDiff = pdiff;
+			info.packageName = pdiff.getName();
+			info.attributes = nExports.get(info.packageName);
+			bnd.trace("attrs for %s %s", info.packageName, info.attributes);
+
+			info.newerVersion = getVersion(info.attributes);
+			info.olderVersion = getVersion(oExports.get(info.packageName));
+			if (pdiff.getDelta() == Delta.UNCHANGED) {
+				info.suggestedVersion = info.olderVersion;
+				if (!info.newerVersion.equals(info.olderVersion)) {
+					info.warning += "No difference but versions are not equal";
+				}
+			} else if (pdiff.getDelta() == Delta.REMOVED) {
+				info.suggestedVersion = null;
+			} else if (pdiff.getDelta() == Delta.ADDED) {
+				if (firstRelease) {
+					info.suggestedVersion = info.newerVersion;
+					if (info.suggestedVersion.equals(Version.emptyVersion)) {
+						info.suggestedVersion = newerVersion.getWithoutQualifier();
+					}
+				} else {
+					info.suggestedVersion = Version.ONE;
+				}
+			} else {
+				// We have an API change
+				info.suggestedVersion = bump(pdiff.getDelta(), info.olderVersion, 1, 0);
+
+				if (info.newerVersion.compareTo(info.suggestedVersion) < 0) {
+					info.mismatch = true; // our suggested version is smaller
+											// than
+											// the
+											// old version!
+
+					// We can fix some major problems by assuming
+					// that an interface is a provider interface
+					if (pdiff.getDelta() == Delta.MAJOR) {
+
+						info.providers = Create.set();
+						if (info.attributes != null)
+							info.providers.addAll(Processor.split(info.attributes
+									.get(Constants.PROVIDER_TYPE_DIRECTIVE)));
+
+						// Calculate the new delta assuming we fix all the major
+						// interfaces
+						// by making them providers
+						Delta tryDelta = pdiff.getDelta(new Ignore() {
+							public boolean contains(Diff diff) {
+								if (diff.getType() == Type.INTERFACE && diff.getDelta() == Delta.MAJOR) {
+									info.providers.add(Descriptors.getShortName(diff.getName()));
+									return true;
+								}
+								return false;
+							}
+						});
+
+						if (tryDelta != Delta.MAJOR) {
+							info.suggestedIfProviders = bump(tryDelta, info.olderVersion, 1, 0);
+						}
+					}
+				}
+			}
+			if (pdiff.getDelta().compareTo(highestDelta) > 0) {
+				highestDelta = pdiff.getDelta();
+			}
+		}
+		if (firstRelease) {
+			suggestedVersion = newerVersion;
+		} else {
+			suggestedVersion = bumpBundle(highestDelta, olderVersion, 1, 0);
+		}
+		return infos;
+	}
+
+	/**
+	 * Gets the generated diff
+	 * 
+	 * @return the diff
+	 */
+	public Diff getDiff() {
+		return diff;
+	}
+
+	public Set<Info> getPackageInfos() {
+		if (infos == null)
+			return Collections.emptySet();
+		return infos;
+	}
+
+	public String getBsn() {
+		return bsn;
+	}
+
+	public Version getSuggestedVersion() {
+		return suggestedVersion;
+	}
+
+	public void setSuggestedVersion(Version suggestedVersion) {
+		this.suggestedVersion = suggestedVersion;
+	}
+
+	public Version getNewerVersion() {
+		return newerVersion;
+	}
+
+	public Version getOlderVersion() {
+		return olderVersion;
+	}
+
+	public String getReleaseRepository() {
+		return releaseRepository;
+	}
+
+	public void setReleaseRepository(String releaseRepository) {
+		this.releaseRepository = releaseRepository;
+	}
+
+	private Version bump(Delta delta, Version last, int offset, int base) {
+		switch (delta) {
+			case UNCHANGED :
+				return last;
+			case MINOR :
+				return new Version(last.getMajor(), last.getMinor() + offset, base);
+			case MAJOR :
+				return new Version(last.getMajor() + 1, base, base);
+			case ADDED :
+				return last;
+			default :
+				return new Version(last.getMajor(), last.getMinor(), last.getMicro() + offset);
+		}
+	}
+
+	private Version getVersion(Map<String,String> map) {
+		if (map == null)
+			return Version.LOWEST;
+
+		return Version.parseVersion(map.get(Constants.VERSION_ATTRIBUTE));
+	}
+
+	private Parameters getExports(Jar jar) throws Exception {
+		Manifest m = jar.getManifest();
+		if (m == null)
+			return new Parameters();
+
+		return OSGiHeader.parseHeader(m.getMainAttributes().getValue(Constants.EXPORT_PACKAGE));
+	}
+	
+	private Version getVersion(Tree top) {
+		Tree manifest = top.get("<manifest>");
+		if (manifest == null) {
+			return Version.emptyVersion;
+		}
+		for (Tree tree : manifest.getChildren()) {
+			if (tree.getName().startsWith(Constants.BUNDLE_VERSION)) {
+				return Version.parseVersion(tree.getName().substring(15));
+			}
+		}
+		return Version.emptyVersion;
+	}
+
+	private String getBsn(Tree top) {
+		Tree manifest = top.get("<manifest>");
+		if (manifest == null) {
+			return "";
+		}
+		for (Tree tree : manifest.getChildren()) {
+			if (tree.getName().startsWith(Constants.BUNDLE_SYMBOLICNAME) && tree.getChildren().length > 0) {
+				return tree.getChildren()[0].getName();
+			}
+		}
+		return "";
+	}
+
+	private Version bumpBundle(Delta delta, Version last, int offset, int base) {
+		switch (delta) {
+			case MINOR :
+				return new Version(last.getMajor(), last.getMinor() + offset, base);
+			case MAJOR :
+				return new Version(last.getMajor() + 1, base, base);
+			case ADDED :
+				return new Version(last.getMajor(), last.getMinor() + offset, base);
+			default :
+				return new Version(last.getMajor(), last.getMinor(), last.getMicro() + offset);
+		}
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/differ/DiffImpl.java b/biz.aQute.bndlib/src/aQute/bnd/differ/DiffImpl.java
new file mode 100644
index 0000000..ef21f65
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/differ/DiffImpl.java
@@ -0,0 +1,243 @@
+package aQute.bnd.differ;
+
+import static aQute.bnd.service.diff.Delta.*;
+
+import java.util.*;
+
+import aQute.bnd.service.diff.*;
+
+/**
+ * A DiffImpl class compares a newer Element to an older Element. The Element
+ * classes hide all the low level details. A Element class is either either
+ * Structured (has children) or it is a Leaf, it only has a value. The
+ * constructor will first build its children (if any) and then calculate the
+ * delta. Each comparable element is translated to an Element. If necessary the
+ * Element can be sub classed to provide special behavior.
+ */
+
+public class DiffImpl implements Diff, Comparable<DiffImpl> {
+
+	final Tree				older;
+	final Tree				newer;
+	final Collection<DiffImpl>	children;
+	final Delta					delta;
+
+	/**
+	 * The transitions table defines how the state is escalated depending on the
+	 * children. horizontally is the current delta and this is indexed with the
+	 * child delta for each child. This escalates deltas from below up.
+	 */
+	final static Delta[][]		TRANSITIONS	= {
+			{
+			IGNORED, UNCHANGED, CHANGED, MICRO, MINOR, MAJOR
+			}, // IGNORED
+			{
+			IGNORED, UNCHANGED, CHANGED, MICRO, MINOR, MAJOR
+			}, // UNCHANGED
+			{
+			IGNORED, CHANGED, CHANGED, MICRO, MINOR, MAJOR
+			}, // CHANGED
+			{
+			IGNORED, MICRO, MICRO, MICRO, MINOR, MAJOR
+			}, // MICRO
+			{
+			IGNORED, MINOR, MINOR, MINOR, MINOR, MAJOR
+			}, // MINOR
+			{
+			IGNORED, MAJOR, MAJOR, MAJOR, MAJOR, MAJOR
+			}, // MAJOR
+			{
+			IGNORED, MAJOR, MAJOR, MAJOR, MAJOR, MAJOR
+			}, // REMOVED
+			{
+			IGNORED, MINOR, MINOR, MINOR, MINOR, MAJOR
+			}, // ADDED
+											};
+
+	/**
+	 * Compares the newer against the older, traversing the children if
+	 * necessary.
+	 * 
+	 * @param newer
+	 *            The newer Element
+	 * @param older
+	 *            The older Element
+	 * @param types
+	 */
+	public DiffImpl(Tree newer, Tree older) {
+		assert newer != null || older != null;
+		this.older = older;
+		this.newer = newer;
+
+		// Either newer or older can be null, indicating remove or add
+		// so we have to be very careful.
+		Tree[] newerChildren = newer == null ? Element.EMPTY : newer.getChildren();
+		Tree[] olderChildren = older == null ? Element.EMPTY : older.getChildren();
+
+		int o = 0;
+		int n = 0;
+		List<DiffImpl> children = new ArrayList<DiffImpl>();
+		while (true) {
+			Tree nw = n < newerChildren.length ? newerChildren[n] : null;
+			Tree ol = o < olderChildren.length ? olderChildren[o] : null;
+			DiffImpl diff;
+
+			if (nw == null && ol == null)
+				break;
+
+			if (nw != null && ol != null) {
+				// we have both sides
+				int result = nw.compareTo(ol);
+				if (result == 0) {
+					// we have two equal named elements
+					// use normal diff
+					diff = new DiffImpl(nw, ol);
+					n++;
+					o++;
+				} else if (result > 0) {
+					// we newer > older, so there is no newer == removed
+					diff = new DiffImpl(null, ol);
+					o++;
+				} else {
+					// we newer < older, so there is no older == added
+					diff = new DiffImpl(nw, null);
+					n++;
+				}
+			} else {
+				// we reached the end of one of the list
+				diff = new DiffImpl(nw, ol);
+				n++;
+				o++;
+			}
+			children.add(diff);
+		}
+
+		// make sure they're read only
+		this.children = Collections.unmodifiableCollection(children);
+		delta = getDelta(null);
+	}
+
+	/**
+	 * Return the absolute delta. Also see
+	 * {@link #getDelta(aQute.bnd.service.diff.Diff.Ignore)} that allows you to
+	 * ignore Diff objects on the fly (and calculate their parents accordingly).
+	 */
+	public Delta getDelta() {
+		return delta;
+	}
+
+	/**
+	 * This getDelta calculates the delta but allows the caller to ignore
+	 * certain Diff objects by calling back the ignore call back parameter. This
+	 * can be useful to ignore warnings/errors.
+	 */
+
+	public Delta getDelta(Ignore ignore) {
+
+		// If ignored, we just return ignore.
+		if (ignore != null && ignore.contains(this))
+			return IGNORED;
+
+		if (newer == null) {
+			return REMOVED;
+		} else if (older == null) {
+			return ADDED;
+		} else {
+			// now we're sure newer and older are both not null
+			assert newer != null && older != null;
+			assert newer.getClass() == older.getClass();
+
+			Delta local = Delta.UNCHANGED;
+
+			for (DiffImpl child : children) {
+				Delta sub = child.getDelta(ignore);
+				if (sub == REMOVED)
+					sub = child.older.ifRemoved();
+				else if (sub == ADDED)
+					sub = child.newer.ifAdded();
+
+				// The escalate method is used to calculate the default
+				// transition in the
+				// delta based on the children. In general the delta can
+				// only escalate, i.e.
+				// move up in the chain.
+
+				local = TRANSITIONS[sub.ordinal()][local.ordinal()];
+			}
+			return local;
+		}
+	}
+
+	public Type getType() {
+		return (newer == null ? older : newer).getType();
+	}
+
+	public String getName() {
+		return (newer == null ? older : newer).getName();
+	}
+
+	public Collection< ? extends Diff> getChildren() {
+		return children;
+	}
+
+	@Override
+	public String toString() {
+		return String.format("%-10s %-10s %s", getDelta(), getType(), getName());
+	}
+
+	@Override
+	public boolean equals(Object other) {
+		if (other instanceof DiffImpl) {
+			DiffImpl o = (DiffImpl) other;
+			return getDelta() == o.getDelta() && getType() == o.getType() && getName().equals(o.getName());
+		}
+		return false;
+	}
+
+	@Override
+	public int hashCode() {
+		return getDelta().hashCode() ^ getType().hashCode() ^ getName().hashCode();
+	}
+
+	public int compareTo(DiffImpl other) {
+		if (getDelta() == other.getDelta()) {
+			if (getType() == other.getType()) {
+				return getName().compareTo(other.getName());
+			}
+			return getType().compareTo(other.getType());
+		}
+		return getDelta().compareTo(other.getDelta());
+	}
+
+	public Diff get(String name) {
+		for (DiffImpl child : children) {
+			if (child.getName().equals(name))
+				return child;
+		}
+		return null;
+	}
+
+	public Tree getOlder() {
+		return older;
+	}
+
+	public Tree getNewer() {
+		return newer;
+	}
+
+	public Data serialize() {
+		Data data = new Data();
+		data.type = getType();
+		data.delta = delta;
+		data.name = getName();
+		data.children = new Data[children.size()];
+		
+		int i=0;		
+		for ( Diff d : children)
+			data.children[i++] = d.serialize();
+				
+		return data;
+	}
+
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/differ/DiffPluginImpl.java b/biz.aQute.bndlib/src/aQute/bnd/differ/DiffPluginImpl.java
new file mode 100644
index 0000000..d3dc6a4
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/differ/DiffPluginImpl.java
@@ -0,0 +1,192 @@
+package aQute.bnd.differ;
+
+import static aQute.bnd.service.diff.Delta.*;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.diff.*;
+import aQute.bnd.service.diff.Tree.Data;
+import aQute.lib.collections.*;
+import aQute.lib.hex.*;
+import aQute.lib.io.*;
+import aQute.libg.cryptography.*;
+
+/**
+ * This Diff Plugin Implementation will compare JARs for their API (based on the
+ * Bundle Class Path and exported packages), the Manifest, and the resources.
+ * The Differences are represented in a {@link Diff} tree.
+ */
+public class DiffPluginImpl implements Differ {
+
+	/**
+	 * Headers that are considered major enough to parse according to spec and
+	 * compare their constituents
+	 */
+	final static Set<String>	MAJOR_HEADERS	= new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
+
+	/**
+	 * Headers that are considered not major enough to be considered
+	 */
+	final static Set<String>	IGNORE_HEADERS	= new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
+
+	/**
+	 * Headers that have values that should be sorted
+	 */
+	final static Set<String>	ORDERED_HEADERS	= new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
+
+	static {
+		MAJOR_HEADERS.add(Constants.EXPORT_PACKAGE);
+		MAJOR_HEADERS.add(Constants.IMPORT_PACKAGE);
+		MAJOR_HEADERS.add(Constants.REQUIRE_BUNDLE);
+		MAJOR_HEADERS.add(Constants.FRAGMENT_HOST);
+		MAJOR_HEADERS.add(Constants.BUNDLE_SYMBOLICNAME);
+		MAJOR_HEADERS.add(Constants.BUNDLE_LICENSE);
+		MAJOR_HEADERS.add(Constants.BUNDLE_NATIVECODE);
+		MAJOR_HEADERS.add(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT);
+		MAJOR_HEADERS.add(Constants.DYNAMICIMPORT_PACKAGE);
+
+		IGNORE_HEADERS.add(Constants.TOOL);
+		IGNORE_HEADERS.add(Constants.BND_LASTMODIFIED);
+		IGNORE_HEADERS.add(Constants.CREATED_BY);
+
+		ORDERED_HEADERS.add(Constants.SERVICE_COMPONENT);
+		ORDERED_HEADERS.add(Constants.TESTCASES);
+	}
+
+	/**
+	 * @see aQute.bnd.service.diff.Differ#diff(aQute.lib.resource.Jar,
+	 *      aQute.lib.resource.Jar)
+	 */
+	public Tree tree(File newer) throws Exception {
+		Jar jnewer = new Jar(newer);
+		try {
+			return tree(jnewer);
+		}
+		finally {
+			jnewer.close();
+		}
+	}
+
+	/**
+	 * @see aQute.bnd.service.diff.Differ#diff(aQute.lib.resource.Jar,
+	 *      aQute.lib.resource.Jar)
+	 */
+	public Tree tree(Jar newer) throws Exception {
+		Analyzer anewer = new Analyzer();
+		try {
+			anewer.setJar(newer);
+			return tree(anewer);
+		}
+		finally {
+			anewer.setJar((Jar) null);
+			anewer.close();
+		}
+	}
+
+	public Tree tree(Analyzer newer) throws Exception {
+		return bundleElement(newer);
+	}
+
+	/**
+	 * Create an element representing a bundle from the Jar.
+	 * 
+	 * @param infos
+	 * @param jar
+	 *            The Jar to be analyzed
+	 * @return the elements that should be compared
+	 * @throws Exception
+	 */
+	private Element bundleElement(Analyzer analyzer) throws Exception {
+		List<Element> result = new ArrayList<Element>();
+
+		Manifest manifest = analyzer.getJar().getManifest();
+
+		if (manifest != null) {
+			result.add(JavaElement.getAPI(analyzer));
+			result.add(manifestElement(manifest));
+		}
+		result.add(resourcesElement(analyzer.getJar()));
+		return new Element(Type.BUNDLE, analyzer.getJar().getName(), result, CHANGED, CHANGED, null);
+	}
+
+	/**
+	 * Create an element representing all resources in the JAR
+	 * 
+	 * @param jar
+	 * @return
+	 * @throws Exception
+	 */
+	private Element resourcesElement(Jar jar) throws Exception {
+		List<Element> resources = new ArrayList<Element>();
+		for (Map.Entry<String,Resource> entry : jar.getResources().entrySet()) {
+
+			InputStream in = entry.getValue().openInputStream();
+			try {
+				Digester<SHA1> digester = SHA1.getDigester();
+				IO.copy(in, digester);
+				String value = Hex.toHexString(digester.digest().digest());
+				resources.add(new Element(Type.RESOURCE, entry.getKey(), Arrays.asList(new Element(Type.SHA,value)), CHANGED, CHANGED, null));
+			}
+			finally {
+				in.close();
+			}
+		}
+		return new Element(Type.RESOURCES, "<resources>", resources, CHANGED, CHANGED, null);
+	}
+
+	/**
+	 * Create an element for each manifest header. There are
+	 * {@link #IGNORE_HEADERS} and {@link #MAJOR_HEADERS} that will be treated
+	 * differently.
+	 * 
+	 * @param manifest
+	 * @return
+	 */
+
+	private Element manifestElement(Manifest manifest) {
+		List<Element> result = new ArrayList<Element>();
+
+		for (Object key : manifest.getMainAttributes().keySet()) {
+			String header = key.toString();
+			String value = manifest.getMainAttributes().getValue(header);
+			if (IGNORE_HEADERS.contains(header))
+				continue;
+
+			if (MAJOR_HEADERS.contains(header)) {
+				Parameters clauses = OSGiHeader.parseHeader(value);
+				Collection<Element> clausesDef = new ArrayList<Element>();
+				for (Map.Entry<String,Attrs> clause : clauses.entrySet()) {
+					Collection<Element> parameterDef = new ArrayList<Element>();
+					for (Map.Entry<String,String> parameter : clause.getValue().entrySet()) {
+						String paramValue = parameter.getValue();
+						if (Constants.EXPORT_PACKAGE.equals(header) && Constants.USES_DIRECTIVE.equals(parameter.getKey())) {
+							ExtList<String> uses = ExtList.from(parameter.getValue());
+							Collections.sort(uses);
+							paramValue = uses.join();
+						}
+						parameterDef.add(new Element(Type.PARAMETER, parameter.getKey() + ":" + paramValue,
+								null, CHANGED, CHANGED, null));
+					}
+					clausesDef.add(new Element(Type.CLAUSE, clause.getKey(), parameterDef, CHANGED, CHANGED, null));
+				}
+				result.add(new Element(Type.HEADER, header, clausesDef, CHANGED, CHANGED, null));
+			} else if (ORDERED_HEADERS.contains(header)) {
+				ExtList<String> values = ExtList.from(value);
+				Collections.sort(values);
+				result.add(new Element(Type.HEADER, header + ":" + values.join(), null, CHANGED, CHANGED, null));
+			} else {
+				result.add(new Element(Type.HEADER, header + ":" + value, null, CHANGED, CHANGED, null));
+			}
+		}
+		return new Element(Type.MANIFEST, "<manifest>", result, CHANGED, CHANGED, null);
+	}
+
+	public Tree deserialize(Data data) throws Exception {
+		return new Element(data);
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/differ/Element.java b/biz.aQute.bndlib/src/aQute/bnd/differ/Element.java
new file mode 100644
index 0000000..6b74b4d
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/differ/Element.java
@@ -0,0 +1,145 @@
+package aQute.bnd.differ;
+
+import java.util.*;
+
+import aQute.bnd.service.diff.*;
+
+/**
+ * An element can be compared to another element of the same type. Elements with
+ * the same name and same place in the hierarchy should have the same type. The
+ * idea is that for a certain resource type you create an element (Structured or
+ * Leaf). This process is done for the newer and older resource.
+ * <p>
+ * A Leaf type has a value, comparison is rather simple in this case.
+ * <p>
+ * A Structured type has named children. The comparison between the newer and
+ * older child elements is then done on their name. Two elements with the same
+ * name are then matched.
+ * <p>
+ * The classes are prepared for extension but so far it turned out to be
+ * unnecessary.
+ */
+
+class Element implements Tree {
+	final static Element[]	EMPTY	= new Element[0];
+	final Type				type;
+	final String			name;
+	final Delta				add;
+	final Delta				remove;
+	final String			comment;
+	final Element[]			children;
+
+	Element(Type type, String name) {
+		this(type, name, null, Delta.MINOR, Delta.MAJOR, null);
+	}
+
+	Element(Type type, String name, Element... children) {
+		this(type, name, Arrays.asList(children), Delta.MINOR, Delta.MAJOR, null);
+	}
+
+	Element(Type type, String name, Collection< ? extends Element> children, Delta add, Delta remove, String comment) {
+		this.type = type;
+		this.name = name;
+		this.add = add;
+		this.remove = remove;
+		this.comment = comment;
+		if (children != null && children.size() > 0) {
+			this.children = children.toArray(new Element[children.size()]);
+			Arrays.sort(this.children);
+		} else
+			this.children = EMPTY;
+	}
+
+	public Element(Data data) {
+		this.name = data.name;
+		this.type = data.type;
+		this.comment = data.comment;
+		this.add = data.add;
+		this.remove = data.rem;
+		if (data.children == null)
+			children = EMPTY;
+		else {
+			this.children = new Element[data.children.length];
+			for (int i = 0; i < children.length; i++)
+				children[i] = new Element(data.children[i]);
+			Arrays.sort(this.children);
+		}
+	}
+
+	public Data serialize() {
+		Data data = new Data();
+		data.type = this.type;
+		data.name = this.name;
+		data.add = this.add;
+		data.rem = this.remove;
+		data.comment = this.comment;
+		if (children.length != 0) {
+			data.children = new Data[children.length];
+			for (int i = 0; i < children.length; i++) {
+				data.children[i] = children[i].serialize();
+			}
+		}
+		return data;
+	}
+
+	public Type getType() {
+		return type;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	String getComment() {
+		return comment;
+	}
+
+	public int compareTo(Tree other) {
+		if (type == other.getType())
+			return name.compareTo(other.getName());
+		return type.compareTo(other.getType());
+	}
+
+	@Override
+	public boolean equals(Object other) {
+		if (other == null || getClass() != other.getClass())
+			return false;
+
+		return compareTo((Element) other) == 0;
+	}
+
+	@Override
+	public int hashCode() {
+		return type.hashCode() ^ name.hashCode();
+	}
+
+	public Tree[] getChildren() {
+		return children;
+	}
+
+	public Delta ifAdded() {
+		return add;
+	}
+
+	public Delta ifRemoved() {
+		return remove;
+	}
+
+	public Diff diff(Tree older) {
+		return new DiffImpl(this, older);
+	}
+
+	public Element get(String name) {
+		for (Element e : children) {
+			if (e.name.equals(name))
+				return e;
+		}
+		return null;
+	}
+
+	@Override
+	public String toString() {
+		return type + " " + name + " (" + add + "/" + remove + ")";
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/differ/JavaElement.java b/biz.aQute.bndlib/src/aQute/bnd/differ/JavaElement.java
new file mode 100644
index 0000000..b8905ea
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/differ/JavaElement.java
@@ -0,0 +1,647 @@
+package aQute.bnd.differ;
+
+import static aQute.bnd.service.diff.Delta.*;
+import static aQute.bnd.service.diff.Type.*;
+import static java.lang.reflect.Modifier.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.concurrent.atomic.*;
+import java.util.jar.*;
+
+import aQute.bnd.annotation.*;
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Clazz.JAVA;
+import aQute.bnd.osgi.Clazz.MethodDef;
+import aQute.bnd.osgi.Descriptors.PackageRef;
+import aQute.bnd.osgi.Descriptors.TypeRef;
+import aQute.bnd.service.diff.*;
+import aQute.bnd.service.diff.Type;
+import aQute.bnd.version.Version;
+import aQute.lib.collections.*;
+import aQute.libg.generics.*;
+
+/**
+ * An element that compares the access field in a binary compatible way. This
+ * element is used for classes, methods, constructors, and fields. For that
+ * reason we also included the only method that uses this class as a static
+ * method.
+ * <p>
+ * Packages
+ * <ul>
+ * <li>MAJOR - Remove a public type
+ * <li>MINOR - Add a public class
+ * <li>MINOR - Add an interface
+ * <li>MINOR - Add a method to a class
+ * <li>MINOR - Add a method to a provider interface
+ * <li>MAJOR - Add a method to a consumer interface
+ * <li>MINOR - Add a field
+ * <li>MICRO - Add an annotation to a member
+ * <li>MINOR - Change the value of a constant
+ * <li>MICRO - -abstract
+ * <li>MICRO - -final
+ * <li>MICRO - -protected
+ * <li>MAJOR - +abstract
+ * <li>MAJOR - +final
+ * <li>MAJOR - +protected
+ * </ul>
+ */
+
+class JavaElement {
+	final static EnumSet<Type>			INHERITED		= EnumSet.of(FIELD, METHOD, EXTENDS, IMPLEMENTS);
+	private static final Element		PROTECTED		= new Element(ACCESS, "protected", null, MAJOR, MINOR, null);
+	private static final Element		STATIC			= new Element(ACCESS, "static", null, MAJOR, MAJOR, null);
+	private static final Element		ABSTRACT		= new Element(ACCESS, "abstract", null, MAJOR, MINOR, null);
+	private static final Element		FINAL			= new Element(ACCESS, "final", null, MAJOR, MINOR, null);
+	// private static final Element DEPRECATED = new Element(ACCESS,
+	// "deprecated", null,
+	// CHANGED, CHANGED, null);
+
+	final Analyzer						analyzer;
+	final Map<PackageRef,Instructions>	providerMatcher	= Create.map();
+	final Set<TypeRef>					notAccessible	= Create.set();
+	final Map<Object,Element>			cache			= Create.map();
+	MultiMap<PackageRef, //
+	Element>							packages;
+	final MultiMap<TypeRef, //
+	Element>							covariant		= new MultiMap<TypeRef,Element>();
+	final Set<JAVA>						javas			= Create.set();
+	final Packages						exports;
+
+	/**
+	 * Create an element for the API. We take the exported packages and traverse
+	 * those for their classes. If there is no manifest or it does not describe
+	 * a bundle we assume the whole contents is exported.
+	 * 
+	 * @param infos
+	 */
+	JavaElement(Analyzer analyzer) throws Exception {
+		this.analyzer = analyzer;
+
+		Manifest manifest = analyzer.getJar().getManifest();
+		if (manifest != null && manifest.getMainAttributes().getValue(Constants.BUNDLE_MANIFESTVERSION) != null) {
+			exports = new Packages();
+			for (Map.Entry<String,Attrs> entry : OSGiHeader.parseHeader(
+					manifest.getMainAttributes().getValue(Constants.EXPORT_PACKAGE)).entrySet())
+				exports.put(analyzer.getPackageRef(entry.getKey()), entry.getValue());
+		} else
+			exports = analyzer.getContained();
+		//
+		// We have to gather the -providers and parse them into instructions
+		// so we can efficiently match them during class parsing to find
+		// out who the providers and consumers are
+		//
+
+		for (Entry<PackageRef,Attrs> entry : exports.entrySet()) {
+			String value = entry.getValue().get(Constants.PROVIDER_TYPE_DIRECTIVE);
+			if (value != null) {
+				providerMatcher.put(entry.getKey(), new Instructions(value));
+			}
+		}
+
+		// we now need to gather all the packages but without
+		// creating the packages yet because we do not yet know
+		// which classes are accessible
+
+		packages = new MultiMap<PackageRef,Element>();
+
+		for (Clazz c : analyzer.getClassspace().values()) {
+			if (c.isPublic() || c.isProtected()) {
+				PackageRef packageName = c.getClassName().getPackageRef();
+
+				if (exports.containsKey(packageName)) {
+					Element cdef = classElement(c);
+					packages.add(packageName, cdef);
+				}
+			}
+		}
+
+	}
+
+	static Element getAPI(Analyzer analyzer) throws Exception {
+		analyzer.analyze();
+		JavaElement te = new JavaElement(analyzer);
+		return te.getLocalAPI();
+	}
+
+	private Element getLocalAPI() throws Exception {
+		List<Element> result = new ArrayList<Element>();
+
+		for (Map.Entry<PackageRef,List<Element>> entry : packages.entrySet()) {
+			List<Element> set = entry.getValue();
+			for (Iterator<Element> i = set.iterator(); i.hasNext();) {
+
+				if (notAccessible.contains(analyzer.getTypeRefFromFQN(i.next().getName())))
+					i.remove();
+
+			}
+			String version = exports.get(entry.getKey()).get(Constants.VERSION_ATTRIBUTE);
+			if (version != null) {
+				Version v = new Version(version);
+				set.add(new Element(Type.VERSION, v.getWithoutQualifier().toString(), null, IGNORED, IGNORED, null));
+			}
+			Element pd = new Element(Type.PACKAGE, entry.getKey().getFQN(), set, MINOR, MAJOR, null);
+			result.add(pd);
+		}
+
+		for (JAVA java : javas) {
+			result.add(new Element(CLASS_VERSION, java.toString(), null, Delta.CHANGED, Delta.CHANGED, null));
+		}
+
+		return new Element(Type.API, "<api>", result, CHANGED, CHANGED, null);
+	}
+
+	/**
+	 * Calculate the class element. This requires parsing the class file and
+	 * finding all the methods that were added etc. The parsing will take super
+	 * interfaces and super classes into account. For this reason it maintains a
+	 * queue of classes/interfaces to parse.
+	 * 
+	 * @param analyzer
+	 * @param clazz
+	 * @param infos
+	 * @return
+	 * @throws Exception
+	 */
+	Element classElement(final Clazz clazz) throws Exception {
+		Element e = cache.get(clazz);
+		if (e != null)
+			return e;
+
+		final StringBuilder comment = new StringBuilder();
+		final Set<Element> members = new HashSet<Element>();
+		final Set<MethodDef> methods = Create.set();
+		final Set<Clazz.FieldDef> fields = Create.set();
+		final MultiMap<Clazz.Def,Element> annotations = new MultiMap<Clazz.Def,Element>();
+
+		final TypeRef name = clazz.getClassName();
+
+		final String fqn = name.getFQN();
+		final String shortName = name.getShortName();
+
+		// Check if this clazz is actually a provider or not
+		// providers must be listed in the exported package in the
+		// PROVIDER_TYPE directive.
+		Instructions matchers = providerMatcher.get(name.getPackageRef());
+		boolean p = matchers != null && matchers.matches(shortName);
+		final AtomicBoolean provider = new AtomicBoolean(p);
+
+		//
+		// Check if we already had this clazz in the cache
+		//
+
+		Element before = cache.get(clazz); // for super classes
+		if (before != null)
+			return before;
+
+		clazz.parseClassFileWithCollector(new ClassDataCollector() {
+			boolean			memberEnd;
+			Clazz.FieldDef	last;
+
+			@Override
+			public void version(int minor, int major) {
+				javas.add(Clazz.JAVA.getJava(major, minor));
+			}
+
+			@Override
+			public void method(MethodDef defined) {
+				if ((defined.isProtected() || defined.isPublic())) {
+					last = defined;
+					methods.add(defined);
+				} else {
+					last = null;
+				}
+			}
+
+			@Override
+			public void deprecated() {
+				if (memberEnd)
+					clazz.setDeprecated(true);
+				else if (last != null)
+					last.setDeprecated(true);
+			}
+
+			@Override
+			public void field(Clazz.FieldDef defined) {
+				if (defined.isProtected() || defined.isPublic()) {
+					last = defined;
+					fields.add(defined);
+				} else
+					last = null;
+			}
+
+			@Override
+			public void constant(Object o) {
+				if (last != null) {
+					// Must be accessible now
+					last.setConstant(o);
+				}
+			}
+
+			@Override
+			public void extendsClass(TypeRef name) throws Exception {
+				String comment = null;
+				if (!clazz.isInterface())
+					comment = inherit(members, name);
+
+				Clazz c = analyzer.findClass(name);
+				if ((c == null || c.isPublic()) && !name.isObject())
+					members.add(new Element(Type.EXTENDS, name.getFQN(), null, MICRO, MAJOR, comment));
+			}
+
+			@Override
+			public void implementsInterfaces(TypeRef names[]) throws Exception {
+				// TODO is interface reordering important for binary
+				// compatibility??
+
+				for (TypeRef name : names) {
+
+					String comment = null;
+					if (clazz.isInterface() || clazz.isAbstract())
+						comment = inherit(members, name);
+					members.add(new Element(Type.IMPLEMENTS, name.getFQN(), null, MINOR, MAJOR, comment));
+				}
+			}
+
+			/**
+			 * @param members
+			 * @param name
+			 * @param comment
+			 * @return
+			 */
+			Set<Element>	OBJECT	= Create.set();
+
+			public String inherit(final Set<Element> members, TypeRef name) throws Exception {
+				if (name.isObject()) {
+					if (OBJECT.isEmpty()) {
+						Clazz c = analyzer.findClass(name);
+						Element s = classElement(c);
+						for (Element child : s.children) {
+							if (INHERITED.contains(child.type)) {
+								String n = child.getName();
+								if (child.type == METHOD) {
+									if (n.startsWith("<init>") || "getClass()".equals(child.getName())
+											|| n.startsWith("wait(") || n.startsWith("notify(")
+											|| n.startsWith("notifyAll("))
+										continue;
+								}
+								OBJECT.add(child);
+							}
+						}
+					}
+					members.addAll(OBJECT);
+				} else {
+
+					Clazz c = analyzer.findClass(name);
+					if (c == null) {
+						return "Cannot load " + name;
+					}
+					Element s = classElement(c);
+					for (Element child : s.children) {
+						if (INHERITED.contains(child.type) && !child.name.startsWith("<")) {
+							members.add(child);
+						}
+					}
+				}
+				return null;
+			}
+
+			@Override
+			public void annotation(Annotation annotation) {
+				Collection<Element> properties = Create.set();
+				if (Deprecated.class.getName().equals(annotation.getName().getFQN())) {
+					if (memberEnd)
+						clazz.setDeprecated(true);
+					else if (last != null)
+						last.setDeprecated(true);
+					return;
+				}
+
+				for (String key : annotation.keySet()) {
+					StringBuilder sb = new StringBuilder();
+					sb.append(key);
+					sb.append('=');
+					toString(sb, annotation.get(key));
+
+					properties.add(new Element(Type.PROPERTY, sb.toString(), null, CHANGED, CHANGED, null));
+				}
+
+				if (memberEnd) {
+					members.add(new Element(Type.ANNOTATED, annotation.getName().getFQN(), properties, CHANGED,
+							CHANGED, null));
+					if (ProviderType.class.getName().equals(annotation.getName().getFQN())) {
+						provider.set(true);
+					} else if (ConsumerType.class.getName().equals(annotation.getName().getFQN())) {
+						provider.set(false);
+					}
+				} else if (last != null)
+					annotations.add(last, new Element(Type.ANNOTATED, annotation.getName().getFQN(), properties,
+							CHANGED, CHANGED, null));
+			}
+
+			private void toString(StringBuilder sb, Object object) {
+
+				if (object.getClass().isArray()) {
+					sb.append('[');
+					int l = Array.getLength(object);
+					for (int i = 0; i < l; i++)
+						toString(sb, Array.get(object, i));
+					sb.append(']');
+				} else
+					sb.append(object);
+			}
+
+			@Override
+			public void innerClass(TypeRef innerClass, TypeRef outerClass, String innerName, int innerClassAccessFlags)
+					throws Exception {
+				Clazz clazz = analyzer.findClass(innerClass);
+				if (clazz != null)
+					clazz.setInnerAccess(innerClassAccessFlags);
+
+				if (Modifier.isProtected(innerClassAccessFlags) || Modifier.isPublic(innerClassAccessFlags))
+					return;
+				notAccessible.add(innerClass);
+			}
+
+			@Override
+			public void memberEnd() {
+				memberEnd = true;
+			}
+		});
+
+		// This is the heart of the semantic versioning. If we
+		// add or remove a method from an interface then
+		Delta add;
+		Delta remove;
+		Type type;
+
+		// Calculate the type of the clazz. A class
+		// can be an interface, class, enum, or annotation
+
+		if (clazz.isInterface())
+			if (clazz.isAnnotation())
+				type = Type.ANNOTATION;
+			else
+				type = Type.INTERFACE;
+		else if (clazz.isEnum())
+			type = Type.ENUM;
+		else
+			type = Type.CLASS;
+
+		if (type == Type.INTERFACE) {
+			if (provider.get()) {
+				// Adding a method for a provider is not an issue
+				// because it must be aware of the changes
+				add = MINOR;
+
+				// Removing a method influences consumers since they
+				// tend to call this guy.
+				remove = MAJOR;
+			} else {
+				// Adding a method is a major change
+				// because the consumer has to implement it
+				// or the provider will call a non existent
+				// method on the consumer
+				add = MAJOR;
+
+				// Removing a method is not an issue for
+				// providers, however, consumers could potentially
+				// call through this interface :-(
+
+				remove = MAJOR;
+			}
+		} else {
+			// Adding a method to a class can never do any harm
+			add = MINOR;
+
+			// Removing it will likely hurt consumers
+			remove = MAJOR;
+		}
+
+		// Remove all synthetic methods, we need
+		// to treat them special for the covariant returns
+
+		Set<MethodDef> synthetic = Create.set();
+		for (Iterator<MethodDef> i = methods.iterator(); i.hasNext();) {
+			MethodDef m = i.next();
+			if (m.isSynthetic()) {
+				synthetic.add(m);
+				i.remove();
+			}
+		}
+
+		for (MethodDef m : methods) {
+			List<Element> children = annotations.get(m);
+			if (children == null)
+				children = new ArrayList<Element>();
+
+			access(children, m.getAccess(), m.isDeprecated());
+
+			// A final class cannot be extended, ergo,
+			// all methods defined in it are by definition
+			// final. However, marking them final (either
+			// on the method or inheriting it from the class)
+			// will create superfluous changes if we
+			// override a method from a super class that was not
+			// final. So we actually remove the final for methods
+			// in a final class.
+			if (clazz.isFinal())
+				children.remove(FINAL);
+
+			// for covariant types we need to add the return types
+			// and all the implemented and extended types. This is already
+			// do for us when we get the element of the return type.
+
+			getCovariantReturns(children, m.getType());
+
+			for (Iterator<MethodDef> i = synthetic.iterator(); i.hasNext();) {
+				MethodDef s = i.next();
+				if (s.getName().equals(m.getName()) && Arrays.equals(s.getPrototype(), m.getPrototype())) {
+					i.remove();
+					getCovariantReturns(children, s.getType());
+				}
+			}
+
+			Element member = new Element(Type.METHOD, m.getName() + toString(m.getPrototype()), children, add, remove,
+					null);
+
+			if (!members.add(member)) {
+				members.remove(member);
+				members.add(member);
+			}
+		}
+
+		/**
+		 * Repeat for the remaining synthetic methods
+		 */
+		for (MethodDef m : synthetic) {
+			List<Element> children = annotations.get(m);
+			if (children == null)
+				children = new ArrayList<Element>();
+			access(children, m.getAccess(), m.isDeprecated());
+
+			// A final class cannot be extended, ergo,
+			// all methods defined in it are by definition
+			// final. However, marking them final (either
+			// on the method or inheriting it from the class)
+			// will create superfluous changes if we
+			// override a method from a super class that was not
+			// final. So we actually remove the final for methods
+			// in a final class.
+			if (clazz.isFinal())
+				children.remove(FINAL);
+
+			// for covariant types we need to add the return types
+			// and all the implemented and extended types. This is already
+			// done for us when we get the element of the return type.
+
+			getCovariantReturns(children, m.getType());
+
+			Element member = new Element(Type.METHOD, m.getName() + toString(m.getPrototype()), children, add, remove,
+					"synthetic");
+
+			if (!members.add(member)) {
+				members.remove(member);
+				members.add(member);
+			}
+		}
+
+		for (Clazz.FieldDef f : fields) {
+			List<Element> children = annotations.get(f);
+			if (children == null)
+				children = new ArrayList<Element>();
+
+			// Fields can have a constant value, this is a new element
+			if (f.getConstant() != null) {
+				children.add(new Element(Type.CONSTANT, f.getConstant().toString(), null, CHANGED, CHANGED, null));
+			}
+
+			access(children, f.getAccess(), f.isDeprecated());
+			Element member = new Element(Type.FIELD, f.getType().getFQN() + " " + f.getName(), children, MINOR, MAJOR,
+					null);
+
+			if (!members.add(member)) {
+				members.remove(member);
+				members.add(member);
+			}
+		}
+
+		access(members, clazz.getAccess(), clazz.isDeprecated());
+
+		// And make the result
+		Element s = new Element(type, fqn, members, MINOR, MAJOR, comment.length() == 0 ? null : comment.toString());
+		cache.put(clazz, s);
+		return s;
+	}
+
+	private String toString(TypeRef[] prototype) {
+		StringBuilder sb = new StringBuilder();
+		sb.append("(");
+		String del = "";
+		for (TypeRef ref : prototype) {
+			sb.append(del);
+			sb.append(ref.getFQN());
+			del = ",";
+		}
+		sb.append(")");
+		return sb.toString();
+	}
+
+	static Element	BOOLEAN_R	= new Element(RETURN, "boolean");
+	static Element	BYTE_R		= new Element(RETURN, "byte");
+	static Element	SHORT_R		= new Element(RETURN, "short");
+	static Element	CHAR_R		= new Element(RETURN, "char");
+	static Element	INT_R		= new Element(RETURN, "int");
+	static Element	LONG_R		= new Element(RETURN, "long");
+	static Element	FLOAT_R		= new Element(RETURN, "float");
+	static Element	DOUBLE_R	= new Element(RETURN, "double");
+
+	private void getCovariantReturns(Collection<Element> elements, TypeRef type) throws Exception {
+		if (type == null || type.isObject())
+			return;
+
+		if (type.isPrimitive()) {
+			if (type.getFQN().equals("void"))
+				return;
+
+			String name = type.getBinary();
+			Element e;
+			switch (name.charAt(0)) {
+				case 'Z' :
+					e = BOOLEAN_R;
+					break;
+				case 'S' :
+					e = SHORT_R;
+					break;
+				case 'I' :
+					e = INT_R;
+					break;
+				case 'B' :
+					e = BYTE_R;
+					break;
+				case 'C' :
+					e = CHAR_R;
+					break;
+				case 'J' :
+					e = LONG_R;
+					break;
+				case 'F' :
+					e = FLOAT_R;
+					break;
+				case 'D' :
+					e = DOUBLE_R;
+					break;
+
+				default :
+					throw new IllegalArgumentException("Unknown primitive " + type);
+			}
+			elements.add(e);
+			return;
+		}
+
+		List<Element> set = covariant.get(type);
+		if (set != null) {
+			elements.addAll(set);
+			return;
+		}
+
+		Element current = new Element(RETURN, type.getFQN());
+		Clazz clazz = analyzer.findClass(type);
+		if (clazz == null) {
+			elements.add(current);
+			return;
+		}
+
+		set = Create.list();
+		set.add(current);
+		getCovariantReturns(set, clazz.getSuper());
+
+		TypeRef[] interfaces = clazz.getInterfaces();
+		if (interfaces != null)
+			for (TypeRef intf : interfaces) {
+				getCovariantReturns(set, intf);
+			}
+
+		covariant.put(type, set);
+		elements.addAll(set);
+	}
+
+	private static void access(Collection<Element> children, int access, @SuppressWarnings("unused") boolean deprecated) {
+		if (!isPublic(access))
+			children.add(PROTECTED);
+		if (isAbstract(access))
+			children.add(ABSTRACT);
+		if (isFinal(access))
+			children.add(FINAL);
+		if (isStatic(access))
+			children.add(STATIC);
+
+		// Ignore for now
+		// if (deprecated)
+		// children.add(DEPRECATED);
+
+	}
+
+}
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/aQute/bnd/differ/RepositoryElement.java b/biz.aQute.bndlib/src/aQute/bnd/differ/RepositoryElement.java
new file mode 100644
index 0000000..99cdf89
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/differ/RepositoryElement.java
@@ -0,0 +1,23 @@
+package aQute.bnd.differ;
+
+import java.util.*;
+
+import aQute.bnd.service.*;
+import aQute.bnd.service.diff.*;
+import aQute.bnd.version.*;
+
+public class RepositoryElement {
+
+	public static Element getTree(RepositoryPlugin repo) throws Exception {
+		List<Element> programs = new ArrayList<Element>();
+		for (String bsn : repo.list(null)) {
+			List<Element> versions = new ArrayList<Element>();
+			for (Version version : repo.versions(bsn)) {
+				versions.add(new Element(Type.VERSION, version.toString()));
+			}
+			programs.add(new Element(Type.PROGRAM, bsn, versions, Delta.MINOR, Delta.MAJOR, null));
+		}
+		return new Element(Type.REPO, repo.getName(), programs, Delta.MINOR, Delta.MAJOR, repo.getLocation());
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/help/packageinfo b/biz.aQute.bndlib/src/aQute/bnd/differ/packageinfo
similarity index 100%
copy from biz.aQute.bndlib/src/aQute/bnd/help/packageinfo
copy to biz.aQute.bndlib/src/aQute/bnd/differ/packageinfo
diff --git a/biz.aQute.bndlib/src/aQute/bnd/filerepo/FileRepo.java b/biz.aQute.bndlib/src/aQute/bnd/filerepo/FileRepo.java
new file mode 100644
index 0000000..548ace7
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/filerepo/FileRepo.java
@@ -0,0 +1,109 @@
+package aQute.bnd.filerepo;
+
+import java.io.*;
+import java.util.*;
+import java.util.regex.*;
+
+import aQute.bnd.version.*;
+
+public class FileRepo {
+	File	root;
+	Pattern	REPO_FILE	= Pattern.compile("([-a-zA-z0-9_\\.]+)-([0-9\\.]+)\\.(jar|lib)");
+
+	public FileRepo(File root) {
+		this.root = root;
+	}
+
+	/**
+	 * Get a list of URLs to bundles that are constrained by the bsn and
+	 * versionRange.
+	 */
+	public File[] get(String bsn, final VersionRange versionRange) throws Exception {
+
+		//
+		// Check if the entry exists
+		//
+		File f = new File(root, bsn);
+		if (!f.isDirectory())
+			return null;
+
+		//
+		// Iterator over all the versions for this BSN.
+		// Create a sorted map over the version as key
+		// and the file as URL as value. Only versions
+		// that match the desired range are included in
+		// this list.
+		//
+		return f.listFiles(new FilenameFilter() {
+			public boolean accept(File dir, String name) {
+				Matcher m = REPO_FILE.matcher(name);
+				if (!m.matches())
+					return false;
+				if (versionRange == null)
+					return true;
+
+				Version v = new Version(m.group(2));
+				return versionRange.includes(v);
+			}
+		});
+	}
+
+	public List<String> list(String regex) throws Exception {
+		if (regex == null)
+			regex = ".*";
+		final Pattern pattern = Pattern.compile(regex);
+
+		String list[] = root.list(new FilenameFilter() {
+
+			public boolean accept(File dir, String name) {
+				Matcher matcher = pattern.matcher(name);
+				return matcher.matches();
+			}
+
+		});
+		return Arrays.asList(list);
+	}
+
+	public List<Version> versions(String bsn) throws Exception {
+		File dir = new File(root, bsn);
+		final List<Version> versions = new ArrayList<Version>();
+		dir.list(new FilenameFilter() {
+
+			public boolean accept(File dir, String name) {
+				Matcher m = REPO_FILE.matcher(name);
+				if (m.matches()) {
+					versions.add(new Version(m.group(2)));
+					return true;
+				}
+				return false;
+			}
+
+		});
+		return versions;
+	}
+
+	public File get(String bsn, VersionRange range, int strategy) throws Exception {
+		File[] files = get(bsn, range);
+		if (files == null || files.length == 0)
+			return null;
+
+		if (files.length == 1)
+			return files[0];
+
+		if (strategy < 0) {
+			return files[0];
+		}
+		return files[files.length - 1];
+	}
+
+	public File put(String bsn, Version version) throws IOException {
+		File dir = new File(root, bsn);
+		if (!dir.exists() && !dir.mkdirs()) {
+			throw new IOException("Could not create directory " + dir);
+		}
+		File file = new File(dir, bsn + "-" + version.getMajor() + "." + version.getMinor() + "." + version.getMicro()
+				+ ".jar");
+		return file;
+	}
+
+}
diff --git a/aQute.libg/src/aQute/libg/filecheck/packageinfo b/biz.aQute.bndlib/src/aQute/bnd/filerepo/packageinfo
similarity index 100%
rename from aQute.libg/src/aQute/libg/filecheck/packageinfo
rename to biz.aQute.bndlib/src/aQute/bnd/filerepo/packageinfo
diff --git a/biz.aQute.bndlib/src/aQute/bnd/header/Attrs.java b/biz.aQute.bndlib/src/aQute/bnd/header/Attrs.java
new file mode 100644
index 0000000..ed23596
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/header/Attrs.java
@@ -0,0 +1,343 @@
+package aQute.bnd.header;
+
+import java.util.*;
+import java.util.regex.*;
+
+import aQute.bnd.version.*;
+import aQute.lib.collections.*;
+
+public class Attrs implements Map<String,String> {
+	public enum Type {
+		STRING(null), LONG(null), VERSION(null), DOUBLE(null), STRINGS(STRING), LONGS(LONG), VERSIONS(VERSION), DOUBLES(
+				DOUBLE);
+
+		Type	sub;
+
+		Type(Type sub) {
+			this.sub = sub;
+		}
+
+	}
+
+	/**
+	 * <pre>
+	 * Provide-Capability ::= capability ::=
+	 * name-space ::= typed-attr ::= type ::= scalar ::=
+	 * capability ( ',' capability )*
+	 * name-space
+	 *     ( ’;’ directive | typed-attr )*
+	 * symbolic-name
+	 * extended ( ’:’ type ) ’=’ argument
+	 * scalar | list
+	 * ’String’ | ’Version’ | ’Long’
+	 * list ::=
+	 * ’List<’ scalar ’>’
+	 * </pre>
+	 */
+	static String							EXTENDED	= "[\\-0-9a-zA-Z\\._]+";
+	static String							SCALAR		= "String|Version|Long|Double";
+	static String							LIST		= "List\\s*<\\s*(" + SCALAR + ")\\s*>";
+	public static final Pattern				TYPED		= Pattern.compile("\\s*(" + EXTENDED + ")\\s*:\\s*(" + SCALAR
+																+ "|" + LIST + ")\\s*");
+
+	private LinkedHashMap<String,String>	map;
+	private Map<String,Type>				types;
+	static Map<String,String>				EMPTY		= Collections.emptyMap();
+
+	public Attrs(Attrs... attrs) {
+		for (Attrs a : attrs) {
+			if (a != null) {
+				putAll(a);
+			}
+		}
+	}
+
+	public void clear() {
+		map.clear();
+	}
+
+	public boolean containsKey(String name) {
+		if (map == null)
+			return false;
+
+		return map.containsKey(name);
+	}
+
+	@SuppressWarnings("cast")
+	@Deprecated
+	public boolean containsKey(Object name) {
+		assert name instanceof String;
+		if (map == null)
+			return false;
+
+		return map.containsKey((String) name);
+	}
+
+	public boolean containsValue(String value) {
+		if (map == null)
+			return false;
+
+		return map.containsValue(value);
+	}
+
+	@SuppressWarnings("cast")
+	@Deprecated
+	public boolean containsValue(Object value) {
+		assert value instanceof String;
+		if (map == null)
+			return false;
+
+		return map.containsValue((String) value);
+	}
+
+	public Set<java.util.Map.Entry<String,String>> entrySet() {
+		if (map == null)
+			return EMPTY.entrySet();
+
+		return map.entrySet();
+	}
+
+	@SuppressWarnings("cast")
+	@Deprecated
+	public String get(Object key) {
+		assert key instanceof String;
+		if (map == null)
+			return null;
+
+		return map.get((String) key);
+	}
+
+	public String get(String key) {
+		if (map == null)
+			return null;
+
+		return map.get(key);
+	}
+
+	public String get(String key, String deflt) {
+		String s = get(key);
+		if (s == null)
+			return deflt;
+		return s;
+	}
+
+	public boolean isEmpty() {
+		return map == null || map.isEmpty();
+	}
+
+	public Set<String> keySet() {
+		if (map == null)
+			return EMPTY.keySet();
+
+		return map.keySet();
+	}
+
+	public String put(String key, String value) {
+		if (key == null)
+			return null;
+
+		if (map == null)
+			map = new LinkedHashMap<String,String>();
+
+		Matcher m = TYPED.matcher(key);
+		if (m.matches()) {
+			key = m.group(1);
+			String type = m.group(2);
+			Type t = Type.STRING;
+
+			if (type.startsWith("List")) {
+				type = m.group(3);
+				if ("String".equals(type))
+					t = Type.STRINGS;
+				else if ("Long".equals(type))
+					t = Type.LONGS;
+				else if ("Double".equals(type))
+					t = Type.DOUBLES;
+				else if ("Version".equals(type))
+					t = Type.VERSIONS;
+			} else {
+				if ("String".equals(type))
+					t = Type.STRING;
+				else if ("Long".equals(type))
+					t = Type.LONG;
+				else if ("Double".equals(type))
+					t = Type.DOUBLE;
+				else if ("Version".equals(type))
+					t = Type.VERSION;
+			}
+			if (types == null)
+				types = new LinkedHashMap<String,Type>();
+			types.put(key, t);
+
+			// TODO verify value?
+		}
+
+		return map.put(key, value);
+	}
+
+	public Type getType(String key) {
+		if (types == null)
+			return Type.STRING;
+		Type t = types.get(key);
+		if (t == null)
+			return Type.STRING;
+		return t;
+	}
+
+	public void putAll(Map< ? extends String, ? extends String> map) {
+		for (Map.Entry< ? extends String, ? extends String> e : map.entrySet())
+			put(e.getKey(), e.getValue());
+	}
+
+	@SuppressWarnings("cast")
+	@Deprecated
+	public String remove(Object var0) {
+		assert var0 instanceof String;
+		if (map == null)
+			return null;
+
+		return map.remove((String) var0);
+	}
+
+	public String remove(String var0) {
+		if (map == null)
+			return null;
+		return map.remove(var0);
+	}
+
+	public int size() {
+		if (map == null)
+			return 0;
+		return map.size();
+	}
+
+	public Collection<String> values() {
+		if (map == null)
+			return EMPTY.values();
+
+		return map.values();
+	}
+
+	public String getVersion() {
+		return get("version");
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		append(sb);
+		return sb.toString();
+	}
+
+	public void append(StringBuilder sb) {
+		String del = "";
+		for (Map.Entry<String,String> e : entrySet()) {
+			sb.append(del);
+			sb.append(e.getKey());
+			sb.append("=");
+			sb.append(e.getValue());
+			del = ";";
+		}
+	}
+
+	@Override
+	@Deprecated
+	public boolean equals(Object other) {
+		return super.equals(other);
+	}
+
+	@Override
+	@Deprecated
+	public int hashCode() {
+		return super.hashCode();
+	}
+
+	public boolean isEqual(Attrs other) {
+		if (this == other)
+			return true;
+
+		if (other == null || size() != other.size())
+			return false;
+
+		if (isEmpty())
+			return true;
+
+		SortedList<String> l = new SortedList<String>(keySet());
+		SortedList<String> lo = new SortedList<String>(other.keySet());
+		if (!l.isEqual(lo))
+			return false;
+
+		for (String key : keySet()) {
+			String value = get(key);
+			String valueo = other.get(key);
+			if (!(value == valueo || (value != null && value.equals(valueo))))
+				return false;
+		}
+		return true;
+	}
+
+	public Object getTyped(String adname) {
+		String s = get(adname);
+		if (s == null)
+			return null;
+
+		Type t = getType(adname);
+		return convert(t, s);
+	}
+
+	private Object convert(Type t, String s) {
+		if (t.sub == null) {
+			switch (t) {
+				case STRING :
+					return s;
+				case LONG :
+					return Long.parseLong(s.trim());
+				case VERSION :
+					return Version.parseVersion(s);
+				case DOUBLE :
+					return Double.parseDouble(s.trim());
+					
+				case DOUBLES :
+				case LONGS :
+				case STRINGS :
+				case VERSIONS :
+					// Cannot happen since the sub is null
+					return null;
+			}
+			return null;
+		}
+		List<Object> list = new ArrayList<Object>();
+		
+		List<String> split = splitListAttribute(s);
+		for (String p : split)
+			list.add(convert(t.sub, p));
+		return list;
+	}
+	
+	static List<String> splitListAttribute(String input) throws IllegalArgumentException {
+		List<String> result = new LinkedList<String>();
+
+		StringBuilder builder = new StringBuilder();
+		for (int i = 0; i < input.length(); i++) {
+			char c = input.charAt(i);
+			switch (c) {
+				case '\\' :
+					i++;
+					if (i >= input.length())
+						throw new IllegalArgumentException("Trailing blackslash in multi-valued attribute value");
+					c = input.charAt(i);
+					builder.append(c);
+					break;
+				case ',' :
+					result.add(builder.toString());
+					builder = new StringBuilder();
+					break;
+				default :
+					builder.append(c);
+					break;
+			}
+		}
+		result.add(builder.toString());
+		return result;
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/header/OSGiHeader.java b/biz.aQute.bndlib/src/aQute/bnd/header/OSGiHeader.java
new file mode 100755
index 0000000..810513a
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/header/OSGiHeader.java
@@ -0,0 +1,134 @@
+package aQute.bnd.header;
+
+import java.util.*;
+
+import aQute.libg.generics.*;
+import aQute.libg.qtokens.*;
+import aQute.service.reporter.*;
+
+public class OSGiHeader {
+
+	static public Parameters parseHeader(String value) {
+		return parseHeader(value, null);
+	}
+
+	/**
+	 * Standard OSGi header parser. This parser can handle the format clauses
+	 * ::= clause ( ',' clause ) + clause ::= name ( ';' name ) (';' key '='
+	 * value ) This is mapped to a Map { name => Map { attr|directive => value }
+	 * }
+	 * 
+	 * @param value
+	 *            A string
+	 * @return a Map<String,Map<String,String>>
+	 */
+	static public Parameters parseHeader(String value, Reporter logger) {
+		return parseHeader(value, logger, new Parameters());
+	}
+
+	static public Parameters parseHeader(String value, Reporter logger, Parameters result) {
+		if (value == null || value.trim().length() == 0)
+			return result;
+
+		QuotedTokenizer qt = new QuotedTokenizer(value, ";=,");
+		char del = 0;
+		do {
+			boolean hadAttribute = false;
+			Attrs clause = new Attrs();
+			List<String> aliases = Create.list();
+			String name = qt.nextToken(",;");
+
+			del = qt.getSeparator();
+			if (name == null || name.length() == 0) {
+				if (logger != null && logger.isPedantic()) {
+					logger.warning("Empty clause, usually caused by repeating a comma without any name field or by having spaces after the backslash of a property file: "
+							+ value);
+				}
+				if (name == null)
+					break;
+			} else {
+				name = name.trim();
+
+				aliases.add(name);
+				while (del == ';') {
+					String adname = qt.nextToken();
+					if ((del = qt.getSeparator()) != '=') {
+						if (hadAttribute)
+							if (logger != null) {
+								logger.error("Header contains name field after attribute or directive: " + adname
+										+ " from " + value
+										+ ". Name fields must be consecutive, separated by a ';' like a;b;c;x=3;y=4");
+							}
+						if (adname != null && adname.length() > 0)
+							aliases.add(adname.trim());
+					} else {
+						String advalue = qt.nextToken();
+						if (clause.containsKey(adname)) {
+							if (logger != null && logger.isPedantic())
+								logger.warning("Duplicate attribute/directive name " + adname + " in " + value
+										+ ". This attribute/directive will be ignored");
+						}
+						if (advalue == null) {
+							if (logger != null)
+								logger.error("No value after '=' sign for attribute " + adname);
+							advalue = "";
+						}
+						clause.put(adname.trim(), advalue.trim());
+						del = qt.getSeparator();
+						hadAttribute = true;
+					}
+				}
+
+				// Check for duplicate names. The aliases list contains
+				// the list of nams, for each check if it exists. If so,
+				// add a number of "~" to make it unique.
+				for (String clauseName : aliases) {
+					if (result.containsKey(clauseName)) {
+						if (logger != null && logger.isPedantic())
+							logger.warning("Duplicate name "
+									+ clauseName
+									+ " used in header: '"
+									+ clauseName
+									+ "'. Duplicate names are specially marked in Bnd with a ~ at the end (which is stripped at printing time).");
+						while (result.containsKey(clauseName))
+							clauseName += "~";
+					}
+					result.put(clauseName, clause);
+				}
+			}
+		} while (del == ',');
+		return result;
+	}
+
+	public static Attrs parseProperties(String input) {
+		return parseProperties(input, null);
+	}
+
+	public static Attrs parseProperties(String input, Reporter logger) {
+		if (input == null || input.trim().length() == 0)
+			return new Attrs();
+
+		Attrs result = new Attrs();
+		QuotedTokenizer qt = new QuotedTokenizer(input, "=,");
+		char del = ',';
+
+		while (del == ',') {
+			String key = qt.nextToken(",=");
+			String value = "";
+			del = qt.getSeparator();
+			if (del == '=') {
+				value = qt.nextToken(",=");
+				del = qt.getSeparator();
+			}
+			result.put(key, value);
+		}
+		if (del != 0) {
+			if (logger == null)
+				throw new IllegalArgumentException("Invalid syntax for properties: " + input);
+			logger.error("Invalid syntax for properties: " + input);
+		}
+
+		return result;
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/header/Parameters.java b/biz.aQute.bndlib/src/aQute/bnd/header/Parameters.java
new file mode 100644
index 0000000..34c593b
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/header/Parameters.java
@@ -0,0 +1,211 @@
+package aQute.bnd.header;
+
+import java.util.*;
+
+import aQute.lib.collections.*;
+import aQute.service.reporter.*;
+
+public class Parameters implements Map<String,Attrs> {
+	private LinkedHashMap<String,Attrs>	map;
+	static Map<String,Attrs>			EMPTY	= Collections.emptyMap();
+	String								error;
+
+	public Parameters() {}
+
+	public Parameters(String header) {
+		OSGiHeader.parseHeader(header, null, this);
+	}
+
+	public Parameters(String header, Reporter reporter) {
+		OSGiHeader.parseHeader(header, reporter, this);
+	}
+
+	public void clear() {
+		map.clear();
+	}
+
+	public boolean containsKey(final String name) {
+		if (map == null)
+			return false;
+
+		return map.containsKey(name);
+	}
+
+	@SuppressWarnings("cast")
+	@Deprecated
+	public boolean containsKey(Object name) {
+		assert name instanceof String;
+		if (map == null)
+			return false;
+
+		return map.containsKey((String) name);
+	}
+
+	public boolean containsValue(Attrs value) {
+		if (map == null)
+			return false;
+
+		return map.containsValue(value);
+	}
+
+	@SuppressWarnings("cast")
+	@Deprecated
+	public boolean containsValue(Object value) {
+		assert value instanceof Attrs;
+		if (map == null)
+			return false;
+
+		return map.containsValue((Attrs) value);
+	}
+
+	public Set<java.util.Map.Entry<String,Attrs>> entrySet() {
+		if (map == null)
+			return EMPTY.entrySet();
+
+		return map.entrySet();
+	}
+
+	@SuppressWarnings("cast")
+	@Deprecated
+	public Attrs get(Object key) {
+		assert key instanceof String;
+		if (map == null)
+			return null;
+
+		return map.get((String) key);
+	}
+
+	public Attrs get(String key) {
+		if (map == null)
+			return null;
+
+		return map.get(key);
+	}
+
+	public boolean isEmpty() {
+		return map == null || map.isEmpty();
+	}
+
+	public Set<String> keySet() {
+		if (map == null)
+			return EMPTY.keySet();
+
+		return map.keySet();
+	}
+
+	public Attrs put(String key, Attrs value) {
+		assert key != null;
+		assert value != null;
+
+		if (map == null)
+			map = new LinkedHashMap<String,Attrs>();
+
+		return map.put(key, value);
+	}
+
+	public void putAll(Map< ? extends String, ? extends Attrs> map) {
+		if (this.map == null) {
+			if (map.isEmpty())
+				return;
+			this.map = new LinkedHashMap<String,Attrs>();
+		}
+		this.map.putAll(map);
+	}
+
+	public void putAllIfAbsent(Map<String, ? extends Attrs> map) {
+		for (Map.Entry<String, ? extends Attrs> entry : map.entrySet()) {
+			if (!containsKey(entry.getKey()))
+				put(entry.getKey(), entry.getValue());
+		}
+	}
+
+	@SuppressWarnings("cast")
+	@Deprecated
+	public Attrs remove(Object var0) {
+		assert var0 instanceof String;
+		if (map == null)
+			return null;
+
+		return map.remove((String) var0);
+	}
+
+	public Attrs remove(String var0) {
+		if (map == null)
+			return null;
+		return map.remove(var0);
+	}
+
+	public int size() {
+		if (map == null)
+			return 0;
+		return map.size();
+	}
+
+	public Collection<Attrs> values() {
+		if (map == null)
+			return EMPTY.values();
+
+		return map.values();
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		append(sb);
+		return sb.toString();
+	}
+
+	public void append(StringBuilder sb) {
+		String del = "";
+		for (Map.Entry<String,Attrs> s : entrySet()) {
+			sb.append(del);
+			sb.append(s.getKey());
+			if (!s.getValue().isEmpty()) {
+				sb.append(';');
+				s.getValue().append(sb);
+			}
+
+			del = ",";
+		}
+	}
+
+	@Override
+	@Deprecated
+	public boolean equals(Object other) {
+		return super.equals(other);
+	}
+
+	@Override
+	@Deprecated
+	public int hashCode() {
+		return super.hashCode();
+	}
+
+	public boolean isEqual(Parameters other) {
+		if (this == other)
+			return true;
+
+		if (other == null || size() != other.size())
+			return false;
+
+		if (isEmpty())
+			return true;
+
+		SortedList<String> l = new SortedList<String>(keySet());
+		SortedList<String> lo = new SortedList<String>(other.keySet());
+		if (!l.isEqual(lo))
+			return false;
+
+		for (String key : keySet()) {
+			Attrs value = get(key);
+			Attrs valueo = other.get(key);
+			if (!(value == valueo || (value != null && value.isEqual(valueo))))
+				return false;
+		}
+		return true;
+	}
+
+	public Map<String, ? extends Map<String,String>> asMapMap() {
+		return this;
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/header/packageinfo b/biz.aQute.bndlib/src/aQute/bnd/header/packageinfo
new file mode 100644
index 0000000..e39f616
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/header/packageinfo
@@ -0,0 +1 @@
+version 1.1.0
diff --git a/biz.aQute.bndlib/src/aQute/bnd/help/Errors.java b/biz.aQute.bndlib/src/aQute/bnd/help/Errors.java
deleted file mode 100644
index 1d950ad..0000000
--- a/biz.aQute.bndlib/src/aQute/bnd/help/Errors.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package aQute.bnd.help;
-
-public interface Errors {
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/help/Syntax.java b/biz.aQute.bndlib/src/aQute/bnd/help/Syntax.java
index 20a7440..b9c6625 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/help/Syntax.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/help/Syntax.java
@@ -3,479 +3,377 @@ package aQute.bnd.help;
 import java.util.*;
 import java.util.regex.*;
 
-import aQute.lib.osgi.*;
+import aQute.bnd.osgi.*;
 
 public class Syntax implements Constants {
-    final String                            header;
-    final String                            lead;
-    final String                            example;
-    final Pattern                           pattern;
-    final String                            values;
-    final Syntax[]                          children;
-
-    static Syntax                           version              = new Syntax(
-                                                                         VERSION_ATTRIBUTE,
-                                                                         "A version range to select the version of an export definition. The default value is 0.0.0 .",
-                                                                         "version=\"[1.2,3.0)\"",
-                                                                         null,
-                                                                         Verifier.VERSIONRANGE);
-    static Syntax                           bundle_symbolic_name = new Syntax(
-                                                                         BUNDLE_SYMBOLIC_NAME_ATTRIBUTE,
-                                                                         "The bundle symbolic name of the exporting bundle.",
-                                                                         "bundle-symbolic-name=com.acme.foo.daffy",
-                                                                         null,
-                                                                         Verifier.SYMBOLICNAME);
-
-    static Syntax                           bundle_version       = new Syntax(
-                                                                         BUNDLE_VERSION_ATTRIBUTE,
-                                                                         "a version range to select the bundle version of the exporting bundle. The default value is 0.0.0.",
-                                                                         "bundle-version=1.3",
-                                                                         null,
-                                                                         Verifier.VERSIONRANGE);
-
-    static Syntax                           path_version         = new Syntax(
-                                                                         VERSION_ATTRIBUTE,
-                                                                         "Specifies the range in the repository, project, or file",
-                                                                         "version=project",
-                                                                         "project,type",
-                                                                         Pattern
-                                                                                 .compile("project|type|"
-                                                                                         + Verifier.VERSIONRANGE
-                                                                                                 .toString()));
-
-    @SuppressWarnings("deprecation")
-	static Syntax[]                         syntaxes             = new Syntax[] {
-            new Syntax(
-                    BUNDLE_ACTIVATIONPOLICY,
-                    "The Bundle-ActivationPolicy specifies how the framework should activate the bundle once started. ",
-                    "Bundle-ActivationPolicy: lazy", "lazy", Pattern
-                            .compile("lazy")),
-
-            new Syntax(
-                    BUNDLE_ACTIVATOR,
-                    "The Bundle-Activator header specifies the name of the class used to start and stop the bundle. ",
-                    "Bundle-Activator: com.acme.foo.Activator",
-                    "${classes;implementing;org.osgi.framework.BundleActivator}",
-                    Verifier.FQNPATTERN),
-            new Syntax(
-                    BUNDLE_CATEGORY,
-                    "The Bundle-Category header holds a comma-separated list of category names",
-                    "Bundle-Category: test",
-                    "osgi,test,game,util,eclipse,netbeans,jdk,specification",
-                    null),
-            new Syntax(
-                    BUNDLE_CLASSPATH,
-                    "The Bundle-ClassPath header defines a comma-separated list of JAR file path names or directories (inside the bundle) containing classes and resources. The period (’.’) specifies the root directory of the bundle’s JAR. The period is also the default.",
-                    "Bundle-Classpath: /lib/libnewgen.so, .", null,
-                    Verifier.PATHPATTERN),
-            new Syntax(
-                    BUNDLE_CONTACTADDRESS,
-                    "The Bundle-ContactAddress header provides the contact address of the vendor. ",
-                    "Bundle-ContactAddress: 2400 Oswego Road, Austin, TX 74563",
-                    null, null),
-            new Syntax(
-                    BUNDLE_COPYRIGHT,
-                    "The Bundle-Copyright header contains the copyright specification for this bundle. ",
-                    "Bundle-Copyright: OSGi (c) 2002", null, null),
-            new Syntax(
-                    BUNDLE_DESCRIPTION,
-                    "The Bundle-Description header defines a short description of this bundle.",
-                    "Bundle-Description: Ceci ce n'est pas une bundle", null,
-                    null),
-
-            new Syntax(
-                    BUNDLE_DOCURL,
-                    "The Bundle-DocURL headers must contain a URL pointing to documentation about this bundle.",
-                    "Bundle-DocURL: http://www.aQute.biz/Code/Bnd", null,
-                    Verifier.URLPATTERN),
-
-            new Syntax(
-                    BUNDLE_ICON,
-                    "The optional Bundle-Icon header provides a list of (relative) URLs to icons representing this bundle in different sizes. ",
-                    "Bundle-Icon: /icons/bnd.png;size=64", "/icons/bundle.png",
-                    Verifier.URLPATTERN, new Syntax("size",
-                            "Icons size in pixels, e.g. 64", "64",
-                            "16,32,48,64,128", Verifier.NUMBERPATTERN)),
-
-            new Syntax(
-                    BUNDLE_LICENSE,
-                    "The Bundle-License header provides an optional machine readable form of license information. The purpose of this header is to automate some of the license processing required by many organizations",
-                    "Bundle License: http://www.opensource.org/licenses/jabberpl.php",
-                    "http://www.apache.org/licenses/LICENSE-2.0,<<EXTERNAL>>",
-                    Pattern.compile("(" + Verifier.URLPATTERN
-                            + "|<<EXTERNAL>>)"), new Syntax(
-                            DESCRIPTION_ATTRIBUTE,
-                            "Human readable description of the license",
-                            "description=\"Described the license here\"", null,
-                            Verifier.ANYPATTERN), new Syntax(LINK_ATTRIBUTE,
-                            "", "", null, Verifier.URLPATTERN)),
-            new Syntax(
-                    BUNDLE_LOCALIZATION,
-                    "The Bundle-Localization header contains the location in the bundle where localization files can be found. The default value is OSGI-INF/l10n/bundle. Translations are by default therefore OSGI-INF/l10n/bundle_de.properties, OSGI-INF/l10n/bundle_nl.properties, etc.",
-                    "Bundle-Localization: OSGI-INF/l10n/bundle",
-                    "OSGI-INF/l10n/bundle", Verifier.URLPATTERN),
-            new Syntax(
-                    BUNDLE_MANIFESTVERSION,
-                    "This header is set by bnd automatically to 2. The Bundle-ManifestVersion header defines that the bundle follows the rules of this specification. The Bundle-ManifestVersion header determines whether the bundle follows the rules of this specification.",
-                    "# Bundle-ManifestVersion: 2", "2", Verifier.NUMBERPATTERN),
-            new Syntax(
-                    BUNDLE_NAME,
-                    "This header will be derived from the  Bundle-SymbolicName if not set. The Bundle-Name header defines a readable name for this bundle. This should be a short, human-readable name that can contain spaces.",
-                    "Bundle-Name: My Bundle", null, Verifier.ANYPATTERN),
-            new Syntax(
-                    BUNDLE_NATIVECODE,
-                    "The Bundle-NativeCode header contains a specification of native code libraries contained in this bundle. ",
-                    "Bundle-NativeCode: /lib/http.DLL; osname = QNX; osversion = 3.1",
-                    null,
-                    Verifier.PATHPATTERN,
-                    new Syntax(OSNAME_ATTRIBUTE,
-                            "The name of the operating system", "osname=MacOS",
-                            Processor.join(Verifier.OSNAMES, ","),
-                            Verifier.ANYPATTERN),
-                    new Syntax(OSVERSION_ATTRIBUTE, "Operating System Version",
-                            "osversion=3.1", null, Verifier.ANYPATTERN),
-                    new Syntax(LANGUAGE_ATTRIBUTE, "Language ISO 639 code",
-                            "language=nl", null, Verifier.ISO639),
-                    new Syntax(PROCESSOR_ATTRIBUTE, "Processor name",
-                            "processor=x86", Processor.join(
-                                    Verifier.PROCESSORNAMES, ","),
-                            Verifier.ANYPATTERN),
-                    new Syntax(
-                            SELECTION_FILTER_ATTRIBUTE,
-                            "The value of this attribute must be a filter expression that indicates if the native code clause should be selected or not.",
-                            "selection-filter=\"(com.acme.windowing=win32)\"",
-                            null, Verifier.FILTERPATTERN)),
-            new Syntax(
-                    BUNDLE_REQUIREDEXECUTIONENVIRONMENT,
-                    "The Bundle-RequiredExecutionEnvironment contains a comma-separated list of execution environments that must be present on the Service Platform.",
-                    "Bundle-RequiredExecutionEnvironment: CDC-1.0/Foundation-1.0",
-                    Processor.join(Verifier.EES, ","), Verifier.ANYPATTERN),
-
-            new Syntax(
-                    BUNDLE_SYMBOLICNAME,
-                    "The Bundle-SymbolicName header specifies a non-localizable name for this bundle. The bundle symbolic name together with a version must identify a  unique bundle. The bundle symbolic name should be based on the reverse  domain name convention",
-                    "Bundle-SymbolicName: com.acme.foo.daffy;singleton:=true",
-                    "${p}",
-                    Verifier.SYMBOLICNAME,
-                    new Syntax(
-                            SINGLETON_DIRECTIVE,
-                            " Indicates that the bundle can only have  a single version resolved.  A value of true indicates that the bundle is a singleton bundle. The default value is false. The Framework must resolve at most one  bundle when multiple versions of a singleton bundle with the same symbolic name are installed. Singleton bundles do not affect the resolution of non-singleton bundles with the same symbolic name.",
-                            "false", "true,false", Verifier.TRUEORFALSEPATTERN),
-                    new Syntax(
-                            FRAGMENT_ATTACHMENT_DIRECTIVE,
-                            "Defines how fragments are allowed to be attached, see the fragments in Fragment Bundles on page73. The following values are valid for this directive:",
-                            "", "always|never|resolve-time", Pattern
-                                    .compile("always|never|resolve-time")),
-                    new Syntax(BLUEPRINT_WAIT_FOR_DEPENDENCIES_ATTRIBUTE, "",
-                            "", "true,false", Verifier.TRUEORFALSEPATTERN),
-                    new Syntax(BLUEPRINT_TIMEOUT_ATTRIBUTE, "", "",
-                            "30000,60000,300000", Verifier.NUMBERPATTERN)),
-
-            new Syntax(
-                    BUNDLE_UPDATELOCATION,
-                    "The Bundle-UpdateLocation header specifies a URL where an update for this bundle should come from. If the bundle is updated, this location should be used, if present, to retrieve the updated JAR file.",
-                    "Bundle-UpdateLocation: http://www.acme.com/Firewall/bundle.jar",
-                    null, Verifier.URLPATTERN),
-
-            new Syntax(
-                    BUNDLE_VENDOR,
-                    "The Bundle-Vendor header contains a human-readable description of the bundle vendor. ",
-                    "Bundle-Vendor: OSGi Alliance ", null, null),
-
-            new Syntax(
-                    BUNDLE_VERSION,
-                    "The Bundle-Version header specifies the version of this bundle",
-                    "Bundle-Version: 1.23.4.build200903221000", null,
-                    Verifier.VERSION),
-
-            new Syntax(
-                    DYNAMICIMPORT_PACKAGE,
-                    "The DynamicImport-Package header contains a comma-separated list of package names that should be dynamically imported when needed.",
-                    "DynamicImport-Package: com.acme.plugin.*", "",
-                    Verifier.WILDCARDNAMEPATTERN, version,
-                    bundle_symbolic_name, bundle_version),
-
-            new Syntax(
-                    EXPORT_PACKAGE,
-                    "The Export-Package header contains a declaration of exported packages.",
-                    "Export-Package: org.osgi.util.tracker;version=1.3",
-                    "${packages}",
-                    null,
-                    new Syntax(
-                            NO_IMPORT_DIRECTIVE,
-                            "By default, bnd makes all exports also imports. Adding a -noimport to an exported package will make it export only",
-                            "-noimport:=true", "true,false",
-                            Verifier.TRUEORFALSEPATTERN),
-                    new Syntax(
-                            USES_DIRECTIVE,
-                            "Calculated by bnd: It is a comma-separated list of package names that are used by the exported package",
-                            "Is calculated by bnd", null, null),
-                    new Syntax(
-                            MANDATORY_DIRECTIVE,
-                            "A comma-separated list of attribute names. Note that the use of a comma in the value requires it to be enclosed in double quotes. A bundle importing the package must specify the mandatory attributes, with a value that matches, to resolve to the exported package",
-                            "mandatory=\"bar,foo\"", null, null),
-                    new Syntax(
-                            INCLUDE_DIRECTIVE,
-                            "A comma-separated list of class names that must be visible to an importer",
-                            "include:=\"Qux*\"", null, null),
-                    new Syntax(
-                            EXCLUDE_DIRECTIVE,
-                            "A comma-separated list of class names that must not be visible to an importer",
-                            "exclude:=\"QuxImpl*,BarImpl\"", null,
-                            Verifier.WILDCARDNAMEPATTERN), new Syntax(
-                            IMPORT_DIRECTIVE, "Experimental", "", null, null)
-
-            ),
-            new Syntax(EXPORT_SERVICE, "Deprecated",
-                    "Export-Service: org.osgi.service.log.LogService ",
-                    "${classes;implementing;*}", null),
-            new Syntax(
-                    FRAGMENT_HOST,
-                    "The Fragment-Host header defines the host bundle for this fragment.",
-                    "Fragment-Host: org.eclipse.swt; bundle-version=\"[3.0.0,4.0.0)\"",
-                    null,
-                    null,
-                    new Syntax(
-                            EXTENSION_DIRECTIVE,
-                            " Indicates this extension is a system or boot class path extension. It is only applicable when the Fragment-Host is the System Bundle",
-                            "extension:=framework", "framework,bootclasspath",
-                            Pattern.compile("framework|bootclasspath")),
-                    bundle_version),
-            new Syntax(
-                    IMPORT_PACKAGE,
-                    "This header is normally calculated by bnd, however, you can decorate packages or skip packages. The Import-Package header declares the imported packages for this bundle",
-                    "Import-Package: !com.exotic.*, com.acme.foo;vendor=ACME, *",
-                    "${exported_packages}",
-                    Verifier.WILDCARDNAMEPATTERN,
-                    new Syntax(
-                            REMOVE_ATTRIBUTE_DIRECTIVE,
-                            "Remove the given attributes from matching imported packages",
-                            "-remove-attribute:=foo.*", null,
-                            Verifier.WILDCARDNAMEPATTERN),
-                    new Syntax(
-                            RESOLUTION_DIRECTIVE,
-                            "Indicates that the packages must be resolved if the value is mandatory, which is the default. If mandatory packages cannot be resolved, then the bundle must fail to resolve. A value of optional indicates that the packages are optional",
-                            "resolution:=optional", "mandatory,optional",
-                            Pattern.compile("mandatory|optional")
-
-                    ), version, bundle_symbolic_name, bundle_version),
-
-            new Syntax(
-                    REQUIRE_BUNDLE,
-                    "The Require-Bundle header specifies the required exports from another bundle.",
-                    "Require-Bundle: com.acme.chess",
-                    null,
-                    Verifier.WILDCARDNAMEPATTERN,
-
-                    new Syntax(
-                            VISIBILITY_DIRECTIVE,
-                            " If the value is private (Default), then all visible packages from the required bundles are not re-exported. If the value is reexport then bundles that require this bundle will transitively have access to these required bundle’s exported packages.",
-                            "visibility:=private", "private,reexport", Pattern
-                                    .compile("private|reexport")),
-
-                    new Syntax(
-                            RESOLUTION_DIRECTIVE,
-                            "If the value is mandatory (default) then the required bundle must exist for this bundle to resolve. If the value is optional, the bundle will resolve even if the required bundle does not exist.",
-                            "resolution:=optional", "mandatory,optional",
-                            Pattern.compile("mandatory|optional")),
-
-                    new Syntax(
-                            SPLIT_PACKAGE_DIRECTIVE,
-                            "Indicates how an imported package should be merged when it is split between different exporters. The default is merge-first with warning",
-                            "-split-package:=merge-first",
-                            "merge-first,merge-last,error,first",
-                            Pattern
-                                    .compile("merge-first|merge-last|error|first")),
-                    bundle_version
-
-            ),
-            new Syntax(
-                    BUILDPATH,
-                    "Provides the class path for building the jar. The entries are references to the repository",
-                    "-buildpath=osgi;version=4.1", "${repo;bsns}",
-                    Verifier.SYMBOLICNAME, path_version),
-            new Syntax(
-                    BUMPPOLICY,
-                    "Sets the version bump policy. This is a parameter to the ${version} macro.",
-                    "-bumppolicy==+0", "==+,=+0,+00", Pattern
-                            .compile("[=+-0][=+-0][=+-0]")),
-
-            new Syntax(
-                    CONDUIT,
-                    "Allows a bnd file to point to files which will be returned when the bnd file is build",
-                    "-conduit= jar/osgi.jar", null, null),
-
-            new Syntax(
-                    DEPENDSON,
-                    "List of project names that this project directly depends on. These projects are always build ahead of this project",
-                    "-dependson=org.acme.cm", "${projects}", null),
-
-            new Syntax(DEPLOYREPO,
-                    "Specifies to which repo the project should be deployed.",
-                    "-deployrepo=cnf", "${repos}", null),
-
-            new Syntax(
-                    DONOTCOPY,
-                    "Regular expression for names of files and directories that should not be copied when discovered",
-                    "-donotcopy=(CVS|\\.svn)", null, null),
-
-            new Syntax(
-                    EXPORT_CONTENTS,
-                    "Build the JAR in the normal way but use this header for the Export-Package header manifest generation, same format",
-                    "-exportcontents=!*impl*,*;version=3.0", null, null),
-
-            new Syntax(
-                    FAIL_OK,
-                    "Return with an ok status (0) even if the build generates errors",
-                    "-failok=true", "true,false", Verifier.TRUEORFALSEPATTERN),
-
-            new Syntax(
-                    INCLUDE,
-                    "Include files. If an entry starts with '-', it does not have to exist. If it starts with '~', it must not overwrite any existing properties",
-                    "-include: -${java.user}/.bnd", null, null),
-
-            new Syntax(
-                    INCLUDERESOURCE,
-                    "Include resources from the file system. You can specify a directory, or file. All files are copied to the root, unless a destination directory is indicated",
-                    "-includeresource: lib=jar", null, null),
-
-            new Syntax(
-                    MAKE,
-                    "Set patterns for make plugins. These patterns are used to find a plugin that can make a resource that can not be found.",
-                    "-make: (*).jar;type=bnd;  recipe=\"bnd/$1.bnd\"", null,
-                    null, new Syntax("type", "Type name for plugin",
-                            "type=bnd", "bnd", null), new Syntax("recipe",
-                            "Recipe for the plugin, can use back references",
-                            "recipe=\"bnd/$1.bnd\"", "bnd", null)),
-
-            new Syntax(
-                    MANIFEST,
-                    "Directly include a manifest, do not use the calculated manifest",
-                    "-manifest = META-INF/MANIFEST.MF", null, null),
-
-            new Syntax(NOEXTRAHEADERS, "Do not generate housekeeping headers",
-                    "-noextraheaders", "true,false",
-                    Verifier.TRUEORFALSEPATTERN),
-
-            new Syntax(NOUSES,
-                    "Do not calculate the uses: directive on exports",
-                    "-nouses=true", "true,false", Verifier.TRUEORFALSEPATTERN),
-
-            new Syntax(NOPE,
-                    "Deprecated, use -nobundles. ",
-                    "-nope=true", "true,false", Verifier.TRUEORFALSEPATTERN),
-
-            new Syntax(
-                    PEDANTIC,
-                    "Warn about things that are not really wrong but still not right",
-                    "-nope=true", "true,false", Verifier.TRUEORFALSEPATTERN),
-
-            new Syntax(
-                    PLUGIN,
-                    "Define the plugins",
-                    "-plugin=aQute.lib.spring.SpringComponent,aQute.lib.deployer.FileRepo;location=${repo}",
-                    null, null),
-
-            new Syntax(SERVICE_COMPONENT,
-                    "The header for Declarative Services",
-                    "Service-Component=com.acme.Foo?;activate='start'", null,
-                    null),
-
-            new Syntax(POM, "Generate a maven pom", "-pom=true", "true,false",
-                    Verifier.TRUEORFALSEPATTERN),
-
-            new Syntax(RELEASEREPO,
-                    "Specifies to which repo the project should be released.",
-                    "-releaserepo=cnf", "${repos}", null),
-
-            new Syntax(REMOVEHEADERS,
-                    "Remove all headers that match the regular expressions",
-                    "-removeheaders=FOO_.*,Proprietary", null, null),
-            new Syntax(
-                    RESOURCEONLY,
-                    "Normally bnd warns when the JAR does not contain any classes, this option suppresses this warning",
-                    "-resourceonly=true", "true,false",
-                    Verifier.TRUEORFALSEPATTERN),
-            new Syntax(SOURCES, "Include sources in the jar", "-sources=true",
-                    "true,false", Verifier.TRUEORFALSEPATTERN),
-            new Syntax(
-                    SOURCEPATH,
-                    "List of directory names that used to source sources for -sources",
-                    "-sourcepath:= src, test", null, null),
-            new Syntax(
-                    SUB,
-                    "Build a set of bnd files that use this bnd file as a basis. The list of bnd file can be specified with wildcards",
-                    "-sub=com.acme.*.bnd", null, null),
-            new Syntax(
-                    RUNPROPERTIES,
-                    "Properties that are set as system properties before the framework is started",
-                    "-runproperties= foo=3, bar=4", null, null),
-            new Syntax(RUNSYSTEMPACKAGES,
-                    "Add additional system packages to a framework run",
-                    "-runsystempackages=com.acme.foo,javax.management", null,
-                    null),
-            new Syntax(
-                    RUNBUNDLES,
-                    "Add additional bundles, specified with their bsn and version like in -buildpath, that are started before the project is run",
-                    "-runbundles=osgi;version=\"[4.1,4.2)\", junit.junit, com.acme.foo;version=project",
-                    null, Verifier.SYMBOLICNAME, path_version),
-            new Syntax(
-                    RUNPATH,
-                    "Additional JARs for the VM path, should include the framework",
-                    "-runpath=org.eclipse.osgi;version=3.5", null, null,
-                    path_version),
-            new Syntax(
-                    RUNVM,
-                    "Additional arguments for the VM invokation. Keys that start with a - are added as options, otherwise they are treated as -D properties for the VM",
-                    "-runvm=-Xmax=30", null, null),
-            new Syntax(
-                    VERSIONPOLICY,
-                    "Provides a version policy to imports that are calculated from exports",
-                    "-versionpolicy = \"[${version;==;${@}},${version;+;${@}})\"",
-                    null, null)
-
-                                                                 };
-
-    public final static Map<String, Syntax> HELP                 = new HashMap<String, Syntax>();
-
-    static {
-        for (Syntax s : syntaxes) {
-            HELP.put(s.header, s);
-        }
-    }
-
-    public Syntax(String header, String lead, String example, String values,
-            Pattern pattern, Syntax... children) {
-        this.header = header;
-        this.children = children;
-        this.lead = lead;
-        this.example = example;
-        this.values = values;
-        this.pattern = pattern;
-    }
-
-    public String getLead() {
-        return lead;
-    }
-
-    public String getExample() {
-        return example;
-    }
-
-    public String getValues() {
-        return values;
-    }
-
-    public String getPattern() {
-        return lead;
-    }
-
-    public Syntax[] getChildren() {
-        return children;
-    }
-
-    public String getHeader() {
-        return header;
-    }
+	final String							header;
+	final String							lead;
+	final String							example;
+	final Pattern							pattern;
+	final String							values;
+	final Syntax[]							children;
+
+	static Syntax							version					= new Syntax(
+																			VERSION_ATTRIBUTE,
+																			"A version range to select the version of an export definition. The default value is 0.0.0.",
+																			VERSION_ATTRIBUTE + "=\"[1.2,3.0)\"", null,
+																			Verifier.VERSIONRANGE);
+	static Syntax							bundle_symbolic_name	= new Syntax(
+																			BUNDLE_SYMBOLIC_NAME_ATTRIBUTE,
+																			"The bundle symbolic name of the exporting bundle.",
+																			BUNDLE_SYMBOLIC_NAME_ATTRIBUTE + "=com.acme.foo.daffy",
+																			null, Verifier.SYMBOLICNAME);
+
+	static Syntax							bundle_version			= new Syntax(
+																			BUNDLE_VERSION_ATTRIBUTE,
+																			"A version range to select the bundle version of the exporting bundle. The default value is 0.0.0.",
+																			BUNDLE_VERSION_ATTRIBUTE + "=1.3", null,
+																			Verifier.VERSIONRANGE);
+
+	static Syntax							path_version			= new Syntax(
+																			VERSION_ATTRIBUTE,
+																			"Specifies the range in the repository, project or file.",
+																			VERSION_ATTRIBUTE + "=project", "project,type", Pattern
+																					.compile("project|type|"
+																							+ Verifier.VERSIONRANGE
+																									.toString()));
+
+	static final Syntax[]					syntaxes				= new Syntax[] {
+			new Syntax(
+					BUNDLE_ACTIVATIONPOLICY,
+					"The " + BUNDLE_ACTIVATIONPOLICY + " header specifies how the framework should activate the bundle once started.",
+					BUNDLE_ACTIVATIONPOLICY + ": lazy", "lazy", Pattern.compile("lazy")),
+
+			new Syntax(BUNDLE_ACTIVATOR,
+					"The " + BUNDLE_ACTIVATOR + " header specifies the name of the class used to start and stop the bundle.",
+					BUNDLE_ACTIVATOR + ": com.acme.foo.Activator",
+					"${classes;implementing;org.osgi.framework.BundleActivator}", Verifier.FQNPATTERN),
+			new Syntax(BUNDLE_CATEGORY, "The " + BUNDLE_CATEGORY + " header holds a comma-separated list of category names.",
+					BUNDLE_CATEGORY + ": test", "osgi,test,game,util,eclipse,netbeans,jdk,specification", null),
+			new Syntax(
+					BUNDLE_CLASSPATH,
+					"The " + BUNDLE_CLASSPATH + " header defines a comma-separated list of JAR file path names or directories (inside the bundle) containing classes and resources. The period (’.’) specifies the root directory of the bundle’s JAR. The period is also the default.",
+					BUNDLE_CLASSPATH + ": /lib/libnewgen.so, .", null, Verifier.PATHPATTERN),
+			new Syntax(BUNDLE_CONTACTADDRESS,
+					"The " + BUNDLE_CONTACTADDRESS + " header provides the contact address of the vendor.",
+					BUNDLE_CONTACTADDRESS + ": 2400 Oswego Road, Austin, TX 74563", null, null),
+			new Syntax(BUNDLE_COPYRIGHT,
+					"The " + BUNDLE_COPYRIGHT + " header contains the copyright specification for this bundle.",
+					BUNDLE_COPYRIGHT + ": OSGi (c) 2002", null, null),
+			new Syntax(BUNDLE_DESCRIPTION, "The " + BUNDLE_DESCRIPTION + " header defines a short description of this bundle.",
+					BUNDLE_DESCRIPTION + ": Ceci ce n'est pas une bundle", null, null),
+
+			new Syntax(BUNDLE_DOCURL,
+					"The " + BUNDLE_DOCURL + " header must contain a URL pointing to documentation about this bundle.",
+					BUNDLE_DOCURL + ": http://www.aQute.biz/Code/Bnd", null, Verifier.URLPATTERN),
+
+			new Syntax(
+					BUNDLE_ICON,
+					"The optional " + BUNDLE_ICON + " header provides a list of (relative) URLs to icons representing this bundle in different sizes.",
+					BUNDLE_ICON + ": /icons/bnd.png;size=64", "/icons/bundle.png", Verifier.URLPATTERN, new Syntax("size",
+							"Icons size in pixels, e.g. 64.", "size=64", "16,32,48,64,128", Verifier.NUMBERPATTERN)),
+
+			new Syntax(
+					BUNDLE_LICENSE,
+					"The " + BUNDLE_LICENSE + " header provides an optional machine readable form of license information. The purpose of this header is to automate some of the license processing required by many organizations.",
+					BUNDLE_LICENSE + ": http://www.opensource.org/licenses/jabberpl.php",
+					"http://www.apache.org/licenses/LICENSE-2.0,<<EXTERNAL>>", Pattern.compile("("
+							+ Verifier.URLPATTERN + "|<<EXTERNAL>>)"), new Syntax(DESCRIPTION_ATTRIBUTE,
+							"Human readable description of the license.", DESCRIPTION_ATTRIBUTE + "=\"Describe the license here\"",
+							null, Verifier.ANYPATTERN), new Syntax(LINK_ATTRIBUTE, "", "", null, Verifier.URLPATTERN)),
+			new Syntax(
+					BUNDLE_LOCALIZATION,
+					"The " + BUNDLE_LOCALIZATION + " header contains the location in the bundle where localization files can be found. The default value is OSGI-INF/l10n/bundle. Translations are by default therefore OSGI-INF/l10n/bundle_de.properties, OSGI-INF/l10n/bundle_nl.properties, etc.",
+					BUNDLE_LOCALIZATION + ": OSGI-INF/l10n/bundle", "OSGI-INF/l10n/bundle", Verifier.URLPATTERN),
+			new Syntax(
+					BUNDLE_MANIFESTVERSION,
+					"The " + BUNDLE_MANIFESTVERSION + " header is set by bnd automatically to 2. The header defines that the bundle follows the rules of this specification.",
+					"# " + BUNDLE_MANIFESTVERSION + ": 2", "2", Verifier.NUMBERPATTERN),
+			new Syntax(
+					BUNDLE_NAME,
+					"The " + BUNDLE_NAME + " header will be derived from the " + BUNDLE_SYMBOLICNAME + " header if not set. The " + BUNDLE_NAME + " header defines a readable name for this bundle. This should be a short, human-readable name that can contain spaces.",
+					BUNDLE_NAME + ": My Bundle", null, Verifier.ANYPATTERN),
+			new Syntax(
+					BUNDLE_NATIVECODE,
+					"The " + BUNDLE_NATIVECODE + " header contains a specification of native code libraries contained in this bundle.",
+					BUNDLE_NATIVECODE + ": /lib/http.DLL; osname = QNX; osversion = 3.1",
+					null,
+					Verifier.PATHPATTERN,
+					new Syntax(OSNAME_ATTRIBUTE, "The name of the operating system.", OSNAME_ATTRIBUTE + "=MacOS", Processor.join(
+							Verifier.OSNAMES, ","), Verifier.ANYPATTERN),
+					new Syntax(OSVERSION_ATTRIBUTE, "Operating System Version.", OSVERSION_ATTRIBUTE + "=3.1", null,
+							Verifier.ANYPATTERN),
+					new Syntax(LANGUAGE_ATTRIBUTE, "Language ISO 639 code.", LANGUAGE_ATTRIBUTE + "=nl", null, Verifier.ISO639),
+					new Syntax(PROCESSOR_ATTRIBUTE, "Processor name.", PROCESSOR_ATTRIBUTE + "=x86", Processor.join(
+							Verifier.PROCESSORNAMES, ","), Verifier.ANYPATTERN),
+					new Syntax(
+							SELECTION_FILTER_ATTRIBUTE,
+							"The value of this attribute must be a filter expression that indicates if the native code clause should be selected or not.",
+							SELECTION_FILTER_ATTRIBUTE + "=\"(com.acme.windowing=win32)\"", null, Verifier.FILTERPATTERN)),
+			new Syntax(
+					BUNDLE_REQUIREDEXECUTIONENVIRONMENT,
+					"The " + BUNDLE_REQUIREDEXECUTIONENVIRONMENT + " contains a comma-separated list of execution environments that must be present on the Service Platform.",
+					BUNDLE_REQUIREDEXECUTIONENVIRONMENT + ": CDC-1.0/Foundation-1.0", Processor.join(Verifier.EES, ","),
+					Verifier.ANYPATTERN),
+
+			new Syntax(
+					BUNDLE_SYMBOLICNAME,
+					"The " + BUNDLE_SYMBOLICNAME + " header specifies a non-localizable name for this bundle. The bundle symbolic name together with a version must identify a unique bundle. The bundle symbolic name should be based on the reverse domain name convention.",
+					BUNDLE_SYMBOLICNAME + ": com.acme.foo.daffy;singleton:=true",
+					"${p}",
+					Verifier.SYMBOLICNAME,
+					new Syntax(
+							SINGLETON_DIRECTIVE,
+							"Indicates that the bundle can only have a single version resolved. A value of true indicates that the bundle is a singleton bundle. The default value is false. The Framework must resolve at most one bundle when multiple versions of a singleton bundle with the same symbolic name are installed. Singleton bundles do not affect the resolution of non-singleton bundles with the same symbolic name.",
+							SINGLETON_DIRECTIVE + "=false", "true,false", Verifier.TRUEORFALSEPATTERN),
+					new Syntax(
+							FRAGMENT_ATTACHMENT_DIRECTIVE,
+							"Defines how fragments are allowed to be attached, see the fragments in Fragment Bundles on page 73. The following values are valid for this directive:",
+							"", "always|never|resolve-time", Pattern.compile("always|never|resolve-time")), new Syntax(
+							BLUEPRINT_WAIT_FOR_DEPENDENCIES_ATTRIBUTE, "", "", "true,false",
+							Verifier.TRUEORFALSEPATTERN), new Syntax(BLUEPRINT_TIMEOUT_ATTRIBUTE, "", "",
+							"30000,60000,300000", Verifier.NUMBERPATTERN)),
+
+			new Syntax(
+					BUNDLE_UPDATELOCATION,
+					"The " + BUNDLE_UPDATELOCATION + " header specifies a URL where an update for this bundle should come from. If the bundle is updated, this location should be used, if present, to retrieve the updated JAR file.",
+					BUNDLE_UPDATELOCATION + ": http://www.acme.com/Firewall/bundle.jar", null, Verifier.URLPATTERN),
+
+			new Syntax(BUNDLE_VENDOR,
+					"The " + BUNDLE_VENDOR + " header contains a human-readable description of the bundle vendor.",
+					BUNDLE_VENDOR + ": OSGi Alliance", null, null),
+
+			new Syntax(BUNDLE_VERSION, "The " + BUNDLE_VERSION + " header specifies the version of this bundle.",
+					BUNDLE_VERSION + ": 1.23.4.build200903221000", null, Verifier.VERSION),
+
+			new Syntax(
+					DYNAMICIMPORT_PACKAGE,
+					"The " + DYNAMICIMPORT_PACKAGE + " header contains a comma-separated list of package names that should be dynamically imported when needed.",
+					DYNAMICIMPORT_PACKAGE + ": com.acme.plugin.*", "", Verifier.WILDCARDNAMEPATTERN, version,
+					bundle_symbolic_name, bundle_version),
+
+			new Syntax(
+					EXPORT_PACKAGE,
+					"The " + EXPORT_PACKAGE + " header contains a declaration of exported packages.",
+					EXPORT_PACKAGE + ": org.osgi.util.tracker;version=1.3",
+					"${packages}",
+					null,
+					new Syntax(
+							NO_IMPORT_DIRECTIVE,
+							"By default, bnd makes all exports also imports. Adding a " + NO_IMPORT_DIRECTIVE + " to an exported package will make it export only.",
+							NO_IMPORT_DIRECTIVE + "=true", "true,false", Verifier.TRUEORFALSEPATTERN),
+					new Syntax(
+							USES_DIRECTIVE,
+							"Calculated by bnd: It is a comma-separated list of package names that are used by the exported package.",
+							"Is calculated by bnd", null, null),
+					new Syntax(
+							MANDATORY_DIRECTIVE,
+							"A comma-separated list of attribute names. Note that the use of a comma in the value requires it to be enclosed in double quotes. A bundle importing the package must specify the mandatory attributes, with a value that matches, to resolve to the exported package.",
+							MANDATORY_DIRECTIVE + "=\"bar,foo\"", null, null), new Syntax(INCLUDE_DIRECTIVE,
+							"A comma-separated list of class names that must be visible to an importer.",
+							INCLUDE_DIRECTIVE + "=\"Qux*\"", null, null), new Syntax(EXCLUDE_DIRECTIVE,
+							"A comma-separated list of class names that must not be visible to an importer.",
+							EXCLUDE_DIRECTIVE + "=\"QuxImpl*,BarImpl\"", null, Verifier.WILDCARDNAMEPATTERN), new Syntax(
+							IMPORT_DIRECTIVE, "Experimental.", "", null, null)
+
+			),
+			new Syntax(EXPORT_SERVICE, "Deprecated.", EXPORT_SERVICE + ": org.osgi.service.log.LogService",
+					"${classes;implementing;*}", null),
+			new Syntax(
+					FRAGMENT_HOST,
+					"The " + FRAGMENT_HOST + " header defines the host bundle for this fragment.",
+					FRAGMENT_HOST + ": org.eclipse.swt; bundle-version=\"[3.0.0,4.0.0)\"",
+					null,
+					null,
+					new Syntax(
+							EXTENSION_DIRECTIVE,
+							"Indicates this extension is a system or boot class path extension. It is only applicable when the Fragment-Host is the System Bundle.",
+							EXTENSION_DIRECTIVE + "=framework", "framework,bootclasspath", Pattern
+									.compile("framework|bootclasspath")), bundle_version),
+			new Syntax(
+					IMPORT_PACKAGE,
+					"The " + IMPORT_PACKAGE + " header is normally calculated by bnd, however, you can decorate packages or skip packages. The header declares the imported packages for this bundle.",
+					IMPORT_PACKAGE + ": !com.exotic.*, com.acme.foo;vendor=ACME, *",
+					"${exported_packages}",
+					Verifier.WILDCARDNAMEPATTERN,
+					new Syntax(REMOVE_ATTRIBUTE_DIRECTIVE,
+							"Remove the given attributes from matching imported packages.", REMOVE_ATTRIBUTE_DIRECTIVE + "=foo.*",
+							null, Verifier.WILDCARDNAMEPATTERN),
+					new Syntax(
+							RESOLUTION_DIRECTIVE,
+							"Indicates that the packages must be resolved if the value is mandatory, which is the default. If mandatory packages cannot be resolved, then the bundle must fail to resolve. A value of optional indicates that the packages are optional.",
+							RESOLUTION_DIRECTIVE + "=optional", "mandatory,optional", Pattern.compile("mandatory|optional")
+
+					), version, bundle_symbolic_name, bundle_version),
+
+			new Syntax(
+					REQUIRE_BUNDLE,
+					"The " + REQUIRE_BUNDLE + " header specifies the required exports from another bundle.",
+					REQUIRE_BUNDLE + ": com.acme.chess",
+					null,
+					Verifier.WILDCARDNAMEPATTERN,
+
+					new Syntax(
+							VISIBILITY_DIRECTIVE,
+							"If the value is private (Default), then all visible packages from the required bundles are not re-exported. If the value is reexport then bundles that require this bundle will transitively have access to these required bundle’s exported packages.",
+							VISIBILITY_DIRECTIVE + "=private", "private,reexport", Pattern.compile("private|reexport")),
+
+					new Syntax(
+							RESOLUTION_DIRECTIVE,
+							"If the value is mandatory (default) then the required bundle must exist for this bundle to resolve. If the value is optional, the bundle will resolve even if the required bundle does not exist.",
+							RESOLUTION_DIRECTIVE + "=optional", "mandatory,optional", Pattern.compile("mandatory|optional")),
+
+					new Syntax(
+							SPLIT_PACKAGE_DIRECTIVE,
+							"Indicates how an imported package should be merged when it is split between different exporters. The default is merge-first with warning.",
+							SPLIT_PACKAGE_DIRECTIVE + "=merge-first", "merge-first,merge-last,error,first", Pattern
+									.compile("merge-first|merge-last|error|first")), bundle_version
+
+			),
+			new Syntax(BUILDPATH,
+					"Provides the class path for building the jar. The entries are references to the repository.",
+					BUILDPATH + "=osgi;version=4.1", "${repo;bsns}", Verifier.SYMBOLICNAME, path_version),
+			new Syntax(BUMPPOLICY, "Sets the version bump policy. This is a parameter to the ${version} macro.",
+					BUMPPOLICY + "==+0", "==+,=+0,+00", Pattern.compile("[=+-0][=+-0][=+-0]")),
+
+			new Syntax(CONDUIT,
+					"Allows a bnd file to point to files which will be returned when the bnd file is build.",
+					CONDUIT + "= jar/osgi.jar", null, null),
+
+			new Syntax(
+					DEPENDSON,
+					"List of project names that this project directly depends on. These projects are always build ahead of this project.",
+					DEPENDSON + "=org.acme.cm", "${projects}", null),
+
+			new Syntax(DEPLOYREPO, "Specifies to which repo the project should be deployed.", DEPLOYREPO + "=cnf",
+					"${repos}", null),
+
+			new Syntax(DONOTCOPY,
+					"Regular expression for names of files and directories that should not be copied when discovered.",
+					DONOTCOPY + "=(CVS|\\.svn)", null, null),
+
+			new Syntax(
+					EXPORT_CONTENTS,
+					"Build the JAR in the normal way but use this header for the " + EXPORT_PACKAGE + " header manifest generation, same format.",
+					EXPORT_CONTENTS + "=!*impl*,*;version=3.0", null, null),
+
+			new Syntax(FAIL_OK, "Return with an ok status (0) even if the build generates errors.", FAIL_OK + "=true",
+					"true,false", Verifier.TRUEORFALSEPATTERN),
+
+			new Syntax(
+					INCLUDE,
+					"Include files. If an entry starts with '-', it does not have to exist. If it starts with '~', it must not overwrite any existing properties.",
+					INCLUDE + ": -${java.user}/.bnd", null, null),
+
+			new Syntax(
+					INCLUDERESOURCE,
+					"Include resources from the file system. You can specify a directory, or file. All files are copied to the root, unless a destination directory is indicated.",
+					INCLUDERESOURCE + ": lib=jar", null, null),
+
+			new Syntax(
+					MAKE,
+					"Set patterns for make plugins. These patterns are used to find a plugin that can make a resource that can not be found.",
+					MAKE + ": (*).jar;type=bnd; recipe=\"bnd/$1.bnd\"", null, null, new Syntax("type",
+							"Type name for plugin.", "type=bnd", "bnd", null), new Syntax("recipe",
+							"Recipe for the plugin, can use back references.", "recipe=\"bnd/$1.bnd\"", "bnd", null)),
+
+			new Syntax(MANIFEST, "Directly include a manifest, do not use the calculated manifest.",
+					MANIFEST + "=META-INF/MANIFEST.MF", null, null),
+
+			new Syntax(NOEXTRAHEADERS, "Do not generate housekeeping headers.", NOEXTRAHEADERS + "=true", "true,false",
+					Verifier.TRUEORFALSEPATTERN),
+
+			new Syntax(NOUSES, "Do not calculate the " + USES_DIRECTIVE + " directive on exports.", NOUSES + "=true", "true,false",
+					Verifier.TRUEORFALSEPATTERN),
+
+			new Syntax(PEDANTIC, "Warn about things that are not really wrong but still not right.", PEDANTIC + "=true",
+					"true,false", Verifier.TRUEORFALSEPATTERN),
+
+			new Syntax(PLUGIN, "Define the plugins.",
+					PLUGIN + "=aQute.lib.spring.SpringComponent,aQute.lib.deployer.FileRepo;location=${repo}", null, null),
+
+			new Syntax(SERVICE_COMPONENT, "The header for Declarative Services.",
+					SERVICE_COMPONENT + "=com.acme.Foo?;activate='start'", null, null),
+
+			new Syntax(POM, "Generate a maven pom.", POM + "=true", "true,false", Verifier.TRUEORFALSEPATTERN),
+
+			new Syntax(RELEASEREPO, "Specifies to which repo the project should be released.", RELEASEREPO + "=cnf",
+					"${repos}", null),
+
+			new Syntax(REMOVEHEADERS, "Remove all headers that match the regular expressions.",
+					REMOVEHEADERS + "=FOO_.*,Proprietary", null, null),
+			new Syntax(
+					RESOURCEONLY,
+					"Normally bnd warns when the JAR does not contain any classes, this option suppresses this warning.",
+					RESOURCEONLY + "=true", "true,false", Verifier.TRUEORFALSEPATTERN),
+			new Syntax(SOURCES, "Include sources in the jar.", SOURCES + "=true", "true,false",
+					Verifier.TRUEORFALSEPATTERN),
+			new Syntax(SOURCEPATH, "List of directory names that used to source sources for " + SOURCES + ".",
+					SOURCEPATH + ":= src, test", null, null),
+			new Syntax(
+					SUB,
+					"Build a set of bnd files that use this bnd file as a basis. The list of bnd file can be specified with wildcards.",
+					SUB + "=com.acme.*.bnd", null, null),
+			new Syntax(RUNPROPERTIES, "Properties that are set as system properties before the framework is started.",
+					RUNPROPERTIES + "= foo=3, bar=4", null, null),
+			new Syntax(RUNSYSTEMPACKAGES, "Add additional system packages to a framework run.",
+					RUNSYSTEMPACKAGES + "=com.acme.foo,javax.management", null, null),
+			new Syntax(
+					RUNBUNDLES,
+					"Add additional bundles, specified with their bsn and version like in " + BUILDPATH + ", that are started before the project is run.",
+					RUNBUNDLES + "=osgi;version=\"[4.1,4.2)\", junit.junit, com.acme.foo;version=project", null,
+					Verifier.SYMBOLICNAME, path_version),
+			new Syntax(RUNPATH, "Additional JARs for the VM path, should include the framework.",
+					RUNPATH + "=org.eclipse.osgi;version=3.5", null, null, path_version),
+			new Syntax(
+					RUNVM,
+					"Additional arguments for the VM invokation. Keys that start with a - are added as options, otherwise they are treated as -D properties for the VM.",
+					RUNVM + "=-Xmax=30", null, null),
+			new Syntax(
+					RUNPROGRAMARGS,
+					"Additional arguments for the program invokation.",
+					RUNPROGRAMARGS + "=/some/file /another/file some_argument", null, null)
+																	};
+
+	public final static Map<String,Syntax>	HELP					= new HashMap<String,Syntax>();
+
+	static {
+		for (Syntax s : syntaxes) {
+			HELP.put(s.header, s);
+		}
+	}
+
+	public Syntax(String header, String lead, String example, String values, Pattern pattern, Syntax... children) {
+		this.header = header;
+		this.children = children;
+		this.lead = lead;
+		this.example = example;
+		this.values = values;
+		this.pattern = pattern;
+	}
+
+	public String getLead() {
+		return lead;
+	}
+
+	public String getExample() {
+		return example;
+	}
+
+	public String getValues() {
+		return values;
+	}
+
+	public String getPattern() {
+		return lead;
+	}
+
+	public Syntax[] getChildren() {
+		return children;
+	}
+
+	public String getHeader() {
+		return header;
+	}
 
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/help/packageinfo b/biz.aQute.bndlib/src/aQute/bnd/help/packageinfo
index a4f1546..7ae9673 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/help/packageinfo
+++ b/biz.aQute.bndlib/src/aQute/bnd/help/packageinfo
@@ -1 +1 @@
-version 1.0
\ No newline at end of file
+version 1.1
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/aQute/bnd/make/Make.java b/biz.aQute.bndlib/src/aQute/bnd/make/Make.java
index 6827c6d..59d252a 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/make/Make.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/make/Make.java
@@ -1,99 +1,97 @@
 package aQute.bnd.make;
 
 import java.util.*;
+import java.util.Map.Entry;
 import java.util.regex.*;
 
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
 import aQute.bnd.service.*;
-import aQute.lib.osgi.*;
 
 public class Make {
-    Builder                               builder;
-    Map<Instruction, Map<String, String>> make;
+	Builder								builder;
+	Map<Instruction,Map<String,String>>	make;
 
-    public Make(Builder builder) {
-        this.builder = builder;
-    }
+	public Make(Builder builder) {
+		this.builder = builder;
+	}
 
-    public Resource process(String source) {
-        Map<Instruction, Map<String, String>> make = getMakeHeader();
-        builder.trace("make " + source);
+	public Resource process(String source) {
+		Map<Instruction,Map<String,String>> make = getMakeHeader();
+		builder.trace("make " + source);
 
-        for (Map.Entry<Instruction, Map<String, String>> entry : make
-                .entrySet()) {
-            Instruction instr = entry.getKey();
-            Matcher m = instr.getMatcher(source);
-            if (m.matches() || instr.isNegated()) {
-                Map<String, String> arguments = replace(m, entry.getValue());
-                List<MakePlugin> plugins = builder.getPlugins(MakePlugin.class);
-                for (MakePlugin plugin : plugins) {
-                    try {
-                        Resource resource = plugin.make(builder,
-                                source, arguments);
-                        if (resource != null) {
-                            builder.trace("Made " + source + " from args "
-                                    + arguments + " with " + plugin);
-                            return resource;
-                        }
-                    } catch (Exception e) {
-                        builder.error("Plugin " + plugin
-                                + " generates error when use in making "
-                                + source + " with args " + arguments, e);
-                    }
-                }
-            }
-        }
-        return null;
-    }
+		for (Map.Entry<Instruction,Map<String,String>> entry : make.entrySet()) {
+			Instruction instr = entry.getKey();
+			Matcher m = instr.getMatcher(source);
+			if (m.matches() || instr.isNegated()) {
+				Map<String,String> arguments = replace(m, entry.getValue());
+				List<MakePlugin> plugins = builder.getPlugins(MakePlugin.class);
+				for (MakePlugin plugin : plugins) {
+					try {
+						Resource resource = plugin.make(builder, source, arguments);
+						if (resource != null) {
+							builder.trace("Made " + source + " from args " + arguments + " with " + plugin);
+							return resource;
+						}
+					}
+					catch (Exception e) {
+						builder.error("Plugin " + plugin + " generates error when use in making " + source
+								+ " with args " + arguments, e);
+					}
+				}
+			}
+		}
+		return null;
+	}
 
-    private Map<String, String> replace(Matcher m, Map<String, String> value) {
-        Map<String, String> newArgs = Processor.newMap();
-        for (Map.Entry<String, String> entry : value.entrySet()) {
-            String s = entry.getValue();
-            s = replace(m, s);
-            newArgs.put(entry.getKey(), s);
-        }
-        return newArgs;
-    }
+	private Map<String,String> replace(Matcher m, Map<String,String> value) {
+		Map<String,String> newArgs = Processor.newMap();
+		for (Map.Entry<String,String> entry : value.entrySet()) {
+			String s = entry.getValue();
+			s = replace(m, s);
+			newArgs.put(entry.getKey(), s);
+		}
+		return newArgs;
+	}
 
-    String replace(Matcher m, CharSequence s) {
-        StringBuffer sb = new StringBuffer();
-        int max = '0' + m.groupCount() + 1;
-        for (int i = 0; i < s.length(); i++) {
-            char c = s.charAt(i);
-            if (c == '$' && i < s.length() - 1) {
-                c = s.charAt(++i);
-                if (c >= '0' && c <= max) {
-                    int index = c - '0';
-                    String replacement = m.group(index);
-                    if (replacement != null)
-                        sb.append(replacement);
-                } else {
-                    if (c == '$')
-                        i++;
-                    sb.append(c);
-                }
-            } else
-                sb.append(c);
-        }
-        return sb.toString();
-    }
+	String replace(Matcher m, CharSequence s) {
+		StringBuilder sb = new StringBuilder();
+		int max = '0' + m.groupCount() + 1;
+		for (int i = 0; i < s.length(); i++) {
+			char c = s.charAt(i);
+			if (c == '$' && i < s.length() - 1) {
+				c = s.charAt(++i);
+				if (c >= '0' && c <= max) {
+					int index = c - '0';
+					String replacement = m.group(index);
+					if (replacement != null)
+						sb.append(replacement);
+				} else {
+					if (c == '$')
+						i++;
+					sb.append(c);
+				}
+			} else
+				sb.append(c);
+		}
+		return sb.toString();
+	}
 
-    Map<Instruction, Map<String, String>> getMakeHeader() {
-        if (make != null)
-            return make;
-        make = Processor.newMap();
+	Map<Instruction,Map<String,String>> getMakeHeader() {
+		if (make != null)
+			return make;
+		make = Processor.newMap();
 
-        String s = builder.getProperty(Builder.MAKE);
-        Map<String, Map<String, String>> make = builder.parseHeader(s);
-        for (Iterator<Map.Entry<String, Map<String, String>>> e = make
-                .entrySet().iterator(); e.hasNext();) {
-            Map.Entry<String, Map<String, String>> entry = e.next();
-            String pattern = Processor.removeDuplicateMarker(entry.getKey());
-            
-            Instruction instr = Instruction.getPattern(pattern);
-            this.make.put(instr, entry.getValue());
-        }
+		String s = builder.getProperty(Builder.MAKE);
+		Parameters make = builder.parseHeader(s);
 
-        return this.make;
-    }
+		for (Entry<String,Attrs> entry : make.entrySet()) {
+			String pattern = Processor.removeDuplicateMarker(entry.getKey());
+
+			Instruction instr = new Instruction(pattern);
+			this.make.put(instr, entry.getValue());
+		}
+
+		return this.make;
+	}
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/make/MakeBnd.java b/biz.aQute.bndlib/src/aQute/bnd/make/MakeBnd.java
index f2e90d8..cda13b4 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/make/MakeBnd.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/make/MakeBnd.java
@@ -5,61 +5,59 @@ import java.util.*;
 import java.util.regex.*;
 
 import aQute.bnd.build.*;
+import aQute.bnd.osgi.*;
 import aQute.bnd.service.*;
-import aQute.lib.osgi.*;
 
 public class MakeBnd implements MakePlugin, Constants {
-    final static Pattern JARFILE = Pattern.compile("(.+)\\.(jar|ipa)");
+	final static Pattern	JARFILE	= Pattern.compile("(.+)\\.(jar|ipa)");
 
-    public Resource make(Builder builder, String destination,
-            Map<String, String> argumentsOnMake) throws Exception {
-        String type = (String) argumentsOnMake.get("type");
-        if (!"bnd".equals(type))
-            return null;
+	public Resource make(Builder builder, String destination, Map<String,String> argumentsOnMake) throws Exception {
+		String type = argumentsOnMake.get("type");
+		if (!"bnd".equals(type))
+			return null;
 
-        String recipe = (String) argumentsOnMake.get("recipe");
-        if (recipe == null) {
-            builder.error("No recipe specified on a make instruction for "
-                    + destination);
-            return null;
-        }
-        File bndfile = builder.getFile(recipe);
-        if (bndfile.isFile()) {
-            // We do not use a parent because then we would
-            // build ourselves again. So we can not blindly
-            // inherit the properties.
-            Builder bchild = builder.getSubBuilder();
-            bchild.removeBundleSpecificHeaders();
-            
-            // We must make sure that we do not include ourselves again!
-            bchild.setProperty(Analyzer.INCLUDE_RESOURCE, "");
-            bchild.setProperty(Analyzer.INCLUDERESOURCE, "");
-            bchild.setProperties(bndfile, builder.getBase());
-            
-            Jar jar = bchild.build();
-            Jar dot = builder.getTarget();
+		String recipe = argumentsOnMake.get("recipe");
+		if (recipe == null) {
+			builder.error("No recipe specified on a make instruction for " + destination);
+			return null;
+		}
+		File bndfile = builder.getFile(recipe);
+		if (bndfile.isFile()) {
+			// We do not use a parent because then we would
+			// build ourselves again. So we can not blindly
+			// inherit the properties.
+			Builder bchild = builder.getSubBuilder();
+			bchild.removeBundleSpecificHeaders();
 
-            if (builder.hasSources()) {
-                for (String key : jar.getResources().keySet()) {
-                    if (key.startsWith("OSGI-OPT/src"))
-                        dot.putResource(key, (Resource) jar.getResource(key));
-                }
-            }
-            builder.getInfo(bchild, bndfile.getName() +": ");
-            String debug = bchild.getProperty(DEBUG);
-            if (Processor.isTrue(debug)) {
-                if ( builder instanceof ProjectBuilder ) {
-                    ProjectBuilder pb = (ProjectBuilder) builder;
-                    File target = pb.getProject().getTarget();
-                    String bsn = bchild.getBsn();
-                    File output = new File(target, bsn+".jar");
-                    jar.write(output);
-                    pb.getProject().getWorkspace().changedFile(output);
-                }
-            }
-            return new JarResource(jar);
-        } else
-            return null;
-    }
+			// We must make sure that we do not include ourselves again!
+			bchild.setProperty(Analyzer.INCLUDE_RESOURCE, "");
+			bchild.setProperty(Analyzer.INCLUDERESOURCE, "");
+			bchild.setProperties(bndfile, builder.getBase());
+
+			Jar jar = bchild.build();
+			Jar dot = builder.getTarget();
+
+			if (builder.hasSources()) {
+				for (String key : jar.getResources().keySet()) {
+					if (key.startsWith("OSGI-OPT/src"))
+						dot.putResource(key, jar.getResource(key));
+				}
+			}
+			builder.getInfo(bchild, bndfile.getName() + ": ");
+			String debug = bchild.getProperty(DEBUG);
+			if (Processor.isTrue(debug)) {
+				if (builder instanceof ProjectBuilder) {
+					ProjectBuilder pb = (ProjectBuilder) builder;
+					File target = pb.getProject().getTarget();
+					String bsn = bchild.getBsn();
+					File output = new File(target, bsn + ".jar");
+					jar.write(output);
+					pb.getProject().getWorkspace().changedFile(output);
+				}
+			}
+			return new JarResource(jar);
+		}
+		return null;
+	}
 
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/make/MakeCopy.java b/biz.aQute.bndlib/src/aQute/bnd/make/MakeCopy.java
index 3d5e4c8..c799dc7 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/make/MakeCopy.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/make/MakeCopy.java
@@ -4,42 +4,35 @@ import java.io.*;
 import java.net.*;
 import java.util.*;
 
+import aQute.bnd.osgi.*;
 import aQute.bnd.service.*;
-import aQute.lib.osgi.*;
 
 public class MakeCopy implements MakePlugin {
 
-    public Resource make(Builder builder, String destination,
-            Map<String, String> argumentsOnMake) throws Exception {
-        String type = argumentsOnMake.get("type");
-        if (!type.equals("copy"))
-            return null;
+	public Resource make(Builder builder, String destination, Map<String,String> argumentsOnMake) throws Exception {
+		String type = argumentsOnMake.get("type");
+		if (!type.equals("copy"))
+			return null;
 
-        String from = argumentsOnMake.get("from");
-        if (from == null) {
-            String content = argumentsOnMake.get("content");
-            if (content == null)
-                throw new IllegalArgumentException(
-                        "No 'from' or 'content' field in copy "
-                                + argumentsOnMake);
-            return new EmbeddedResource(content.getBytes("UTF-8"),0);
-        } else {
-
-            File f = builder.getFile(from);
-            if (f.isFile())
-                return new FileResource(f);
-            else {
-                try {
-                    URL url = new URL(from);
-                    return new URLResource(url);
-                } catch(MalformedURLException mfue) {
-                    // We ignore this
-                }
-                throw new IllegalArgumentException(
-                        "Copy source does not exist " + from
-                                + " for destination " + destination);
-            }
-        }
-    }
+		String from = argumentsOnMake.get("from");
+		if (from == null) {
+			String content = argumentsOnMake.get("content");
+			if (content == null)
+				throw new IllegalArgumentException("No 'from' or 'content' field in copy " + argumentsOnMake);
+			return new EmbeddedResource(content.getBytes("UTF-8"), 0);
+		}
+		File f = builder.getFile(from);
+		if (f.isFile())
+			return new FileResource(f);
+		try {
+			URL url = new URL(from);
+			return new URLResource(url);
+		}
+		catch (MalformedURLException mfue) {
+			// We ignore this
+		}
+		throw new IllegalArgumentException("Copy source does not exist " + from + " for destination "
+				+ destination);
+	}
 
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/make/calltree/CalltreeResource.java b/biz.aQute.bndlib/src/aQute/bnd/make/calltree/CalltreeResource.java
index 2775a57..76fac28 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/make/calltree/CalltreeResource.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/make/calltree/CalltreeResource.java
@@ -4,7 +4,8 @@ import java.io.*;
 import java.lang.reflect.*;
 import java.util.*;
 
-import aQute.lib.osgi.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Clazz.MethodDef;
 
 /**
  * Create an XML call tree of a set of classes. The structure of the XML is:
@@ -13,153 +14,163 @@ import aQute.lib.osgi.*;
  *    calltree ::= <using> <usedby>
  *    using    ::= <method> *
  *    usedby   ::= <method> *
- *    method   ::= <ref> 
+ *    method   ::= <ref>
  * </pre>
  * 
  * The <code>using</code> element contains methods in the set of classes and
  * their references. The <code>usedby</code> element contains the used methods
  * and their references to the set of classes. The <code>ref</code> element
  * contains the class, the method name, the descriptor, and a pretty print
- * version of the method.
- * 
- * The XML does not contain an XML processor instruction to make it easier to
- * include in other XML. The encoding is always UTF-8.
- * 
- * This class can be used as a resource, just add it to a JAR and the data is
+ * version of the method. The XML does not contain an XML processor instruction
+ * to make it easier to include in other XML. The encoding is always UTF-8. This
+ * class can be used as a resource, just add it to a JAR and the data is
  * generated when the resource is written (saving time when the JAR is up to
  * date and does not have to be generated). However, the actual write method is
  * a static method and can be called as well:
  * {@link #writeCalltree(PrintWriter, Collection)}.
  */
 public class CalltreeResource extends WriteResource {
-    Collection<Clazz> classes;
-
-    /**
-     * Create a resource for inclusion that will print a call tree.
-     * 
-     * @param values the classes for which the call tree is generated.
-     */
-    public CalltreeResource(Collection<Clazz> values) {
-        this.classes = values;
-        System.out.println(values);
-    }
-
-    /**
-     * We set the last modified to 0 so this resource does not force
-     * a new JAR if all other resources are up to date.
-     */
-    public long lastModified() {
-        return 0;
-    }
-
-    /**
-     * The write method is called to write the resource. We just call the static
-     * method.
-     */
-    public void write(OutputStream out) throws Exception {
-        OutputStreamWriter osw = new OutputStreamWriter(out, Constants.DEFAULT_CHARSET);
-        PrintWriter pw = new PrintWriter(osw);
-        try {
-            writeCalltree(pw, classes);
-        } finally {
-            pw.flush();
-        }
-    }
-
-    /**
-     * Print the call tree in XML.
-     * 
-     * @param out The output writer
-     * @param classes The set of classes
-     * @throws IOException Any errors
-     */
-    public static void writeCalltree(PrintWriter out, Collection<Clazz> classes)
-            throws Exception {
-
-        final Map<Clazz.MethodDef, Set<Clazz.MethodDef>> using = new TreeMap<Clazz.MethodDef, Set<Clazz.MethodDef>>();
-        final Map<Clazz.MethodDef, Set<Clazz.MethodDef>> usedby = new TreeMap<Clazz.MethodDef, Set<Clazz.MethodDef>>();
-
-        ClassDataCollector cd = new ClassDataCollector() {
-            Clazz.MethodDef source;
-
-            // Before a method is parsed
-            public void method(Clazz.MethodDef source) {
-                this.source = source;
-                xref(using, source, null);
-                xref(usedby, source, null);
-            }
-
-            // For any reference in the previous method.
-            public void reference(Clazz.MethodDef reference) {
-                xref(using, source, reference);
-                xref(usedby, reference, source);
-            }
-        };
-        for (Clazz clazz : classes) {
-            clazz.parseClassFileWithCollector(cd);
-        }
-
-        out.println("<calltree>");
-        xref(out, "using", using);
-        xref(out, "usedby", usedby);
-        out.println("</calltree>");
-    }
-
-    /*
-     * Add a new reference
-     */
-    private static void xref(
-            Map<Clazz.MethodDef, Set<Clazz.MethodDef>> references,
-            Clazz.MethodDef source, Clazz.MethodDef reference) {
-        Set<Clazz.MethodDef> set = references.get(source);
-        if (set == null)
-            references.put(source, set=new TreeSet<Clazz.MethodDef>());
-        if ( reference != null)
-            set.add(reference);
-    }
-
-    /*
-     * Print out either using or usedby sets
-     */
-    private static void xref(PrintWriter out, String group,
-            Map<Clazz.MethodDef, Set<Clazz.MethodDef>> references) {
-        out.println("  <" + group + ">");
-        for (Map.Entry<Clazz.MethodDef, Set<Clazz.MethodDef>> entry : references
-                .entrySet()) {
-            Clazz.MethodDef source = entry.getKey();
-            Set<Clazz.MethodDef> refs = entry.getValue();
-            method(out, "method", source, ">");
-            for (Clazz.MethodDef ref : refs) {
-                method(out, "ref", ref, "/>");
-            }
-            out.println("      </method>");
-        }
-        out.println("  </" + group + ">");
-    }
-
-    /*
-     * Print out a method.
-     */
-    private static void method(PrintWriter out, String element,
-            Clazz.MethodDef source, String closeElement) {
-        out.println("      <" + element + " class='" + source.clazz + "'"
-                + getAccess(source.access) + 
-                ( source.isConstructor() ? "" :  " name='" + source.name + "'") + " descriptor='" + source.descriptor + "' pretty='"
-                + source.getPretty() + "'" + closeElement);
-    }
-
-    private static String getAccess(int access) {
-        StringBuilder sb = new StringBuilder();
-        if ( Modifier.isPublic(access) )
-            sb.append(" public='true'");
-        if ( Modifier.isStatic(access) )
-            sb.append(" static='true'");
-        if ( Modifier.isProtected(access) )
-            sb.append(" protected='true'");
-        if ( Modifier.isInterface(access) )
-            sb.append(" interface='true'");
-        
-        return sb.toString();
-    }
+	Collection<Clazz>	classes;
+
+	/**
+	 * Create a resource for inclusion that will print a call tree.
+	 * 
+	 * @param values
+	 *            the classes for which the call tree is generated.
+	 */
+	public CalltreeResource(Collection<Clazz> values) {
+		this.classes = values;
+		System.err.println(values);
+	}
+
+	/**
+	 * We set the last modified to 0 so this resource does not force a new JAR
+	 * if all other resources are up to date.
+	 */
+	@Override
+	public long lastModified() {
+		return 0;
+	}
+
+	/**
+	 * The write method is called to write the resource. We just call the static
+	 * method.
+	 */
+	@Override
+	public void write(OutputStream out) throws Exception {
+		OutputStreamWriter osw = new OutputStreamWriter(out, Constants.DEFAULT_CHARSET);
+		PrintWriter pw = new PrintWriter(osw);
+		try {
+			writeCalltree(pw, classes);
+		}
+		finally {
+			pw.flush();
+		}
+	}
+
+	/**
+	 * Print the call tree in XML.
+	 * 
+	 * @param out
+	 *            The output writer
+	 * @param classes
+	 *            The set of classes
+	 * @throws IOException
+	 *             Any errors
+	 */
+	public static void writeCalltree(PrintWriter out, Collection<Clazz> classes) throws Exception {
+
+		final Map<Clazz.MethodDef,Set<Clazz.MethodDef>> using = new TreeMap<Clazz.MethodDef,Set<Clazz.MethodDef>>(
+				COMPARATOR);
+		final Map<Clazz.MethodDef,Set<Clazz.MethodDef>> usedby = new TreeMap<Clazz.MethodDef,Set<Clazz.MethodDef>>(
+				COMPARATOR);
+
+		ClassDataCollector cd = new ClassDataCollector() {
+//			Clazz.MethodDef	source;
+
+			// Before a method is parsed
+			@Override
+			public void method(Clazz.MethodDef source) {
+//				this.source = source;
+				xref(using, source, null);
+				xref(usedby, source, null);
+			}
+
+			// For any reference in the previous method.
+//			public void reference(Clazz.MethodDef reference) {
+//				xref(using, source, reference);
+//				xref(usedby, reference, source);
+//			}
+		};
+		for (Clazz clazz : classes) {
+			clazz.parseClassFileWithCollector(cd);
+		}
+
+		out.println("<calltree>");
+		xref(out, "using", using);
+		xref(out, "usedby", usedby);
+		out.println("</calltree>");
+	}
+
+	/*
+	 * Add a new reference
+	 */
+	static Comparator<Clazz.MethodDef>	COMPARATOR	= new Comparator<Clazz.MethodDef>() {
+
+														public int compare(MethodDef a, MethodDef b) {
+															int r = a.getName().compareTo(b.getName());
+															return r != 0 ? r : a.getDescriptor().toString()
+																	.compareTo(b.getDescriptor().toString());
+														}
+													};
+
+	static void xref(Map<Clazz.MethodDef,Set<Clazz.MethodDef>> references, Clazz.MethodDef source,
+			Clazz.MethodDef reference) {
+		Set<Clazz.MethodDef> set = references.get(source);
+		if (set == null)
+			references.put(source, set = new TreeSet<Clazz.MethodDef>(COMPARATOR));
+		if (reference != null)
+			set.add(reference);
+	}
+
+	/*
+	 * Print out either using or usedby sets
+	 */
+	private static void xref(PrintWriter out, String group, Map<Clazz.MethodDef,Set<Clazz.MethodDef>> references) {
+		out.println("  <" + group + ">");
+		for (Map.Entry<Clazz.MethodDef,Set<Clazz.MethodDef>> entry : references.entrySet()) {
+			Clazz.MethodDef source = entry.getKey();
+			Set<Clazz.MethodDef> refs = entry.getValue();
+			method(out, "method", source, ">");
+			for (Clazz.MethodDef ref : refs) {
+				method(out, "ref", ref, "/>");
+			}
+			out.println("      </method>");
+		}
+		out.println("  </" + group + ">");
+	}
+
+	/*
+	 * Print out a method.
+	 */
+	private static void method(PrintWriter out, String element, Clazz.MethodDef source, String closeElement) {
+		out.println("      <" + element + " class='" + source.getContainingClass().getFQN() + "'"
+				+ getAccess(source.getAccess()) + (source.isConstructor() ? "" : " name='" + source.getName() + "'")
+				+ " descriptor='" + source.getDescriptor() + "' pretty='" + source.toString() + "'" + closeElement);
+	}
+
+	private static String getAccess(int access) {
+		StringBuilder sb = new StringBuilder();
+		if (Modifier.isPublic(access))
+			sb.append(" public='true'");
+		if (Modifier.isStatic(access))
+			sb.append(" static='true'");
+		if (Modifier.isProtected(access))
+			sb.append(" protected='true'");
+		if (Modifier.isInterface(access))
+			sb.append(" interface='true'");
+
+		return sb.toString();
+	}
 
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/make/component/ComponentAnnotationReader.java b/biz.aQute.bndlib/src/aQute/bnd/make/component/ComponentAnnotationReader.java
index 0490aee..b9d7e4f 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/make/component/ComponentAnnotationReader.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/make/component/ComponentAnnotationReader.java
@@ -1,17 +1,21 @@
 package aQute.bnd.make.component;
 
-import static aQute.lib.osgi.Constants.*;
+import static aQute.bnd.osgi.Constants.*;
 
 import java.lang.reflect.*;
 import java.util.*;
 import java.util.regex.*;
 
-import aQute.lib.osgi.Annotation;
-
 import aQute.bnd.annotation.component.*;
-import aQute.lib.osgi.*;
-import aQute.libg.reporter.*;
-
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Clazz.MethodDef;
+import aQute.bnd.osgi.Descriptors.TypeRef;
+import aQute.service.reporter.*;
+
+/**
+ * This converts bnd style annotations to, roughly, the header format.
+ *
+ */
 public class ComponentAnnotationReader extends ClassDataCollector {
 	String						EMPTY[]					= new String[0];
 	private static final String	V1_1					= "1.1.0";																																// "1.1.0"
@@ -23,22 +27,29 @@ public class ComponentAnnotationReader extends ClassDataCollector {
 																.compile("\\(((Lorg/osgi/service/component/ComponentContext;)|(Lorg/osgi/framework/BundleContext;)|(Ljava/util/Map;))*\\)V");
 	static Pattern				OLDACTIVATEDESCRIPTOR	= Pattern
 																.compile("\\(Lorg/osgi/service/component/ComponentContext;\\)V");
+
 	static Pattern				OLDBINDDESCRIPTOR		= Pattern.compile("\\(L([^;]*);\\)V");
 	static Pattern				REFERENCEBINDDESCRIPTOR	= Pattern
 																.compile("\\(Lorg/osgi/framework/ServiceReference;\\)V");
 
+	static String[]				ACTIVATE_ARGUMENTS		= {
+			"org.osgi.service.component.ComponentContext", "org.osgi.framework.BundleContext", Map.class.getName(),
+			"org.osgi.framework.BundleContext"
+														};
+	static String[]				OLD_ACTIVATE_ARGUMENTS	= {
+															"org.osgi.service.component.ComponentContext"
+														};
+
 	Reporter					reporter				= new Processor();
-	String						method;
-	String						methodDescriptor;
-	int							methodAccess;
-	String						className;
+	MethodDef					method;
+	TypeRef						className;
 	Clazz						clazz;
-	String						interfaces[];
+	TypeRef						interfaces[];
 	Set<String>					multiple				= new HashSet<String>();
 	Set<String>					optional				= new HashSet<String>();
 	Set<String>					dynamic					= new HashSet<String>();
 
-	Map<String, String>			map						= new TreeMap<String, String>();
+	Map<String,String>			map						= new TreeMap<String,String>();
 	Set<String>					descriptors				= new HashSet<String>();
 	List<String>				properties				= new ArrayList<String>();
 	String						version					= null;
@@ -57,11 +68,11 @@ public class ComponentAnnotationReader extends ClassDataCollector {
 		return this.reporter;
 	}
 
-	public static Map<String, String> getDefinition(Clazz c) throws Exception {
+	public static Map<String,String> getDefinition(Clazz c) throws Exception {
 		return getDefinition(c, new Processor());
 	}
 
-	public static Map<String, String> getDefinition(Clazz c, Reporter reporter) throws Exception {
+	public static Map<String,String> getDefinition(Clazz c, Reporter reporter) throws Exception {
 		ComponentAnnotationReader r = new ComponentAnnotationReader(c);
 		r.setReporter(reporter);
 		c.parseClassFileWithCollector(r);
@@ -69,9 +80,11 @@ public class ComponentAnnotationReader extends ClassDataCollector {
 		return r.map;
 	}
 
+	@Override
 	public void annotation(Annotation annotation) {
+		String fqn = annotation.getName().getFQN();
 
-		if (annotation.getName().equals(Component.RNAME)) {
+		if (fqn.equals(Component.class.getName())) {
 			set(COMPONENT_NAME, annotation.get(Component.NAME), "<>");
 			set(COMPONENT_FACTORY, annotation.get(Component.FACTORY), false);
 			setBoolean(COMPONENT_ENABLED, annotation.get(Component.ENABLED), true);
@@ -108,8 +121,8 @@ public class ComponentAnnotationReader extends ClassDataCollector {
 				if (interfaces != null) {
 					List<String> result = new ArrayList<String>();
 					for (int i = 0; i < interfaces.length; i++) {
-						if (!interfaces[i].equals("scala/ScalaObject") )
-							result.add(Clazz.internalToFqn(interfaces[i]));
+						if (!interfaces[i].getBinary().equals("scala/ScalaObject"))
+							result.add(interfaces[i].getFQN());
 					}
 					p = result.toArray(EMPTY);
 				} else
@@ -125,59 +138,65 @@ public class ComponentAnnotationReader extends ClassDataCollector {
 				set(COMPONENT_PROVIDE, Processor.join(Arrays.asList(p)), "<>");
 			}
 
-		} else if (annotation.getName().equals(Activate.RNAME)) {
+		} else if (fqn.equals(Activate.class.getName())) {
 			if (!checkMethod())
 				setVersion(V1_1);
 
-			if (!ACTIVATEDESCRIPTOR.matcher(methodDescriptor).matches())
+			// TODO ... use the new descriptor to do better check
+
+			if (!ACTIVATEDESCRIPTOR.matcher(method.getDescriptor().toString()).matches())
 				reporter.error(
 						"Activate method for %s does not have an acceptable prototype, only Map, ComponentContext, or BundleContext is allowed. Found: %s",
-						className, methodDescriptor);
+						className, method.getDescriptor());
 
-			if (method.equals("activate")
-					&& OLDACTIVATEDESCRIPTOR.matcher(methodDescriptor).matches()) {
+			if (method.getName().equals("activate")
+					&& OLDACTIVATEDESCRIPTOR.matcher(method.getDescriptor().toString()).matches()) {
 				// this is the default!
 			} else {
 				setVersion(V1_1);
 				set(COMPONENT_ACTIVATE, method, "<>");
 			}
 
-		} else if (annotation.getName().equals(Deactivate.RNAME)) {
+		} else if (fqn.equals(Deactivate.class.getName())) {
 			if (!checkMethod())
 				setVersion(V1_1);
 
-			if (!ACTIVATEDESCRIPTOR.matcher(methodDescriptor).matches())
+			if (!ACTIVATEDESCRIPTOR.matcher(method.getDescriptor().toString()).matches())
 				reporter.error(
 						"Deactivate method for %s does not have an acceptable prototype, only Map, ComponentContext, or BundleContext is allowed. Found: %s",
-						className, methodDescriptor);
-			if (method.equals("deactivate")
-					&& OLDACTIVATEDESCRIPTOR.matcher(methodDescriptor).matches()) {
+						className, method.getDescriptor());
+			if (method.getName().equals("deactivate")
+					&& OLDACTIVATEDESCRIPTOR.matcher(method.getDescriptor().toString()).matches()) {
 				// This is the default!
 			} else {
 				setVersion(V1_1);
 				set(COMPONENT_DEACTIVATE, method, "<>");
 			}
-		} else if (annotation.getName().equals(Modified.RNAME)) {
+		} else if (fqn.equals(Modified.class.getName())) {
 			set(COMPONENT_MODIFIED, method, "<>");
 			setVersion(V1_1);
-		} else if (annotation.getName().equals(Reference.RNAME)) {
+		} else if (fqn.equals(Reference.class.getName())) {
 
-			String name = (String) annotation.get(Reference.NAME);
-			String bind = method;
+			String name = (String) annotation.get(Reference.class.getName());
+			String bind = method.getName();
 			String unbind = null;
 
 			if (name == null) {
-				Matcher m = BINDMETHOD.matcher(method);
+				Matcher m = BINDMETHOD.matcher(method.getName());
 				if (m.matches()) {
 					name = m.group(2).toLowerCase() + m.group(3);
 				} else {
-					name = method.toLowerCase();
+					name = method.getName().toLowerCase();
 				}
 			}
 			String simpleName = name;
 
 			unbind = annotation.get(Reference.UNBIND);
 
+			//this error reporting currently handled in HeaderReader.  If we rewrite this to go directly to ComponentDesc, we'll want this.
+//			if (unbind != null && !descriptors.contains(unbind))
+//				reporter.error("In component %s, for bind method %s, missing unbind method %s", name, bind, unbind);
+
 			if (bind != null) {
 				name = name + "/" + bind;
 				if (unbind != null)
@@ -190,13 +209,13 @@ public class ComponentAnnotationReader extends ClassDataCollector {
 			} else {
 				// We have to find the type of the current method to
 				// link it to the referenced service.
-				Matcher m = BINDDESCRIPTOR.matcher(methodDescriptor);
+				Matcher m = BINDDESCRIPTOR.matcher(method.getDescriptor().toString());
 				if (m.matches()) {
-					service = Clazz.internalToFqn(m.group(1));
+					service = Descriptors.binaryToFQN(m.group(1));
 				} else
 					throw new IllegalArgumentException(
 							"Cannot detect the type of a Component Reference from the descriptor: "
-									+ methodDescriptor);
+									+ method.getDescriptor());
 			}
 
 			// Check if we have a target, this must be a filter
@@ -226,8 +245,8 @@ public class ComponentAnnotationReader extends ClassDataCollector {
 
 			if (!checkMethod())
 				setVersion(V1_1);
-			else if (REFERENCEBINDDESCRIPTOR.matcher(methodDescriptor).matches()
-					|| !OLDBINDDESCRIPTOR.matcher(methodDescriptor).matches())
+			else if (REFERENCEBINDDESCRIPTOR.matcher(method.getDescriptor().toString()).matches()
+					|| !OLDBINDDESCRIPTOR.matcher(method.getDescriptor().toString()).matches())
 				setVersion(V1_1);
 		}
 	}
@@ -243,19 +262,20 @@ public class ComponentAnnotationReader extends ClassDataCollector {
 	}
 
 	private boolean checkMethod() {
-		return Modifier.isPublic(methodAccess) || Modifier.isProtected(methodAccess);
+		return Modifier.isPublic(method.getAccess()) || Modifier.isProtected(method.getAccess());
 	}
 
-	static Pattern	PROPERTY_PATTERN	= Pattern.compile("[^=]+=.+");
+	static Pattern	PROPERTY_PATTERN	= Pattern.compile("\\s*([^=\\s]+)\\s*=(.+)");
 
-	private void doProperties(aQute.lib.osgi.Annotation annotation) {
+	private void doProperties(aQute.bnd.osgi.Annotation annotation) {
 		Object[] properties = annotation.get(Component.PROPERTIES);
 
 		if (properties != null) {
 			for (Object o : properties) {
 				String p = (String) o;
-				if (PROPERTY_PATTERN.matcher(p).matches())
-					this.properties.add(p);
+				Matcher m = PROPERTY_PATTERN.matcher(p);
+				if (m.matches())
+					this.properties.add(m.group(1)+"="+m.group(2));
 				else
 					throw new IllegalArgumentException("Malformed property '" + p + "' on: "
 							+ annotation.get(Component.NAME));
@@ -288,9 +308,8 @@ public class ComponentAnnotationReader extends ClassDataCollector {
 	}
 
 	/**
-	 * Skip L and ; and replace / for . in an object descriptor.
-	 * 
-	 * A string like Lcom/acme/Foo; becomes com.acme.Foo
+	 * Skip L and ; and replace / for . in an object descriptor. A string like
+	 * Lcom/acme/Foo; becomes com.acme.Foo
 	 * 
 	 * @param string
 	 * @return
@@ -307,19 +326,20 @@ public class ComponentAnnotationReader extends ClassDataCollector {
 		return sb.toString();
 	}
 
-	@Override public void classBegin(int access, String name) {
+	@Override
+	public void classBegin(int access, TypeRef name) {
 		className = name;
 	}
 
-	@Override public void implementsInterfaces(String[] interfaces) {
+	@Override
+	public void implementsInterfaces(TypeRef[] interfaces) {
 		this.interfaces = interfaces;
 	}
 
-	@Override public void method(int access, String name, String descriptor) {
-		this.method = name;
-		this.methodDescriptor = descriptor;
-		this.methodAccess = access;
-		descriptors.add(method);
+	@Override
+	public void method(Clazz.MethodDef method) {
+		this.method = method;
+		descriptors.add(method.getName());
 	}
 
 	void set(String name, Collection<String> l) {
diff --git a/biz.aQute.bndlib/src/aQute/bnd/make/component/ServiceComponent.java b/biz.aQute.bndlib/src/aQute/bnd/make/component/ServiceComponent.java
index d9e18f2..eaa5ddb 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/make/component/ServiceComponent.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/make/component/ServiceComponent.java
@@ -2,14 +2,17 @@ package aQute.bnd.make.component;
 
 import java.io.*;
 import java.util.*;
-import java.util.regex.*;
+import java.util.Map.Entry;
 
 import aQute.bnd.annotation.component.*;
+import aQute.bnd.component.*;
+import aQute.bnd.header.*;
 import aQute.bnd.make.metatype.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Clazz.QUERY;
+import aQute.bnd.osgi.Descriptors.TypeRef;
 import aQute.bnd.service.*;
-import aQute.lib.osgi.*;
-import aQute.lib.osgi.Clazz.*;
-import aQute.libg.version.*;
+import aQute.lib.tag.*;
 
 /**
  * This class is an analyzer plugin. It looks at the properties and tries to
@@ -23,7 +26,7 @@ public class ServiceComponent implements AnalyzerPlugin {
 
 		ComponentMaker m = new ComponentMaker(analyzer);
 
-		Map<String, Map<String, String>> l = m.doServiceComponent();
+		Map<String,Map<String,String>> l = m.doServiceComponent();
 
 		analyzer.setProperty(Constants.SERVICE_COMPONENT, Processor.printClauses(l));
 
@@ -47,21 +50,20 @@ public class ServiceComponent implements AnalyzerPlugin {
 		 * <li>An XML file reference</li>
 		 * <li>A FQN/wildcard with a set of attributes</li>
 		 * </ol>
-		 * 
 		 * An XML reference is immediately expanded, an FQN/wildcard is more
 		 * complicated and is delegated to
 		 * {@link #componentEntry(Map, String, Map)}.
 		 * 
 		 * @throws Exception
 		 */
-		Map<String, Map<String, String>> doServiceComponent() throws Exception {
-			Map<String, Map<String, String>> serviceComponents = newMap();
+		Map<String,Map<String,String>> doServiceComponent() throws Exception {
+			Map<String,Map<String,String>> serviceComponents = newMap();
 			String header = getProperty(SERVICE_COMPONENT);
-			Map<String, Map<String, String>> sc = parseHeader(header);
+			Parameters sc = parseHeader(header);
 
-			for (Map.Entry<String, Map<String, String>> entry : sc.entrySet()) {
+			for (Entry<String,Attrs> entry : sc.entrySet()) {
 				String name = entry.getKey();
-				Map<String, String> info = entry.getValue();
+				Map<String,String> info = entry.getValue();
 
 				try {
 					if (name.indexOf('/') >= 0 || name.endsWith(".xml")) {
@@ -70,9 +72,11 @@ public class ServiceComponent implements AnalyzerPlugin {
 					} else {
 						componentEntry(serviceComponents, name, info);
 					}
-				} catch (Exception e) {
+				}
+				catch (Exception e) {
 					e.printStackTrace();
 					error("Invalid Service-Component header: %s %s, throws %s", name, info, e);
+					throw e;
 				}
 			}
 			return serviceComponents;
@@ -86,17 +90,16 @@ public class ServiceComponent implements AnalyzerPlugin {
 		 * <li>A wildcard expression for finding annotated components.</li>
 		 * </ol>
 		 * The problem is the distinction between an FQN and a wildcard because
-		 * an FQN can also be used as a wildcard.
-		 * 
-		 * If the info specifies {@link Constants#NOANNOTATIONS} then wildcards
-		 * are an error and the component must be fully described by the info.
-		 * Otherwise the FQN/wildcard is expanded into a list of classes with
-		 * annotations. If this list is empty, the FQN case is interpreted as a
-		 * complete component definition. For the wildcard case, it is checked
-		 * if any matching classes for the wildcard have been compiled for a
-		 * class file format that does not support annotations, this can be a
-		 * problem with JSR14 who silently ignores annotations. An error is
-		 * reported in such a case.
+		 * an FQN can also be used as a wildcard. If the info specifies
+		 * {@link Constants#NOANNOTATIONS} then wildcards are an error and the
+		 * component must be fully described by the info. Otherwise the
+		 * FQN/wildcard is expanded into a list of classes with annotations. If
+		 * this list is empty, the FQN case is interpreted as a complete
+		 * component definition. For the wildcard case, it is checked if any
+		 * matching classes for the wildcard have been compiled for a class file
+		 * format that does not support annotations, this can be a problem with
+		 * JSR14 who silently ignores annotations. An error is reported in such
+		 * a case.
 		 * 
 		 * @param serviceComponents
 		 * @param name
@@ -104,8 +107,8 @@ public class ServiceComponent implements AnalyzerPlugin {
 		 * @throws Exception
 		 * @throws IOException
 		 */
-		private void componentEntry(Map<String, Map<String, String>> serviceComponents,
-				String name, Map<String, String> info) throws Exception, IOException {
+		private void componentEntry(Map<String,Map<String,String>> serviceComponents, String name,
+				Map<String,String> info) throws Exception, IOException {
 
 			boolean annotations = !Processor.isTrue(info.get(NOANNOTATIONS));
 			boolean fqn = Verifier.isFQN(name);
@@ -114,8 +117,8 @@ public class ServiceComponent implements AnalyzerPlugin {
 
 				// Annotations possible!
 
-				Collection<Clazz> annotatedComponents = analyzer.getClasses("",
-						QUERY.ANNOTATION.toString(), Component.class.getName(), //
+				Collection<Clazz> annotatedComponents = analyzer.getClasses("", QUERY.ANNOTATED.toString(),
+						Component.class.getName(), //
 						QUERY.NAMED.toString(), name //
 						);
 
@@ -166,29 +169,28 @@ public class ServiceComponent implements AnalyzerPlugin {
 		private Collection<Clazz> checkAnnotationsFeasible(String name) throws Exception {
 			Collection<Clazz> not = analyzer.getClasses("", QUERY.NAMED.toString(), name //
 					);
-			
-			if (not.isEmpty())
-				if ( "*".equals(name))
+
+			if (not.isEmpty()) {
+				if ("*".equals(name))
 					return not;
-				else
-					error("Specified %s but could not find any class matching this pattern", name);
+				error("Specified %s but could not find any class matching this pattern", name);
+			}
 
 			for (Clazz c : not) {
 				if (c.getFormat().hasAnnotations())
 					return not;
 			}
-			
+
 			warning("Wildcards are used (%s) requiring annotations to decide what is a component. Wildcard maps to classes that are compiled with java.target < 1.5. Annotations were introduced in Java 1.5",
 					name);
-			
+
 			return not;
 		}
 
-		void annotated(Map<String, Map<String, String>> components, Clazz c,
-				Map<String, String> info) throws Exception {
+		void annotated(Map<String,Map<String,String>> components, Clazz c, Map<String,String> info) throws Exception {
 			// Get the component definition
 			// from the annotations
-			Map<String, String> map = ComponentAnnotationReader.getDefinition(c, this);
+			Map<String,String> map = ComponentAnnotationReader.getDefinition(c, this);
 
 			// Pick the name, the annotation can override
 			// the name.
@@ -199,16 +201,15 @@ public class ServiceComponent implements AnalyzerPlugin {
 			// Override the component info without manifest
 			// entries. We merge the properties though.
 
-			String merged = Processor.merge(info.remove(COMPONENT_PROPERTIES),
-					map.remove(COMPONENT_PROPERTIES));
+			String merged = Processor.merge(info.remove(COMPONENT_PROPERTIES), map.remove(COMPONENT_PROPERTIES));
 			if (merged != null && merged.length() > 0)
 				map.put(COMPONENT_PROPERTIES, merged);
 			map.putAll(info);
 			createComponentResource(components, localname, map);
 		}
 
-		private void createComponentResource(Map<String, Map<String, String>> components,
-				String name, Map<String, String> info) throws IOException {
+		private void createComponentResource(Map<String,Map<String,String>> components, String name,
+				Map<String,String> info) throws Exception {
 
 			// We can override the name in the parameters
 			if (info.containsKey(COMPONENT_NAME))
@@ -219,8 +220,9 @@ public class ServiceComponent implements AnalyzerPlugin {
 			if (info.containsKey(COMPONENT_IMPLEMENTATION))
 				impl = info.get(COMPONENT_IMPLEMENTATION);
 
+			TypeRef implRef = analyzer.getTypeRefFromFQN(impl);
 			// Check if such a class exists
-			analyzer.referTo(impl);
+			analyzer.referTo(implRef);
 
 			boolean designate = designate(name, info.get(COMPONENT_DESIGNATE), false)
 					|| designate(name, info.get(COMPONENT_DESIGNATEFACTORY), true);
@@ -250,18 +252,17 @@ public class ServiceComponent implements AnalyzerPlugin {
 				return false;
 
 			for (String c : Processor.split(config)) {
-				Clazz clazz = analyzer.getClassspace().get(Clazz.fqnToPath(c));
+				TypeRef ref = analyzer.getTypeRefFromFQN(c);
+				Clazz clazz = analyzer.getClassspace().get(ref);
 				if (clazz != null) {
-					analyzer.referTo(c);
+					analyzer.referTo(ref);
 					MetaTypeReader r = new MetaTypeReader(clazz, analyzer);
 					r.setDesignate(name, factory);
 					String rname = "OSGI-INF/metatype/" + name + ".xml";
 
 					analyzer.getJar().putResource(rname, r);
 				} else {
-					analyzer.error(
-							"Cannot find designated configuration class %s for component %s", c,
-							name);
+					analyzer.error("Cannot find designated configuration class %s for component %s", c, name);
 				}
 			}
 			return true;
@@ -276,345 +277,10 @@ public class ServiceComponent implements AnalyzerPlugin {
 		 * @throws UnsupportedEncodingException
 		 */
 		Resource createComponentResource(String name, String impl, Map<String, String> info)
-				throws IOException {
-			String namespace = getNamespace(info);
-			ByteArrayOutputStream out = new ByteArrayOutputStream();
-			PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, Constants.DEFAULT_CHARSET));
-			pw.println("<?xml version='1.0' encoding='utf-8'?>");
-			if (namespace != null)
-				pw.print("<scr:component xmlns:scr='" + namespace + "'");
-			else
-				pw.print("<component");
-
-			doAttribute(pw, name, "name");
-			doAttribute(pw, info.get(COMPONENT_FACTORY), "factory");
-			doAttribute(pw, info.get(COMPONENT_IMMEDIATE), "immediate", "false", "true");
-			doAttribute(pw, info.get(COMPONENT_ENABLED), "enabled", "true", "false");
-			doAttribute(pw, info.get(COMPONENT_CONFIGURATION_POLICY), "configuration-policy",
-					"optional", "require", "ignore");
-			doAttribute(pw, info.get(COMPONENT_ACTIVATE), "activate", JIDENTIFIER);
-			doAttribute(pw, info.get(COMPONENT_DEACTIVATE), "deactivate", JIDENTIFIER);
-			doAttribute(pw, info.get(COMPONENT_MODIFIED), "modified", JIDENTIFIER);
-
-			pw.println(">");
-
-			// Allow override of the implementation when people
-			// want to choose their own name
-			pw.println("  <implementation class='" + (impl == null ? name : impl) + "'/>");
-
-			String provides = info.get(COMPONENT_PROVIDE);
-			boolean servicefactory = Processor.isTrue(info.get(COMPONENT_SERVICEFACTORY));
-
-			if (servicefactory && Processor.isTrue(info.get(COMPONENT_IMMEDIATE))) {
-				// TODO can become error() if it is up to me
-				warning("For a Service Component, the immediate option and the servicefactory option are mutually exclusive for %(%s)",
-						name, impl);
-			}
-			provide(pw, provides, servicefactory, impl);
-			properties(pw, info);
-			reference(info, pw);
-
-			if (namespace != null)
-				pw.println("</scr:component>");
-			else
-				pw.println("</component>");
-
-			pw.close();
-			byte[] data = out.toByteArray();
-			out.close();
-			return new EmbeddedResource(data, 0);
-		}
-
-		private void doAttribute(PrintWriter pw, String value, String name, String... matches) {
-			if (value != null) {
-				if (matches.length != 0) {
-					if (matches.length == 1 && matches[0].equals(JIDENTIFIER)) {
-						if (!Verifier.isIdentifier(value))
-							error("Component attribute %s has value %s but is not a Java identifier",
-									name, value);
-					} else {
-
-						if (!Verifier.isMember(value, matches))
-							error("Component attribute %s has value %s but is not a member of %s",
-									name, value, Arrays.toString(matches));
-					}
-				}
-				pw.print(" ");
-				pw.print(name);
-				pw.print("='");
-				pw.print(value);
-				pw.print("'");
-			}
-		}
-
-		/**
-		 * Check if we need to use the v1.1 namespace (or later).
-		 * 
-		 * @param info
-		 * @return
-		 */
-		private String getNamespace(Map<String, String> info) {
-			String version = info.get(COMPONENT_VERSION);
-			if (version != null) {
-				try {
-					Version v = new Version(version);
-					return NAMESPACE_STEM + "/v" + v;
-				} catch (Exception e) {
-					error("version: specified on component header but not a valid version: "
-							+ version);
-					return null;
-				}
-			}
-			for (String key : info.keySet()) {
-				if (SET_COMPONENT_DIRECTIVES_1_1.contains(key)) {
-					return NAMESPACE_STEM + "/v1.1.0";
-				}
-			}
-			return null;
-		}
-
-		/**
-		 * Print the Service-Component properties element
-		 * 
-		 * @param pw
-		 * @param info
-		 */
-		void properties(PrintWriter pw, Map<String, String> info) {
-			Collection<String> properties = split(info.get(COMPONENT_PROPERTIES));
-			for (Iterator<String> p = properties.iterator(); p.hasNext();) {
-				String clause = p.next();
-				int n = clause.indexOf('=');
-				if (n <= 0) {
-					error("Not a valid property in service component: " + clause);
-				} else {
-					String type = null;
-					String name = clause.substring(0, n);
-					if (name.indexOf('@') >= 0) {
-						String parts[] = name.split("@");
-						name = parts[1];
-						type = parts[0];
-					} else if (name.indexOf(':') >= 0) {
-						String parts[] = name.split(":");
-						name = parts[0];
-						type = parts[1];
-					}
-					String value = clause.substring(n + 1).trim();
-					// TODO verify validity of name and value.
-					pw.print("  <property name='");
-					pw.print(name);
-					pw.print("'");
-
-					if (type != null) {
-						if (VALID_PROPERTY_TYPES.matcher(type).matches()) {
-							pw.print(" type='");
-							pw.print(type);
-							pw.print("'");
-						} else {
-							warning("Invalid property type '" + type + "' for property " + name);
-						}
-					}
-
-					String parts[] = value.split("\\s*(\\||\\n)\\s*");
-					if (parts.length > 1) {
-						pw.println(">");
-						for (String part : parts) {
-							pw.println(part);
-						}
-						pw.println("</property>");
-					} else {
-						pw.print(" value='");
-						pw.print(parts[0]);
-						pw.println("'/>");
-					}
-				}
-			}
-		}
-
-		/**
-		 * @param pw
-		 * @param provides
-		 */
-		void provide(PrintWriter pw, String provides, boolean servicefactory, String impl) {
-			if (provides != null) {
-				if (!servicefactory)
-					pw.println("  <service>");
-				else
-					pw.println("  <service servicefactory='true'>");
-
-				StringTokenizer st = new StringTokenizer(provides, ",");
-				while (st.hasMoreTokens()) {
-					String interfaceName = st.nextToken();
-					pw.println("    <provide interface='" + interfaceName + "'/>");
-					analyzer.referTo(interfaceName);
-
-					// TODO verifies the impl. class extends or implements the
-					// interface
-				}
-				pw.println("  </service>");
-			} else if (servicefactory)
-				warning("The servicefactory:=true directive is set but no service is provided, ignoring it");
-		}
-
-		public final static Pattern	REFERENCE	= Pattern.compile("([^(]+)(\\(.+\\))?");
-
-		/**
-		 * @param info
-		 * @param pw
-		 */
-
-		void reference(Map<String, String> info, PrintWriter pw) {
-			Collection<String> dynamic = new ArrayList<String>(split(info.get(COMPONENT_DYNAMIC)));
-			Collection<String> optional = new ArrayList<String>(split(info.get(COMPONENT_OPTIONAL)));
-			Collection<String> multiple = new ArrayList<String>(split(info.get(COMPONENT_MULTIPLE)));
-
-			Collection<String> descriptors = split(info.get(COMPONENT_DESCRIPTORS));
-
-			for (Map.Entry<String, String> entry : info.entrySet()) {
-
-				// Skip directives
-				String referenceName = entry.getKey();
-				if (referenceName.endsWith(":")) {
-					if (!SET_COMPONENT_DIRECTIVES.contains(referenceName))
-						error("Unrecognized directive in Service-Component header: "
-								+ referenceName);
-					continue;
-				}
-
-				// Parse the bind/unbind methods from the name
-				// if set. They are separated by '/'
-				String bind = null;
-				String unbind = null;
-
-				boolean unbindCalculated = false;
-
-				if (referenceName.indexOf('/') >= 0) {
-					String parts[] = referenceName.split("/");
-					referenceName = parts[0];
-					bind = parts[1];
-					if (parts.length > 2) {
-						unbind = parts[2];
-					} else {
-						unbindCalculated = true;
-						if (bind.startsWith("add"))
-							unbind = bind.replaceAll("add(.+)", "remove$1");
-						else
-							unbind = "un" + bind;
-					}
-				} else if (Character.isLowerCase(referenceName.charAt(0))) {
-					unbindCalculated = true;
-					bind = "set" + Character.toUpperCase(referenceName.charAt(0))
-							+ referenceName.substring(1);
-					unbind = "un" + bind;
-				}
-
-				String interfaceName = entry.getValue();
-				if (interfaceName == null || interfaceName.length() == 0) {
-					error("Invalid Interface Name for references in Service Component: "
-							+ referenceName + "=" + interfaceName);
-					continue;
-				}
-
-				// If we have descriptors, we have analyzed the component.
-				// So why not check the methods
-				if (descriptors.size() > 0) {
-					// Verify that the bind method exists
-					if (!descriptors.contains(bind))
-						error("The bind method %s for %s not defined", bind, referenceName);
-
-					// Check if the unbind method exists
-					if (!descriptors.contains(unbind)) {
-						if (unbindCalculated)
-							// remove it
-							unbind = null;
-						else
-							error("The unbind method %s for %s not defined", unbind, referenceName);
-					}
-				}
-				// Check tje cardinality by looking at the last
-				// character of the value
-				char c = interfaceName.charAt(interfaceName.length() - 1);
-				if ("?+*~".indexOf(c) >= 0) {
-					if (c == '?' || c == '*' || c == '~')
-						optional.add(referenceName);
-					if (c == '+' || c == '*')
-						multiple.add(referenceName);
-					if (c == '+' || c == '*' || c == '?')
-						dynamic.add(referenceName);
-					interfaceName = interfaceName.substring(0, interfaceName.length() - 1);
-				}
-
-				// Parse the target from the interface name
-				// The target is a filter.
-				String target = null;
-				Matcher m = REFERENCE.matcher(interfaceName);
-				if (m.matches()) {
-					interfaceName = m.group(1);
-					target = m.group(2);
-				}
-
-				analyzer.referTo(interfaceName);
-
-				pw.printf("  <reference name='%s'", referenceName);
-				pw.printf(" interface='%s'", interfaceName);
-
-				String cardinality = optional.contains(referenceName) ? "0" : "1";
-				cardinality += "..";
-				cardinality += multiple.contains(referenceName) ? "n" : "1";
-				if (!cardinality.equals("1..1"))
-					pw.print(" cardinality='" + cardinality + "'");
-
-				if (bind != null) {
-					pw.printf(" bind='%s'", bind);
-					if (unbind != null) {
-						pw.printf(" unbind='%s'", unbind);
-					}
-				}
-
-				if (dynamic.contains(referenceName)) {
-					pw.print(" policy='dynamic'");
-				}
-
-				if (target != null) {
-					// Filter filter = new Filter(target);
-					// if (filter.verify() == null)
-					// pw.print(" target='" + filter.toString() + "'");
-					// else
-					// error("Target for " + referenceName
-					// + " is not a correct filter: " + target + " "
-					// + filter.verify());
-					pw.print(" target='" + escape(target) + "'");
-				}
-				pw.println("/>");
-			}
-		}
-	}
-
-	/**
-	 * Escape a string, do entity conversion.
-	 */
-	static String escape(String s) {
-		StringBuffer sb = new StringBuffer();
-		for (int i = 0; i < s.length(); i++) {
-			char c = s.charAt(i);
-			switch (c) {
-			case '<':
-				sb.append("<");
-				break;
-			case '>':
-				sb.append(">");
-				break;
-			case '&':
-				sb.append("&");
-				break;
-			case '\'':
-				sb.append(""");
-				break;
-			default:
-				sb.append(c);
-				break;
-			}
+				throws Exception {
+			Tag tag = new HeaderReader(analyzer).createComponentTag(name, impl, info);
+			return new TagResource(tag);
 		}
-		return sb.toString();
 	}
 
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/make/coverage/Coverage.java b/biz.aQute.bndlib/src/aQute/bnd/make/coverage/Coverage.java
index bc33dc2..672c5cd 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/make/coverage/Coverage.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/make/coverage/Coverage.java
@@ -1,95 +1,99 @@
 package aQute.bnd.make.coverage;
 
 import java.io.*;
-import java.lang.reflect.*;
 import java.util.*;
 
-import aQute.lib.osgi.*;
-import aQute.lib.osgi.Clazz.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Clazz.MethodDef;
+import aQute.bnd.osgi.Descriptors.TypeRef;
 
 /**
  * This class can create a coverage table between two classspaces. The
  * destination class space is used to create a table of methods. All source
  * methods that refer to a specific dest are then filled into the table.
- * 
  */
 public class Coverage {
 
-    /**
-     * Create a cross reference table from source to dest.
-     * 
-     * @param source
-     *            The methods that refer to dest
-     * @param dest
-     *            The methods that are being referred to
-     * @return A mapping of source methods to destination methods.
-     * @throws IOException
-     */
-    public static Map<MethodDef, List<MethodDef>> getCrossRef(
-            Collection<Clazz> source, Collection<Clazz> dest)
-            throws Exception {
-        final Map<MethodDef, List<MethodDef>> catalog = buildCatalog(dest);
-        crossRef(source, catalog);
-        return catalog;
-    }
+	/**
+	 * Create a cross reference table from source to dest.
+	 * 
+	 * @param source
+	 *            The methods that refer to dest
+	 * @param dest
+	 *            The methods that are being referred to
+	 * @return A mapping of source methods to destination methods.
+	 * @throws IOException
+	 */
+	public static Map<MethodDef,List<MethodDef>> getCrossRef(Collection<Clazz> source, Collection<Clazz> dest)
+			throws Exception {
+		final Map<MethodDef,List<MethodDef>> catalog = buildCatalog(dest);
+		crossRef(source, catalog);
+		return catalog;
+	}
 
-    private static void crossRef(Collection<Clazz> source,
-            final Map<MethodDef, List<MethodDef>> catalog) throws Exception {
-        for (final Clazz clazz : source) {
-            clazz.parseClassFileWithCollector(new ClassDataCollector() {
-                MethodDef source;
+	private static void crossRef(Collection<Clazz> source, final Map<MethodDef,List<MethodDef>> catalog)
+			throws Exception {
+		for (final Clazz clazz : source) {
+			clazz.parseClassFileWithCollector(new ClassDataCollector() {
+//				MethodDef	source;
 
-                public void implementsInterfaces(String names[]) {
-                    MethodDef def = new MethodDef(0, clazz.getFQN(),
-                            "<implements>", "()V");
-                    for (String interfaceName : names) {
-                        interfaceName = Clazz.internalToFqn(interfaceName);
-                        for (Map.Entry<MethodDef, List<MethodDef>> entry : catalog
-                                .entrySet()) {
-                            String catalogClass = entry.getKey().clazz;
-                            List<MethodDef> references = entry.getValue();
+				@Override
+				public void implementsInterfaces(TypeRef names[]) {
+					MethodDef def = clazz.getMethodDef(0, "<implements>", "()V");
+					// TODO
+					for (TypeRef interfaceName : names) {
+						for (Map.Entry<MethodDef,List<MethodDef>> entry : catalog.entrySet()) {
+							String catalogClass = entry.getKey().getContainingClass().getFQN();
+							List<MethodDef> references = entry.getValue();
 
-                            if (catalogClass.equals(interfaceName)) {
-                                references.add(def);
-                            }
-                        }
-                    }
-                }
+							if (catalogClass.equals(interfaceName.getFQN())) {
+								references.add(def);
+							}
+						}
+					}
+				}
 
-                // Method definitions
-                public void method(MethodDef source) {
-                    this.source = source;
-                }
+				// Method definitions
+				@Override
+				public void method(MethodDef source) {
+//					this.source = source;
+				}
 
-                public void reference(MethodDef reference) {
-                    List<MethodDef> references = catalog.get(reference);
-                    if (references != null) {
-                        references.add(source);
-                    }
-                }
-            });
-        }
-    }
+				// TODO need to use different reference method
+//				public void reference(MethodDef reference) {
+//					List<MethodDef> references = catalog.get(reference);
+//					if (references != null) {
+//						references.add(source);
+//					}
+//				}
+			});
+		}
+	}
 
-    private static Map<MethodDef, List<MethodDef>> buildCatalog(
-            Collection<Clazz> sources) throws Exception {
-        final Map<MethodDef, List<MethodDef>> catalog = new TreeMap<MethodDef, List<MethodDef>>();
-        for (final Clazz clazz : sources) {
-            clazz.parseClassFileWithCollector(new ClassDataCollector() {
+	private static Map<MethodDef,List<MethodDef>> buildCatalog(Collection<Clazz> sources) throws Exception {
+		final Map<MethodDef,List<MethodDef>> catalog = new TreeMap<MethodDef,List<MethodDef>>(
+				new Comparator<MethodDef>() {
+					public int compare(MethodDef a, MethodDef b) {
+						return a.getName().compareTo(b.getName());
+					}
+				});
+		for (final Clazz clazz : sources) {
+			clazz.parseClassFileWithCollector(new ClassDataCollector() {
 
-                public boolean classStart(int access, String name) {
-                    return clazz.isPublic();
-                }
+				@Override
+				public boolean classStart(int access, TypeRef name) {
+					return clazz.isPublic();
+				}
 
-                public void method(MethodDef source) {
-                    if (java.lang.reflect.Modifier.isPublic(source.access)
-                            || Modifier.isProtected(source.access))
-                        catalog.put(source, new ArrayList<MethodDef>());
-                }
+				@Override
+				public void method(MethodDef source) {
+					if (source.isPublic() || source.isProtected())
+						catalog.put(source, new ArrayList<MethodDef>());
+				}
 
-            });
-        }
-        return catalog;
-    }
+			});
+		}
+		return catalog;
+	}
 
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/make/coverage/CoverageResource.java b/biz.aQute.bndlib/src/aQute/bnd/make/coverage/CoverageResource.java
index 3827391..753b69d 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/make/coverage/CoverageResource.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/make/coverage/CoverageResource.java
@@ -3,90 +3,88 @@ package aQute.bnd.make.coverage;
 import static aQute.bnd.make.coverage.Coverage.*;
 
 import java.io.*;
-import java.lang.reflect.*;
 import java.util.*;
 
-import aQute.lib.osgi.*;
-import aQute.lib.osgi.Clazz.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Clazz.MethodDef;
 import aQute.lib.tag.*;
 
 /**
  * Creates an XML Coverage report. This class can be used as a resource so the
  * report is created only when the JAR is written.
- * 
  */
 public class CoverageResource extends WriteResource {
-    Collection<Clazz> testsuite;
-    Collection<Clazz> service;
+	Collection<Clazz>	testsuite;
+	Collection<Clazz>	service;
 
-    public CoverageResource(Collection<Clazz> testsuite,
-            Collection<Clazz> service) {
-        this.testsuite = testsuite;
-        this.service = service;
-    }
+	public CoverageResource(Collection<Clazz> testsuite, Collection<Clazz> service) {
+		this.testsuite = testsuite;
+		this.service = service;
+	}
 
-    @Override
-    public long lastModified() {
-        return 0;
-    }
+	@Override
+	public long lastModified() {
+		return 0;
+	}
 
-    @Override
-    public void write(OutputStream out) throws IOException {
-        try {
-            Map<MethodDef, List<MethodDef>> table = getCrossRef(testsuite,
-                    service);
-            Tag coverage = toTag(table);
-            PrintWriter pw = new PrintWriter(new OutputStreamWriter(out,
-                    Constants.DEFAULT_CHARSET));
-            try {
-                coverage.print(0, pw);
-            } finally {
-                pw.flush();
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
+	@Override
+	public void write(OutputStream out) throws IOException {
+		try {
+			Map<MethodDef,List<MethodDef>> table = getCrossRef(testsuite, service);
+			Tag coverage = toTag(table);
+			PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, Constants.DEFAULT_CHARSET));
+			try {
+				coverage.print(0, pw);
+			}
+			finally {
+				pw.flush();
+			}
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
 
-    public static Tag toTag(Map<MethodDef, List<MethodDef>> catalog) {
-        Tag coverage = new Tag("coverage");
-        String currentClass = null;
-        Tag classTag = null;
+	public static Tag toTag(Map<MethodDef,List<MethodDef>> catalog) {
+		Tag coverage = new Tag("coverage");
+		String currentClass = null;
+		Tag classTag = null;
 
-        for (Map.Entry<MethodDef, List<MethodDef>> m : catalog.entrySet()) {
-            String className = m.getKey().clazz;
-            if (!className.equals(currentClass)) {
-                classTag = new Tag("class");
-                classTag.addAttribute("name", className);
-                classTag.addAttribute("package", Clazz.getPackage(className));
-                classTag.addAttribute("short", Clazz.getShortName(className));
-                coverage.addContent(classTag);
-                currentClass = className;
-            }
-            Tag method = doMethod(new Tag("method"), m.getKey());
-            classTag.addContent(method);
-            for (MethodDef r : m.getValue()) {
-                Tag ref = doMethod(new Tag("ref"), r);
-                method.addContent(ref);
-            }
-        }
-        return coverage;
-    }
+		for (Map.Entry<MethodDef,List<MethodDef>> m : catalog.entrySet()) {
+			String className = m.getKey().getContainingClass().getFQN();
+			if (!className.equals(currentClass)) {
+				classTag = new Tag("class");
+				classTag.addAttribute("name", className);
+				classTag.addAttribute("package", Descriptors.getPackage(className));
+				classTag.addAttribute("short", Descriptors.getShortName(className));
+				coverage.addContent(classTag);
+				currentClass = className;
+			}
+			Tag method = doMethod(new Tag("method"), m.getKey());
+			if ( classTag != null)
+				classTag.addContent(method);
+			for (MethodDef r : m.getValue()) {
+				Tag ref = doMethod(new Tag("ref"), r);
+				method.addContent(ref);
+			}
+		}
+		return coverage;
+	}
 
-    private static Tag doMethod(Tag tag, MethodDef method) {
-        tag.addAttribute("pretty", method.getPretty());
-        if (Modifier.isPublic(method.access))
-            tag.addAttribute("public", true);
-        if (Modifier.isStatic(method.access))
-            tag.addAttribute("static", true);
-        if (Modifier.isProtected(method.access))
-            tag.addAttribute("protected", true);
-        if (Modifier.isInterface(method.access))
-            tag.addAttribute("interface", true);
-        tag.addAttribute("constructor", method.isConstructor());
-        if (!method.isConstructor())
-            tag.addAttribute("name", method.name);
-        tag.addAttribute("descriptor", method.descriptor);
-        return tag;
-    }
+	private static Tag doMethod(Tag tag, MethodDef method) {
+		tag.addAttribute("pretty", method.toString());
+		if (method.isPublic())
+			tag.addAttribute("public", true);
+		if (method.isStatic())
+			tag.addAttribute("static", true);
+		if (method.isProtected())
+			tag.addAttribute("protected", true);
+		if (method.isInterface())
+			tag.addAttribute("interface", true);
+		tag.addAttribute("constructor", method.isConstructor());
+		if (!method.isConstructor())
+			tag.addAttribute("name", method.getName());
+		tag.addAttribute("descriptor", method.getDescriptor());
+		return tag;
+	}
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/make/metatype/MetaTypeReader.java b/biz.aQute.bndlib/src/aQute/bnd/make/metatype/MetaTypeReader.java
index f170c54..fe058ba 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/make/metatype/MetaTypeReader.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/make/metatype/MetaTypeReader.java
@@ -2,67 +2,50 @@ package aQute.bnd.make.metatype;
 
 import java.io.*;
 import java.util.*;
-import java.util.concurrent.*;
 import java.util.regex.*;
 
 import aQute.bnd.annotation.metatype.*;
-import aQute.lib.io.*;
-import aQute.lib.osgi.*;
-import aQute.lib.osgi.Clazz.MethodDef;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Clazz.MethodDef;
+import aQute.bnd.osgi.Descriptors.TypeRef;
 import aQute.lib.tag.*;
 import aQute.libg.generics.*;
 
-public class MetaTypeReader extends ClassDataCollector implements Resource {
-	final Analyzer				reporter;
-	Clazz						clazz;
-	String						interfaces[];
-	Tag							metadata	= new Tag("metatype:MetaData", new String[] {
-			"xmlns:metatype", "http://www.osgi.org/xmlns/metatype/v1.1.0" });
-	Tag							ocd			= new Tag(metadata, "OCD");
-	Tag							designate	= new Tag(metadata, "Designate");
-	Tag							object		= new Tag(designate, "Object");
+public class MetaTypeReader extends WriteResource {
+	final Analyzer			reporter;
+	Clazz					clazz;
+	String					interfaces[];
+	Tag						metadata	= new Tag("metatype:MetaData", new String[] {
+			"xmlns:metatype", "http://www.osgi.org/xmlns/metatype/v1.1.0"
+										});
+	Tag						ocd			= new Tag(metadata, "OCD");
+	Tag						designate	= new Tag(metadata, "Designate");
+	Tag						object		= new Tag(designate, "Object");
 
 	// Resource
-	String						extra;
+	String					extra;
 
 	// One time init
-	boolean						finished;
+	boolean					finished;
 
 	// Designate
-	boolean						override;
-	String						designatePid;
-	boolean						factory;
+	boolean					override;
+	String					designatePid;
+	boolean					factory;
 
 	// AD
-	Map<MethodDef, Meta.AD>	methods		= new LinkedHashMap<MethodDef, Meta.AD>();
+	Map<MethodDef,Meta.AD>	methods		= new LinkedHashMap<MethodDef,Meta.AD>();
 
 	// OCD
-	Annotation					ocdAnnotation;
+	Annotation				ocdAnnotation;
 
-	MethodDef					method;
+	MethodDef				method;
 
 	public MetaTypeReader(Clazz clazz, Analyzer reporter) {
 		this.clazz = clazz;
 		this.reporter = reporter;
 	}
 
-	public void annotation(Annotation annotation) {
-		try {
-			Meta.OCD ocd = annotation.getAnnotation(Meta.OCD.class);
-			Meta.AD ad = annotation.getAnnotation(Meta.AD.class);
-			if (ocd != null) {
-				this.ocdAnnotation = annotation;
-			}
-			if (ad != null) {
-				assert method != null;
-				methods.put(method, ad);
-			}
-		} catch (Exception e) {
-			reporter.error("Error during annotation parsing %s : %s", clazz, e);
-			e.printStackTrace();
-		}
-	}
-
 	/**
 	 * @param id
 	 * @param name
@@ -76,14 +59,14 @@ public class MetaTypeReader extends ClassDataCollector implements Resource {
 	 * @param optionValues
 	 */
 
-	static Pattern	COLLECTION	= Pattern
-										.compile("(.*(Collection|Set|List|Queue|Stack|Deque))<(L.+;)>");
+	static Pattern	COLLECTION	= Pattern.compile("(.*(Collection|Set|List|Queue|Stack|Deque))<(L.+;)>");
 
 	private void addMethod(MethodDef method, Meta.AD ad) throws Exception {
 
 		// Set all the defaults.
-		String rtype = method.getReturnType();
-		String id = Configurable.mangleMethodName(method.name);
+
+		String rtype = method.getGenericReturnType();
+		String id = Configurable.mangleMethodName(method.getName());
 		String name = Clazz.unCamel(id);
 
 		int cardinality = 0;
@@ -96,7 +79,7 @@ public class MetaTypeReader extends ClassDataCollector implements Resource {
 			if (cardinality != 0)
 				reporter.error(
 						"AD for %s.%s uses an array of collections in return type (%s), Metatype allows either Vector or array",
-						clazz.getFQN(), method.name, method.getReturnType());
+						clazz.getClassName().getFQN(), method.getName(), method.getType().getFQN());
 			Matcher m = COLLECTION.matcher(rtype);
 			if (m.matches()) {
 				rtype = Clazz.objectDescriptorToFQN(m.group(3));
@@ -105,8 +88,8 @@ public class MetaTypeReader extends ClassDataCollector implements Resource {
 		}
 
 		Meta.Type type = getType(rtype);
-		
-		boolean required = ad ==null || ad.required();
+
+		boolean required = ad == null || ad.required();
 		String deflt = null;
 		String max = null;
 		String min = null;
@@ -114,7 +97,8 @@ public class MetaTypeReader extends ClassDataCollector implements Resource {
 		String[] optionValues = null;
 		String description = null;
 
-		Clazz c = reporter.findClass(Clazz.fqnToPath(rtype));
+		TypeRef typeRef = reporter.getTypeRefFromFQN(rtype);
+		Clazz c = reporter.findClass(typeRef);
 		if (c != null && c.isEnum()) {
 			optionValues = parseOptionValues(c);
 		}
@@ -130,15 +114,15 @@ public class MetaTypeReader extends ClassDataCollector implements Resource {
 				cardinality = ad.cardinality();
 			if (ad.type() != null)
 				type = ad.type();
-			if (ad.required() || ad.deflt() == null)
-				required = true;
+			// if (ad.required() || ad.deflt() == null)
+			// required = true;
 
 			if (ad.description() != null)
 				description = ad.description();
 
 			if (ad.optionLabels() != null)
 				optionLabels = ad.optionLabels();
-			if (ad.optionValues() != null )
+			if (ad.optionValues() != null)
 				optionValues = ad.optionValues();
 
 			if (ad.min() != null)
@@ -174,7 +158,7 @@ public class MetaTypeReader extends ClassDataCollector implements Resource {
 		adt.addAttribute("min", min);
 		adt.addAttribute("description", description);
 
-		if (optionLabels != null) {
+		if (optionLabels != null && optionValues != null) {
 			for (int i = 0; i < optionLabels.length; i++) {
 				Tag option = new Tag(adt, "Option");
 				option.addAttribute("label", optionLabels[i]);
@@ -187,9 +171,10 @@ public class MetaTypeReader extends ClassDataCollector implements Resource {
 		final List<String> values = Create.list();
 
 		c.parseClassFileWithCollector(new ClassDataCollector() {
+			@Override
 			public void field(Clazz.FieldDef def) {
 				if (def.isEnum()) {
-					values.add(def.name);
+					values.add(def.getName());
 				}
 			}
 		});
@@ -223,48 +208,48 @@ public class MetaTypeReader extends ClassDataCollector implements Resource {
 			return Meta.Type.String;
 	}
 
-	@Override public void method(MethodDef mdef) {
-		method = mdef;
-		methods.put(mdef, null);
-	}
-
-	public String getExtra() {
-		return extra;
-	}
+	class Find extends ClassDataCollector {
 
-	public long lastModified() {
-		return 0;
-	}
+		@Override
+		public void method(MethodDef mdef) {
+			method = mdef;
+			methods.put(mdef, null);
+		}
 
-	public InputStream openInputStream() throws IOException {
-		final PipedInputStream pin = new PipedInputStream();
-		final PipedOutputStream pout = new PipedOutputStream(pin);
-		getExecutor().execute(new Runnable() {
-			public void run() {
-				try {
-					write(pout);
-				} catch (IOException e) {
-					// Cause an exception in the other end
-					IO.close(pin);
+		@Override
+		public void annotation(Annotation annotation) {
+			try {
+				Meta.OCD ocd = annotation.getAnnotation(Meta.OCD.class);
+				Meta.AD ad = annotation.getAnnotation(Meta.AD.class);
+				if (ocd != null) {
+					MetaTypeReader.this.ocdAnnotation = annotation;
+				}
+				if (ad != null) {
+					assert method != null;
+					// Fixup required since it is default true
+					// but we have no access to these defaults.
+					// i.e. the defaults are implemented in the code
+					// thus here
+					if ( annotation.get("required") == null)
+						annotation.put("required", true);
+					
+					methods.put(method, ad);
 				}
-				IO.close(pout);
 			}
-		});
-		return pin;
-	}
-
-	private Executor getExecutor() {
-		return reporter.getPlugin(Executor.class);
-	}
+			catch (Exception e) {
+				reporter.error("Error during annotation parsing %s : %s", clazz, e);
+				e.printStackTrace();
+			}
+		}
 
-	public void setExtra(String extra) {
-		this.extra = extra;
 	}
 
+	@Override
 	public void write(OutputStream out) throws IOException {
 		try {
 			finish();
-		} catch (Exception e) {
+		}
+		catch (Exception e) {
 			throw new RuntimeException(e);
 		}
 		PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, "UTF-8"));
@@ -276,17 +261,16 @@ public class MetaTypeReader extends ClassDataCollector implements Resource {
 	void finish() throws Exception {
 		if (!finished) {
 			finished = true;
-			clazz.parseClassFileWithCollector(this);
+			clazz.parseClassFileWithCollector(new Find());
 			Meta.OCD ocd = null;
 			if (this.ocdAnnotation != null)
 				ocd = this.ocdAnnotation.getAnnotation(Meta.OCD.class);
 			else
-				ocd = Configurable.createConfigurable(Meta.OCD.class,
-						new HashMap<String, Object>());
+				ocd = Configurable.createConfigurable(Meta.OCD.class, new HashMap<String,Object>());
 
 			// defaults
-			String id = clazz.getFQN();
-			String name = Clazz.unCamel(Clazz.getShortName(clazz.getFQN()));
+			String id = clazz.getClassName().getFQN();
+			String name = Clazz.unCamel(clazz.getClassName().getShortName());
 			String description = null;
 			String localization = id;
 			boolean factory = this.factory;
@@ -294,7 +278,6 @@ public class MetaTypeReader extends ClassDataCollector implements Resource {
 			if (ocd.id() != null)
 				id = ocd.id();
 
-			
 			if (ocd.name() != null)
 				name = ocd.name();
 
@@ -321,7 +304,7 @@ public class MetaTypeReader extends ClassDataCollector implements Resource {
 			this.ocd.addAttribute("localization", localization);
 
 			// do ADs
-			for (Map.Entry<MethodDef, Meta.AD> entry : methods.entrySet())
+			for (Map.Entry<MethodDef,Meta.AD> entry : methods.entrySet())
 				addMethod(entry.getKey(), entry.getValue());
 
 			this.designate.addAttribute("pid", pid);
@@ -338,4 +321,9 @@ public class MetaTypeReader extends ClassDataCollector implements Resource {
 		this.factory = factory;
 		this.designatePid = pid;
 	}
+
+	@Override
+	public long lastModified() {
+		return 0;
+	}
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/make/metatype/MetatypePlugin.java b/biz.aQute.bndlib/src/aQute/bnd/make/metatype/MetatypePlugin.java
index 4801ec9..4f30469 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/make/metatype/MetatypePlugin.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/make/metatype/MetatypePlugin.java
@@ -3,31 +3,29 @@ package aQute.bnd.make.metatype;
 import java.util.*;
 
 import aQute.bnd.annotation.metatype.*;
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Clazz.QUERY;
 import aQute.bnd.service.*;
-import aQute.lib.osgi.*;
-import aQute.lib.osgi.Clazz.*;
 
 /**
- * This class is responsible for meta type types. It is a plugin that can 
+ * This class is responsible for meta type types. It is a plugin that can
+ * 
  * @author aqute
- *
  */
 public class MetatypePlugin implements AnalyzerPlugin {
 
 	public boolean analyzeJar(Analyzer analyzer) throws Exception {
 
-		Map<String, Map<String, String>> map = analyzer.parseHeader(analyzer
-				.getProperty(Constants.METATYPE));
+		Parameters map = analyzer.parseHeader(analyzer.getProperty(Constants.METATYPE));
 
 		Jar jar = analyzer.getJar();
 		for (String name : map.keySet()) {
-			Collection<Clazz> metatypes = analyzer.getClasses("", QUERY.ANNOTATION.toString(),
-					Meta.OCD.class.getName(), // 
+			Collection<Clazz> metatypes = analyzer.getClasses("", QUERY.ANNOTATED.toString(), Meta.OCD.class.getName(), //
 					QUERY.NAMED.toString(), name //
 					);
 			for (Clazz c : metatypes) {
-				jar.putResource("OSGI-INF/metatype/" + c.getFQN() + ".xml", new MetaTypeReader(c,
-						analyzer));
+				jar.putResource("OSGI-INF/metatype/" + c.getFQN() + ".xml", new MetaTypeReader(c, analyzer));
 			}
 		}
 		return false;
diff --git a/biz.aQute.bndlib/src/aQute/bnd/maven/BsnToMavenPath.java b/biz.aQute.bndlib/src/aQute/bnd/maven/BsnToMavenPath.java
index 6dc716c..85125ce 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/maven/BsnToMavenPath.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/maven/BsnToMavenPath.java
@@ -1,5 +1,5 @@
 package aQute.bnd.maven;
 
 public interface BsnToMavenPath {
-    String[] getGroupAndArtifact(String bsn);
+	String[] getGroupAndArtifact(String bsn);
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/maven/MavenCommand.java b/biz.aQute.bndlib/src/aQute/bnd/maven/MavenCommand.java
index c274ca5..bf5e15c 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/maven/MavenCommand.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/maven/MavenCommand.java
@@ -3,25 +3,26 @@ package aQute.bnd.maven;
 import java.io.*;
 import java.net.*;
 import java.util.*;
+import java.util.Map.Entry;
 import java.util.concurrent.*;
 import java.util.jar.*;
 import java.util.regex.*;
 
+import aQute.bnd.header.*;
 import aQute.bnd.maven.support.*;
-import aQute.bnd.maven.support.Pom.*;
-import aQute.bnd.settings.*;
+import aQute.bnd.maven.support.Pom.Scope;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Descriptors.PackageRef;
 import aQute.lib.collections.*;
 import aQute.lib.io.*;
-import aQute.lib.osgi.*;
+import aQute.lib.settings.*;
 import aQute.libg.command.*;
-import aQute.libg.header.*;
 
 public class MavenCommand extends Processor {
 	final Settings	settings	= new Settings();
 	File			temp;
 
-	public MavenCommand() {
-	}
+	public MavenCommand() {}
 
 	public MavenCommand(Processor p) {
 		super(p);
@@ -59,7 +60,9 @@ public class MavenCommand extends Processor {
 
 		trace("temp dir " + temp);
 		IO.delete(temp);
-		temp.mkdirs();
+		if (!temp.exists() && !temp.mkdirs()) {
+			throw new IOException("Could not create directory " + temp);
+		}
 		if (!temp.isDirectory())
 			throw new IOException("Cannot create temp directory");
 
@@ -76,23 +79,23 @@ public class MavenCommand extends Processor {
 	}
 
 	private void help() {
-		System.err.println("Usage:\n");
+		System.err.printf("Usage:%n");
 		System.err
-				.println("  maven \n" //
-						+ "  [-temp <dir>]            use as temp directory\n" //
-						+ "  settings                 show maven settings\n" //
-						+ "  bundle                   turn a bundle into a maven bundle\n" //
-						+ "    [-properties <file>]   provide properties, properties starting with javadoc are options for javadoc, like javadoc-tag=...\n"
-						+ "    [-javadoc <file|url>]  where to find the javadoc (zip/dir), otherwise generated\n" //
-						+ "    [-source <file|url>]   where to find the source (zip/dir), otherwise from OSGI-OPT/src\n" //
-						+ "    [-scm <url>]           required scm in pom, otherwise from Bundle-SCM\n" //
-						+ "    [-url <url>]           required project url in pom\n" //
-						+ "    [-bsn bsn]             overrides bsn\n" //
-						+ "    [-version <version>]   overrides version\n" //
-						+ "    [-developer <email>]   developer email\n" //
-						+ "    [-nodelete]            do not delete temp files\n" //
-						+ "    [-passphrase <gpgp passphrase>] signer password\n"//
-						+ "        <file|url> ");
+				.printf("  maven %n" //
+						+ "  [-temp <dir>]            use as temp directory%n" //
+						+ "  settings                 show maven settings%n" //
+						+ "  bundle                   turn a bundle into a maven bundle%n" //
+						+ "    [-properties <file>]   provide properties, properties starting with javadoc are options for javadoc, like javadoc-tag=...%n"
+						+ "    [-javadoc <file|url>]  where to find the javadoc (zip/dir), otherwise generated%n" //
+						+ "    [-source <file|url>]   where to find the source (zip/dir), otherwise from OSGI-OPT/src%n" //
+						+ "    [-scm <url>]           required scm in pom, otherwise from Bundle-SCM%n" //
+						+ "    [-url <url>]           required project url in pom%n" //
+						+ "    [-bsn bsn]             overrides bsn%n" //
+						+ "    [-version <version>]   overrides version%n" //
+						+ "    [-developer <email>]   developer email%n" //
+						+ "    [-nodelete]            do not delete temp files%n" //
+						+ "    [-passphrase <gpgp passphrase>] signer password%n"//
+						+ "        <file|url>%n");
 	}
 
 	/**
@@ -113,12 +116,9 @@ public class MavenCommand extends Processor {
 			error("There is no settings file at '%s'", settings.getAbsolutePath());
 			return;
 		}
-
-		FileReader rdr = new FileReader(settings);
-
-		LineCollection lc = new LineCollection(new BufferedReader(rdr));
+		LineCollection lc = new LineCollection(IO.reader(settings));
 		while (lc.hasNext()) {
-			System.out.println(lc.next());
+			System.err.println(lc.next());
 		}
 	}
 
@@ -168,19 +168,24 @@ public class MavenCommand extends Processor {
 			else if (option.equals("-output"))
 				output = args[i++];
 			else if (option.equals("-nodelete"))
-				nodelete=true;
+				nodelete = true;
 			else if (option.startsWith("-properties")) {
-				InputStream in = new FileInputStream(args[i++]);
+				InputStream in = null;
 				try {
+					in = new FileInputStream(args[i++]);
 					properties.load(in);
-				} catch (Exception e) {
-					in.close();
+				}
+				catch (Exception e) {}
+				finally {
+					if (in != null) {
+						in.close();
+					}
 				}
 			}
 		}
 
 		if (developers.isEmpty()) {
-			String email = settings.globalGet(Settings.EMAIL, null);
+			String email = settings.remove("email");
 			if (email == null)
 				error("No developer email set, you can set global default email with: bnd global email Peter.Kriens at aQute.biz");
 			else
@@ -207,7 +212,9 @@ public class MavenCommand extends Processor {
 		}
 
 		File original = getFile(temp, "original");
-		original.mkdirs();
+		if (!original.exists() && !original.mkdirs()) {
+			throw new IOException("Could not create directory " + original);
+		}
 		binaryJar.expand(original);
 		binaryJar.calcChecksums(null);
 
@@ -230,17 +237,16 @@ public class MavenCommand extends Processor {
 		for (String d : developers)
 			pom.addDeveloper(d);
 
-		Set<String> exports = OSGiHeader.parseHeader(
-				manifest.getMainAttributes().getValue(Constants.EXPORT_PACKAGE)).keySet();
+		Set<String> exports = OSGiHeader.parseHeader(manifest.getMainAttributes().getValue(Constants.EXPORT_PACKAGE))
+				.keySet();
 
 		Jar sourceJar;
 		if (source == null) {
 			trace("Splitting source code");
 			sourceJar = new Jar("source");
-			for (Map.Entry<String, Resource> entry : binaryJar.getResources().entrySet()) {
+			for (Map.Entry<String,Resource> entry : binaryJar.getResources().entrySet()) {
 				if (entry.getKey().startsWith("OSGI-OPT/src")) {
-					sourceJar.putResource(entry.getKey().substring("OSGI-OPT/src/".length()),
-							entry.getValue());
+					sourceJar.putResource(entry.getKey().substring("OSGI-OPT/src/".length()), entry.getValue());
 				}
 			}
 			copyInfo(binaryJar, sourceJar, "source");
@@ -248,7 +254,7 @@ public class MavenCommand extends Processor {
 			sourceJar = getJarFromFileOrURL(source);
 		}
 		sourceJar.calcChecksums(null);
-		
+
 		Jar javadocJar;
 		if (javadoc == null) {
 			trace("creating javadoc because -javadoc not used");
@@ -263,22 +269,23 @@ public class MavenCommand extends Processor {
 			javadocJar = getJarFromFileOrURL(javadoc);
 		}
 		javadocJar.calcChecksums(null);
-		
+
 		addClose(binaryJar);
 		addClose(sourceJar);
 		addClose(javadocJar);
 
 		trace("creating bundle dir");
 		File bundle = new File(temp, "bundle");
-		bundle.mkdirs();
+		if (!bundle.exists() && !bundle.mkdirs()) {
+			throw new IOException("Could not create directory " + bundle);
+		}
 
 		String prefix = pom.getArtifactId() + "-" + pom.getVersion();
 		File binaryFile = new File(bundle, prefix + ".jar");
 		File sourceFile = new File(bundle, prefix + "-sources.jar");
 		File javadocFile = new File(bundle, prefix + "-javadoc.jar");
 		File pomFile = new File(bundle, "pom.xml").getAbsoluteFile();
-		trace("creating output files %s, %s,%s, and %s", binaryFile, sourceFile, javadocFile,
-				pomFile);
+		trace("creating output files %s, %s,%s, and %s", binaryFile, sourceFile, javadocFile, pomFile);
 
 		IO.copy(pom.openInputStream(), pomFile);
 		trace("copied pom");
@@ -315,39 +322,39 @@ public class MavenCommand extends Processor {
 	private void copyInfo(Jar source, Jar dest, String type) throws Exception {
 		source.ensureManifest();
 		dest.ensureManifest();
-		copyInfoResource( source, dest, "LICENSE");
-		copyInfoResource( source, dest, "LICENSE.html");
-		copyInfoResource( source, dest, "about.html");
-		
+		copyInfoResource(source, dest, "LICENSE");
+		copyInfoResource(source, dest, "LICENSE.html");
+		copyInfoResource(source, dest, "about.html");
+
 		Manifest sm = source.getManifest();
 		Manifest dm = dest.getManifest();
-		copyInfoHeader( sm, dm, "Bundle-Description","");
-		copyInfoHeader( sm, dm, "Bundle-Vendor","");
-		copyInfoHeader( sm, dm, "Bundle-Copyright","");
-		copyInfoHeader( sm, dm, "Bundle-DocURL","");
-		copyInfoHeader( sm, dm, "Bundle-License","");
-		copyInfoHeader( sm, dm, "Bundle-Name", " " + type);
-		copyInfoHeader( sm, dm, "Bundle-SymbolicName", "." + type);
-		copyInfoHeader( sm, dm, "Bundle-Version", "");
+		copyInfoHeader(sm, dm, "Bundle-Description", "");
+		copyInfoHeader(sm, dm, "Bundle-Vendor", "");
+		copyInfoHeader(sm, dm, "Bundle-Copyright", "");
+		copyInfoHeader(sm, dm, "Bundle-DocURL", "");
+		copyInfoHeader(sm, dm, "Bundle-License", "");
+		copyInfoHeader(sm, dm, "Bundle-Name", " " + type);
+		copyInfoHeader(sm, dm, "Bundle-SymbolicName", "." + type);
+		copyInfoHeader(sm, dm, "Bundle-Version", "");
 	}
 
 	private void copyInfoHeader(Manifest sm, Manifest dm, String key, String value) {
 		String v = sm.getMainAttributes().getValue(key);
-		if ( v == null) {
+		if (v == null) {
 			trace("no source for " + key);
 			return;
 		}
-		
-		if ( dm.getMainAttributes().getValue(key) != null) {
-			trace("already have " + key );
+
+		if (dm.getMainAttributes().getValue(key) != null) {
+			trace("already have " + key);
 			return;
 		}
-		
+
 		dm.getMainAttributes().putValue(key, v + value);
 	}
 
 	private void copyInfoResource(Jar source, Jar dest, String type) {
-		if ( source.getResources().containsKey(type) && !dest.getResources().containsKey(type))
+		if (source.getResources().containsKey(type) && !dest.getResources().containsKey(type))
 			dest.putResource(type, source.getResource(type));
 	}
 
@@ -366,7 +373,8 @@ public class MavenCommand extends Processor {
 			InputStream in = url.openStream();
 			try {
 				jar = new Jar(url.getFile(), in);
-			} finally {
+			}
+			finally {
 				in.close();
 			}
 		}
@@ -387,19 +395,20 @@ public class MavenCommand extends Processor {
 			command.add("--passphrase", passphrase);
 		command.add("-ab", "--sign"); // not the -b!!
 		command.add(file.getAbsolutePath());
-		System.out.println(command);
-		StringBuffer stdout = new StringBuffer();
-		StringBuffer stderr = new StringBuffer();
+		System.err.println(command);
+		StringBuilder stdout = new StringBuilder();
+		StringBuilder stderr = new StringBuilder();
 		int result = command.execute(stdout, stderr);
 		if (result != 0) {
 			error("gpg signing %s failed because %s", file, "" + stdout + stderr);
 		}
 	}
 
-	private Jar javadoc(File source, Set<String> exports, Manifest m, Properties p)
-			throws Exception {
+	private Jar javadoc(File source, Set<String> exports, Manifest m, Properties p) throws Exception {
 		File tmp = new File(temp, "javadoc");
-		tmp.mkdirs();
+		if (!tmp.exists() && !tmp.mkdirs()) {
+			throw new IOException("Could not create directory " + tmp);
+		}
 
 		Command command = new Command();
 		command.add(getProperty("javadoc", "javadoc"));
@@ -435,7 +444,7 @@ public class MavenCommand extends Processor {
 		command.add("-tag");
 		command.add("noimplement:t:Consumers of this API must not implement this interface");
 
-		for (Enumeration<?> e = pp.propertyNames(); e.hasMoreElements();) {
+		for (Enumeration< ? > e = pp.propertyNames(); e.hasMoreElements();) {
 			String key = (String) e.nextElement();
 			String value = pp.getProperty(key);
 
@@ -450,15 +459,14 @@ public class MavenCommand extends Processor {
 			command.add(packageName);
 		}
 
-		StringBuffer out = new StringBuffer();
-		StringBuffer err = new StringBuffer();
+		StringBuilder out = new StringBuilder();
+		StringBuilder err = new StringBuilder();
 
-		System.out.println(command);
+		System.err.println(command);
 
 		int result = command.execute(out, err);
 		if (result != 0) {
-			warning("Error during execution of javadoc command: %s\n******************\n%s", out,
-					err);
+			warning("Error during execution of javadoc command: %s\n******************\n%s", out, err);
 		}
 		Jar jar = new Jar(tmp);
 		addClose(jar);
@@ -472,14 +480,13 @@ public class MavenCommand extends Processor {
 	 * @return
 	 */
 	private String license(Attributes attr) {
-		Map<String, Map<String, String>> map = Processor.parseHeader(
-				attr.getValue(Constants.BUNDLE_LICENSE), null);
+		Parameters map = Processor.parseHeader(attr.getValue(Constants.BUNDLE_LICENSE), null);
 		if (map.isEmpty())
 			return null;
 
 		StringBuilder sb = new StringBuilder();
 		String sep = "Licensed under ";
-		for (Map.Entry<String, Map<String, String>> entry : map.entrySet()) {
+		for (Entry<String,Attrs> entry : map.entrySet()) {
 			sb.append(sep);
 			String key = entry.getKey();
 			String link = entry.getValue().get("link");
@@ -538,78 +545,74 @@ public class MavenCommand extends Processor {
 		pp.setProperty(key, defaultValue);
 	}
 
-	
 	/**
 	 * View - Show the dependency details of an artifact
 	 */
-	
 
-	static Executor executor = Executors.newCachedThreadPool();
-	static Pattern GROUP_ARTIFACT_VERSION = Pattern.compile("([^+]+)\\+([^+]+)\\+([^+]+)");
-	void view( String args[], int i) throws Exception {
+	static Executor	executor				= Executors.newCachedThreadPool();
+	static Pattern	GROUP_ARTIFACT_VERSION	= Pattern.compile("([^+]+)\\+([^+]+)\\+([^+]+)");
+
+	void view(String args[], int i) throws Exception {
 		Maven maven = new Maven(executor);
-		OutputStream out = System.out;
-		
-		List<URI>	urls = new ArrayList<URI>();
-		
-		while ( i < args.length && args[i].startsWith("-")) {
-			if( "-r".equals(args[i])) {
+		OutputStream out = System.err;
+
+		List<URI> urls = new ArrayList<URI>();
+
+		while (i < args.length && args[i].startsWith("-")) {
+			if ("-r".equals(args[i])) {
 				URI uri = new URI(args[++i]);
-				urls.add( uri );
-				System.out.println("URI for repo " + uri);
-			}
-			else
-				if ( "-o".equals(args[i])) {
-					out = new FileOutputStream(args[++i]);
-				}
-				else
-					throw new IllegalArgumentException("Unknown option: " + args[i]);
-			
+				urls.add(uri);
+				System.err.println("URI for repo " + uri);
+			} else if ("-o".equals(args[i])) {
+				out = new FileOutputStream(args[++i]);
+			} else
+				throw new IllegalArgumentException("Unknown option: " + args[i]);
+
 			i++;
 		}
-		
+
 		URI[] urls2 = urls.toArray(new URI[urls.size()]);
-		PrintWriter pw = new PrintWriter(out);
-		
-		while ( i < args.length) {
+		PrintWriter pw = IO.writer(out);
+
+		while (i < args.length) {
 			String ref = args[i++];
 			pw.println("Ref " + ref);
-			
+
 			Matcher matcher = GROUP_ARTIFACT_VERSION.matcher(ref);
 			if (matcher.matches()) {
-				
+
 				String group = matcher.group(1);
 				String artifact = matcher.group(2);
 				String version = matcher.group(3);
 				CachedPom pom = maven.getPom(group, artifact, version, urls2);
-				
+
 				Builder a = new Builder();
 				a.setProperty("Private-Package", "*");
 				Set<Pom> dependencies = pom.getDependencies(Scope.compile, urls2);
-				for ( Pom dep : dependencies ) {
-					System.out.printf( "%20s %-20s %10s\n", dep.getGroupId(), dep.getArtifactId(), dep.getVersion());
+				for (Pom dep : dependencies) {
+					System.err.printf("%20s %-20s %10s%n", dep.getGroupId(), dep.getArtifactId(), dep.getVersion());
 					a.addClasspath(dep.getArtifact());
 				}
 				pw.println(a.getClasspath());
 				a.build();
 
-				TreeSet<String> sorted = new TreeSet<String>( a.getImports().keySet());
-				for ( String p :sorted) {
-					pw.printf("%-40s\n",p);
+				TreeSet<PackageRef> sorted = new TreeSet<PackageRef>(a.getImports().keySet());
+				for (PackageRef p : sorted) {
+					pw.printf("%-40s\n", p);
 				}
-//				for ( Map.Entry<String, Set<String>> entry : a.getUses().entrySet()) {
-//					String from = entry.getKey();
-//					for ( String uses : entry.getValue()) {
-//						System.out.printf("%40s %s\n", from, uses);
-//						from = "";
-//					}
-//				}
+				// for ( Map.Entry<String, Set<String>> entry :
+				// a.getUses().entrySet()) {
+				// String from = entry.getKey();
+				// for ( String uses : entry.getValue()) {
+				// System.err.printf("%40s %s\n", from, uses);
+				// from = "";
+				// }
+				// }
 				a.close();
 			} else
 				System.err.println("Wrong, must look like group+artifact+version, is " + ref);
-			
+
 		}
 	}
-	
-	
+
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/maven/MavenDependencyGraph.java b/biz.aQute.bndlib/src/aQute/bnd/maven/MavenDependencyGraph.java
index 6278be2..e9e928e 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/maven/MavenDependencyGraph.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/maven/MavenDependencyGraph.java
@@ -14,14 +14,13 @@ public class MavenDependencyGraph {
 	final List<Artifact>				dependencies	= new ArrayList<Artifact>();
 	final List<URL>						repositories	= new ArrayList<URL>();
 	final XPath							xpath			= xpathFactory.newXPath();
-	final Map<URL, Artifact>			cache			= new HashMap<URL, Artifact>();
-	Artifact						root;
+	final Map<URI,Artifact>				cache			= new HashMap<URI,Artifact>();
+	Artifact							root;
 
 	enum Scope {
 		COMPILE, RUNTIME, TEST, PROVIDED, SYSTEM, IMPORT,
-	};
+	}
 
-	
 	public class Artifact {
 
 		String			groupId;
@@ -49,33 +48,28 @@ public class MavenDependencyGraph {
 				if (scope != null && scope.length() > 0) {
 					this.scope = Scope.valueOf(scope.toUpperCase());
 				}
-				NodeList evaluate = (NodeList) xpath.evaluate("//dependencies/dependency", doc,
-						XPathConstants.NODESET);
+				NodeList evaluate = (NodeList) xpath.evaluate("//dependencies/dependency", doc, XPathConstants.NODESET);
 
 				for (int i = 0; i < evaluate.getLength(); i++) {
 					Node childNode = evaluate.item(i);
-					Artifact artifact = getArtifact(xpath.evaluate("groupId", childNode), xpath
-							.evaluate("artifactId", childNode), xpath.evaluate("version", childNode));
+					Artifact artifact = getArtifact(xpath.evaluate("groupId", childNode),
+							xpath.evaluate("artifactId", childNode), xpath.evaluate("version", childNode));
 					add(artifact);
 				}
 			}
 		}
-		
-		
 
 		public void add(Artifact artifact) {
 			dependencies.add(artifact);
 		}
 
-
-
+		@Override
 		public String toString() {
 			return groupId + "." + artifactId + "-" + version + "[" + scope + "," + optional + "]";
 		}
 
 		public String getPath() throws URISyntaxException {
-			return groupId.replace('.', '/') + "/" + artifactId + "/" + version + "/" + artifactId
-					+ "-" + version;
+			return groupId.replace('.', '/') + "/" + artifactId + "/" + version + "/" + artifactId + "-" + version;
 		}
 
 	}
@@ -96,13 +90,13 @@ public class MavenDependencyGraph {
 			String path = getPath(repository.toString(), groupId, artifactId, version);
 
 			try {
-				URL url = new URL(path + ".pom");
+				URI url = new URL(path + ".pom").toURI();
 				if (cache.containsKey(url)) {
 					return cache.get(url);
-				} else {
-					return new Artifact(url);
 				}
-			} catch (Exception e) {
+				return new Artifact(url.toURL());
+			}
+			catch (Exception e) {
 				System.err.println("Failed to get " + artifactId + " from " + repository);
 			}
 		}
@@ -127,13 +121,10 @@ public class MavenDependencyGraph {
 		return null;
 	}
 
-	
-	
-	public void addArtifact( Artifact artifact ) throws Exception {
-		if ( root == null)
+	public void addArtifact(Artifact artifact) throws Exception {
+		if (root == null)
 			root = new Artifact(null);
 		root.add(artifact);
 	}
-	
-	
+
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/maven/MavenDeploy.java b/biz.aQute.bndlib/src/aQute/bnd/maven/MavenDeploy.java
index 24981ca..592b3f9 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/maven/MavenDeploy.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/maven/MavenDeploy.java
@@ -5,10 +5,11 @@ import java.util.*;
 import java.util.jar.*;
 
 import aQute.bnd.build.*;
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
 import aQute.bnd.service.*;
-import aQute.lib.osgi.*;
 import aQute.libg.command.*;
-import aQute.libg.reporter.*;
+import aQute.service.reporter.*;
 
 public class MavenDeploy implements Deploy, Plugin {
 
@@ -20,7 +21,7 @@ public class MavenDeploy implements Deploy, Plugin {
 	String		passphrase;
 	Reporter	reporter;
 
-	public void setProperties(Map<String, String> map) {
+	public void setProperties(Map<String,String> map) {
 		repository = map.get("repository");
 		url = map.get("url");
 		passphrase = map.get("passphrase");
@@ -39,62 +40,70 @@ public class MavenDeploy implements Deploy, Plugin {
 
 	/**
 	 */
-	public boolean deploy(Project project, Jar original) throws Exception {
-		Map<String, Map<String, String>> deploy = project.parseHeader(project
-				.getProperty(Constants.DEPLOY));
+	public boolean deploy(Project project, String jarName, InputStream jarStream) throws Exception {
+		Parameters deploy = project.parseHeader(project.getProperty(Constants.DEPLOY));
 
-		Map<String, String> maven = deploy.get(repository);
+		Map<String,String> maven = deploy.get(repository);
 		if (maven == null)
 			return false; // we're not playing for this bundle
 
-		project.progress("deploying %s to Maven repo: %s", original, repository);
+		project.progress("deploying %s to Maven repo: %s", jarName, repository);
 		File target = project.getTarget();
 		File tmp = Processor.getFile(target, repository);
-		tmp.mkdirs();
-
-		Manifest manifest = original.getManifest();
-		if (manifest == null)
-			project.error("Jar has no manifest: %s", original);
-		else {
-			project.progress("Writing pom.xml");
-			PomResource pom = new PomResource(manifest);
-			pom.setProperties(maven);
-			File pomFile = write(tmp, pom, "pom.xml");
-
-			Jar main = new Jar("main");
-			Jar src = new Jar("src");
-			try {
-				split(original, main, src);
-				Map<String, Map<String, String>> exports = project.parseHeader(manifest
-						.getMainAttributes().getValue(Constants.EXPORT_PACKAGE));
-				File jdoc = new File(tmp, "jdoc");
-				jdoc.mkdirs();
-				project.progress("Generating Javadoc for: " + exports.keySet());
-				Jar javadoc = javadoc(jdoc, project, exports.keySet());
-				project.progress("Writing javadoc jar");
-				File javadocFile = write(tmp, new JarResource(javadoc), "javadoc.jar");
-				project.progress("Writing main file");
-				File mainFile = write(tmp, new JarResource(main), "main.jar");
-				project.progress("Writing sources file");
-				File srcFile = write(tmp, new JarResource(main), "src.jar");
-
-				project.progress("Deploying main file");
-				maven_gpg_sign_and_deploy(project, mainFile, null, pomFile);
-				project.progress("Deploying main sources file");
-				maven_gpg_sign_and_deploy(project, srcFile, "sources", null);
-				project.progress("Deploying main javadoc file");
-				maven_gpg_sign_and_deploy(project, javadocFile, "javadoc", null);
-
-			} finally {
-				main.close();
-				src.close();
+		if (!tmp.exists() && !tmp.mkdirs()) {
+			throw new IOException("Could not create directory " + tmp);
+		}
+
+		Jar original = new Jar(jarName, jarStream);
+		try {
+			Manifest manifest = original.getManifest();
+			if (manifest == null)
+				project.error("Jar has no manifest: %s", original);
+			else {
+				project.progress("Writing pom.xml");
+				PomResource pom = new PomResource(manifest);
+				pom.setProperties(maven);
+				File pomFile = write(tmp, pom, "pom.xml");
+
+				Jar main = new Jar("main");
+				Jar src = new Jar("src");
+				try {
+					split(original, main, src);
+					Parameters exports = project.parseHeader(manifest.getMainAttributes().getValue(
+							Constants.EXPORT_PACKAGE));
+					File jdoc = new File(tmp, "jdoc");
+					jdoc.mkdirs();
+					project.progress("Generating Javadoc for: " + exports.keySet());
+					Jar javadoc = javadoc(jdoc, project, exports.keySet());
+					project.progress("Writing javadoc jar");
+					File javadocFile = write(tmp, new JarResource(javadoc), "javadoc.jar");
+					project.progress("Writing main file");
+					File mainFile = write(tmp, new JarResource(main), "main.jar");
+					project.progress("Writing sources file");
+					File srcFile = write(tmp, new JarResource(main), "src.jar");
+
+					project.progress("Deploying main file");
+					maven_gpg_sign_and_deploy(project, mainFile, null, pomFile);
+					project.progress("Deploying main sources file");
+					maven_gpg_sign_and_deploy(project, srcFile, "sources", null);
+					project.progress("Deploying main javadoc file");
+					maven_gpg_sign_and_deploy(project, javadocFile, "javadoc", null);
+
+				}
+				finally {
+					main.close();
+					src.close();
+				}
 			}
 		}
+		finally {
+			original.close();
+		}
 		return true;
 	}
 
 	private void split(Jar original, Jar main, Jar src) {
-		for (Map.Entry<String, Resource> e : original.getResources().entrySet()) {
+		for (Map.Entry<String,Resource> e : original.getResources().entrySet()) {
 			String path = e.getKey();
 			if (path.startsWith("OSGI-OPT/src/")) {
 				src.putResource(path.substring("OSGI-OPT/src/".length()), e.getValue());
@@ -113,8 +122,7 @@ public class MavenDeploy implements Deploy, Plugin {
 	// -Dfile=/Ws/bnd/biz.aQute.bndlib/tmp/biz.aQute.bndlib.jar \
 	// -Dpassphrase=a1k3v3t5x3
 
-	private void maven_gpg_sign_and_deploy(Project b, File file, String classifier, File pomFile)
-			throws Exception {
+	private void maven_gpg_sign_and_deploy(Project b, File file, String classifier, File pomFile) throws Exception {
 		Command command = new Command();
 		command.setTrace();
 		command.add(b.getProperty("mvn", "mvn"));
@@ -128,17 +136,17 @@ public class MavenDeploy implements Deploy, Plugin {
 		optional(command, "classifier", classifier);
 		optional(command, "pomFile", pomFile == null ? null : pomFile.getAbsolutePath());
 
-		StringBuffer stdout = new StringBuffer();
-		StringBuffer stderr = new StringBuffer();
+		StringBuilder stdout = new StringBuilder();
+		StringBuilder stderr = new StringBuilder();
 
 		int result = command.execute(stdout, stderr);
 		if (result != 0) {
-			b.error("Maven deploy to %s failed to sign and transfer %s because %s", repository,
-					file, "" + stdout + stderr);
+			b.error("Maven deploy to %s failed to sign and transfer %s because %s", repository, file, "" + stdout
+					+ stderr);
 		}
 	}
 
-	private void optional(Command command, String key, String value) {
+	private void optional(Command command, @SuppressWarnings("unused") String key, String value) {
 		if (value == null)
 			return;
 
@@ -147,19 +155,19 @@ public class MavenDeploy implements Deploy, Plugin {
 
 	private Jar javadoc(File tmp, Project b, Set<String> exports) throws Exception {
 		Command command = new Command();
-		
+
 		command.add(b.getProperty("javadoc", "javadoc"));
 		command.add("-d");
 		command.add(tmp.getAbsolutePath());
 		command.add("-sourcepath");
-		command.add( Processor.join(b.getSourcePath(),File.pathSeparator));
+		command.add(Processor.join(b.getSourcePath(), File.pathSeparator));
 
 		for (String packageName : exports) {
 			command.add(packageName);
 		}
 
-		StringBuffer out = new StringBuffer();
-		StringBuffer err = new StringBuffer();
+		StringBuilder out = new StringBuilder();
+		StringBuilder err = new StringBuilder();
 		Command c = new Command();
 		c.setTrace();
 		int result = c.execute(out, err);
@@ -177,7 +185,8 @@ public class MavenDeploy implements Deploy, Plugin {
 		OutputStream out = new FileOutputStream(f);
 		try {
 			r.write(out);
-		} finally {
+		}
+		finally {
 			out.close();
 		}
 		return f;
diff --git a/biz.aQute.bndlib/src/aQute/bnd/maven/MavenDeployCmd.java b/biz.aQute.bndlib/src/aQute/bnd/maven/MavenDeployCmd.java
index aaa23ff..8d19093 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/maven/MavenDeployCmd.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/maven/MavenDeployCmd.java
@@ -5,9 +5,10 @@ import java.util.*;
 import java.util.jar.*;
 
 import aQute.bnd.build.*;
-import aQute.lib.osgi.*;
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
 import aQute.libg.command.*;
-import aQute.libg.reporter.*;
+import aQute.service.reporter.*;
 
 public class MavenDeployCmd extends Processor {
 
@@ -29,15 +30,16 @@ public class MavenDeployCmd extends Processor {
 	 */
 	void run(String args[], int i) throws Exception {
 		if (i >= args.length) {
+			System.err.printf("Usage:%n");
 			System.err
-					.println("Usage:\n");
-			System.err.println("  deploy [-url repo] [-passphrase passphrase] [-homedir homedir] [-keyname keyname] bundle ...");
+					.println("  deploy [-url repo] [-passphrase passphrase] [-homedir homedir] [-keyname keyname] bundle ...");
 			System.err.println("  settings");
 			return;
 		}
 
-		@SuppressWarnings("unused") String cmd = args[i++];
-		
+		/* skip first argument */
+		i++;
+
 		while (i < args.length && args[i].startsWith("-")) {
 			String option = args[i];
 			if (option.equals("-url"))
@@ -52,10 +54,9 @@ public class MavenDeployCmd extends Processor {
 				error("Invalid command ");
 		}
 
-		
 	}
 
-	public void setProperties(Map<String, String> map) {
+	public void setProperties(Map<String,String> map) {
 		repository = map.get("repository");
 		url = map.get("url");
 		passphrase = map.get("passphrase");
@@ -75,17 +76,18 @@ public class MavenDeployCmd extends Processor {
 	/**
 	 */
 	public boolean deploy(Project project, Jar original) throws Exception {
-		Map<String, Map<String, String>> deploy = project.parseHeader(project
-				.getProperty(Constants.DEPLOY));
+		Parameters deploy = project.parseHeader(project.getProperty(Constants.DEPLOY));
 
-		Map<String, String> maven = deploy.get(repository);
+		Map<String,String> maven = deploy.get(repository);
 		if (maven == null)
 			return false; // we're not playing for this bundle
 
 		project.progress("deploying %s to Maven repo: %s", original, repository);
 		File target = project.getTarget();
 		File tmp = Processor.getFile(target, repository);
-		tmp.mkdirs();
+		if (!tmp.exists() && !tmp.mkdirs()) {
+			throw new IOException("Could not create directory " + tmp);
+		}
 
 		Manifest manifest = original.getManifest();
 		if (manifest == null)
@@ -100,10 +102,12 @@ public class MavenDeployCmd extends Processor {
 			Jar src = new Jar("src");
 			try {
 				split(original, main, src);
-				Map<String, Map<String, String>> exports = project.parseHeader(manifest
-						.getMainAttributes().getValue(Constants.EXPORT_PACKAGE));
+				Parameters exports = project.parseHeader(manifest.getMainAttributes()
+						.getValue(Constants.EXPORT_PACKAGE));
 				File jdoc = new File(tmp, "jdoc");
-				jdoc.mkdirs();
+				if (!jdoc.exists() && !jdoc.mkdirs()) {
+					throw new IOException("Could not create directory " + jdoc);
+				}
 				project.progress("Generating Javadoc for: " + exports.keySet());
 				Jar javadoc = javadoc(jdoc, project, exports.keySet());
 				project.progress("Writing javadoc jar");
@@ -120,7 +124,8 @@ public class MavenDeployCmd extends Processor {
 				project.progress("Deploying main javadoc file");
 				maven_gpg_sign_and_deploy(project, javadocFile, "javadoc", null);
 
-			} finally {
+			}
+			finally {
 				main.close();
 				src.close();
 			}
@@ -129,7 +134,7 @@ public class MavenDeployCmd extends Processor {
 	}
 
 	private void split(Jar original, Jar main, Jar src) {
-		for (Map.Entry<String, Resource> e : original.getResources().entrySet()) {
+		for (Map.Entry<String,Resource> e : original.getResources().entrySet()) {
 			String path = e.getKey();
 			if (path.startsWith("OSGI-OPT/src/")) {
 				src.putResource(path.substring("OSGI-OPT/src/".length()), e.getValue());
@@ -148,8 +153,7 @@ public class MavenDeployCmd extends Processor {
 	// -Dfile=/Ws/bnd/biz.aQute.bndlib/tmp/biz.aQute.bndlib.jar \
 	// -Dpassphrase=a1k3v3t5x3
 
-	private void maven_gpg_sign_and_deploy(Project b, File file, String classifier, File pomFile)
-			throws Exception {
+	private void maven_gpg_sign_and_deploy(Project b, File file, String classifier, File pomFile) throws Exception {
 		Command command = new Command();
 		command.setTrace();
 		command.add(b.getProperty("mvn", "mvn"));
@@ -163,17 +167,17 @@ public class MavenDeployCmd extends Processor {
 		optional(command, "classifier", classifier);
 		optional(command, "pomFile", pomFile == null ? null : pomFile.getAbsolutePath());
 
-		StringBuffer stdout = new StringBuffer();
-		StringBuffer stderr = new StringBuffer();
+		StringBuilder stdout = new StringBuilder();
+		StringBuilder stderr = new StringBuilder();
 
 		int result = command.execute(stdout, stderr);
 		if (result != 0) {
-			b.error("Maven deploy to %s failed to sign and transfer %s because %s", repository,
-					file, "" + stdout + stderr);
+			b.error("Maven deploy to %s failed to sign and transfer %s because %s", repository, file, "" + stdout
+					+ stderr);
 		}
 	}
 
-	private void optional(Command command, String key, String value) {
+	private void optional(Command command, @SuppressWarnings("unused") String key, String value) {
 		if (value == null)
 			return;
 
@@ -193,8 +197,8 @@ public class MavenDeployCmd extends Processor {
 			command.add(packageName);
 		}
 
-		StringBuffer out = new StringBuffer();
-		StringBuffer err = new StringBuffer();
+		StringBuilder out = new StringBuilder();
+		StringBuilder err = new StringBuilder();
 		Command c = new Command();
 		c.setTrace();
 		int result = c.execute(out, err);
@@ -212,7 +216,8 @@ public class MavenDeployCmd extends Processor {
 		OutputStream out = new FileOutputStream(f);
 		try {
 			r.write(out);
-		} finally {
+		}
+		finally {
 			out.close();
 		}
 		return f;
diff --git a/biz.aQute.bndlib/src/aQute/bnd/maven/MavenGroup.java b/biz.aQute.bndlib/src/aQute/bnd/maven/MavenGroup.java
index 2d49be6..7be8c9e 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/maven/MavenGroup.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/maven/MavenGroup.java
@@ -3,25 +3,24 @@ package aQute.bnd.maven;
 import java.util.*;
 
 import aQute.bnd.service.*;
-import aQute.libg.reporter.*;
+import aQute.service.reporter.*;
 
 public class MavenGroup implements BsnToMavenPath, Plugin {
-    String    groupId = "";
+	String	groupId	= "";
 
-    public String[] getGroupAndArtifact(String bsn) {
-        String[] result = new String[2];
-        result[0] = groupId;
-        result[1] = bsn;
-        return result;
-    }
+	public String[] getGroupAndArtifact(String bsn) {
+		String[] result = new String[2];
+		result[0] = groupId;
+		result[1] = bsn;
+		return result;
+	}
 
-    public void setProperties(Map<String, String> map) {
-        if (map.containsKey("groupId")) {
-            groupId = map.get("groupId");
-        }
-    }
+	public void setProperties(Map<String,String> map) {
+		if (map.containsKey("groupId")) {
+			groupId = map.get("groupId");
+		}
+	}
 
-    public void setReporter(Reporter processor) {
-    }
+	public void setReporter(Reporter processor) {}
 
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/maven/MavenRepository.java b/biz.aQute.bndlib/src/aQute/bnd/maven/MavenRepository.java
index 506ea53..d8d54e0 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/maven/MavenRepository.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/maven/MavenRepository.java
@@ -4,19 +4,21 @@ import java.io.*;
 import java.util.*;
 import java.util.regex.*;
 
+import aQute.bnd.osgi.*;
 import aQute.bnd.service.*;
-import aQute.lib.osgi.*;
-import aQute.libg.reporter.*;
-import aQute.libg.version.*;
+import aQute.bnd.version.*;
+import aQute.lib.collections.*;
+import aQute.service.reporter.*;
 
 public class MavenRepository implements RepositoryPlugin, Plugin, BsnToMavenPath {
 
-	public static String	NAME	= "name";
+	public final static String	NAME	= "name";
 
-	File					root;
-	Reporter				reporter;
-	String					name;
+	File						root;
+	Reporter					reporter;
+	String						name;
 
+	@Override
 	public String toString() {
 		return "maven:" + root;
 	}
@@ -25,15 +27,15 @@ public class MavenRepository implements RepositoryPlugin, Plugin, BsnToMavenPath
 		return false;
 	}
 
-	public File[] get(String bsn, String version) throws Exception {
+	private File[] get(String bsn, String version) throws Exception {
 		VersionRange range = new VersionRange("0");
 		if (version != null)
 			range = new VersionRange(version);
 
 		List<BsnToMavenPath> plugins = ((Processor) reporter).getPlugins(BsnToMavenPath.class);
-		if ( plugins.isEmpty())
+		if (plugins.isEmpty())
 			plugins.add(this);
-		
+
 		for (BsnToMavenPath cvr : plugins) {
 			String[] paths = cvr.getGroupAndArtifact(bsn);
 			if (paths != null) {
@@ -62,18 +64,16 @@ public class MavenRepository implements RepositoryPlugin, Plugin, BsnToMavenPath
 				if (Verifier.isVersion(vv)) {
 					Version vvv = new Version(vv);
 					if (range.includes(vvv)) {
-						File file = Processor.getFile(vsdir, v + "/" + artifactId + "-" + v
-								+ ".jar");
+						File file = Processor.getFile(vsdir, v + "/" + artifactId + "-" + v + ".jar");
 						if (file.isFile())
 							result.add(file);
 						else
 							reporter.warning("Expected maven entry was not a valid file %s ", file);
 					}
 				} else {
-					reporter
-							.warning(
-									"Expected a version directory in maven: dir=%s raw-version=%s cleaned-up-version=%s",
-									vsdir, vv, v);
+					reporter.warning(
+							"Expected a version directory in maven: dir=%s raw-version=%s cleaned-up-version=%s",
+							vsdir, vv, v);
 				}
 			}
 		} else
@@ -114,34 +114,39 @@ public class MavenRepository implements RepositoryPlugin, Plugin, BsnToMavenPath
 		}
 	}
 
-	public File put(Jar jar) throws Exception {
-		throw new IllegalStateException("Maven does not support the put command");
+	public PutResult put(InputStream stream, PutOptions options) throws Exception {
+		throw new UnsupportedOperationException("Maven does not support the put command");
 	}
 
-	public List<Version> versions(String bsn) throws Exception {
-		
-		File files[] = get( bsn, null);
+	public SortedSet<Version> versions(String bsn) throws Exception {
+
+		File files[] = get(bsn, null);
 		List<Version> versions = new ArrayList<Version>();
-		for ( File f : files ) {
-			Version v = new Version( f.getParentFile().getName());
+		for (File f : files) {
+			String version = f.getParentFile().getName();
+			version = Builder.cleanupVersion(version);
+			Version v = new Version(version);
 			versions.add(v);
 		}
-		return versions;
+		if ( versions.isEmpty())
+			return SortedList.empty();
+		
+		return new SortedList<Version>(versions);
 	}
 
-	public void setProperties(Map<String, String> map) {
+	public void setProperties(Map<String,String> map) {
 		File home = new File("");
 		String root = map.get("root");
 		if (root == null) {
-			home = new File( System.getProperty("user.home") );
-			this.root = Processor.getFile(home , ".m2/repository").getAbsoluteFile();
+			home = new File(System.getProperty("user.home"));
+			this.root = Processor.getFile(home, ".m2/repository").getAbsoluteFile();
 		} else
 			this.root = Processor.getFile(home, root).getAbsoluteFile();
-		
+
 		if (!this.root.isDirectory()) {
 			reporter.error("Maven repository did not get a proper URL to the repository %s", root);
 		}
-		name = (String) map.get(NAME);
+		name = map.get(NAME);
 
 	}
 
@@ -153,21 +158,23 @@ public class MavenRepository implements RepositoryPlugin, Plugin, BsnToMavenPath
 		String groupId;
 		String artifactId;
 		int n = bsn.indexOf('.');
-		
-		while ( n > 0 ) {
-			artifactId = bsn.substring(n+1);
-			groupId = bsn.substring(0,n);
-			
-			File gdir = new File(root, groupId.replace('.',File.separatorChar)).getAbsoluteFile();
-			File adir = new File( gdir, artifactId).getAbsoluteFile();
-			if ( adir.isDirectory() )
-				return new String[] {groupId, artifactId};
-			
-			n = bsn.indexOf('.',n+1);
+
+		while (n > 0) {
+			artifactId = bsn.substring(n + 1);
+			groupId = bsn.substring(0, n);
+
+			File gdir = new File(root, groupId.replace('.', File.separatorChar)).getAbsoluteFile();
+			File adir = new File(gdir, artifactId).getAbsoluteFile();
+			if (adir.isDirectory())
+				return new String[] {
+						groupId, artifactId
+				};
+
+			n = bsn.indexOf('.', n + 1);
 		}
 		return null;
 	}
-	
+
 	public String getName() {
 		if (name == null) {
 			return toString();
@@ -179,16 +186,39 @@ public class MavenRepository implements RepositoryPlugin, Plugin, BsnToMavenPath
 		File[] files = get(bsn, range);
 		if (files.length >= 0) {
 			switch (strategy) {
-			case LOWEST:
-				return files[0];
-			case HIGHEST:
-				return files[files.length - 1];
+				case LOWEST :
+					return files[0];
+				case HIGHEST :
+					return files[files.length - 1];
+				case EXACT :
+					// TODO exact
+					break;
 			}
 		}
 		return null;
 	}
 
-	public void setRoot( File f  ) {
+	public void setRoot(File f) {
 		root = f;
 	}
+
+	public String getLocation() {
+		return root.toString();
+	}
+
+	public File get(String bsn, Version version, Map<String,String> properties, DownloadListener ... listeners) throws Exception {
+		File file = get(bsn, version.toString(), Strategy.EXACT, properties);
+		if ( file == null)
+			return null;
+		
+		for (DownloadListener l : listeners) {
+			try {
+				l.success(file);
+			}
+			catch (Exception e) {
+				reporter.exception(e, "Download listener for %s", file);
+			}
+		}
+		return file;
+	}
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/maven/PomFromManifest.java b/biz.aQute.bndlib/src/aQute/bnd/maven/PomFromManifest.java
index 3ed560d..33d9d44 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/maven/PomFromManifest.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/maven/PomFromManifest.java
@@ -2,12 +2,15 @@ package aQute.bnd.maven;
 
 import java.io.*;
 import java.util.*;
+import java.util.Map.Entry;
 import java.util.jar.*;
 import java.util.regex.*;
 
-import aQute.lib.osgi.*;
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.version.*;
+import aQute.lib.io.*;
 import aQute.lib.tag.*;
-import aQute.libg.version.*;
 
 public class PomFromManifest extends WriteResource {
 	final Manifest			manifest;
@@ -67,12 +70,14 @@ public class PomFromManifest extends WriteResource {
 		this.manifest = manifest;
 	}
 
-	@Override public long lastModified() {
+	@Override
+	public long lastModified() {
 		return 0;
 	}
 
-	@Override public void write(OutputStream out) throws IOException {
-		PrintWriter ps = new PrintWriter(out);
+	@Override
+	public void write(OutputStream out) throws IOException {
+		PrintWriter ps = IO.writer(out);
 
 		String name = manifest.getMainAttributes().getValue(Analyzer.BUNDLE_NAME);
 
@@ -145,8 +150,7 @@ public class PomFromManifest extends WriteResource {
 				String xname = email;
 				String organization = null;
 
-				Matcher m = Pattern.compile("([^@]+)@([\\d\\w\\-_\\.]+)\\.([\\d\\w\\-_\\.]+)")
-						.matcher(email);
+				Matcher m = Pattern.compile("([^@]+)@([\\d\\w\\-_\\.]+)\\.([\\d\\w\\-_\\.]+)").matcher(email);
 				if (m.matches()) {
 					xname = m.group(1);
 					organization = m.group(2);
@@ -163,9 +167,8 @@ public class PomFromManifest extends WriteResource {
 		if (licenses != null) {
 			Tag ls = new Tag(project, "licenses");
 
-			Map<String, Map<String, String>> map = Processor.parseHeader(licenses, null);
-			for (Iterator<Map.Entry<String, Map<String, String>>> e = map.entrySet().iterator(); e
-					.hasNext();) {
+			Parameters map = Processor.parseHeader(licenses, null);
+			for (Iterator<Entry<String,Attrs>> e = map.entrySet().iterator(); e.hasNext();) {
 
 				// Bundle-License:
 				// http://www.opensource.org/licenses/apache2.0.php; \
@@ -179,9 +182,9 @@ public class PomFromManifest extends WriteResource {
 				//    <distribution>repo</distribution>
 				//    </license>
 
-				Map.Entry<String, Map<String, String>> entry = e.next();
+				Entry<String,Attrs> entry = e.next();
 				Tag l = new Tag(ls, "license");
-				Map<String, String> values = entry.getValue();
+				Map<String,String> values = entry.getValue();
 				String url = entry.getKey();
 
 				if (values.containsKey("description"))
@@ -206,9 +209,8 @@ public class PomFromManifest extends WriteResource {
 	 * @param tag
 	 * @param object
 	 */
-	private Tag tagFromMap(Tag parent, Map<String, String> values, String string, String tag,
-			String object) {
-		String value = (String) values.get(string);
+	private Tag tagFromMap(Tag parent, Map<String,String> values, String string, String tag, String object) {
+		String value = values.get(string);
 		if (value == null)
 			value = object;
 		if (value == null)
diff --git a/biz.aQute.bndlib/src/aQute/bnd/maven/PomParser.java b/biz.aQute.bndlib/src/aQute/bnd/maven/PomParser.java
index e529141..3eda682 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/maven/PomParser.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/maven/PomParser.java
@@ -8,26 +8,25 @@ import javax.xml.xpath.*;
 
 import org.w3c.dom.*;
 
+import aQute.bnd.osgi.*;
 import aQute.lib.io.*;
-import aQute.lib.osgi.*;
 
 /**
- * Provides a way to parse a maven pom as properties.
- * 
- * This provides most of the maven elements as properties. It also
- * provides pom.scope.[compile|test|runtime|provided|system] properties
- * that can be appended to the build and run path. That is, they are
- * in the correct format for this.
+ * Provides a way to parse a maven pom as properties. This provides most of the
+ * maven elements as properties. It also provides
+ * pom.scope.[compile|test|runtime|provided|system] properties that can be
+ * appended to the build and run path. That is, they are in the correct format
+ * for this.
  */
 public class PomParser extends Processor {
 	static DocumentBuilderFactory	dbf			= DocumentBuilderFactory.newInstance();
 	static XPathFactory				xpathf		= XPathFactory.newInstance();
 	static Set<String>				multiple	= new HashSet<String>();
-	static Set<String>				skip	= new HashSet<String>();
+	static Set<String>				skip		= new HashSet<String>();
 
 	static {
 		dbf.setNamespaceAware(false);
-		
+
 		// Set all elements that need enumeration of their elements
 		// these will not use the name of the subelement but instead
 		// they use an index from 0..n
@@ -46,7 +45,7 @@ public class PomParser extends Processor {
 		skip.add("dependencies");
 		skip.add("reporting");
 		skip.add("extensions");
-		
+
 	}
 
 	public Properties getProperties(File pom) throws Exception {
@@ -58,7 +57,7 @@ public class PomParser extends Processor {
 
 		// Check if there is a parent pom
 		String relativePath = xpath.evaluate("project/parent/relativePath", doc);
-		if (relativePath != null && relativePath.length()!=0) {
+		if (relativePath != null && relativePath.length() != 0) {
 			File parentPom = IO.getFile(pom.getParentFile(), relativePath);
 			if (parentPom.isFile()) {
 				Properties parentProps = getProperties(parentPom);
@@ -71,15 +70,16 @@ public class PomParser extends Processor {
 		Element e = doc.getDocumentElement();
 		traverse("pom", e, p);
 
-		String scopes[] = { "provided", "runtime", "test", "system" };
+		String scopes[] = {
+				"provided", "runtime", "test", "system"
+		};
 		NodeList set = (NodeList) xpath.evaluate("//dependency[not(scope) or scope='compile']", doc,
 				XPathConstants.NODESET);
 		if (set.getLength() != 0)
 			p.put("pom.scope.compile", toBsn(set));
 
 		for (String scope : scopes) {
-			set = (NodeList) xpath.evaluate("//dependency[scope='" + scope + "']", doc,
-					XPathConstants.NODESET);
+			set = (NodeList) xpath.evaluate("//dependency[scope='" + scope + "']", doc, XPathConstants.NODESET);
 			if (set.getLength() != 0)
 				p.put("pom.scope." + scope, toBsn(set));
 		}
@@ -98,9 +98,9 @@ public class PomParser extends Processor {
 			sb.append(xpath.evaluate("groupId", child));
 			sb.append(".");
 			sb.append(xpath.evaluate("artifactId", child));
-			if (version != null && version.trim().length()!=0) {
+			if (version != null && version.trim().length() != 0) {
 				sb.append(";version=");
-				sb.append( Analyzer.cleanupVersion(version));
+				sb.append(Analyzer.cleanupVersion(version));
 			}
 			del = ", ";
 		}
@@ -108,15 +108,17 @@ public class PomParser extends Processor {
 	}
 
 	/**
-	 * The maven POM is quite straightforward, it is basically a structured property file.
+	 * The maven POM is quite straightforward, it is basically a structured
+	 * property file.
+	 * 
 	 * @param name
 	 * @param parent
 	 * @param p
 	 */
 	static void traverse(String name, Node parent, Properties p) {
-		if ( skip.contains(parent.getNodeName()))
+		if (skip.contains(parent.getNodeName()))
 			return;
-		
+
 		NodeList children = parent.getChildNodes();
 		if (multiple.contains(parent.getNodeName())) {
 			int n = 0;
@@ -132,7 +134,7 @@ public class PomParser extends Processor {
 				Node child = children.item(i);
 				if (child instanceof Text) {
 					String value = child.getNodeValue().trim();
-					if (value.length()!=0) {
+					if (value.length() != 0) {
 						p.put(name, value);
 					}
 				} else {
diff --git a/biz.aQute.bndlib/src/aQute/bnd/maven/PomResource.java b/biz.aQute.bndlib/src/aQute/bnd/maven/PomResource.java
index e5e6b8d..b3582a3 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/maven/PomResource.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/maven/PomResource.java
@@ -2,27 +2,32 @@ package aQute.bnd.maven;
 
 import java.io.*;
 import java.util.*;
+import java.util.Map.Entry;
 import java.util.jar.*;
 import java.util.regex.*;
 
-import aQute.lib.osgi.*;
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
+import aQute.lib.io.*;
 import aQute.lib.tag.*;
 
 public class PomResource extends WriteResource {
 	final Manifest				manifest;
-	private Map<String, String>	scm;
+	private Map<String,String>	scm;
 	final static Pattern		NAME_URL	= Pattern.compile("(.*)(http://.*)");
 
 	public PomResource(Manifest manifest) {
 		this.manifest = manifest;
 	}
 
-	@Override public long lastModified() {
+	@Override
+	public long lastModified() {
 		return 0;
 	}
 
-	@Override public void write(OutputStream out) throws IOException {
-		PrintWriter ps = new PrintWriter(out);
+	@Override
+	public void write(OutputStream out) throws IOException {
+		PrintWriter ps = IO.writer(out);
 
 		String name = manifest.getMainAttributes().getValue(Analyzer.BUNDLE_NAME);
 
@@ -77,7 +82,7 @@ public class PomResource extends WriteResource {
 
 		if (scm != null) {
 			Tag scm = new Tag(project, "scm");
-			for (Map.Entry<String, String> e : this.scm.entrySet()) {
+			for (Map.Entry<String,String> e : this.scm.entrySet()) {
 				new Tag(scm, e.getKey()).addContent(e.getValue());
 			}
 		}
@@ -99,9 +104,8 @@ public class PomResource extends WriteResource {
 		if (licenses != null) {
 			Tag ls = new Tag(project, "licenses");
 
-			Map<String, Map<String, String>> map = Processor.parseHeader(licenses, null);
-			for (Iterator<Map.Entry<String, Map<String, String>>> e = map.entrySet().iterator(); e
-					.hasNext();) {
+			Parameters map = Processor.parseHeader(licenses, null);
+			for (Iterator<Entry<String,Attrs>> e = map.entrySet().iterator(); e.hasNext();) {
 
 				// Bundle-License:
 				// http://www.opensource.org/licenses/apache2.0.php; \
@@ -115,9 +119,9 @@ public class PomResource extends WriteResource {
 				//    <distribution>repo</distribution>
 				//    </license>
 
-				Map.Entry<String, Map<String, String>> entry = e.next();
+				Entry<String,Attrs> entry = e.next();
 				Tag l = new Tag(ls, "license");
-				Map<String, String> values = entry.getValue();
+				Map<String,String> values = entry.getValue();
 				String url = entry.getKey();
 
 				if (values.containsKey("description"))
@@ -142,9 +146,8 @@ public class PomResource extends WriteResource {
 	 * @param tag
 	 * @param object
 	 */
-	private Tag tagFromMap(Tag parent, Map<String, String> values, String string, String tag,
-			String object) {
-		String value = (String) values.get(string);
+	private Tag tagFromMap(Tag parent, Map<String,String> values, String string, String tag, String object) {
+		String value = values.get(string);
 		if (value == null)
 			value = object;
 		if (value == null)
@@ -153,7 +156,7 @@ public class PomResource extends WriteResource {
 		return parent;
 	}
 
-	public void setProperties(Map<String, String> scm) {
+	public void setProperties(Map<String,String> scm) {
 		this.scm = scm;
 	}
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/maven/support/CachedPom.java b/biz.aQute.bndlib/src/aQute/bnd/maven/support/CachedPom.java
index 02449fa..d784767 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/maven/support/CachedPom.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/maven/support/CachedPom.java
@@ -4,13 +4,14 @@ import java.io.*;
 import java.net.*;
 
 public class CachedPom extends Pom {
-	final MavenEntry				maven;
+	final MavenEntry	maven;
 
 	CachedPom(MavenEntry mavenEntry, URI repo) throws Exception {
 		super(mavenEntry.maven, mavenEntry.getPomFile(), repo);
 		this.maven = mavenEntry;
 	}
 
+	@Override
 	public File getArtifact() throws Exception {
 		return maven.getArtifact();
 	}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/maven/support/Maven.java b/biz.aQute.bndlib/src/aQute/bnd/maven/support/Maven.java
index 2124a05..416f255 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/maven/support/Maven.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/maven/support/Maven.java
@@ -12,25 +12,27 @@ import java.util.regex.*;
  */
 public class Maven {
 	final File						userHome	= new File(System.getProperty("user.home"));
-	final Map<String, MavenEntry>	entries		= new ConcurrentHashMap<String, MavenEntry>();
-	final static String[]			ALGORITHMS	= { "md5", "sha1" };
+	final Map<String,MavenEntry>	entries		= new ConcurrentHashMap<String,MavenEntry>();
+	final static String[]			ALGORITHMS	= {
+			"md5", "sha1"
+												};
 	boolean							usecache	= false;
 	final Executor					executor;
 	File							m2			= new File(userHome, ".m2");
 	File							repository	= new File(m2, "repository");
 
 	public Maven(Executor executor) {
-		if ( executor == null)
+		if (executor == null)
 			this.executor = Executors.newCachedThreadPool();
 		else
 			this.executor = executor;
 	}
-	
-	//http://repo1.maven.org/maven2/junit/junit/maven-metadata.xml
-	
-	static Pattern MAVEN_RANGE = Pattern.compile("(\\[|\\()(.+)(,(.+))(\\]|\\))");
-	public CachedPom getPom(String groupId, String artifactId, String version, URI... extra)
-			throws Exception {		
+
+	// http://repo1.maven.org/maven2/junit/junit/maven-metadata.xml
+
+	static Pattern	MAVEN_RANGE	= Pattern.compile("(\\[|\\()(.+)(,(.+))(\\]|\\))");
+
+	public CachedPom getPom(String groupId, String artifactId, String version, URI... extra) throws Exception {
 		MavenEntry entry = getEntry(groupId, artifactId, version);
 		return entry.getPom(extra);
 	}
@@ -59,8 +61,7 @@ public class Maven {
 	}
 
 	private String path(String groupId, String artifactId, String version) {
-		return groupId.replace('.', '/') + '/' + artifactId + '/' + version + "/" + artifactId
-				+ "-" + version;
+		return groupId.replace('.', '/') + '/' + artifactId + '/' + version + "/" + artifactId + "-" + version;
 	}
 
 	public void schedule(Runnable runnable) {
@@ -82,7 +83,7 @@ public class Maven {
 
 	public void setM2(File dir) {
 		this.m2 = dir;
-		this.repository = new File(dir,"repository");
+		this.repository = new File(dir, "repository");
 	}
 
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/maven/support/MavenEntry.java b/biz.aQute.bndlib/src/aQute/bnd/maven/support/MavenEntry.java
index f23ba82..4e153c3 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/maven/support/MavenEntry.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/maven/support/MavenEntry.java
@@ -13,7 +13,6 @@ import aQute.libg.filelock.*;
 /**
  * An entry (a group/artifact) in the maven cache in the .m2/repository
  * directory. It provides methods to get the pom and the artifact.
- * 
  */
 public class MavenEntry implements Closeable {
 	final Maven					maven;
@@ -21,7 +20,7 @@ public class MavenEntry implements Closeable {
 	final File					dir;
 	final String				path;
 	final DirectoryLock			lock;
-	final Map<URI, CachedPom>	poms	= new HashMap<URI, CachedPom>();
+	final Map<URI,CachedPom>	poms	= new HashMap<URI,CachedPom>();
 	final File					pomFile;
 	final File					artifactFile;
 	final String				pomPath;
@@ -29,7 +28,7 @@ public class MavenEntry implements Closeable {
 	Properties					properties;
 	private boolean				propertiesChanged;
 	FutureTask<File>			artifact;
-	private String				artifactPath;
+	String						artifactPath;
 
 	/**
 	 * Constructor.
@@ -44,7 +43,9 @@ public class MavenEntry implements Closeable {
 		this.pomPath = path + ".pom";
 		this.artifactPath = path + ".jar";
 		this.dir = IO.getFile(maven.repository, path).getParentFile();
-		this.dir.mkdirs();
+		if (!this.dir.exists() && !this.dir.mkdirs()) {
+			throw new ExceptionInInitializerError("Could not create directory " + this.dir);
+		}
 		this.pomFile = new File(maven.repository, pomPath);
 		this.artifactFile = new File(maven.repository, artifactPath);
 		this.propertiesFile = new File(dir, "bnd.properties");
@@ -57,7 +58,6 @@ public class MavenEntry implements Closeable {
 	 * @param urls
 	 *            The allowed URLs
 	 * @return a CachedPom for this maven entry
-	 * 
 	 * @throws Exception
 	 *             If something goes haywire
 	 */
@@ -100,7 +100,9 @@ public class MavenEntry implements Closeable {
 				// the file.
 
 			} else {
-				dir.mkdirs();
+				if (!dir.exists() && !dir.mkdirs()) {
+					throw new IOException("Could not create directory " + dir);
+				}
 				// We really do not have the file
 				// so we have to find out who has it.
 				for (final URI url : urls) {
@@ -124,7 +126,8 @@ public class MavenEntry implements Closeable {
 				}
 			}
 			return null;
-		} finally {
+		}
+		finally {
 			saveProperties();
 			// lock.release();
 		}
@@ -140,15 +143,16 @@ public class MavenEntry implements Closeable {
 	 * @return
 	 * @throws MalformedURLException
 	 */
-	private boolean download(URI repo, String path) throws MalformedURLException {
+	boolean download(URI repo, String path) throws MalformedURLException {
 		try {
 			URL url = toURL(repo, path);
-			System.out.println("Downloading "  + repo + " path " + path + " url " + url);
+			System.err.println("Downloading " + repo + " path " + path + " url " + url);
 			File file = new File(root, path);
 			IO.copy(url.openStream(), file);
-			System.out.println("Downloaded "  + url);
+			System.err.println("Downloaded " + url);
 			return true;
-		} catch (Exception e) {
+		}
+		catch (Exception e) {
 			System.err.println("debug: " + e);
 			return false;
 		}
@@ -162,7 +166,6 @@ public class MavenEntry implements Closeable {
 	 * @param path
 	 *            The path in the directory + url
 	 * @return a URL that points to the file in the repo
-	 * 
 	 * @throws MalformedURLException
 	 */
 	URL toURL(URI base, String path) throws MalformedURLException {
@@ -181,8 +184,7 @@ public class MavenEntry implements Closeable {
 	 * @return true if valid
 	 */
 	private boolean isValid() {
-		return pomFile.isFile() && pomFile.length() > 100 && artifactFile.isFile()
-				&& artifactFile.length() > 100;
+		return pomFile.isFile() && pomFile.length() > 100 && artifactFile.isFile() && artifactFile.length() > 100;
 	}
 
 	/**
@@ -207,12 +209,17 @@ public class MavenEntry implements Closeable {
 			properties = new Properties();
 			File props = new File(dir, "bnd.properties");
 			if (props.exists()) {
+				FileInputStream in = null;
 				try {
-					FileInputStream in = new FileInputStream(props);
+					in = new FileInputStream(props);
 					properties.load(in);
-				} catch (Exception e) {
+				}
+				catch (Exception e) {
 					// we ignore for now, will handle it on safe
 				}
+				finally {
+					IO.close(in);
+				}
 			}
 		}
 		return properties;
@@ -235,7 +242,8 @@ public class MavenEntry implements Closeable {
 			FileOutputStream fout = new FileOutputStream(propertiesFile);
 			try {
 				properties.store(fout, "");
-			} finally {
+			}
+			finally {
 				properties = null;
 				propertiesChanged = false;
 				fout.close();
@@ -295,11 +303,13 @@ public class MavenEntry implements Closeable {
 			File digestFile = new File(root, digestPath);
 			final MessageDigest md = MessageDigest.getInstance(algorithm);
 			IO.copy(actualFile, new OutputStream() {
-				@Override public void write(int c) throws IOException {
+				@Override
+				public void write(int c) throws IOException {
 					md.update((byte) c);
 				}
 
-				@Override public void write(byte[] buffer, int offset, int length) {
+				@Override
+				public void write(byte[] buffer, int offset, int length) {
 					md.update(buffer, offset, length);
 				}
 			});
@@ -307,16 +317,16 @@ public class MavenEntry implements Closeable {
 			String source = IO.collect(digestFile).toUpperCase();
 			String hex = Hex.toHexString(digest).toUpperCase();
 			if (source.startsWith(hex)) {
-				System.out.println("Verified ok " + actualFile + " digest " + algorithm);
+				System.err.println("Verified ok " + actualFile + " digest " + algorithm);
 				return true;
 			}
 		}
-		System.out.println("Failed to verify " + actualFile + " for digest " + algorithm);
+		System.err.println("Failed to verify " + actualFile + " for digest " + algorithm);
 		return false;
 	}
 
 	public File getArtifact() throws Exception {
-		if (artifact == null )
+		if (artifact == null)
 			return artifactFile;
 		return artifact.get();
 	}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/maven/support/MavenRemoteRepository.java b/biz.aQute.bndlib/src/aQute/bnd/maven/support/MavenRemoteRepository.java
index bbe2411..345d3eb 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/maven/support/MavenRemoteRepository.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/maven/support/MavenRemoteRepository.java
@@ -5,10 +5,9 @@ import java.net.*;
 import java.util.*;
 
 import aQute.bnd.service.*;
+import aQute.bnd.version.*;
 import aQute.lib.io.*;
-import aQute.lib.osgi.*;
-import aQute.libg.reporter.*;
-import aQute.libg.version.*;
+import aQute.service.reporter.*;
 
 public class MavenRemoteRepository implements RepositoryPlugin, RegistryPlugin, Plugin {
 	Reporter	reporter;
@@ -16,28 +15,19 @@ public class MavenRemoteRepository implements RepositoryPlugin, RegistryPlugin,
 	Registry	registry;
 	Maven		maven;
 
-	public File[] get(String bsn, String range) throws Exception {
-		File f = get(bsn, range, Strategy.HIGHEST, null);
-		if (f == null)
-			return null;
-
-		return new File[] { f };
-	}
-
-	public File get(String bsn, String version, Strategy strategy, Map<String, String> properties)
-			throws Exception {
+	public File get(String bsn, String version, Strategy strategy, Map<String,String> properties) throws Exception {
 		String groupId = null;
-		
+
 		if (properties != null)
 			groupId = properties.get("groupId");
-		
+
 		if (groupId == null) {
 			int n = bsn.indexOf('+');
-			if ( n < 0)
+			if (n < 0)
 				return null;
-			
-			groupId = bsn.substring(0,n);
-			bsn = bsn.substring(n+1);
+
+			groupId = bsn.substring(0, n);
+			bsn = bsn.substring(n + 1);
 		}
 
 		String artifactId = bsn;
@@ -59,15 +49,16 @@ public class MavenRemoteRepository implements RepositoryPlugin, RegistryPlugin,
 		try {
 			action = Pom.Scope.valueOf(value);
 			return pom.getLibrary(action, repositories);
-		} catch (Exception e) {
+		}
+		catch (Exception e) {
 			return pom.getArtifact();
 		}
 	}
 
 	public Maven getMaven() {
-		if ( maven != null)
+		if (maven != null)
 			return maven;
-		
+
 		maven = registry.getPlugin(Maven.class);
 		return maven;
 	}
@@ -76,7 +67,7 @@ public class MavenRemoteRepository implements RepositoryPlugin, RegistryPlugin,
 		return false;
 	}
 
-	public File put(Jar jar) throws Exception {
+	public PutResult put(InputStream stream, PutOptions options) throws Exception {
 		throw new UnsupportedOperationException("cannot do put");
 	}
 
@@ -84,7 +75,7 @@ public class MavenRemoteRepository implements RepositoryPlugin, RegistryPlugin,
 		throw new UnsupportedOperationException("cannot do list");
 	}
 
-	public List<Version> versions(String bsn) throws Exception {
+	public SortedSet<Version> versions(String bsn) throws Exception {
 		throw new UnsupportedOperationException("cannot do versions");
 	}
 
@@ -96,7 +87,7 @@ public class MavenRemoteRepository implements RepositoryPlugin, RegistryPlugin,
 		repositories = urls;
 	}
 
-	public void setProperties(Map<String, String> map) {
+	public void setProperties(Map<String,String> map) {
 		String repoString = map.get("repositories");
 		if (repoString != null) {
 			String[] repos = repoString.split("\\s*,\\s*");
@@ -105,10 +96,11 @@ public class MavenRemoteRepository implements RepositoryPlugin, RegistryPlugin,
 			for (String repo : repos) {
 				try {
 					URI uri = new URI(repo);
-					if ( !uri.isAbsolute())
-						uri = IO.getFile( new File(""),repo).toURI();
+					if (!uri.isAbsolute())
+						uri = IO.getFile(new File(""), repo).toURI();
 					repositories[n++] = uri;
-				} catch (Exception e) {
+				}
+				catch (Exception e) {
 					if (reporter != null)
 						reporter.error("Invalid repository %s for maven plugin, %s", repo, e);
 				}
@@ -127,4 +119,28 @@ public class MavenRemoteRepository implements RepositoryPlugin, RegistryPlugin,
 	public void setMaven(Maven maven) {
 		this.maven = maven;
 	}
+
+	public String getLocation() {
+		if (repositories == null || repositories.length == 0)
+			return "maven central";
+
+		return Arrays.toString(repositories);
+	}
+
+	public File get(String bsn, Version version, Map<String,String> properties, DownloadListener ... listeners) throws Exception {
+		File f= get(bsn, version.toString(), Strategy.EXACT, properties);
+		if ( f == null)
+			return null;
+		
+		for (DownloadListener l : listeners) {
+			try {
+				l.success(f);
+			}
+			catch (Exception e) {
+				reporter.exception(e, "Download listener for %s", f);
+			}
+		}
+		return f;
+	}
+
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/maven/support/Pom.java b/biz.aQute.bndlib/src/aQute/bnd/maven/support/Pom.java
index 2b7ab46..a778d8b 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/maven/support/Pom.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/maven/support/Pom.java
@@ -9,6 +9,8 @@ import javax.xml.xpath.*;
 
 import org.w3c.dom.*;
 
+import aQute.lib.io.*;
+
 public abstract class Pom {
 	static DocumentBuilderFactory	dbf	= DocumentBuilderFactory.newInstance();
 	static XPathFactory				xpf	= XPathFactory.newInstance();
@@ -16,20 +18,20 @@ public abstract class Pom {
 	static {
 		dbf.setNamespaceAware(false);
 	}
-	
+
 	public enum Scope {
 		compile, runtime, system, import_, provided, test, ;
-		
-		private boolean includes(Scope other) {
-			if (other == this) return true;
-			switch (this) {
-			case compile:
-				return other == provided || other == test;
-			default:
-				return false;
-			}
-		}
-	};
+
+		// private boolean includes(Scope other) {
+		// if (other == this) return true;
+		// switch (this) {
+		// case compile:
+		// return other == provided || other == test;
+		// default:
+		// return false;
+		// }
+		// }
+	}
 
 	final Maven			maven;
 	final URI			home;
@@ -38,9 +40,8 @@ public abstract class Pom {
 	String				artifactId;
 	String				version;
 	List<Dependency>	dependencies	= new ArrayList<Dependency>();
-	Exception			exception;
 	File				pomFile;
-	String				description="";
+	String				description		= "";
 	String				name;
 
 	public String getDescription() {
@@ -87,6 +88,7 @@ public abstract class Pom {
 		public Pom getPom() throws Exception {
 			return maven.getPom(groupId, artifactId, version);
 		}
+
 		@Override
 		public String toString() {
 			StringBuilder builder = new StringBuilder();
@@ -117,7 +119,7 @@ public abstract class Pom {
 
 	void parse() throws Exception {
 		DocumentBuilder db = dbf.newDocumentBuilder();
-		System.out.println("Parsing " + pomFile.getAbsolutePath());
+		System.err.println("Parsing " + pomFile.getAbsolutePath());
 		Document doc = db.parse(pomFile);
 		XPath xp = xpf.newXPath();
 		parse(doc, xp);
@@ -128,16 +130,15 @@ public abstract class Pom {
 		this.artifactId = replace(xp.evaluate("project/artifactId", doc).trim(), this.artifactId);
 		this.groupId = replace(xp.evaluate("project/groupId", doc).trim(), this.groupId);
 		this.version = replace(xp.evaluate("project/version", doc).trim(), this.version);
-		
+
 		String nextDescription = xp.evaluate("project/description", doc).trim();
-		if ( this.description.length() != 0 && nextDescription.length() != 0)
+		if (this.description.length() != 0 && nextDescription.length() != 0)
 			this.description += "\n";
 		this.description += replace(nextDescription);
-		
+
 		this.name = replace(xp.evaluate("project/name", doc).trim(), this.name);
 
-		NodeList list = (NodeList) xp.evaluate("project/dependencies/dependency", doc,
-				XPathConstants.NODESET);
+		NodeList list = (NodeList) xp.evaluate("project/dependencies/dependency", doc, XPathConstants.NODESET);
 		for (int i = 0; i < list.getLength(); i++) {
 			Node node = list.item(i);
 			Dependency dep = new Dependency();
@@ -156,8 +157,7 @@ public abstract class Pom {
 			dep.version = replace(xp.evaluate("version", node).trim());
 			dependencies.add(dep);
 
-			NodeList exclusions = (NodeList) xp
-					.evaluate("exclusions", node, XPathConstants.NODESET);
+			NodeList exclusions = (NodeList) xp.evaluate("exclusions", node, XPathConstants.NODESET);
 			for (int e = 0; e < exclusions.getLength(); e++) {
 				Node exc = exclusions.item(e);
 				String exclGroupId = xp.evaluate("groupId", exc).trim();
@@ -169,9 +169,9 @@ public abstract class Pom {
 	}
 
 	private String replace(String key, String dflt) {
-		if ( key == null || key.length() == 0)
+		if (key == null || key.length() == 0)
 			return dflt;
-		
+
 		return replace(key);
 	}
 
@@ -184,7 +184,7 @@ public abstract class Pom {
 	}
 
 	public String getVersion() throws Exception {
-		if ( version == null)
+		if (version == null)
 			return "<not set>";
 		return replace(version);
 	}
@@ -193,7 +193,7 @@ public abstract class Pom {
 		return dependencies;
 	}
 
-	class Rover {
+	static class Rover {
 
 		public Rover(Rover rover, Dependency d) {
 			this.previous = rover;
@@ -204,8 +204,7 @@ public abstract class Pom {
 		final Dependency	dependency;
 
 		public boolean excludes(String name) {
-			return dependency.exclusions.contains(name) && previous != null
-					&& previous.excludes(name);
+			return dependency.exclusions.contains(name) && previous != null && previous.excludes(name);
 		}
 	}
 
@@ -228,7 +227,7 @@ public abstract class Pom {
 
 			if (rover.excludes(name) || dep.optional)
 				continue;
-			
+
 			if (dep.scope == scope && !dep.optional) {
 				try {
 					Pom sub = maven.getPom(groupId, artifactId, version, urls);
@@ -239,35 +238,35 @@ public abstract class Pom {
 								queue.add(new Rover(rover, subd));
 							}
 						}
-					} else
-						if (rover.previous != null)
-							System.out.println("Cannot find " + dep + " from "
-									+ rover.previous.dependency);
-						else
-							System.out.println("Cannot find " + dep + " from top");
-				} catch (Exception e) {
+					} else if (rover.previous != null)
+						System.err.println("Cannot find " + dep + " from " + rover.previous.dependency);
+					else
+						System.err.println("Cannot find " + dep + " from top");
+				}
+				catch (Exception e) {
 					if (rover.previous != null)
-						System.out.println("Cannot find " + dep + " from "
-								+ rover.previous.dependency);
+						System.err.println("Cannot find " + dep + " from " + rover.previous.dependency);
 					else
-						System.out.println("Cannot find " + dep + " from top");
-
-//			boolean include = false;
-//			if (dep.scope == Scope.compile) {
-//				include = true;
-//			} else if (dep.scope == Scope.test) {
-//				include = rover.previous == null && (action == Action.compile || action == Action.test);
-//			} else if (dep.scope == Scope.runtime) {
-//				include = action == Action.run;
-//			}
-//			if (include) {
-//				Pom sub = maven.getPom(groupId, artifactId, version, urls);
-//				if (!result.contains(sub)) {
-//					result.add(sub);
-//					for (Dependency subd : sub.dependencies) {
-//						queue.add(new Rover(rover, subd));
-//					}
-					
+						System.err.println("Cannot find " + dep + " from top");
+
+					// boolean include = false;
+					// if (dep.scope == Scope.compile) {
+					// include = true;
+					// } else if (dep.scope == Scope.test) {
+					// include = rover.previous == null && (action ==
+					// Action.compile || action == Action.test);
+					// } else if (dep.scope == Scope.runtime) {
+					// include = action == Action.run;
+					// }
+					// if (include) {
+					// Pom sub = maven.getPom(groupId, artifactId, version,
+					// urls);
+					// if (!result.contains(sub)) {
+					// result.add(sub);
+					// for (Dependency subd : sub.dependencies) {
+					// queue.add(new Rover(rover, subd));
+					// }
+
 				}
 			}
 		}
@@ -275,13 +274,12 @@ public abstract class Pom {
 	}
 
 	protected String replace(String in) {
-		System.out.println("replace: " + in);
+		System.err.println("replace: " + in);
 		if (in == null)
 			return "null";
 
 		in = in.trim();
-		if ("${pom.version}".equals(in) || "${version}".equals(in)
-				|| "${project.version}".equals(in))
+		if ("${pom.version}".equals(in) || "${version}".equals(in) || "${project.version}".equals(in))
 			return version;
 
 		if ("${basedir}".equals(in))
@@ -298,6 +296,7 @@ public abstract class Pom {
 		return in;
 	}
 
+	@Override
 	public String toString() {
 		return groupId + "+" + artifactId + "-" + version;
 	}
@@ -311,13 +310,14 @@ public abstract class Pom {
 
 		file.delete();
 
-		Writer writer = new FileWriter(file);
-		doEntry(writer, this);
+		Writer writer = IO.writer(file);
 		try {
+			doEntry(writer, this);
 			for (Pom dep : getDependencies(action, repositories)) {
 				doEntry(writer, dep);
 			}
-		} finally {
+		}
+		finally {
 			writer.close();
 		}
 		return file;
diff --git a/biz.aQute.bndlib/src/aQute/bnd/maven/support/ProjectPom.java b/biz.aQute.bndlib/src/aQute/bnd/maven/support/ProjectPom.java
index 8187954..eedff8c 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/maven/support/ProjectPom.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/maven/support/ProjectPom.java
@@ -13,20 +13,21 @@ import aQute.lib.io.*;
 
 public class ProjectPom extends Pom {
 
-	final List<URI>	repositories	= new ArrayList<URI>();
+	final List<URI>		repositories	= new ArrayList<URI>();
 	final Properties	properties		= new Properties();
-	String 		packaging;
-	String 		url;
-	
+	String				packaging;
+	String				url;
+
 	ProjectPom(Maven maven, File pomFile) throws Exception {
 		super(maven, pomFile, pomFile.toURI());
 	}
 
-	@Override protected void parse(Document doc, XPath xp) throws Exception {
+	@Override
+	protected void parse(Document doc, XPath xp) throws Exception {
 
 		packaging = xp.evaluate("project/packaging", doc);
 		url = xp.evaluate("project/url", doc);
-		
+
 		Node parent = (Node) xp.evaluate("project/parent", doc, XPathConstants.NODE);
 		if (parent != null && parent.hasChildNodes()) {
 			File parentFile = IO.getFile(getPomFile().getParentFile(), "../pom.xml");
@@ -35,20 +36,20 @@ public class ProjectPom extends Pom {
 			String parentArtifactId = xp.evaluate("artifactId", parent).trim();
 			String parentVersion = xp.evaluate("version", parent).trim();
 			String parentPath = xp.evaluate("relativePath", parent).trim();
-			if (parentPath != null && parentPath.length()!=0) {
+			if (parentPath != null && parentPath.length() != 0) {
 				parentFile = IO.getFile(getPomFile().getParentFile(), parentPath);
 			}
 			if (parentFile.isFile()) {
 				ProjectPom parentPom = new ProjectPom(maven, parentFile);
 				parentPom.parse();
 				dependencies.addAll(parentPom.dependencies);
-				for ( Enumeration<?> e = parentPom.properties.propertyNames(); e.hasMoreElements(); ) {
+				for (Enumeration< ? > e = parentPom.properties.propertyNames(); e.hasMoreElements();) {
 					String key = (String) e.nextElement();
-					if ( ! properties.contains(key))
+					if (!properties.contains(key))
 						properties.put(key, parentPom.properties.get(key));
 				}
 				repositories.addAll(parentPom.repositories);
-				
+
 				setNames(parentPom);
 			} else {
 				// This seems to be a bit bizarre, extending an external pom?
@@ -58,42 +59,40 @@ public class ProjectPom extends Pom {
 			}
 		}
 
-		NodeList propNodes = (NodeList) xp.evaluate("project/properties/*", doc,
-				XPathConstants.NODESET);
+		NodeList propNodes = (NodeList) xp.evaluate("project/properties/*", doc, XPathConstants.NODESET);
 		for (int i = 0; i < propNodes.getLength(); i++) {
 			Node node = propNodes.item(i);
 			String key = node.getNodeName();
 			String value = node.getTextContent();
-			if ( key == null || key.length()==0)
+			if (key == null || key.length() == 0)
 				throw new IllegalArgumentException("Pom has an empty or null key");
-			if ( value == null || value.length()==0)
+			if (value == null || value.length() == 0)
 				throw new IllegalArgumentException("Pom has an empty or null value for property " + key);
 			properties.setProperty(key, value.trim());
 		}
 
-		NodeList repos = (NodeList) xp.evaluate("project/repositories/repository/url", doc,
-				XPathConstants.NODESET);
+		NodeList repos = (NodeList) xp.evaluate("project/repositories/repository/url", doc, XPathConstants.NODESET);
 		for (int i = 0; i < repos.getLength(); i++) {
 			Node node = repos.item(i);
 			String URIString = node.getTextContent().trim();
 			URI uri = new URI(URIString);
-			if ( uri.getScheme() ==null )
-				uri = IO.getFile(pomFile.getParentFile(),URIString).toURI();
+			if (uri.getScheme() == null)
+				uri = IO.getFile(pomFile.getParentFile(), URIString).toURI();
 			repositories.add(uri);
 		}
 
 		super.parse(doc, xp);
 	}
 
-//	private void print(Node node, String indent) {
-//		System.out.print(indent);
-//		System.out.println(node.getNodeName());
-//		Node rover = node.getFirstChild();
-//		while ( rover != null) {
-//			print( rover, indent+" ");
-//			rover = rover.getNextSibling();
-//		}
-//	}
+	// private void print(Node node, String indent) {
+	// System.err.print(indent);
+	// System.err.println(node.getNodeName());
+	// Node rover = node.getFirstChild();
+	// while ( rover != null) {
+	// print( rover, indent+" ");
+	// rover = rover.getNextSibling();
+	// }
+	// }
 
 	/**
 	 * @param parentArtifactId
@@ -102,20 +101,20 @@ public class ProjectPom extends Pom {
 	 * @throws Exception
 	 */
 	private void setNames(Pom pom) throws Exception {
-		if (artifactId == null || artifactId.length()==0)
+		if (artifactId == null || artifactId.length() == 0)
 			artifactId = pom.getArtifactId();
-		if (groupId == null || groupId.length()==0)
+		if (groupId == null || groupId.length() == 0)
 			groupId = pom.getGroupId();
-		if (version == null || version.length()==0)
+		if (version == null || version.length() == 0)
 			version = pom.getVersion();
-		if ( description == null )
+		if (description == null)
 			description = pom.getDescription();
 		else
 			description = pom.getDescription() + "\n" + description;
-	
+
 	}
 
-	class Rover {
+	static class Rover {
 
 		public Rover(Rover rover, Dependency d) {
 			this.previous = rover;
@@ -126,8 +125,7 @@ public class ProjectPom extends Pom {
 		final Dependency	dependency;
 
 		public boolean excludes(String name) {
-			return dependency.exclusions.contains(name) && previous != null
-					&& previous.excludes(name);
+			return dependency.exclusions.contains(name) && previous != null && previous.excludes(name);
 		}
 	}
 
@@ -138,28 +136,30 @@ public class ProjectPom extends Pom {
 	// Match any macros
 	final static Pattern	MACRO	= Pattern.compile("(\\$\\{\\s*([^}\\s]+)\\s*\\})");
 
+	@Override
 	protected String replace(String in) {
-		System.out.println("Replce: " + in);
-		if ( in == null) {
-			System.out.println("null??");
+		System.err.println("Replce: " + in);
+		if (in == null) {
+			System.err.println("null??");
+			in = "<<???>>";
 		}
 		Matcher matcher = MACRO.matcher(in);
 		int last = 0;
 		StringBuilder sb = new StringBuilder();
 		while (matcher.find()) {
 			int n = matcher.start();
-			sb.append( in, last, n);
+			sb.append(in, last, n);
 			String replacement = get(matcher.group(2));
-			if ( replacement == null )
-				sb.append( matcher.group(1));
+			if (replacement == null)
+				sb.append(matcher.group(1));
 			else
-				sb.append( replacement );
+				sb.append(replacement);
 			last = matcher.end();
 		}
-		if ( last == 0)
+		if (last == 0)
 			return in;
-		
-		sb.append( in, last, in.length());
+
+		sb.append(in, last, in.length());
 		return sb.toString();
 	}
 
@@ -170,14 +170,14 @@ public class ProjectPom extends Pom {
 			return groupId;
 		if (key.equals("pom.version"))
 			return version;
-		
+
 		if (key.equals("pom.name"))
 			return name;
-		
+
 		String prop = properties.getProperty(key);
-		if ( prop != null )
+		if (prop != null)
 			return prop;
-		
+
 		return System.getProperty(key);
 	}
 
@@ -198,7 +198,8 @@ public class ProjectPom extends Pom {
 		return replace(s);
 	}
 
-	@Override public File getArtifact() throws Exception {
+	@Override
+	public File getArtifact() throws Exception {
 		return null;
 	}
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/maven/support/packageinfo b/biz.aQute.bndlib/src/aQute/bnd/maven/support/packageinfo
new file mode 100644
index 0000000..a3d9bcc
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/maven/support/packageinfo
@@ -0,0 +1 @@
+version 2.0
diff --git a/biz.aQute.bndlib/src/aQute/bnd/obr/OBRFragment.java b/biz.aQute.bndlib/src/aQute/bnd/obr/OBRFragment.java
new file mode 100644
index 0000000..1af3518
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/obr/OBRFragment.java
@@ -0,0 +1,300 @@
+package aQute.bnd.obr;
+
+import java.io.*;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.jar.*;
+import java.util.regex.*;
+
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.*;
+import org.osgi.namespace.service.*;
+import org.osgi.resource.*;
+import org.osgi.service.repository.*;
+
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.resource.*;
+import aQute.bnd.version.*;
+import aQute.libg.cryptography.*;
+import aQute.libg.map.*;
+import aQute.service.reporter.*;
+
+public class OBRFragment {
+
+	// The mime-type of an OSGi bundle
+	static final String	MIME_TYPE_OSGI_BUNDLE	= "application/vnd.osgi.bundle";
+static Pattern EE_PATTERN = Pattern.compile("[^.]-([\\d]+(?:\\.[\\d]+(?:\\.[\\d]+(?:\\.)?)?)?)");
+
+	@SuppressWarnings("deprecation")
+	public static Reporter parse(Jar jar, ResourceBuilder resource) throws Exception {
+		Manifest m = jar.getManifest();
+		if (m == null)
+			return null;
+
+		Domain d = Domain.domain(m);
+		d.setTranslation(jar);
+		Entry<String,Attrs> bundleSymbolicName = d.getBundleSymbolicName();
+
+		if (bundleSymbolicName == null)
+			return null;
+
+		boolean singleton = "true".equals(bundleSymbolicName.getValue().get(Constants.SINGLETON_DIRECTIVE + ":"));
+		boolean isFragment = d.get(Constants.FRAGMENT_HOST) != null;
+		Version version = d.getBundleVersion() == null ? Version.emptyVersion : new Version(d.getBundleVersion());
+		
+		CapReqBuilder identity = new CapReqBuilder(IdentityNamespace.IDENTITY_NAMESPACE);
+		identity.addAttribute(IdentityNamespace.IDENTITY_NAMESPACE, bundleSymbolicName.getKey());
+		identity.addAttribute(IdentityNamespace.CAPABILITY_COPYRIGHT_ATTRIBUTE, d.translate(Constants.BUNDLE_COPYRIGHT));
+		identity.addAttribute(IdentityNamespace.CAPABILITY_DESCRIPTION_ATTRIBUTE,
+				d.translate(Constants.BUNDLE_DESCRIPTION));
+		identity.addAttribute(IdentityNamespace.CAPABILITY_DOCUMENTATION_ATTRIBUTE,
+				d.translate(Constants.BUNDLE_DOCURL));
+		identity.addAttribute(IdentityNamespace.CAPABILITY_LICENSE_ATTRIBUTE, d.translate("Bundle-License"));
+		if (singleton)
+			identity.addAttribute(IdentityNamespace.CAPABILITY_SINGLETON_DIRECTIVE, "true");
+		identity.addAttribute(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE,
+				isFragment ? IdentityNamespace.TYPE_FRAGMENT
+						: IdentityNamespace.TYPE_BUNDLE);
+		identity.addAttribute(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, new Version(d.getBundleVersion()));
+
+		resource.addCapability(identity);
+
+		
+		if ( isFragment ) {
+			
+			//
+			// Fragment-Host
+			//
+
+			Entry<String,Attrs> fragmentHost = d.getFragmentHost();
+			CapReqBuilder fragment = new CapReqBuilder(HostNamespace.HOST_NAMESPACE);
+			String v = fragmentHost.getValue().get("version");
+			if ( v == null)
+				v = "0";
+			Version fragmentVersion = new Version(v);
+			String filter = filter(PackageNamespace.PACKAGE_NAMESPACE, fragmentHost.getKey(), fragmentHost.getValue());
+			fragment.addDirective(HostNamespace.REQUIREMENT_FILTER_DIRECTIVE, filter.toString());
+			resource.addRequirement(fragment);
+		} else {
+			
+			//
+			// Bundle-SymbolicName
+			//
+			
+			CapReqBuilder bundle = new CapReqBuilder(BundleNamespace.BUNDLE_NAMESPACE);
+			CapReqBuilder host = new CapReqBuilder(HostNamespace.HOST_NAMESPACE);
+			
+			bundle.addAttribute("version", version);
+			host.addAttribute("version", version);
+			
+			for (Entry<String,String> e : bundleSymbolicName.getValue().entrySet()) {
+				String key = e.getKey();
+				if (key.endsWith(":")) {
+					String directive = key.substring(0, key.length() - 1);
+					if (Constants.FRAGMENT_ATTACHMENT_DIRECTIVE.equalsIgnoreCase(directive)) {
+						if (Constants.FRAGMENT_ATTACHMENT_NEVER.equalsIgnoreCase(e.getValue()))
+							host = null;
+						
+					} else if (!Constants.SINGLETON_DIRECTIVE.equalsIgnoreCase(directive)) {
+						bundle.addDirective(directive, e.getValue());
+					}
+					if ( host != null )
+						host.addDirective(directive, e.getValue());
+					bundle.addDirective(directive, e.getValue());					
+				} else {
+					if ( host != null )
+						host.addAttribute(key, e.getValue());
+					bundle.addAttribute(key, e.getValue());
+				}
+			}
+			if ( host != null)
+				resource.addCapability(host);
+			resource.addCapability(bundle);
+		}		
+		
+		//
+		// Export-Package
+		//
+		
+		Parameters exports = d.getExportPackage();		
+		for (Entry<String,Attrs> entry : exports.entrySet()) {
+			CapReqBuilder exported = new CapReqBuilder(PackageNamespace.PACKAGE_NAMESPACE);
+
+			String pkgName = Processor.removeDuplicateMarker(entry.getKey());
+			exported.addAttribute(PackageNamespace.PACKAGE_NAMESPACE, pkgName);
+
+			String versionStr = entry.getValue().get(Constants.VERSION_ATTRIBUTE);
+			Version v = Version.parseVersion(entry.getValue().get("version"));
+			
+			exported.addAttribute(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE, version);
+
+			for (Entry<String,String> attribEntry : entry.getValue().entrySet()) {
+				String key = attribEntry.getKey();
+				if (key.endsWith(":")) {
+					String directive = key.substring(0, key.length()-1);
+					exported.addDirective(directive, attribEntry.getValue());
+				} else {
+					if ( key.equals("specification-version") || key.equals("version"))
+						exported.addAttribute("version",  Version.parseVersion(attribEntry.getValue()));
+					else
+						exported.addAttribute(key, attribEntry.getValue());
+				}
+			}
+
+			exported.addAttribute(PackageNamespace.CAPABILITY_BUNDLE_SYMBOLICNAME_ATTRIBUTE, bundleSymbolicName.getKey());
+			exported.addAttribute(PackageNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE, version);
+
+			resource.addCapability(exported);
+		}
+
+		//
+		// Import-Package
+		//
+		
+		Parameters imports = d.getImportPackage();		
+		for (Entry<String,Attrs> entry : imports.entrySet()) {
+			CapReqBuilder imported = new CapReqBuilder(PackageNamespace.PACKAGE_NAMESPACE);
+			String name = Processor.removeDuplicateMarker(entry.getKey());
+			String filter = filter(PackageNamespace.PACKAGE_NAMESPACE, Processor.removeDuplicateMarker(entry.getKey()), entry.getValue());
+			imported.addDirective(Namespace.REQUIREMENT_FILTER_DIRECTIVE, filter);			
+			resource.addRequirement(imported);
+		}
+
+		//
+		// Require-Bundle
+		//
+		
+		Parameters requires = d.getRequireBundle();
+		for (Entry<String,Attrs> entry : requires.entrySet()) {
+			CapReqBuilder req = new CapReqBuilder(BundleNamespace.BUNDLE_NAMESPACE);
+			String bsn = Processor.removeDuplicateMarker(entry.getKey());
+			String filter = filter(BundleNamespace.BUNDLE_NAMESPACE, bsn, entry.getValue());
+			req.addDirective(Namespace.REQUIREMENT_FILTER_DIRECTIVE, filter);			
+			resource.addRequirement(req);
+		}
+
+		//
+		// Bundle-RequiredExecutionEnvironment
+		//
+		
+		Parameters brees = d.getBundleRequiredExecutionEnvironment();
+		Formatter formatter = new Formatter();
+			formatter.format("(|");
+		
+		for ( Entry<String,Attrs> bree : brees.entrySet()	) {
+			String name = Processor.removeDuplicateMarker(bree.getKey());
+			Matcher matcher = EE_PATTERN.matcher(name);
+			if ( matcher.matches()) {
+				name = matcher.group(1);
+				Version v = Version.parseVersion(matcher.group(2));
+				formatter.format("%s", filter(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE, name, MAP.$("version", v.toString())));
+			}
+		}
+		formatter.format(")");
+		
+		CapReqBuilder breeReq = new CapReqBuilder(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE);
+		breeReq.addDirective(Namespace.REQUIREMENT_FILTER_DIRECTIVE, formatter.toString());
+
+		//
+		// Export-Service (deprecated)
+		//
+		
+		for (Entry<String,Attrs> export : d.getParameters(Constants.EXPORT_SERVICE).entrySet()) {
+			CapReqBuilder	exportedService = new CapReqBuilder(ServiceNamespace.SERVICE_NAMESPACE);
+			String service = Processor.removeDuplicateMarker(export.getKey());
+			exportedService.addAttribute(ServiceNamespace.SERVICE_NAMESPACE, service);
+			exportedService.addAttribute(ServiceNamespace.CAPABILITY_OBJECTCLASS_ATTRIBUTE, export.getValue().get("objectclass"));
+			resource.addCapability(exportedService);
+		}
+		
+		//
+		// Import-Service (deprecated)
+		//
+		
+		for (Entry<String,Attrs> imported : d.getParameters(Constants.IMPORT_SERVICE).entrySet()) {
+			CapReqBuilder	importedService = new CapReqBuilder(ServiceNamespace.SERVICE_NAMESPACE);
+			String service = Processor.removeDuplicateMarker(imported.getKey());
+			importedService.addDirective(Namespace.REQUIREMENT_FILTER_DIRECTIVE, filter(ServiceNamespace.SERVICE_NAMESPACE, service, imported.getValue()));
+			resource.addRequirement(importedService);
+		}
+		
+		//
+		// Provide-Capability
+		//
+		
+		for ( Entry<String,Attrs> rc : d.getProvideCapability().entrySet()) {
+			resource.addCapability( toCapability(rc.getKey(), rc.getValue()));
+		}
+		
+		//
+		// Require-Capability
+		//
+
+		for ( Entry<String,Attrs> rc : d.getRequireCapability().entrySet()) {
+			resource.addCapability( toRequirement(rc.getKey(), rc.getValue()));
+		}
+		
+		
+		return null;
+	}
+
+	private static Capability toRequirement(String key, Attrs value) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	private static Capability toCapability(String key, Attrs value) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public static Reporter parse(File file, ResourceBuilder resource, String base) throws Exception {
+		Jar jar = new Jar(file);
+		try {
+			Reporter reporter = parse(jar, resource);
+			if (!reporter.isOk())
+				return reporter;
+
+			CapReqBuilder content = new CapReqBuilder(ContentNamespace.CONTENT_NAMESPACE);
+			String sha = SHA1.digest(file).asHex();
+			content.addAttribute(ContentNamespace.CONTENT_NAMESPACE, sha);
+			content.addAttribute(ContentNamespace.CAPABILITY_SIZE_ATTRIBUTE, (long) file.length());
+			content.addAttribute(ContentNamespace.CAPABILITY_MIME_ATTRIBUTE, MIME_TYPE_OSGI_BUNDLE);
+
+			if (base != null) {
+				String path = file.getAbsolutePath();
+				if (base.startsWith(path)) {
+					content.addAttribute(ContentNamespace.CAPABILITY_URL_ATTRIBUTE, path.substring(base.length())
+							.replace(File.separatorChar, '/'));
+				} else {
+					reporter.error("Base path %s is not parent of file path: %s", base, file.getAbsolutePath());
+				}
+			}
+
+			resource.addCapability(content);
+			return reporter;
+		}
+		finally {
+			jar.close();
+		}
+	}
+	
+	// TODO finish
+	private static String filter(String ns, String primary, Map<String,String> value) {
+		Formatter f = new Formatter();
+		f.format("(&(%s=%s)", ns, primary);
+		for ( String key : value.keySet()) {
+			if ( key.equals("version") || key.equals("bundle-version")) {
+				VersionRange vr = new VersionRange(value.get(key));
+			} else {
+				f.format("(%s=%s)", key, value.get(key));
+			}
+		}
+		
+		f.format(")");
+		return null;
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/About.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/About.java
new file mode 100755
index 0000000..727208b
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/About.java
@@ -0,0 +1,39 @@
+package aQute.bnd.osgi;
+
+import aQute.bnd.header.*;
+
+/**
+ * This package contains a number of classes that assists by analyzing JARs and
+ * constructing bundles. The Analyzer class can be used to analyze an existing
+ * bundle and can create a manifest specification from proposed (wildcard)
+ * Export-Package, Bundle-Includes, and Import-Package headers. The Builder
+ * class can use the headers to construct a JAR from the classpath. The Verifier
+ * class can take an existing JAR and verify that all headers are correctly set.
+ * It will verify the syntax of the headers, match it against the proper
+ * contents, and verify imports and exports. A number of utility classes are
+ * available. Jar, provides an abstraction of a Jar file. It has constructors
+ * for creating a Jar from a stream, a directory, or a jar file. A Jar, keeps a
+ * collection Resource's. There are Resource implementations for File, from
+ * ZipFile, or from a stream (which copies the data). The Jar tries to minimize
+ * the work during build up so that it is cheap to use. The Resource's can be
+ * used to iterate over the names and later read the resources when needed.
+ * Clazz, provides a parser for the class files. This will be used to define the
+ * imports and exports. Headers are translated to {@link Parameters} that
+ * contains all headers (the order is maintained). The attribute of each header
+ * are maintained in an {@link Attrs}. Each additional file in a header
+ * definition will have its own entry (only native code does not work this way).
+ * The ':' of directives is considered part of the name. This allows attributes
+ * and directives to be maintained in the Attributes map. An important aspect of
+ * the specification is to allow the use of wildcards. Wildcards select from a
+ * set and can decorate the entries with new attributes. This functionality is
+ * implemented in Instructions. Much of the information calculated is in
+ * packages. A package is identified by a PackageRef (and a type by a TypeRef).
+ * The namespace is maintained by {@link Descriptors}, which here is owned by
+ * {@link Analyzer}. A special class, {@link Packages} maintains the attributes
+ * that are found in the code.
+ * 
+ * @version $Revision: 1.2 $
+ */
+public class About {
+	// Empty
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/AbstractResource.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/AbstractResource.java
new file mode 100644
index 0000000..e023985
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/AbstractResource.java
@@ -0,0 +1,56 @@
+package aQute.bnd.osgi;
+
+import java.io.*;
+
+public abstract class AbstractResource implements Resource {
+	String	extra;
+	byte[]	calculated;
+	long	lastModified;
+
+	protected AbstractResource(long modified) {
+		lastModified = modified;
+	}
+
+	public String getExtra() {
+		return extra;
+	}
+
+	public long lastModified() {
+		return lastModified;
+	}
+
+	public InputStream openInputStream() throws IOException {
+		return new ByteArrayInputStream(getLocalBytes());
+	}
+
+	private byte[] getLocalBytes() throws IOException {
+		try {
+			if (calculated != null)
+				return calculated;
+
+			return calculated = getBytes();
+		}
+		catch (IOException e) {
+			throw e;
+		}
+		catch (Exception e) {
+			IOException ee = new IOException("Opening resource");
+			ee.initCause(e);
+			throw ee;
+		}
+	}
+
+	public void setExtra(String extra) {
+		this.extra = extra;
+	}
+
+	public void write(OutputStream out) throws IOException {
+		out.write(getLocalBytes());
+	}
+
+	abstract protected byte[] getBytes() throws Exception;
+
+	public long size() throws IOException {
+		return getLocalBytes().length;
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/Analyzer.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/Analyzer.java
new file mode 100755
index 0000000..8712e33
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/Analyzer.java
@@ -0,0 +1,2644 @@
+package aQute.bnd.osgi;
+
+/**
+ * This class can calculate the required headers for a (potential) JAR file. It
+ * analyzes a directory or JAR for the packages that are contained and that are
+ * referred to by the bytecodes. The user can the use regular expressions to
+ * define the attributes and directives. The matching is not fully regex for
+ * convenience. A * and ? get a . prefixed and dots are escaped.
+ * 
+ * <pre>
+ *                                                             			*;auto=true				any		
+ *                                                             			org.acme.*;auto=true    org.acme.xyz
+ *                                                             			org.[abc]*;auto=true    org.acme.xyz
+ * </pre>
+ * 
+ * Additional, the package instruction can start with a '=' or a '!'. The '!'
+ * indicates negation. Any matching package is removed. The '=' is literal, the
+ * expression will be copied verbatim and no matching will take place.
+ * 
+ * Any headers in the given properties are used in the output properties.
+ */
+import static aQute.libg.generics.Create.*;
+
+import java.io.*;
+import java.net.*;
+import java.text.*;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.jar.*;
+import java.util.jar.Attributes.Name;
+import java.util.regex.*;
+
+import aQute.bnd.annotation.*;
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.Descriptors.Descriptor;
+import aQute.bnd.osgi.Descriptors.PackageRef;
+import aQute.bnd.osgi.Descriptors.TypeRef;
+import aQute.bnd.service.*;
+import aQute.bnd.version.*;
+import aQute.bnd.version.Version;
+import aQute.lib.base64.*;
+import aQute.lib.collections.*;
+import aQute.lib.filter.*;
+import aQute.lib.hex.*;
+import aQute.lib.io.*;
+import aQute.libg.cryptography.*;
+import aQute.libg.generics.*;
+import aQute.libg.reporter.*;
+
+public class Analyzer extends Processor {
+	private final SortedSet<Clazz.JAVA>				ees						= new TreeSet<Clazz.JAVA>();
+	static Properties								bndInfo;
+
+	// Bundle parameters
+	private Jar										dot;
+	private final Packages							contained				= new Packages();
+	private final Packages							referred				= new Packages();
+	private Packages								exports;
+	private Packages								imports;
+	private TypeRef									activator;
+
+	// Global parameters
+	private final MultiMap<PackageRef,PackageRef>	uses					= new MultiMap<PackageRef,PackageRef>(
+																					PackageRef.class, PackageRef.class,
+																					true);
+	private final MultiMap<PackageRef,PackageRef>	apiUses					= new MultiMap<PackageRef,PackageRef>(
+																					PackageRef.class, PackageRef.class,
+																					true);
+	private final Packages							classpathExports		= new Packages();
+	private final Descriptors						descriptors				= new Descriptors();
+	private final List<Jar>							classpath				= list();
+	private final Map<TypeRef,Clazz>				classspace				= map();
+	private final Map<TypeRef,Clazz>				importedClassesCache	= map();
+	private boolean									analyzed				= false;
+	private boolean									diagnostics				= false;
+	private boolean									inited					= false;
+	final protected AnalyzerMessages				msgs					= ReporterMessages.base(this,
+																					AnalyzerMessages.class);
+
+	public Analyzer(Processor parent) {
+		super(parent);
+	}
+
+	public Analyzer() {}
+
+	/**
+	 * Specifically for Maven
+	 * 
+	 * @param properties
+	 *            the properties
+	 */
+
+	public static Properties getManifest(File dirOrJar) throws Exception {
+		Analyzer analyzer = new Analyzer();
+		try {
+			analyzer.setJar(dirOrJar);
+			Properties properties = new Properties();
+			properties.put(IMPORT_PACKAGE, "*");
+			properties.put(EXPORT_PACKAGE, "*");
+			analyzer.setProperties(properties);
+			Manifest m = analyzer.calcManifest();
+			Properties result = new Properties();
+			for (Iterator<Object> i = m.getMainAttributes().keySet().iterator(); i.hasNext();) {
+				Attributes.Name name = (Attributes.Name) i.next();
+				result.put(name.toString(), m.getMainAttributes().getValue(name));
+			}
+			return result;
+		}
+		finally {
+			analyzer.close();
+		}
+	}
+
+	/**
+	 * Calculates the data structures for generating a manifest.
+	 * 
+	 * @throws IOException
+	 */
+	public void analyze() throws Exception {
+		if (!analyzed) {
+			analyzed = true;
+			uses.clear();
+			apiUses.clear();
+			classspace.clear();
+			classpathExports.clear();
+
+			// Parse all the class in the
+			// the jar according to the OSGi bcp
+			analyzeBundleClasspath();
+
+			//
+			// calculate class versions in use
+			//
+			for (Clazz c : classspace.values()) {
+				ees.add(c.getFormat());
+			}
+
+			//
+			// Get exported packages from the
+			// entries on the classpath
+			//
+
+			for (Jar current : getClasspath()) {
+				getExternalExports(current, classpathExports);
+				for (String dir : current.getDirectories().keySet()) {
+					PackageRef packageRef = getPackageRef(dir);
+					Resource resource = current.getResource(dir + "/packageinfo");
+					getExportVersionsFromPackageInfo(packageRef, resource, classpathExports);
+				}
+			}
+
+			// Handle the bundle activator
+
+			String s = getProperty(BUNDLE_ACTIVATOR);
+			if (s != null) {
+				activator = getTypeRefFromFQN(s);
+				referTo(activator);
+				trace("activator %s %s", s, activator);
+			}
+
+			// Execute any plugins
+			// TODO handle better reanalyze
+			doPlugins();
+
+			Jar extra = getExtra();
+			while (extra != null) {
+				dot.addAll(extra);
+				analyzeJar(extra, "", true);
+				extra = getExtra();
+			}
+
+			referred.keySet().removeAll(contained.keySet());
+
+			//
+			// EXPORTS
+			//
+			{
+				Set<Instruction> unused = Create.set();
+
+				Instructions filter = new Instructions(getExportPackage());
+				filter.append(getExportContents());
+
+				exports = filter(filter, contained, unused);
+
+				if (!unused.isEmpty()) {
+					warning("Unused Export-Package instructions: %s ", unused);
+				}
+
+				// See what information we can find to augment the
+				// exports. I.e. look on the classpath
+				augmentExports(exports);
+			}
+
+			//
+			// IMPORTS
+			// Imports MUST come after exports because we use information from
+			// the exports
+			//
+			{
+				// Add all exports that do not have an -noimport: directive
+				// to the imports.
+				Packages referredAndExported = new Packages(referred);
+				referredAndExported.putAll(doExportsToImports(exports));
+
+				removeDynamicImports(referredAndExported);
+
+				// Remove any Java references ... where are the closures???
+				for (Iterator<PackageRef> i = referredAndExported.keySet().iterator(); i.hasNext();) {
+					if (i.next().isJava())
+						i.remove();
+				}
+
+				Set<Instruction> unused = Create.set();
+				String h = getProperty(IMPORT_PACKAGE);
+				if (h == null) // If not set use a default
+					h = "*";
+
+				if (isPedantic() && h.trim().length() == 0)
+					warning("Empty Import-Package header");
+
+				Instructions filter = new Instructions(h);
+				imports = filter(filter, referredAndExported, unused);
+				if (!unused.isEmpty()) {
+					// We ignore the end wildcard catch
+					if (!(unused.size() == 1 && unused.iterator().next().toString().equals("*")))
+						warning("Unused Import-Package instructions: %s ", unused);
+				}
+
+				// See what information we can find to augment the
+				// imports. I.e. look in the exports
+				augmentImports(imports, exports);
+			}
+
+			//
+			// USES
+			//
+			// Add the uses clause to the exports
+
+			boolean api = isTrue(getProperty(EXPERIMENTS)) || true; // brave,
+																	// lets see
+
+			doUses(exports, api ? apiUses : uses, imports);
+
+			//
+			// Verify that no exported package has a reference to a private
+			// package
+			// This can cause a lot of harm.
+			// TODO restrict the check to public API only, but even then
+			// exported packages
+			// should preferably not refer to private packages.
+			//
+			Set<PackageRef> privatePackages = getPrivates();
+
+			// References to java are not imported so they would show up as
+			// private
+			// packages, lets kill them as well.
+
+			for (Iterator<PackageRef> p = privatePackages.iterator(); p.hasNext();)
+				if (p.next().isJava())
+					p.remove();
+
+			for (PackageRef exported : exports.keySet()) {
+				List<PackageRef> used = uses.get(exported);
+				if (used != null) {
+					Set<PackageRef> privateReferences = new HashSet<PackageRef>(apiUses.get(exported));
+					privateReferences.retainAll(privatePackages);
+					if (!privateReferences.isEmpty())
+						msgs.Export_Has_PrivateReferences_(exported, privateReferences.size(), privateReferences);
+				}
+			}
+
+			//
+			// Checks
+			//
+			if (referred.containsKey(Descriptors.DEFAULT_PACKAGE)) {
+				error("The default package '.' is not permitted by the Import-Package syntax. \n"
+						+ " This can be caused by compile errors in Eclipse because Eclipse creates \n"
+						+ "valid class files regardless of compile errors.\n"
+						+ "The following package(s) import from the default package "
+						+ uses.transpose().get(Descriptors.DEFAULT_PACKAGE));
+			}
+
+		}
+	}
+
+	/**
+	 * Discussed with BJ and decided to kill the .
+	 * 
+	 * @param referredAndExported
+	 */
+	void removeDynamicImports(Packages referredAndExported) {
+
+		// // Remove any matching a dynamic import package instruction
+		// Instructions dynamicImports = new
+		// Instructions(getDynamicImportPackage());
+		// Collection<PackageRef> dynamic = dynamicImports.select(
+		// referredAndExported.keySet(), false);
+		// referredAndExported.keySet().removeAll(dynamic);
+	}
+
+	protected Jar getExtra() throws Exception {
+		return null;
+	}
+
+	/**
+	 * 
+	 */
+	void doPlugins() {
+		for (AnalyzerPlugin plugin : getPlugins(AnalyzerPlugin.class)) {
+			try {
+				Processor previous = beginHandleErrors(plugin.toString());
+				boolean reanalyze = plugin.analyzeJar(this);
+				endHandleErrors(previous);
+				if (reanalyze) {
+					classspace.clear();
+					analyzeBundleClasspath();
+				}
+			}
+			catch (Exception e) {
+				error("Analyzer Plugin %s failed %s", plugin, e);
+			}
+		}
+	}
+
+	/**
+	 * @return
+	 */
+	boolean isResourceOnly() {
+		return isTrue(getProperty(RESOURCEONLY));
+	}
+
+	/**
+	 * One of the main workhorses of this class. This will analyze the current
+	 * setp and calculate a new manifest according to this setup. This method
+	 * will also set the manifest on the main jar dot
+	 * 
+	 * @return
+	 * @throws IOException
+	 */
+	public Manifest calcManifest() throws Exception {
+		try {
+			analyze();
+			Manifest manifest = new Manifest();
+			Attributes main = manifest.getMainAttributes();
+
+			main.put(Attributes.Name.MANIFEST_VERSION, "1.0");
+			main.putValue(BUNDLE_MANIFESTVERSION, "2");
+
+			boolean noExtraHeaders = "true".equalsIgnoreCase(getProperty(NOEXTRAHEADERS));
+
+			if (!noExtraHeaders) {
+				main.putValue(CREATED_BY, System.getProperty("java.version") + " (" + System.getProperty("java.vendor")
+						+ ")");
+				main.putValue(TOOL, "Bnd-" + getBndVersion());
+				main.putValue(BND_LASTMODIFIED, "" + System.currentTimeMillis());
+			}
+
+			String exportHeader = printClauses(exports, true);
+
+			if (exportHeader.length() > 0)
+				main.putValue(EXPORT_PACKAGE, exportHeader);
+			else
+				main.remove(EXPORT_PACKAGE);
+
+			// Remove all the Java packages from the imports
+			if (!imports.isEmpty()) {
+				main.putValue(IMPORT_PACKAGE, printClauses(imports));
+			} else {
+				main.remove(IMPORT_PACKAGE);
+			}
+
+			Packages temp = new Packages(contained);
+			temp.keySet().removeAll(exports.keySet());
+
+			if (!temp.isEmpty())
+				main.putValue(PRIVATE_PACKAGE, printClauses(temp));
+			else
+				main.remove(PRIVATE_PACKAGE);
+
+			Parameters bcp = getBundleClasspath();
+			if (bcp.isEmpty() || (bcp.containsKey(".") && bcp.size() == 1))
+				main.remove(BUNDLE_CLASSPATH);
+			else
+				main.putValue(BUNDLE_CLASSPATH, printClauses(bcp));
+
+			doNamesection(dot, manifest);
+
+			for (Enumeration< ? > h = getProperties().propertyNames(); h.hasMoreElements();) {
+				String header = (String) h.nextElement();
+				if (header.trim().length() == 0) {
+					warning("Empty property set with value: " + getProperties().getProperty(header));
+					continue;
+				}
+
+				if (isMissingPlugin(header.trim())) {
+					error("Missing plugin for command %s", header);
+				}
+				if (!Character.isUpperCase(header.charAt(0))) {
+					if (header.charAt(0) == '@')
+						doNameSection(manifest, header);
+					continue;
+				}
+
+				if (header.equals(BUNDLE_CLASSPATH) || header.equals(EXPORT_PACKAGE) || header.equals(IMPORT_PACKAGE))
+					continue;
+
+				if (header.equalsIgnoreCase("Name")) {
+					error("Your bnd file contains a header called 'Name'. This interferes with the manifest name section.");
+					continue;
+				}
+
+				if (Verifier.HEADER_PATTERN.matcher(header).matches()) {
+					String value = getProperty(header);
+					if (value != null && main.getValue(header) == null) {
+						if (value.trim().length() == 0)
+							main.remove(header);
+						else if (value.trim().equals(EMPTY_HEADER))
+							main.putValue(header, "");
+						else
+							main.putValue(header, value);
+					}
+				} else {
+					// TODO should we report?
+				}
+			}
+
+			// Copy old values into new manifest, when they
+			// exist in the old one, but not in the new one
+			merge(manifest, dot.getManifest());
+
+			//
+			// Calculate the bundle symbolic name if it is
+			// not set.
+			// 1. set
+			// 2. name of properties file (must be != bnd.bnd)
+			// 3. name of directory, which is usualy project name
+			//
+			String bsn = getBsn();
+			if (main.getValue(BUNDLE_SYMBOLICNAME) == null) {
+				main.putValue(BUNDLE_SYMBOLICNAME, bsn);
+			}
+
+			//
+			// Use the same name for the bundle name as BSN when
+			// the bundle name is not set
+			//
+			if (main.getValue(BUNDLE_NAME) == null) {
+				main.putValue(BUNDLE_NAME, bsn);
+			}
+
+			if (main.getValue(BUNDLE_VERSION) == null)
+				main.putValue(BUNDLE_VERSION, "0");
+
+			// Remove all the headers mentioned in -removeheaders
+			Instructions instructions = new Instructions(getProperty(REMOVEHEADERS));
+			Collection<Object> result = instructions.select(main.keySet(), false);
+			main.keySet().removeAll(result);
+
+			// We should not set the manifest here, this is in general done
+			// by the caller.
+			// dot.setManifest(manifest);
+			return manifest;
+		}
+		catch (Exception e) {
+			// This should not really happen. The code should never throw
+			// exceptions in normal situations. So if it happens we need more
+			// information. So to help diagnostics. We do a full property dump
+			throw new IllegalStateException("Calc manifest failed, state=\n" + getFlattenedProperties(), e);
+		}
+	}
+
+	/**
+	 * Parse the namesection as instructions and then match them against the
+	 * current set of resources For example:
+	 * 
+	 * <pre>
+	 * 	-namesection: *;baz=true, abc/def/bar/X.class=3
+	 * </pre>
+	 * 
+	 * The raw value of {@link Constants#NAMESECTION} is used but the values of
+	 * the attributes are replaced where @ is set to the resource name. This
+	 * allows macro to operate on the resource
+	 */
+
+	private void doNamesection(Jar dot, Manifest manifest) {
+
+		Parameters namesection = parseHeader(getProperties().getProperty(NAMESECTION));
+		Instructions instructions = new Instructions(namesection);
+		Set<String> resources = new HashSet<String>(dot.getResources().keySet());
+
+		//
+		// For each instruction, iterator over the resources and filter
+		// them. If a resource matches, it must be removed even if the
+		// instruction is negative. If positive, add a name section
+		// to the manifest for the given resource name. Then add all
+		// attributes from the instruction to that name section.
+		//
+		for (Map.Entry<Instruction,Attrs> instr : instructions.entrySet()) {
+			boolean matched = false;
+
+			// For each instruction
+
+			for (Iterator<String> i = resources.iterator(); i.hasNext();) {
+				String path = i.next();
+				// For each resource
+
+				if (instr.getKey().matches(path)) {
+
+					// Instruction matches the resource
+
+					matched = true;
+					if (!instr.getKey().isNegated()) {
+
+						// Positive match, add the attributes
+
+						Attributes attrs = manifest.getAttributes(path);
+						if (attrs == null) {
+							attrs = new Attributes();
+							manifest.getEntries().put(path, attrs);
+						}
+
+						//
+						// Add all the properties from the instruction to the
+						// name section
+						//
+
+						for (Map.Entry<String,String> property : instr.getValue().entrySet()) {
+							setProperty("@", path);
+							try {
+								String processed = getReplacer().process(property.getValue());
+								attrs.putValue(property.getKey(), processed);
+							}
+							finally {
+								unsetProperty("@");
+							}
+						}
+					}
+					i.remove();
+				}
+			}
+
+			if (!matched && resources.size() > 0)
+				warning("The instruction %s in %s did not match any resources", instr.getKey(), NAMESECTION);
+		}
+
+	}
+
+	/**
+	 * This method is called when the header starts with a @, signifying a name
+	 * section header. The name part is defined by replacing all the @ signs to
+	 * a /, removing the first and the last, and using the last part as header
+	 * name:
+	 * 
+	 * <pre>
+	 * @org at osgi@service at event@Implementation-Title
+	 * </pre>
+	 * 
+	 * This will be the header Implementation-Title in the
+	 * org/osgi/service/event named section.
+	 * 
+	 * @param manifest
+	 * @param header
+	 */
+	private void doNameSection(Manifest manifest, String header) {
+		String path = header.replace('@', '/');
+		int n = path.lastIndexOf('/');
+		// Must succeed because we start with @
+		String name = path.substring(n + 1);
+		// Skip first /
+		path = path.substring(1, n);
+		if (name.length() != 0 && path.length() != 0) {
+			Attributes attrs = manifest.getAttributes(path);
+			if (attrs == null) {
+				attrs = new Attributes();
+				manifest.getEntries().put(path, attrs);
+			}
+			attrs.putValue(name, getProperty(header));
+		} else {
+			warning("Invalid header (starts with @ but does not seem to be for the Name section): %s", header);
+		}
+	}
+
+	/**
+	 * Clear the key part of a header. I.e. remove everything from the first ';'
+	 * 
+	 * @param value
+	 * @return
+	 */
+	public String getBsn() {
+		String value = getProperty(BUNDLE_SYMBOLICNAME);
+		if (value == null) {
+			if (getPropertiesFile() != null)
+				value = getPropertiesFile().getName();
+
+			String projectName = getBase().getName();
+			if (value == null || value.equals("bnd.bnd")) {
+				value = projectName;
+			} else if (value.endsWith(".bnd")) {
+				value = value.substring(0, value.length() - 4);
+				if (!value.startsWith(getBase().getName()))
+					value = projectName + "." + value;
+			}
+		}
+
+		if (value == null)
+			return "untitled";
+
+		int n = value.indexOf(';');
+		if (n > 0)
+			value = value.substring(0, n);
+		return value.trim();
+	}
+
+	public String _bsn(@SuppressWarnings("unused")
+	String args[]) {
+		return getBsn();
+	}
+
+	/**
+	 * Calculate an export header solely based on the contents of a JAR file
+	 * 
+	 * @param bundle
+	 *            The jar file to analyze
+	 * @return
+	 */
+	public String calculateExportsFromContents(Jar bundle) {
+		String ddel = "";
+		StringBuilder sb = new StringBuilder();
+		Map<String,Map<String,Resource>> map = bundle.getDirectories();
+		for (Iterator<String> i = map.keySet().iterator(); i.hasNext();) {
+			String directory = i.next();
+			if (directory.equals("META-INF") || directory.startsWith("META-INF/"))
+				continue;
+			if (directory.equals("OSGI-OPT") || directory.startsWith("OSGI-OPT/"))
+				continue;
+			if (directory.equals("/"))
+				continue;
+
+			if (directory.endsWith("/"))
+				directory = directory.substring(0, directory.length() - 1);
+
+			directory = directory.replace('/', '.');
+			sb.append(ddel);
+			sb.append(directory);
+			ddel = ",";
+		}
+		return sb.toString();
+	}
+
+	public Packages getContained() {
+		return contained;
+	}
+
+	public Packages getExports() {
+		return exports;
+	}
+
+	public Packages getImports() {
+		return imports;
+	}
+
+	public Set<PackageRef> getPrivates() {
+		HashSet<PackageRef> privates = new HashSet<PackageRef>(contained.keySet());
+		privates.removeAll(exports.keySet());
+		privates.removeAll(imports.keySet());
+		return privates;
+	}
+
+	public Jar getJar() {
+		return dot;
+	}
+
+	public Packages getReferred() {
+		return referred;
+	}
+
+	/**
+	 * Return the set of unreachable code depending on exports and the bundle
+	 * activator.
+	 * 
+	 * @return
+	 */
+	public Set<PackageRef> getUnreachable() {
+		Set<PackageRef> unreachable = new HashSet<PackageRef>(uses.keySet()); // all
+		for (Iterator<PackageRef> r = exports.keySet().iterator(); r.hasNext();) {
+			PackageRef packageRef = r.next();
+			removeTransitive(packageRef, unreachable);
+		}
+		if (activator != null) {
+			removeTransitive(activator.getPackageRef(), unreachable);
+		}
+		return unreachable;
+	}
+
+	public Map<PackageRef,List<PackageRef>> getUses() {
+		return uses;
+	}
+
+	public Map<PackageRef,List<PackageRef>> getAPIUses() {
+		return apiUses;
+	}
+
+	public Packages getClasspathExports() {
+		return classpathExports;
+	}
+
+	/**
+	 * Get the version for this bnd
+	 * 
+	 * @return version or unknown.
+	 */
+	public String getBndVersion() {
+		return getBndInfo("version", "<unknown>");
+	}
+
+	static SimpleDateFormat df = new SimpleDateFormat("EEE MMM dd hh:mm:ss z yyyy");
+	public long getBndLastModified() {
+		String time = getBndInfo("lastmodified", "0");
+		if ( time.matches("\\d+"))
+			return Long.parseLong(time);
+		
+		try {
+			Date parse = df.parse(time);
+			if ( parse != null)
+				return parse.getTime();
+		} catch( ParseException e) {
+			// Ignore
+		}
+		return 0;
+	}
+
+	public String getBndInfo(String key, String defaultValue) {
+		if (bndInfo == null) {
+			try {
+				Properties bndInfoLocal = new Properties();
+				URL url = Analyzer.class.getResource("bnd.info");
+				if (url != null) {
+					InputStream in = url.openStream();
+					try {
+						bndInfoLocal.load(in);
+					}
+					finally {
+						in.close();
+					}
+				}
+				bndInfo = bndInfoLocal;
+			}
+			catch (Exception e) {
+				e.printStackTrace();
+				return defaultValue;
+			}
+		}
+		String value = bndInfo.getProperty(key);
+		if (value == null)
+			return defaultValue;
+		return value;
+	}
+
+	/**
+	 * Merge the existing manifest with the instructions but do not override
+	 * existing properties.
+	 * 
+	 * @param manifest
+	 *            The manifest to merge with
+	 * @throws IOException
+	 */
+	public void mergeManifest(Manifest manifest) throws IOException {
+		if (manifest != null) {
+			Attributes attributes = manifest.getMainAttributes();
+			for (Iterator<Object> i = attributes.keySet().iterator(); i.hasNext();) {
+				Name name = (Name) i.next();
+				String key = name.toString();
+				// Dont want instructions
+				if (key.startsWith("-"))
+					continue;
+
+				if (getProperty(key) == null)
+					setProperty(key, attributes.getValue(name));
+			}
+		}
+	}
+
+	@Override
+	public void setBase(File file) {
+		super.setBase(file);
+		getProperties().put("project.dir", getBase().getAbsolutePath());
+	}
+
+	/**
+	 * Set the classpath for this analyzer by file.
+	 * 
+	 * @param classpath
+	 * @throws IOException
+	 */
+	public void setClasspath(File[] classpath) throws IOException {
+		List<Jar> list = new ArrayList<Jar>();
+		for (int i = 0; i < classpath.length; i++) {
+			if (classpath[i].exists()) {
+				Jar current = new Jar(classpath[i]);
+				list.add(current);
+			} else {
+				error("Missing file on classpath: %s", classpath[i]);
+			}
+		}
+		for (Iterator<Jar> i = list.iterator(); i.hasNext();) {
+			addClasspath(i.next());
+		}
+	}
+
+	public void setClasspath(Jar[] classpath) {
+		for (int i = 0; i < classpath.length; i++) {
+			addClasspath(classpath[i]);
+		}
+	}
+
+	public void setClasspath(String[] classpath) {
+		for (int i = 0; i < classpath.length; i++) {
+			Jar jar = getJarFromName(classpath[i], " setting classpath");
+			if (jar != null)
+				addClasspath(jar);
+		}
+	}
+
+	/**
+	 * Set the JAR file we are going to work in. This will read the JAR in
+	 * memory.
+	 * 
+	 * @param jar
+	 * @return
+	 * @throws IOException
+	 */
+	public Jar setJar(File jar) throws IOException {
+		Jar jarx = new Jar(jar);
+		addClose(jarx);
+		return setJar(jarx);
+	}
+
+	/**
+	 * Set the JAR directly we are going to work on.
+	 * 
+	 * @param jar
+	 * @return
+	 */
+	public Jar setJar(Jar jar) {
+		if (dot != null)
+			removeClose(dot);
+
+		this.dot = jar;
+		if (dot != null)
+			addClose(dot);
+
+		return jar;
+	}
+
+	@Override
+	protected void begin() {
+		if (inited == false) {
+			inited = true;
+			super.begin();
+
+			updateModified(getBndLastModified(), "bnd last modified");
+			verifyManifestHeadersCase(getProperties());
+
+		}
+	}
+
+	/**
+	 * Try to get a Jar from a file name/path or a url, or in last resort from
+	 * the classpath name part of their files.
+	 * 
+	 * @param name
+	 *            URL or filename relative to the base
+	 * @param from
+	 *            Message identifying the caller for errors
+	 * @return null or a Jar with the contents for the name
+	 */
+	Jar getJarFromName(String name, String from) {
+		File file = new File(name);
+		if (!file.isAbsolute())
+			file = new File(getBase(), name);
+
+		if (file.exists())
+			try {
+				Jar jar = new Jar(file);
+				addClose(jar);
+				return jar;
+			}
+			catch (Exception e) {
+				error("Exception in parsing jar file for " + from + ": " + name + " " + e);
+			}
+		// It is not a file ...
+		try {
+			// Lets try a URL
+			URL url = new URL(name);
+			Jar jar = new Jar(fileName(url.getPath()));
+			addClose(jar);
+			URLConnection connection = url.openConnection();
+			InputStream in = connection.getInputStream();
+			long lastModified = connection.getLastModified();
+			if (lastModified == 0)
+				// We assume the worst :-(
+				lastModified = System.currentTimeMillis();
+			EmbeddedResource.build(jar, in, lastModified);
+			in.close();
+			return jar;
+		}
+		catch (IOException ee) {
+			// Check if we have files on the classpath
+			// that have the right name, allows us to specify those
+			// names instead of the full path.
+			for (Iterator<Jar> cp = getClasspath().iterator(); cp.hasNext();) {
+				Jar entry = cp.next();
+				if (entry.getSource() != null && entry.getSource().getName().equals(name)) {
+					return entry;
+				}
+			}
+			// error("Can not find jar file for " + from + ": " + name);
+		}
+		return null;
+	}
+
+	private String fileName(String path) {
+		int n = path.lastIndexOf('/');
+		if (n > 0)
+			return path.substring(n + 1);
+		return path;
+	}
+
+	/**
+	 * @param manifests
+	 * @throws Exception
+	 */
+	private void merge(Manifest result, Manifest old) {
+		if (old != null) {
+			for (Iterator<Map.Entry<Object,Object>> e = old.getMainAttributes().entrySet().iterator(); e.hasNext();) {
+				Map.Entry<Object,Object> entry = e.next();
+				Attributes.Name name = (Attributes.Name) entry.getKey();
+				String value = (String) entry.getValue();
+				if (name.toString().equalsIgnoreCase("Created-By"))
+					name = new Attributes.Name("Originally-Created-By");
+				if (!result.getMainAttributes().containsKey(name))
+					result.getMainAttributes().put(name, value);
+			}
+
+			// do not overwrite existing entries
+			Map<String,Attributes> oldEntries = old.getEntries();
+			Map<String,Attributes> newEntries = result.getEntries();
+			for (Iterator<Map.Entry<String,Attributes>> e = oldEntries.entrySet().iterator(); e.hasNext();) {
+				Map.Entry<String,Attributes> entry = e.next();
+				if (!newEntries.containsKey(entry.getKey())) {
+					newEntries.put(entry.getKey(), entry.getValue());
+				}
+			}
+		}
+	}
+
+	/**
+	 * Bnd is case sensitive for the instructions so we better check people are
+	 * not using an invalid case. We do allow this to set headers that should
+	 * not be processed by us but should be used by the framework.
+	 * 
+	 * @param properties
+	 *            Properties to verify.
+	 */
+
+	void verifyManifestHeadersCase(Properties properties) {
+		for (Iterator<Object> i = properties.keySet().iterator(); i.hasNext();) {
+			String header = (String) i.next();
+			for (int j = 0; j < headers.length; j++) {
+				if (!headers[j].equals(header) && headers[j].equalsIgnoreCase(header)) {
+					warning("Using a standard OSGi header with the wrong case (bnd is case sensitive!), using: "
+							+ header + " and expecting: " + headers[j]);
+					break;
+				}
+			}
+		}
+	}
+
+	/**
+	 * We will add all exports to the imports unless there is a -noimport
+	 * directive specified on an export. This directive is skipped for the
+	 * manifest. We also remove any version parameter so that augmentImports can
+	 * do the version policy. The following method is really tricky and evolved
+	 * over time. Coming from the original background of OSGi, it was a weird
+	 * idea for me to have a public package that should not be substitutable. I
+	 * was so much convinced that this was the right rule that I rücksichtlos
+	 * imported them all. Alas, the real world was more subtle than that. It
+	 * turns out that it is not a good idea to always import. First, there must
+	 * be a need to import, i.e. there must be a contained package that refers
+	 * to the exported package for it to make use importing that package.
+	 * Second, if an exported package refers to an internal package than it
+	 * should not be imported. Additionally, it is necessary to treat the
+	 * exports in groups. If an exported package refers to another exported
+	 * packages than it must be in the same group. A framework can only
+	 * substitute exports for imports for the whole of such a group. WHY?????
+	 * Not clear anymore ...
+	 */
+	Packages doExportsToImports(Packages exports) {
+
+		// private packages = contained - exported.
+		Set<PackageRef> privatePackages = new HashSet<PackageRef>(contained.keySet());
+		privatePackages.removeAll(exports.keySet());
+
+		// private references = ∀ p : private packages | uses(p)
+		Set<PackageRef> privateReferences = newSet();
+		for (PackageRef p : privatePackages) {
+			Collection<PackageRef> uses = this.uses.get(p);
+			if (uses != null)
+				privateReferences.addAll(uses);
+		}
+
+		// Assume we are going to export all exported packages
+		Set<PackageRef> toBeImported = new HashSet<PackageRef>(exports.keySet());
+
+		// Remove packages that are not referenced privately
+		toBeImported.retainAll(privateReferences);
+
+		// Not necessary to import anything that is already
+		// imported in the Import-Package statement.
+		// TODO toBeImported.removeAll(imports.keySet());
+
+		// Remove exported packages that are referring to
+		// private packages.
+		// Each exported package has a uses clause. We just use
+		// the used packages for each exported package to find out
+		// if it refers to an internal package.
+		//
+
+		for (Iterator<PackageRef> i = toBeImported.iterator(); i.hasNext();) {
+			PackageRef next = i.next();
+			Collection<PackageRef> usedByExportedPackage = this.uses.get(next);
+
+			// We had an NPE on usedByExportedPackage in GF.
+			// I guess this can happen with hard coded
+			// imports that do not match reality ...
+			if (usedByExportedPackage == null || usedByExportedPackage.isEmpty()) {
+				continue;
+			}
+
+			for (PackageRef privatePackage : privatePackages) {
+				if (usedByExportedPackage.contains(privatePackage)) {
+					i.remove();
+					break;
+				}
+			}
+		}
+
+		// Clean up attributes and generate result map
+		Packages result = new Packages();
+		for (Iterator<PackageRef> i = toBeImported.iterator(); i.hasNext();) {
+			PackageRef ep = i.next();
+			Attrs parameters = exports.get(ep);
+
+			String noimport = parameters == null ? null : parameters.get(NO_IMPORT_DIRECTIVE);
+			if (noimport != null && noimport.equalsIgnoreCase("true"))
+				continue;
+
+			// // we can't substitute when there is no version
+			// String version = parameters.get(VERSION_ATTRIBUTE);
+			// if (version == null) {
+			// if (isPedantic())
+			// warning(
+			// "Cannot automatically import exported package %s because it has no version defined",
+			// ep);
+			// continue;
+			// }
+
+			parameters = new Attrs();
+			parameters.remove(VERSION_ATTRIBUTE);
+			result.put(ep, parameters);
+		}
+		return result;
+	}
+
+	public boolean referred(PackageRef packageName) {
+		// return true;
+		for (Map.Entry<PackageRef,List<PackageRef>> contained : uses.entrySet()) {
+			if (!contained.getKey().equals(packageName)) {
+				if (contained.getValue().contains(packageName))
+					return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * @param jar
+	 */
+	private void getExternalExports(Jar jar, Packages classpathExports) {
+		try {
+			Manifest m = jar.getManifest();
+			if (m != null) {
+				Domain domain = Domain.domain(m);
+				Parameters exported = domain.getExportPackage();
+				for (Entry<String,Attrs> e : exported.entrySet()) {
+					PackageRef ref = getPackageRef(e.getKey());
+					if (!classpathExports.containsKey(ref)) {
+						// TODO e.getValue().put(SOURCE_DIRECTIVE,
+						// jar.getBsn()+"-"+jar.getVersion());
+
+						classpathExports.put(ref, e.getValue());
+					}
+				}
+			}
+		}
+		catch (Exception e) {
+			warning("Erroneous Manifest for " + jar + " " + e);
+		}
+	}
+
+	/**
+	 * Find some more information about imports in manifest and other places. It
+	 * is assumed that the augmentsExports has already copied external attrs
+	 * from the classpathExports.
+	 * 
+	 * @throws Exception
+	 */
+	void augmentImports(Packages imports, Packages exports) throws Exception {
+		List<PackageRef> noimports = Create.list();
+		Set<PackageRef> provided = findProvidedPackages();
+
+		for (PackageRef packageRef : imports.keySet()) {
+			String packageName = packageRef.getFQN();
+
+			setProperty(CURRENT_PACKAGE, packageName);
+			try {
+				Attrs importAttributes = imports.get(packageRef);
+				Attrs exportAttributes = exports.get(packageRef, classpathExports.get(packageRef, new Attrs()));
+
+				String exportVersion = exportAttributes.getVersion();
+				String importRange = importAttributes.getVersion();
+
+				if (exportVersion == null) {
+					// TODO Should check if the source is from a bundle.
+
+				} else {
+
+					//
+					// Version Policy - Import version substitution. We
+					// calculate the export version and then allow the
+					// import version attribute to use it in a substitution
+					// by using a ${@} macro. The export version can
+					// be defined externally or locally
+					//
+
+					boolean provider = isTrue(importAttributes.get(PROVIDE_DIRECTIVE))
+							|| isTrue(exportAttributes.get(PROVIDE_DIRECTIVE)) || provided.contains(packageRef);
+
+					exportVersion = cleanupVersion(exportVersion);
+
+					try {
+						setProperty("@", exportVersion);
+
+						if (importRange != null) {
+							importRange = cleanupVersion(importRange);
+							importRange = getReplacer().process(importRange);
+						} else
+							importRange = getVersionPolicy(provider);
+
+					}
+					finally {
+						unsetProperty("@");
+					}
+					importAttributes.put(VERSION_ATTRIBUTE, importRange);
+				}
+
+				//
+				// Check if exporter has mandatory attributes
+				//
+				String mandatory = exportAttributes.get(MANDATORY_DIRECTIVE);
+				if (mandatory != null) {
+					String[] attrs = mandatory.split("\\s*,\\s*");
+					for (int i = 0; i < attrs.length; i++) {
+						if (!importAttributes.containsKey(attrs[i]))
+							importAttributes.put(attrs[i], exportAttributes.get(attrs[i]));
+					}
+				}
+
+				if (exportAttributes.containsKey(IMPORT_DIRECTIVE))
+					importAttributes.put(IMPORT_DIRECTIVE, exportAttributes.get(IMPORT_DIRECTIVE));
+
+				fixupAttributes(importAttributes);
+				removeAttributes(importAttributes);
+
+				String result = importAttributes.get(Constants.VERSION_ATTRIBUTE);
+				if (result == null)
+					noimports.add(packageRef);
+			}
+			finally {
+				unsetProperty(CURRENT_PACKAGE);
+			}
+		}
+
+		if (isPedantic() && noimports.size() != 0) {
+			warning("Imports that lack version ranges: %s", noimports);
+		}
+	}
+
+	/**
+	 * Find the packages we depend on, where we implement an interface that is a
+	 * Provider Type. These packages, when we import them, must use the provider
+	 * policy.
+	 * 
+	 * @throws Exception
+	 */
+	Set<PackageRef> findProvidedPackages() throws Exception {
+		Set<PackageRef> providers = Create.set();
+		Set<TypeRef> cached = Create.set();
+
+		for (Clazz c : classspace.values()) {
+			TypeRef[] interfaces = c.getInterfaces();
+			if (interfaces != null)
+				for (TypeRef t : interfaces)
+					if (cached.contains(t) || isProvider(t)) {
+						cached.add(t);
+						providers.add(t.getPackageRef());
+					}
+		}
+		return providers;
+	}
+
+	private boolean isProvider(TypeRef t) throws Exception {
+		Clazz c = findClass(t);
+		if (c == null)
+			return false;
+
+		if (c.annotations == null)
+			return false;
+
+		TypeRef pt = getTypeRefFromFQN(ProviderType.class.getName());
+		boolean result = c.annotations.contains(pt);
+		return result;
+	}
+
+	/**
+	 * Provide any macro substitutions and versions for exported packages.
+	 */
+
+	void augmentExports(Packages exports) {
+		for (PackageRef packageRef : exports.keySet()) {
+			String packageName = packageRef.getFQN();
+			setProperty(CURRENT_PACKAGE, packageName);
+			try {
+				Attrs attributes = exports.get(packageRef);
+				Attrs exporterAttributes = classpathExports.get(packageRef);
+				if (exporterAttributes == null)
+					continue;
+
+				for (Map.Entry<String,String> entry : exporterAttributes.entrySet()) {
+					String key = entry.getKey();
+					if (key.equalsIgnoreCase(SPECIFICATION_VERSION))
+						key = VERSION_ATTRIBUTE;
+
+					// dont overwrite and no directives
+					if (!key.endsWith(":") && !attributes.containsKey(key)) {
+						attributes.put(key, entry.getValue());
+					}
+				}
+
+				fixupAttributes(attributes);
+				removeAttributes(attributes);
+
+			}
+			finally {
+				unsetProperty(CURRENT_PACKAGE);
+			}
+		}
+	}
+
+	/**
+	 * Fixup Attributes Execute any macros on an export and
+	 */
+
+	void fixupAttributes(Attrs attributes) {
+		// Convert any attribute values that have macros.
+		for (String key : attributes.keySet()) {
+			String value = attributes.get(key);
+			if (value.indexOf('$') >= 0) {
+				value = getReplacer().process(value);
+				attributes.put(key, value);
+			}
+		}
+
+	}
+
+	/**
+	 * Remove the attributes mentioned in the REMOVE_ATTRIBUTE_DIRECTIVE. You
+	 * can add a remove-attribute: directive with a regular expression for
+	 * attributes that need to be removed. We also remove all attributes that
+	 * have a value of !. This allows you to use macros with ${if} to remove
+	 * values.
+	 */
+
+	void removeAttributes(Attrs attributes) {
+		String remove = attributes.remove(REMOVE_ATTRIBUTE_DIRECTIVE);
+
+		if (remove != null) {
+			Instructions removeInstr = new Instructions(remove);
+			attributes.keySet().removeAll(removeInstr.select(attributes.keySet(), false));
+		}
+
+		// Remove any ! valued attributes
+		for (Iterator<Entry<String,String>> i = attributes.entrySet().iterator(); i.hasNext();) {
+			String v = i.next().getValue();
+			if (v.equals("!"))
+				i.remove();
+		}
+	}
+
+	/**
+	 * Calculate a version from a version policy.
+	 * 
+	 * @param version
+	 *            The actual exported version
+	 * @param impl
+	 *            true for implementations and false for clients
+	 */
+
+	String calculateVersionRange(String version, boolean impl) {
+		setProperty("@", version);
+		try {
+			return getVersionPolicy(impl);
+		}
+		finally {
+			unsetProperty("@");
+		}
+	}
+
+	/**
+	 * Add the uses clauses. This method iterates over the exports and cal
+	 * 
+	 * @param exports
+	 * @param uses
+	 * @throws MojoExecutionException
+	 */
+	void doUses(Packages exports, Map<PackageRef,List<PackageRef>> uses, Packages imports) {
+		if ("true".equalsIgnoreCase(getProperty(NOUSES)))
+			return;
+
+		for (Iterator<PackageRef> i = exports.keySet().iterator(); i.hasNext();) {
+			PackageRef packageRef = i.next();
+			String packageName = packageRef.getFQN();
+			setProperty(CURRENT_PACKAGE, packageName);
+			try {
+				doUses(packageRef, exports, uses, imports);
+			}
+			finally {
+				unsetProperty(CURRENT_PACKAGE);
+			}
+
+		}
+	}
+
+	/**
+	 * @param packageName
+	 * @param exports
+	 * @param uses
+	 * @param imports
+	 */
+	protected void doUses(PackageRef packageRef, Packages exports, Map<PackageRef,List<PackageRef>> uses,
+			Packages imports) {
+		Attrs clause = exports.get(packageRef);
+
+		// Check if someone already set the uses: directive
+		String override = clause.get(USES_DIRECTIVE);
+		if (override == null)
+			override = USES_USES;
+
+		// Get the used packages
+		Collection<PackageRef> usedPackages = uses.get(packageRef);
+
+		if (usedPackages != null) {
+
+			// Only do a uses on exported or imported packages
+			// and uses should also not contain our own package
+			// name
+			Set<PackageRef> sharedPackages = new TreeSet<PackageRef>();
+			sharedPackages.addAll(imports.keySet());
+			sharedPackages.addAll(exports.keySet());
+			sharedPackages.retainAll(usedPackages);
+			sharedPackages.remove(packageRef);
+
+			StringBuilder sb = new StringBuilder();
+			String del = "";
+			for (Iterator<PackageRef> u = sharedPackages.iterator(); u.hasNext();) {
+				PackageRef usedPackage = u.next();
+				if (!usedPackage.isJava()) {
+					sb.append(del);
+					sb.append(usedPackage.getFQN());
+					del = ",";
+				}
+			}
+			if (override.indexOf('$') >= 0) {
+				setProperty(CURRENT_USES, sb.toString());
+				override = getReplacer().process(override);
+				unsetProperty(CURRENT_USES);
+			} else
+				// This is for backward compatibility 0.0.287
+				// can be deprecated over time
+				override = override.replaceAll(USES_USES, Matcher.quoteReplacement(sb.toString())).trim();
+
+			if (override.endsWith(","))
+				override = override.substring(0, override.length() - 1);
+			if (override.startsWith(","))
+				override = override.substring(1);
+			if (override.length() > 0) {
+				clause.put(USES_DIRECTIVE, override);
+			}
+		}
+	}
+
+	/**
+	 * Transitively remove all elemens from unreachable through the uses link.
+	 * 
+	 * @param name
+	 * @param unreachable
+	 */
+	void removeTransitive(PackageRef name, Set<PackageRef> unreachable) {
+		if (!unreachable.contains(name))
+			return;
+
+		unreachable.remove(name);
+
+		List<PackageRef> ref = uses.get(name);
+		if (ref != null) {
+			for (Iterator<PackageRef> r = ref.iterator(); r.hasNext();) {
+				PackageRef element = r.next();
+				removeTransitive(element, unreachable);
+			}
+		}
+	}
+
+	/**
+	 * Helper method to set the package info resource
+	 * 
+	 * @param dir
+	 * @param key
+	 * @param value
+	 * @throws Exception
+	 */
+	void getExportVersionsFromPackageInfo(PackageRef packageRef, Resource r, Packages classpathExports)
+			throws Exception {
+		if (r == null)
+			return;
+
+		Properties p = new Properties();
+		try {
+			InputStream in = r.openInputStream();
+			try {
+				p.load(in);
+			}
+			finally {
+				in.close();
+			}
+			Attrs map = classpathExports.get(packageRef);
+			if (map == null) {
+				classpathExports.put(packageRef, map = new Attrs());
+			}
+			for (Enumeration<String> t = (Enumeration<String>) p.propertyNames(); t.hasMoreElements();) {
+				String key = t.nextElement();
+				String value = map.get(key);
+				if (value == null) {
+					value = p.getProperty(key);
+
+					// Messy, to allow directives we need to
+					// allow the value to start with a ':' since we cannot
+					// encode this in a property name
+
+					if (value.startsWith(":")) {
+						key = key + ":";
+						value = value.substring(1);
+					}
+					map.put(key, value);
+				}
+			}
+		}
+		catch (Exception e) {
+			msgs.NoSuchFile_(r);
+		}
+	}
+
+	@Override
+	public void close() {
+		if (diagnostics) {
+			PrintStream out = System.err;
+			out.printf("Current directory            : %s%n", new File("").getAbsolutePath());
+			out.println("Classpath used");
+			for (Jar jar : getClasspath()) {
+				out.printf("File                                : %s%n", jar.getSource());
+				out.printf("File abs path                       : %s%n", jar.getSource().getAbsolutePath());
+				out.printf("Name                                : %s%n", jar.getName());
+				Map<String,Map<String,Resource>> dirs = jar.getDirectories();
+				for (Map.Entry<String,Map<String,Resource>> entry : dirs.entrySet()) {
+					Map<String,Resource> dir = entry.getValue();
+					String name = entry.getKey().replace('/', '.');
+					if (dir != null) {
+						out.printf("                                      %-30s %d%n", name, dir.size());
+					} else {
+						out.printf("                                      %-30s <<empty>>%n", name);
+					}
+				}
+			}
+		}
+
+		super.close();
+		if (dot != null)
+			dot.close();
+
+		if (classpath != null)
+			for (Iterator<Jar> j = classpath.iterator(); j.hasNext();) {
+				Jar jar = j.next();
+				jar.close();
+			}
+	}
+
+	/**
+	 * Findpath looks through the contents of the JAR and finds paths that end
+	 * with the given regular expression ${findpath (; reg-expr (; replacement)?
+	 * )? }
+	 * 
+	 * @param args
+	 * @return
+	 */
+	public String _findpath(String args[]) {
+		return findPath("findpath", args, true);
+	}
+
+	public String _findname(String args[]) {
+		return findPath("findname", args, false);
+	}
+
+	String findPath(String name, String[] args, boolean fullPathName) {
+		if (args.length > 3) {
+			warning("Invalid nr of arguments to " + name + " " + Arrays.asList(args) + ", syntax: ${" + name
+					+ " (; reg-expr (; replacement)? )? }");
+			return null;
+		}
+
+		String regexp = ".*";
+		String replace = null;
+
+		switch (args.length) {
+			case 3 :
+				replace = args[2];
+				//$FALL-THROUGH$
+			case 2 :
+				regexp = args[1];
+		}
+		StringBuilder sb = new StringBuilder();
+		String del = "";
+
+		Pattern expr = Pattern.compile(regexp);
+		for (Iterator<String> e = dot.getResources().keySet().iterator(); e.hasNext();) {
+			String path = e.next();
+			if (!fullPathName) {
+				int n = path.lastIndexOf('/');
+				if (n >= 0) {
+					path = path.substring(n + 1);
+				}
+			}
+
+			Matcher m = expr.matcher(path);
+			if (m.matches()) {
+				if (replace != null)
+					path = m.replaceAll(replace);
+
+				sb.append(del);
+				sb.append(path);
+				del = ", ";
+			}
+		}
+		return sb.toString();
+	}
+
+	public void putAll(Map<String,String> additional, boolean force) {
+		for (Iterator<Map.Entry<String,String>> i = additional.entrySet().iterator(); i.hasNext();) {
+			Map.Entry<String,String> entry = i.next();
+			if (force || getProperties().get(entry.getKey()) == null)
+				setProperty(entry.getKey(), entry.getValue());
+		}
+	}
+
+	boolean	firstUse	= true;
+
+	public List<Jar> getClasspath() {
+		if (firstUse) {
+			firstUse = false;
+			String cp = getProperty(CLASSPATH);
+			if (cp != null)
+				for (String s : split(cp)) {
+					Jar jar = getJarFromName(s, "getting classpath");
+					if (jar != null)
+						addClasspath(jar);
+					else
+						warning("Cannot find entry on -classpath: %s", s);
+				}
+		}
+		return classpath;
+	}
+
+	public void addClasspath(Jar jar) {
+		if (isPedantic() && jar.getResources().isEmpty())
+			warning("There is an empty jar or directory on the classpath: " + jar.getName());
+
+		classpath.add(jar);
+	}
+
+	public void addClasspath(Collection< ? > jars) throws IOException {
+		for (Object jar : jars) {
+			if (jar instanceof Jar)
+				addClasspath((Jar) jar);
+			else if (jar instanceof File)
+				addClasspath((File) jar);
+			else if (jar instanceof String)
+				addClasspath(getFile((String) jar));
+			else
+				error("Cannot convert to JAR to add to classpath %s. Not a File, Jar, or String", jar);
+		}
+	}
+
+	public void addClasspath(File cp) throws IOException {
+		if (!cp.exists())
+			warning("File on classpath that does not exist: " + cp);
+		Jar jar = new Jar(cp);
+		addClose(jar);
+		classpath.add(jar);
+	}
+
+	@Override
+	public void clear() {
+		classpath.clear();
+	}
+
+	public Jar getTarget() {
+		return dot;
+	}
+
+	private void analyzeBundleClasspath() throws Exception {
+		Parameters bcp = getBundleClasspath();
+
+		if (bcp.isEmpty()) {
+			analyzeJar(dot, "", true);
+		} else {
+			boolean okToIncludeDirs = true;
+
+			for (String path : bcp.keySet()) {
+				if (dot.getDirectories().containsKey(path)) {
+					okToIncludeDirs = false;
+					break;
+				}
+			}
+
+			for (String path : bcp.keySet()) {
+				Attrs info = bcp.get(path);
+
+				if (path.equals(".")) {
+					analyzeJar(dot, "", okToIncludeDirs);
+					continue;
+				}
+				//
+				// There are 3 cases:
+				// - embedded JAR file
+				// - directory
+				// - error
+				//
+
+				Resource resource = dot.getResource(path);
+				if (resource != null) {
+					try {
+						Jar jar = new Jar(path);
+						addClose(jar);
+						EmbeddedResource.build(jar, resource);
+						analyzeJar(jar, "", true);
+					}
+					catch (Exception e) {
+						warning("Invalid bundle classpath entry: " + path + " " + e);
+					}
+				} else {
+					if (dot.getDirectories().containsKey(path)) {
+						// if directories are used, we should not have dot as we
+						// would have the classes in these directories on the
+						// class path twice.
+						if (bcp.containsKey("."))
+							warning("Bundle-ClassPath uses a directory '%s' as well as '.'. This means bnd does not know if a directory is a package.",
+									path, path);
+						analyzeJar(dot, Processor.appendPath(path) + "/", true);
+					} else {
+						if (!"optional".equals(info.get(RESOLUTION_DIRECTIVE)))
+							warning("No sub JAR or directory " + path);
+					}
+				}
+			}
+
+		}
+	}
+
+	/**
+	 * We traverse through all the classes that we can find and calculate the
+	 * contained and referred set and uses. This method ignores the Bundle
+	 * classpath.
+	 * 
+	 * @param jar
+	 * @param contained
+	 * @param referred
+	 * @param uses
+	 * @throws IOException
+	 */
+	private boolean analyzeJar(Jar jar, String prefix, boolean okToIncludeDirs) throws Exception {
+		Map<String,Clazz> mismatched = new HashMap<String,Clazz>();
+
+		next: for (String path : jar.getResources().keySet()) {
+			if (path.startsWith(prefix)) {
+
+				String relativePath = path.substring(prefix.length());
+
+				if (okToIncludeDirs) {
+					int n = relativePath.lastIndexOf('/');
+					if (n < 0)
+						n = relativePath.length();
+					String relativeDir = relativePath.substring(0, n);
+
+					PackageRef packageRef = getPackageRef(relativeDir);
+					if (!packageRef.isMetaData() && !contained.containsKey(packageRef)) {
+						contained.put(packageRef);
+
+						// For each package we encounter for the first
+						// time. Unfortunately we can only do this once
+						// we found a class since the bcp has a tendency
+						// to overlap
+						if (!packageRef.isMetaData()) {
+							Resource pinfo = jar.getResource(prefix + packageRef.getPath() + "/packageinfo");
+							getExportVersionsFromPackageInfo(packageRef, pinfo, classpathExports);
+						}
+					}
+				}
+
+				// Check class resources, we need to analyze them
+				if (path.endsWith(".class")) {
+					Resource resource = jar.getResource(path);
+					Clazz clazz;
+					Attrs info = null;
+
+					try {
+						InputStream in = resource.openInputStream();
+						clazz = new Clazz(this, path, resource);
+						try {
+							// Check if we have a package-info
+							if (relativePath.endsWith("/package-info.class")) {
+								// package-info can contain an Export annotation
+								info = new Attrs();
+								parsePackageInfoClass(clazz, info);
+							} else {
+								// Otherwise we just parse it simply
+								clazz.parseClassFile();
+							}
+						}
+						finally {
+							in.close();
+						}
+					}
+					catch (Throwable e) {
+						error("Invalid class file %s (%s)", e, relativePath, e);
+						e.printStackTrace();
+						continue next;
+					}
+
+					String calculatedPath = clazz.getClassName().getPath();
+					if (!calculatedPath.equals(relativePath)) {
+						// If there is a mismatch we
+						// warning
+						if (okToIncludeDirs) // assume already reported
+							mismatched.put(clazz.getAbsolutePath(), clazz);
+					} else {
+						classspace.put(clazz.getClassName(), clazz);
+						PackageRef packageRef = clazz.getClassName().getPackageRef();
+
+						if (!contained.containsKey(packageRef)) {
+							contained.put(packageRef);
+							if (!packageRef.isMetaData()) {
+								Resource pinfo = jar.getResource(prefix + packageRef.getPath() + "/packageinfo");
+								getExportVersionsFromPackageInfo(packageRef, pinfo, classpathExports);
+							}
+						}
+						if (info != null)
+							contained.merge(packageRef, false, info);
+
+						// Look at the referred packages
+						// and copy them to our baseline
+						Set<PackageRef> refs = Create.set();
+						for (PackageRef p : clazz.getReferred()) {
+							referred.put(p);
+							refs.add(p);
+						}
+						refs.remove(packageRef);
+						uses.addAll(packageRef, refs);
+
+						// Collect the API
+						apiUses.addAll(packageRef, clazz.getAPIUses());
+					}
+				}
+			}
+		}
+
+		if (mismatched.size() > 0) {
+			error("Classes found in the wrong directory: %s", mismatched);
+			return false;
+		}
+		return true;
+	}
+
+	static Pattern	OBJECT_REFERENCE	= Pattern.compile("L([^/]+/)*([^;]+);");
+
+	private void parsePackageInfoClass(final Clazz clazz, final Attrs info) throws Exception {
+		clazz.parseClassFileWithCollector(new ClassDataCollector() {
+			@Override
+			public void annotation(Annotation a) {
+				String name = a.name.getFQN();
+				if (aQute.bnd.annotation.Version.class.getName().equals(name)) {
+
+					// Check version
+					String version = a.get("value");
+					if (!info.containsKey(Constants.VERSION_ATTRIBUTE)) {
+						if (version != null) {
+							version = getReplacer().process(version);
+							if (Verifier.VERSION.matcher(version).matches())
+								info.put(VERSION_ATTRIBUTE, version);
+							else
+								error("Export annotation in %s has invalid version info: %s", clazz, version);
+						}
+					} else {
+						// Verify this matches with packageinfo
+						String presentVersion = info.get(VERSION_ATTRIBUTE);
+						try {
+							Version av = new Version(presentVersion);
+							Version bv = new Version(version);
+							if (!av.equals(bv)) {
+								error("Version from annotation for %s differs with packageinfo or Manifest", clazz
+										.getClassName().getFQN());
+							}
+						}
+						catch (Exception e) {
+							// Ignore
+						}
+					}
+				} else if (name.equals(Export.class.getName())) {
+
+					// Check mandatory attributes
+					Attrs attrs = doAttrbutes((Object[]) a.get(Export.MANDATORY), clazz, getReplacer());
+					if (!attrs.isEmpty()) {
+						info.putAll(attrs);
+						info.put(MANDATORY_DIRECTIVE, Processor.join(attrs.keySet()));
+					}
+
+					// Check optional attributes
+					attrs = doAttrbutes((Object[]) a.get(Export.OPTIONAL), clazz, getReplacer());
+					if (!attrs.isEmpty()) {
+						info.putAll(attrs);
+					}
+
+					// Check Included classes
+					Object[] included = a.get(Export.INCLUDE);
+					if (included != null && included.length > 0) {
+						StringBuilder sb = new StringBuilder();
+						String del = "";
+						for (Object i : included) {
+							Matcher m = OBJECT_REFERENCE.matcher((String) i);
+							if (m.matches()) {
+								sb.append(del);
+								sb.append(m.group(2));
+								del = ",";
+							}
+						}
+						info.put(INCLUDE_DIRECTIVE, sb.toString());
+					}
+
+					// Check Excluded classes
+					Object[] excluded = a.get(Export.EXCLUDE);
+					if (excluded != null && excluded.length > 0) {
+						StringBuilder sb = new StringBuilder();
+						String del = "";
+						for (Object i : excluded) {
+							Matcher m = OBJECT_REFERENCE.matcher((String) i);
+							if (m.matches()) {
+								sb.append(del);
+								sb.append(m.group(2));
+								del = ",";
+							}
+						}
+						info.put(EXCLUDE_DIRECTIVE, sb.toString());
+					}
+
+					// Check Uses
+					Object[] uses = a.get(Export.USES);
+					if (uses != null && uses.length > 0) {
+						String old = info.get(USES_DIRECTIVE);
+						if (old == null)
+							old = "";
+						StringBuilder sb = new StringBuilder(old);
+						String del = sb.length() == 0 ? "" : ",";
+
+						for (Object use : uses) {
+							sb.append(del);
+							sb.append(use);
+							del = ",";
+						}
+						info.put(USES_DIRECTIVE, sb.toString());
+					}
+				}
+			}
+
+		});
+	}
+
+	/**
+	 * Clean up version parameters. Other builders use more fuzzy definitions of
+	 * the version syntax. This method cleans up such a version to match an OSGi
+	 * version.
+	 * 
+	 * @param VERSION_STRING
+	 * @return
+	 */
+	static Pattern	fuzzyVersion		= Pattern.compile("(\\d+)(\\.(\\d+)(\\.(\\d+))?)?([^a-zA-Z0-9](.*))?",
+												Pattern.DOTALL);
+	static Pattern	fuzzyVersionRange	= Pattern.compile(
+												"(\\(|\\[)\\s*([-\\da-zA-Z.]+)\\s*,\\s*([-\\da-zA-Z.]+)\\s*(\\]|\\))",
+												Pattern.DOTALL);
+	static Pattern	fuzzyModifier		= Pattern.compile("(\\d+[.-])*(.*)", Pattern.DOTALL);
+
+	static Pattern	nummeric			= Pattern.compile("\\d*");
+
+	static public String cleanupVersion(String version) {
+		Matcher m = Verifier.VERSIONRANGE.matcher(version);
+
+		if (m.matches()) {
+			try {
+				VersionRange vr = new VersionRange(version);
+				return version;
+			} catch( Exception e) {
+				// ignore
+			}
+		}
+
+		m = fuzzyVersionRange.matcher(version);
+		if (m.matches()) {
+			String prefix = m.group(1);
+			String first = m.group(2);
+			String last = m.group(3);
+			String suffix = m.group(4);
+			return prefix + cleanupVersion(first) + "," + cleanupVersion(last) + suffix;
+		}
+
+		m = fuzzyVersion.matcher(version);
+		if (m.matches()) {
+			StringBuilder result = new StringBuilder();
+			String major = removeLeadingZeroes(m.group(1));
+			String minor = removeLeadingZeroes(m.group(3));
+			String micro = removeLeadingZeroes(m.group(5));
+			String qualifier = m.group(7);
+
+			if (qualifier == null) {
+				if (!isInteger(minor)) {
+					qualifier = minor;
+					minor = "0";
+				} else if (!isInteger(micro)) {
+					qualifier = micro;
+					micro = "0";
+				}
+			}
+			if (major != null) {
+				result.append(major);
+				if (minor != null) {
+					result.append(".");
+					result.append(minor);
+					if (micro != null) {
+						result.append(".");
+						result.append(micro);
+						if (qualifier != null) {
+							result.append(".");
+							cleanupModifier(result, qualifier);
+						}
+					} else if (qualifier != null) {
+						result.append(".0.");
+						cleanupModifier(result, qualifier);
+					}
+				} else if (qualifier != null) {
+					result.append(".0.0.");
+					cleanupModifier(result, qualifier);
+				}
+				return result.toString();
+			}
+		}
+		return version;
+	}
+
+	/**
+	 * TRhe cleanup version got confused when people used numeric dates like
+	 * 201209091230120 as qualifiers. These are too large for Integers. This
+	 * method checks if the all digit string fits in an integer.
+	 * <pre>
+	 * maxint = 2,147,483,647 = 10 digits
+	 * </pre>	 
+	 * @param integer
+	 * @return if this fits in an integer
+	 */
+	private static boolean isInteger(String minor) {
+		return minor.length() < 10 || (minor.length() == 10 && minor.compareTo("2147483647") < 0);
+	}
+
+	private static String removeLeadingZeroes(String group) {
+		if (group == null)
+			return "0";
+
+		int n = 0;
+		while (n < group.length() - 1 && group.charAt(n) == '0')
+			n++;
+		if (n == 0)
+			return group;
+
+		return group.substring(n);
+	}
+
+	static void cleanupModifier(StringBuilder result, String modifier) {
+		Matcher m = fuzzyModifier.matcher(modifier);
+		if (m.matches())
+			modifier = m.group(2);
+
+		for (int i = 0; i < modifier.length(); i++) {
+			char c = modifier.charAt(i);
+			if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || c == '-')
+				result.append(c);
+		}
+	}
+
+	final static String	DEFAULT_PROVIDER_POLICY	= "${range;[==,=+)}";
+	final static String	DEFAULT_CONSUMER_POLICY	= "${range;[==,+)}";
+
+	public String getVersionPolicy(boolean implemented) {
+		if (implemented) {
+			return getProperty(PROVIDER_POLICY, DEFAULT_PROVIDER_POLICY);
+		}
+
+		return getProperty(CONSUMER_POLICY, DEFAULT_CONSUMER_POLICY);
+	}
+
+	/**
+	 * The extends macro traverses all classes and returns a list of class names
+	 * that extend a base class.
+	 */
+
+	static String	_classesHelp	= "${classes;'implementing'|'extending'|'importing'|'named'|'version'|'any';<pattern>}, Return a list of class fully qualified class names that extend/implement/import any of the contained classes matching the pattern\n";
+
+	public String _classes(String... args) throws Exception {
+		// Macro.verifyCommand(args, _classesHelp, new
+		// Pattern[]{null,Pattern.compile("(implementing|implements|extending|extends|importing|imports|any)"),
+		// null}, 3,3);
+
+		Collection<Clazz> matched = getClasses(args);
+		if (matched.isEmpty())
+			return "";
+
+		return join(matched);
+	}
+
+	public Collection<Clazz> getClasses(String... args) throws Exception {
+
+		Set<Clazz> matched = new HashSet<Clazz>(classspace.values());
+		for (int i = 1; i < args.length; i++) {
+			if (args.length < i + 1)
+				throw new IllegalArgumentException("${classes} macro must have odd number of arguments. "
+						+ _classesHelp);
+
+			String typeName = args[i];
+			if (typeName.equalsIgnoreCase("extending"))
+				typeName = "extends";
+			else if (typeName.equalsIgnoreCase("importing"))
+				typeName = "imports";
+			else if (typeName.equalsIgnoreCase("annotation"))
+				typeName = "annotated";
+			else if (typeName.equalsIgnoreCase("implementing"))
+				typeName = "implements";
+
+			Clazz.QUERY type = Clazz.QUERY.valueOf(typeName.toUpperCase());
+
+			if (type == null)
+				throw new IllegalArgumentException("${classes} has invalid type: " + typeName + ". " + _classesHelp);
+
+			Instruction instr = null;
+			if (Clazz.HAS_ARGUMENT.contains(type)) {
+				String s = args[++i];
+				instr = new Instruction(s);
+			}
+			for (Iterator<Clazz> c = matched.iterator(); c.hasNext();) {
+				Clazz clazz = c.next();
+				if (!clazz.is(type, instr, this)) {
+					c.remove();
+				}
+			}
+		}
+		return matched;
+	}
+
+	/**
+	 * Get the exporter of a package ...
+	 */
+
+	public String _exporters(String args[]) throws Exception {
+		Macro.verifyCommand(args, "${exporters;<packagename>}, returns the list of jars that export the given package",
+				null, 2, 2);
+		StringBuilder sb = new StringBuilder();
+		String del = "";
+		String pack = args[1].replace('.', '/');
+		for (Jar jar : classpath) {
+			if (jar.getDirectories().containsKey(pack)) {
+				sb.append(del);
+				sb.append(jar.getName());
+			}
+		}
+		return sb.toString();
+	}
+
+	public Map<TypeRef,Clazz> getClassspace() {
+		return classspace;
+	}
+
+	/**
+	 * Locate a resource on the class path.
+	 * 
+	 * @param path
+	 *            Path of the reosurce
+	 * @return A resource or <code>null</code>
+	 */
+	public Resource findResource(String path) {
+		for (Jar entry : getClasspath()) {
+			Resource r = entry.getResource(path);
+			if (r != null)
+				return r;
+		}
+		return null;
+	}
+
+	/**
+	 * Find a clazz on the class path. This class has been parsed.
+	 * 
+	 * @param path
+	 * @return
+	 */
+	public Clazz findClass(TypeRef typeRef) throws Exception {
+		Clazz c = classspace.get(typeRef);
+		if (c != null)
+			return c;
+
+		c = importedClassesCache.get(typeRef);
+		if (c != null)
+			return c;
+
+		Resource r = findResource(typeRef.getPath());
+		if (r == null) {
+			getClass().getClassLoader();
+			URL url = ClassLoader.getSystemResource(typeRef.getPath());
+			if (url != null)
+				r = new URLResource(url);
+		}
+		if (r != null) {
+			c = new Clazz(this, typeRef.getPath(), r);
+			c.parseClassFile();
+			importedClassesCache.put(typeRef, c);
+		}
+		return c;
+	}
+
+	/**
+	 * Answer the bundle version.
+	 * 
+	 * @return
+	 */
+	public String getVersion() {
+		String version = getProperty(BUNDLE_VERSION);
+		if (version == null)
+			version = "0.0.0";
+		return version;
+	}
+
+	public boolean isNoBundle() {
+		return isTrue(getProperty(RESOURCEONLY)) || isTrue(getProperty(NOMANIFEST));
+	}
+
+	public void referTo(TypeRef ref) {
+		PackageRef pack = ref.getPackageRef();
+		if (!referred.containsKey(pack))
+			referred.put(pack, new Attrs());
+	}
+
+	public void referToByBinaryName(String binaryClassName) {
+		TypeRef ref = descriptors.getTypeRef(binaryClassName);
+		referTo(ref);
+	}
+
+	/**
+	 * Ensure that we are running on the correct bnd.
+	 */
+	void doRequireBnd() {
+		Attrs require = OSGiHeader.parseProperties(getProperty(REQUIRE_BND));
+		if (require == null || require.isEmpty())
+			return;
+
+		Hashtable<String,String> map = new Hashtable<String,String>();
+		map.put(Constants.VERSION_FILTER, getBndVersion());
+
+		for (String filter : require.keySet()) {
+			try {
+				Filter f = new Filter(filter);
+				if (f.match(map))
+					continue;
+				error("%s fails %s", REQUIRE_BND, require.get(filter));
+			}
+			catch (Exception t) {
+				error("%s with value %s throws exception", t, REQUIRE_BND, require);
+			}
+		}
+	}
+
+	/**
+	 * md5 macro
+	 */
+
+	static String	_md5Help	= "${md5;path}";
+
+	public String _md5(String args[]) throws Exception {
+		Macro.verifyCommand(args, _md5Help, new Pattern[] {
+				null, null, Pattern.compile("base64|hex")
+		}, 2, 3);
+
+		Digester<MD5> digester = MD5.getDigester();
+		Resource r = dot.getResource(args[1]);
+		if (r == null)
+			throw new FileNotFoundException("From " + digester + ", not found " + args[1]);
+
+		IO.copy(r.openInputStream(), digester);
+		boolean hex = args.length > 2 && args[2].equals("hex");
+		if (hex)
+			return Hex.toHexString(digester.digest().digest());
+
+		return Base64.encodeBase64(digester.digest().digest());
+	}
+
+	/**
+	 * SHA1 macro
+	 */
+
+	static String	_sha1Help	= "${sha1;path}";
+
+	public String _sha1(String args[]) throws Exception {
+		Macro.verifyCommand(args, _sha1Help, new Pattern[] {
+				null, null, Pattern.compile("base64|hex")
+		}, 2, 3);
+		Digester<SHA1> digester = SHA1.getDigester();
+		Resource r = dot.getResource(args[1]);
+		if (r == null)
+			throw new FileNotFoundException("From sha1, not found " + args[1]);
+
+		IO.copy(r.openInputStream(), digester);
+		return Base64.encodeBase64(digester.digest().digest());
+	}
+
+	public Descriptor getDescriptor(String descriptor) {
+		return descriptors.getDescriptor(descriptor);
+	}
+
+	public TypeRef getTypeRef(String binaryClassName) {
+		return descriptors.getTypeRef(binaryClassName);
+	}
+
+	public PackageRef getPackageRef(String binaryName) {
+		return descriptors.getPackageRef(binaryName);
+	}
+
+	public TypeRef getTypeRefFromFQN(String fqn) {
+		return descriptors.getTypeRefFromFQN(fqn);
+	}
+
+	public TypeRef getTypeRefFromPath(String path) {
+		return descriptors.getTypeRefFromPath(path);
+	}
+
+	public boolean isImported(PackageRef packageRef) {
+		return imports.containsKey(packageRef);
+	}
+
+	/**
+	 * Merge the attributes of two maps, where the first map can contain
+	 * wildcarded names. The idea is that the first map contains instructions
+	 * (for example *) with a set of attributes. These patterns are matched
+	 * against the found packages in actual. If they match, the result is set
+	 * with the merged set of attributes. It is expected that the instructions
+	 * are ordered so that the instructor can define which pattern matches
+	 * first. Attributes in the instructions override any attributes from the
+	 * actual.<br/>
+	 * A pattern is a modified regexp so it looks like globbing. The * becomes a
+	 * .* just like the ? becomes a .?. '.' are replaced with \\. Additionally,
+	 * if the pattern starts with an exclamation mark, it will remove that
+	 * matches for that pattern (- the !) from the working set. So the following
+	 * patterns should work:
+	 * <ul>
+	 * <li>com.foo.bar</li>
+	 * <li>com.foo.*</li>
+	 * <li>com.foo.???</li>
+	 * <li>com.*.[^b][^a][^r]</li>
+	 * <li>!com.foo.* (throws away any match for com.foo.*)</li>
+	 * </ul>
+	 * Enough rope to hang the average developer I would say.
+	 * 
+	 * @param instructions
+	 *            the instructions with patterns.
+	 * @param source
+	 *            the actual found packages, contains no duplicates
+	 * @return Only the packages that were filtered by the given instructions
+	 */
+
+	Packages filter(Instructions instructions, Packages source, Set<Instruction> nomatch) {
+		Packages result = new Packages();
+		List<PackageRef> refs = new ArrayList<PackageRef>(source.keySet());
+		Collections.sort(refs);
+
+		List<Instruction> filters = new ArrayList<Instruction>(instructions.keySet());
+		if (nomatch == null)
+			nomatch = Create.set();
+
+		for (Instruction instruction : filters) {
+			boolean match = false;
+
+			for (Iterator<PackageRef> i = refs.iterator(); i.hasNext();) {
+				PackageRef packageRef = i.next();
+
+				if (packageRef.isMetaData()) {
+					i.remove(); // no use checking it again
+					continue;
+				}
+
+				String packageName = packageRef.getFQN();
+
+				if (instruction.matches(packageName)) {
+					match = true;
+					if (!instruction.isNegated()) {
+						result.merge(packageRef, instruction.isDuplicate(), source.get(packageRef),
+								instructions.get(instruction));
+					}
+					i.remove(); // Can never match again for another pattern
+				}
+			}
+			if (!match && !instruction.isAny())
+				nomatch.add(instruction);
+		}
+
+		/*
+		 * Tricky. If we have umatched instructions they might indicate that we
+		 * want to have multiple decorators for the same package. So we check
+		 * the unmatched against the result list. If then then match and have
+		 * actually interesting properties then we merge them
+		 */
+
+		for (Iterator<Instruction> i = nomatch.iterator(); i.hasNext();) {
+			Instruction instruction = i.next();
+
+			// We assume the user knows what he is
+			// doing and inserted a literal. So
+			// we ignore any not matched literals
+			// #252, we should not be negated to make it a constant
+			if (instruction.isLiteral() && !instruction.isNegated()) {
+				result.merge(getPackageRef(instruction.getLiteral()), true, instructions.get(instruction));
+				i.remove();
+				continue;
+			}
+
+			// Not matching a negated instruction looks
+			// like an error ... Though so, but
+			// in the second phase of Export-Package
+			// the !package will never match anymore.
+			if (instruction.isNegated()) {
+				i.remove();
+				continue;
+			}
+
+			// An optional instruction should not generate
+			// an error
+			if (instruction.isOptional()) {
+				i.remove();
+				continue;
+			}
+
+			// boolean matched = false;
+			// Set<PackageRef> prefs = new HashSet<PackageRef>(result.keySet());
+			// for (PackageRef ref : prefs) {
+			// if (instruction.matches(ref.getFQN())) {
+			// result.merge(ref, true, source.get(ref),
+			// instructions.get(instruction));
+			// matched = true;
+			// }
+			// }
+			// if (matched)
+			// i.remove();
+		}
+		return result;
+	}
+
+	public void setDiagnostics(boolean b) {
+		diagnostics = b;
+	}
+
+	public Clazz.JAVA getLowestEE() {
+		if (ees.isEmpty())
+			return Clazz.JAVA.JDK1_4;
+
+		return ees.first();
+	}
+
+	public String _ee(@SuppressWarnings("unused")
+	String args[]) {
+		return getLowestEE().getEE();
+	}
+
+	/**
+	 * Calculate the output file for the given target. The strategy is:
+	 * 
+	 * <pre>
+	 * parameter given if not null and not directory
+	 * if directory, this will be the output directory
+	 * based on bsn-version.jar
+	 * name of the source file if exists
+	 * Untitled-[n]
+	 * </pre>
+	 * 
+	 * @param output
+	 *            may be null, otherwise a file path relative to base
+	 */
+	public File getOutputFile(String output) {
+
+		if (output == null)
+			output = get(Constants.OUTPUT);
+
+		File outputDir;
+
+		if (output != null) {
+			File outputFile = getFile(output);
+			if (outputFile.isDirectory())
+				outputDir = outputFile;
+			else
+				return outputFile;
+		} else
+			outputDir = getBase();
+
+		Entry<String,Attrs> name = getBundleSymbolicName();
+		if (name != null) {
+			String bsn = name.getKey();
+			String version = getBundleVersion();
+			Version v = Version.parseVersion(version);
+			String outputName = bsn + "-" + v.getWithoutQualifier() + Constants.DEFAULT_JAR_EXTENSION;
+			return new File(outputDir, outputName);
+		}
+
+		File source = getJar().getSource();
+		if (source != null) {
+			String outputName = source.getName();
+			return new File(outputDir, outputName);
+		}
+
+		error("Cannot establish an output name from %s, nor bsn, nor source file name, using Untitled", output);
+		int n = 0;
+		File f = getFile(outputDir, "Untitled");
+		while (f.isFile()) {
+			f = getFile(outputDir, "Untitled-" + n++);
+		}
+		return f;
+	}
+
+	/**
+	 * Utility function to carefully save the file. Will create a backup if the
+	 * source file has the same path as the output. It will also only save if
+	 * the file was modified or the force flag is true
+	 * 
+	 * @param output
+	 *            the output file, if null {@link #getOutputFile(String)} is
+	 *            used.
+	 * @param force
+	 *            if it needs to be overwritten
+	 * @throws Exception
+	 */
+
+	public boolean save(File output, boolean force) throws Exception {
+		if (output == null)
+			output = getOutputFile(null);
+
+		Jar jar = getJar();
+		File source = jar.getSource();
+
+		trace("check for modified build=%s file=%s, diff=%s", jar.lastModified(), output.lastModified(),
+				jar.lastModified() - output.lastModified());
+
+		if (!output.exists() || output.lastModified() <= jar.lastModified() || force) {
+			File op = output.getParentFile();
+			if (!op.exists() && !op.mkdirs()) {
+				throw new IOException("Could not create directory " + op);
+			}
+			if (source != null && output.getCanonicalPath().equals(source.getCanonicalPath())) {
+				File bak = new File(source.getParentFile(), source.getName() + ".bak");
+				if (!source.renameTo(bak)) {
+					error("Could not create backup file %s", bak);
+				} else
+					source.delete();
+			}
+			try {
+				trace("Saving jar to %s", output);
+				getJar().write(output);
+			}
+			catch (Exception e) {
+				output.delete();
+				error("Cannot write JAR file to %s due to %s", e, output, e.getMessage());
+			}
+			return true;
+		}
+		trace("Not modified %s", output);
+		return false;
+
+	}
+
+	/**
+	 * Set default import and export instructions if none are set
+	 */
+	public void setDefaults(String bsn, Version version) {
+		if (getExportPackage() == null)
+			setExportPackage("*");
+		if (getImportPackage() == null)
+			setExportPackage("*");
+		if (bsn != null && getBundleSymbolicName() == null)
+			setBundleSymbolicName(bsn);
+		if (version != null && getBundleVersion() == null)
+			setBundleVersion(version);
+	}
+
+	/**
+	 * Remove the own references and optional java references from the uses lib
+	 * 
+	 * @param apiUses
+	 * @param removeJava
+	 * @return
+	 */
+	public Map<PackageRef,List<PackageRef>> cleanupUses(Map<PackageRef,List<PackageRef>> apiUses, boolean removeJava) {
+		MultiMap<PackageRef,PackageRef> map = new MultiMap<PackageRef,PackageRef>(apiUses);
+		for (Entry<PackageRef,List<PackageRef>> e : map.entrySet()) {
+			e.getValue().remove(e.getKey());
+			if (!removeJava)
+				continue;
+
+			for (Iterator<PackageRef> i = e.getValue().iterator(); i.hasNext();) {
+				if (i.next().isJava())
+					i.remove();
+			}
+		}
+		return map;
+	}
+
+	/**
+	 * Return the classes for a given source package.
+	 * 
+	 * @param source
+	 *            the source package
+	 * @return a set of classes for the requested package.
+	 */
+	public Set<Clazz> getClassspace(PackageRef source) {
+		Set<Clazz> result = new HashSet<Clazz>();
+		for (Clazz c : getClassspace().values()) {
+			if (c.getClassName().getPackageRef() == source)
+				result.add(c);
+		}
+		return result;
+	}
+
+	/**
+	 * Create a cross reference from package source, to packages in dest
+	 * 
+	 * @param source
+	 * @param dest
+	 * @param sourceModifiers
+	 * @return
+	 * @throws Exception
+	 */
+	public Map<Clazz.Def,List<TypeRef>> getXRef(final PackageRef source, final Collection<PackageRef> dest,
+			final int sourceModifiers) throws Exception {
+		final MultiMap<Clazz.Def,TypeRef> xref = new MultiMap<Clazz.Def,TypeRef>(Clazz.Def.class, TypeRef.class, true);
+
+		for (final Clazz clazz : getClassspace().values()) {
+			if ((clazz.accessx & sourceModifiers) == 0)
+				continue;
+
+			if (source != null && source != clazz.getClassName().getPackageRef())
+				continue;
+
+			clazz.parseClassFileWithCollector(new ClassDataCollector() {
+				Clazz.Def	member;
+
+				@Override
+				public void extendsClass(TypeRef zuper) throws Exception {
+					if (dest.contains(zuper.getPackageRef()))
+						xref.add(clazz.getExtends(zuper), zuper);
+				}
+
+				@Override
+				public void implementsInterfaces(TypeRef[] interfaces) throws Exception {
+					for (TypeRef i : interfaces) {
+						if (dest.contains(i.getPackageRef()))
+							xref.add(clazz.getImplements(i), i);
+					}
+				}
+
+				@Override
+				public void referTo(TypeRef to, int modifiers) {
+					if (to.isJava())
+						return;
+
+					if (!dest.contains(to.getPackageRef()))
+						return;
+
+					if (member != null && ((modifiers & sourceModifiers) != 0)) {
+						xref.add(member, to);
+					}
+
+				}
+
+				@Override
+				public void method(Clazz.MethodDef defined) {
+					member = defined;
+				}
+
+				@Override
+				public void field(Clazz.FieldDef defined) {
+					member = defined;
+				}
+
+			});
+
+		}
+		return xref;
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/AnalyzerMessages.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/AnalyzerMessages.java
new file mode 100644
index 0000000..95b32df
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/AnalyzerMessages.java
@@ -0,0 +1,13 @@
+package aQute.bnd.osgi;
+
+import java.util.*;
+
+import aQute.bnd.osgi.Descriptors.PackageRef;
+import aQute.service.reporter.*;
+
+public interface AnalyzerMessages extends Messages {
+
+	WARNING Export_Has_PrivateReferences_(PackageRef exported, int count, Collection<PackageRef> local);
+/**/
+}
+
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/Annotation.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/Annotation.java
new file mode 100644
index 0000000..aca0a11
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/Annotation.java
@@ -0,0 +1,82 @@
+package aQute.bnd.osgi;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import aQute.bnd.annotation.metatype.*;
+import aQute.bnd.osgi.Descriptors.TypeRef;
+
+public class Annotation {
+	TypeRef				name;
+	Map<String,Object>	elements;
+	ElementType			member;
+	RetentionPolicy		policy;
+
+	public Annotation(TypeRef name, Map<String,Object> elements, ElementType member, RetentionPolicy policy) {
+		this.name = name;
+		if (elements == null)
+			this.elements = Collections.emptyMap();
+		else
+			this.elements = elements;
+		this.member = member;
+		this.policy = policy;
+	}
+
+	public TypeRef getName() {
+		return name;
+	}
+
+	public ElementType getElementType() {
+		return member;
+	}
+
+	public RetentionPolicy getRetentionPolicy() {
+		return policy;
+	}
+
+	@Override
+	public String toString() {
+		return name + ":" + member + ":" + policy + ":" + elements;
+	}
+
+	public <T> T get(String string) {
+		if (elements == null)
+			return null;
+
+		return (T) elements.get(string);
+	}
+
+	public <T> void put(String string, Object v) {
+		if (elements == null)
+			return;
+
+		elements.put(string, v);
+	}
+
+	public Set<String> keySet() {
+		if (elements == null)
+			return Collections.emptySet();
+
+		return elements.keySet();
+	}
+
+	public <T extends java.lang.annotation.Annotation> T getAnnotation() throws Exception {
+		String cname = name.getFQN();
+		try {
+			Class<T> c = (Class<T>) getClass().getClassLoader().loadClass(cname);
+			return getAnnotation(c);
+		}
+		catch (ClassNotFoundException e) {
+		}
+		catch (NoClassDefFoundError e) {
+		}
+		return null;
+	}
+
+	public <T extends java.lang.annotation.Annotation> T getAnnotation(Class<T> c) throws Exception {
+		String cname = name.getFQN();
+		if (!c.getName().equals(cname))
+			return null;
+		return Configurable.createConfigurable(c, elements);
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/Builder.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/Builder.java
new file mode 100755
index 0000000..a6aab45
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/Builder.java
@@ -0,0 +1,1527 @@
+package aQute.bnd.osgi;
+
+import java.io.*;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.jar.*;
+import java.util.regex.*;
+import java.util.zip.*;
+
+import aQute.bnd.component.*;
+import aQute.bnd.differ.*;
+import aQute.bnd.header.*;
+import aQute.bnd.make.*;
+import aQute.bnd.make.component.*;
+import aQute.bnd.make.metatype.*;
+import aQute.bnd.maven.*;
+import aQute.bnd.osgi.Descriptors.PackageRef;
+import aQute.bnd.osgi.Descriptors.TypeRef;
+import aQute.bnd.service.*;
+import aQute.bnd.service.diff.*;
+import aQute.lib.collections.*;
+import aQute.libg.generics.*;
+
+/**
+ * Include-Resource: ( [name '=' ] file )+ Private-Package: package-decl ( ','
+ * package-decl )* Export-Package: package-decl ( ',' package-decl )*
+ * Import-Package: package-decl ( ',' package-decl )*
+ * 
+ * @version $Revision: 1.27 $
+ */
+public class Builder extends Analyzer {
+	static Pattern					IR_PATTERN			= Pattern.compile("[{]?-?@?(?:[^=]+=)?\\s*([^}!]+).*");
+	private final DiffPluginImpl	differ				= new DiffPluginImpl();
+	private Pattern					xdoNotCopy			= null;
+	private static final int		SPLIT_MERGE_LAST	= 1;
+	private static final int		SPLIT_MERGE_FIRST	= 2;
+	private static final int		SPLIT_ERROR			= 3;
+	private static final int		SPLIT_FIRST			= 4;
+	private static final int		SPLIT_DEFAULT		= 0;
+	private final List<File>		sourcePath			= new ArrayList<File>();
+	private final Make				make				= new Make(this);
+
+	public Builder(Processor parent) {
+		super(parent);
+	}
+
+	public Builder() {}
+
+	public Jar build() throws Exception {
+		trace("build");
+		init();
+		if (isTrue(getProperty(NOBUNDLES)))
+			return null;
+
+		if (getProperty(CONDUIT) != null)
+			error("Specified " + CONDUIT + " but calls build() instead of builds() (might be a programmer error");
+
+		Jar dot = new Jar("dot");
+		try {
+			long modified = Long.parseLong(getProperty("base.modified"));
+			dot.updateModified(modified, "Base modified");
+		}
+		catch (Exception e) {
+			// Ignore
+		}
+		setJar(dot);
+
+		doExpand(dot);
+		doIncludeResources(dot);
+		doWab(dot);
+
+
+		// Check if we override the calculation of the
+		// manifest. We still need to calculated it because
+		// we need to have analyzed the classpath.
+
+		Manifest manifest = calcManifest();
+
+		String mf = getProperty(MANIFEST);
+		if (mf != null) {
+			File mff = getFile(mf);
+			if (mff.isFile()) {
+				try {
+					InputStream in = new FileInputStream(mff);
+					manifest = new Manifest(in);
+					in.close();
+				}
+				catch (Exception e) {
+					error(MANIFEST + " while reading manifest file", e);
+				}
+			} else {
+				error(MANIFEST + ", no such file " + mf);
+			}
+		}
+
+		if (getProperty(NOMANIFEST) == null)
+			dot.setManifest(manifest);
+		else
+			dot.setDoNotTouchManifest();
+
+		// This must happen after we analyzed so
+		// we know what it is on the classpath
+		addSources(dot);
+
+		if (getProperty(POM) != null)
+			dot.putResource("pom.xml", new PomResource(dot.getManifest()));
+		
+		if (!isNoBundle())
+			doVerify(dot);
+
+		if (dot.getResources().isEmpty())
+			warning("The JAR is empty: The instructions for the JAR named %s did not cause any content to be included, this is likely wrong",
+					getBsn());
+
+		dot.updateModified(lastModified(), "Last Modified Processor");
+		dot.setName(getBsn());
+
+		doDigests(dot);
+		
+		sign(dot);
+		doSaveManifest(dot);
+
+		doDiff(dot); // check if need to diff this bundle
+		doBaseline(dot); // check for a baseline
+		return dot;
+	}
+
+
+	/**
+	 * Check if we need to calculate any checksums.
+	 * 
+	 * @param dot
+	 * @throws Exception
+	 */
+	private void doDigests(Jar dot) throws Exception {
+		Parameters ps = OSGiHeader.parseHeader(getProperty(DIGESTS));
+		if (ps.isEmpty())
+			return;
+		trace("digests %s", ps);
+		String[] digests = ps.keySet().toArray(new String[ps.size()]);
+		dot.setDigestAlgorithms(digests);
+	}
+
+	/**
+	 * Allow any local initialization by subclasses before we build.
+	 */
+	public void init() throws Exception {
+		begin();
+		doRequireBnd();
+
+		// Check if we have sensible setup
+
+		if (getClasspath().size() == 0
+				&& (getProperty(EXPORT_PACKAGE) != null || getProperty(EXPORT_PACKAGE) != null || getProperty(PRIVATE_PACKAGE) != null))
+			warning("Classpath is empty. Private-Package and Export-Package can only expand from the classpath when there is one");
+
+	}
+
+	/**
+	 * Turn this normal bundle in a web and add any resources.
+	 * 
+	 * @throws Exception
+	 */
+	private Jar doWab(Jar dot) throws Exception {
+		String wab = getProperty(WAB);
+		String wablib = getProperty(WABLIB);
+		if (wab == null && wablib == null)
+			return dot;
+
+		trace("wab %s %s", wab, wablib);
+		setBundleClasspath(append("WEB-INF/classes", getProperty(BUNDLE_CLASSPATH)));
+
+		Set<String> paths = new HashSet<String>(dot.getResources().keySet());
+
+		for (String path : paths) {
+			if (path.indexOf('/') > 0 && !Character.isUpperCase(path.charAt(0))) {
+				trace("wab: moving: %s", path);
+				dot.rename(path, "WEB-INF/classes/" + path);
+			}
+		}
+
+		Parameters clauses = parseHeader(getProperty(WABLIB));
+		for (String key : clauses.keySet()) {
+			File f = getFile(key);
+			addWabLib(dot, f);
+		}
+		doIncludeResource(dot, wab);
+		return dot;
+	}
+
+	/**
+	 * Add a wab lib to the jar.
+	 * 
+	 * @param f
+	 */
+	private void addWabLib(Jar dot, File f) throws Exception {
+		if (f.exists()) {
+			Jar jar = new Jar(f);
+			jar.setDoNotTouchManifest();
+			addClose(jar);
+			String path = "WEB-INF/lib/" + f.getName();
+			dot.putResource(path, new JarResource(jar));
+			setProperty(BUNDLE_CLASSPATH, append(getProperty(BUNDLE_CLASSPATH), path));
+
+			Manifest m = jar.getManifest();
+			String cp = m.getMainAttributes().getValue("Class-Path");
+			if (cp != null) {
+				Collection<String> parts = split(cp, ",");
+				for (String part : parts) {
+					File sub = getFile(f.getParentFile(), part);
+					if (!sub.exists() || !sub.getParentFile().equals(f.getParentFile())) {
+						warning("Invalid Class-Path entry %s in %s, must exist and must reside in same directory", sub,
+								f);
+					} else {
+						addWabLib(dot, sub);
+					}
+				}
+			}
+		} else {
+			error("WAB lib does not exist %s", f);
+		}
+	}
+
+	/**
+	 * Get the manifest and write it out separately if -savemanifest is set
+	 * 
+	 * @param dot
+	 */
+	private void doSaveManifest(Jar dot) throws Exception {
+		String output = getProperty(SAVEMANIFEST);
+		if (output == null)
+			return;
+
+		File f = getFile(output);
+		if (f.isDirectory()) {
+			f = new File(f, "MANIFEST.MF");
+		}
+		f.delete();
+		File fp = f.getParentFile();
+		if (!fp.exists() && !fp.mkdirs()) {
+			throw new IOException("Could not create directory " + fp);
+		}
+		OutputStream out = new FileOutputStream(f);
+		try {
+			Jar.writeManifest(dot.getManifest(), out);
+		}
+		finally {
+			out.close();
+		}
+		changedFile(f);
+	}
+
+	protected void changedFile(@SuppressWarnings("unused") File f) {}
+
+	/**
+	 * Sign the jar file. -sign : <alias> [ ';' 'password:=' <password> ] [ ';'
+	 * 'keystore:=' <keystore> ] [ ';' 'sign-password:=' <pw> ] ( ',' ... )*
+	 * 
+	 * @return
+	 */
+
+	void sign(@SuppressWarnings("unused") Jar jar) throws Exception {
+		String signing = getProperty(SIGN);
+		if (signing == null)
+			return;
+
+		trace("Signing %s, with %s", getBsn(), signing);
+		List<SignerPlugin> signers = getPlugins(SignerPlugin.class);
+
+		Parameters infos = parseHeader(signing);
+		for (Entry<String,Attrs> entry : infos.entrySet()) {
+			for (SignerPlugin signer : signers) {
+				signer.sign(this, entry.getKey());
+			}
+		}
+	}
+
+	public boolean hasSources() {
+		return isTrue(getProperty(SOURCES));
+	}
+
+	/**
+	 * Answer extra packages. In this case we implement conditional package. Any
+	 */
+	@Override
+	protected Jar getExtra() throws Exception {
+		Parameters conditionals = getParameters(CONDITIONAL_PACKAGE);
+		if (conditionals.isEmpty())
+			return null;
+		trace("do Conditional Package %s", conditionals);
+		Instructions instructions = new Instructions(conditionals);
+
+		Collection<PackageRef> referred = instructions.select(getReferred().keySet(), false);
+		referred.removeAll(getContained().keySet());
+
+		Jar jar = new Jar("conditional-import");
+		addClose(jar);
+		for (PackageRef pref : referred) {
+			for (Jar cpe : getClasspath()) {
+				Map<String,Resource> map = cpe.getDirectories().get(pref.getPath());
+				if (map != null) {
+					copy(jar, cpe, pref.getPath(), false);
+// Now use copy so that bnd.info is processed, next line should be 
+// removed in the future TODO
+//					jar.addDirectory(map, false);
+					break;
+				}
+			}
+		}
+		if (jar.getDirectories().size() == 0) {
+			trace("extra dirs %s", jar.getDirectories());
+			return null;
+		}
+		return jar;
+	}
+
+	/**
+	 * Intercept the call to analyze and cleanup versions after we have analyzed
+	 * the setup. We do not want to cleanup if we are going to verify.
+	 */
+
+	@Override
+	public void analyze() throws Exception {
+		super.analyze();
+		cleanupVersion(getImports(), null);
+		cleanupVersion(getExports(), getVersion());
+		String version = getProperty(BUNDLE_VERSION);
+		if (version != null) {
+			version = cleanupVersion(version);
+			if (version.endsWith(".SNAPSHOT")) {
+				version = version.replaceAll("SNAPSHOT$", getProperty(SNAPSHOT, "SNAPSHOT"));
+			}
+			setProperty(BUNDLE_VERSION, version);
+		}
+	}
+
+	public void cleanupVersion(Packages packages, String defaultVersion) {
+		for (Map.Entry<PackageRef,Attrs> entry : packages.entrySet()) {
+			Attrs attributes = entry.getValue();
+			String v = attributes.get(Constants.VERSION_ATTRIBUTE);
+			if (v == null && defaultVersion != null) {
+				if (!isTrue(getProperty(Constants.NODEFAULTVERSION))) {
+					v = defaultVersion;
+					if (isPedantic())
+						warning("Used bundle version %s for exported package %s", v, entry.getKey());
+				} else {
+					if (isPedantic())
+						warning("No export version for exported package %s", entry.getKey());
+				}
+			}
+			if (v != null)
+				attributes.put(Constants.VERSION_ATTRIBUTE, cleanupVersion(v));
+		}
+	}
+
+	/**
+     * 
+     */
+	private void addSources(Jar dot) {
+		if (!hasSources())
+			return;
+
+		Set<PackageRef> packages = Create.set();
+
+		for (TypeRef typeRef : getClassspace().keySet()) {
+			PackageRef packageRef = typeRef.getPackageRef();
+			String sourcePath = typeRef.getSourcePath();
+			String packagePath = packageRef.getPath();
+
+			boolean found = false;
+			String[] fixed = {
+					"packageinfo", "package.html", "module-info.java", "package-info.java"
+			};
+
+			for (Iterator<File> i = getSourcePath().iterator(); i.hasNext();) {
+				File root = i.next();
+
+				// TODO should use bcp?
+
+				File f = getFile(root, sourcePath);
+				if (f.exists()) {
+					found = true;
+					if (!packages.contains(packageRef)) {
+						packages.add(packageRef);
+						File bdir = getFile(root, packagePath);
+						for (int j = 0; j < fixed.length; j++) {
+							File ff = getFile(bdir, fixed[j]);
+							if (ff.isFile()) {
+								String name = "OSGI-OPT/src/" + packagePath + "/" + fixed[j];
+								dot.putResource(name, new FileResource(ff));
+							}
+						}
+					}
+					if (packageRef.isDefaultPackage())
+						System.err.println("Duh?");
+					dot.putResource("OSGI-OPT/src/" + sourcePath, new FileResource(f));
+				}
+			}
+			if (!found) {
+				for (Jar jar : getClasspath()) {
+					Resource resource = jar.getResource(sourcePath);
+					if (resource != null) {
+						dot.putResource("OSGI-OPT/src/" + sourcePath, resource);
+					} else {
+						resource = jar.getResource("OSGI-OPT/src/" + sourcePath);
+						if (resource != null) {
+							dot.putResource("OSGI-OPT/src/" + sourcePath, resource);
+						}
+					}
+				}
+			}
+			if (getSourcePath().isEmpty())
+				warning("Including sources but " + SOURCEPATH + " does not contain any source directories ");
+			// TODO copy from the jars where they came from
+		}
+	}
+
+	boolean			firstUse	= true;
+	private Tree	tree;
+
+	public Collection<File> getSourcePath() {
+		if (firstUse) {
+			firstUse = false;
+			String sp = getProperty(SOURCEPATH);
+			if (sp != null) {
+				Parameters map = parseHeader(sp);
+				for (Iterator<String> i = map.keySet().iterator(); i.hasNext();) {
+					String file = i.next();
+					if (!isDuplicate(file)) {
+						File f = getFile(file);
+						if (!f.isDirectory()) {
+							error("Adding a sourcepath that is not a directory: " + f);
+						} else {
+							sourcePath.add(f);
+						}
+					}
+				}
+			}
+		}
+		return sourcePath;
+	}
+
+	private void doVerify(@SuppressWarnings("unused") Jar dot) throws Exception {
+		Verifier verifier = new Verifier(this);
+		// Give the verifier the benefit of our analysis
+		// prevents parsing the files twice
+		verifier.verify();
+		getInfo(verifier);
+	}
+
+	private void doExpand(Jar dot) {
+
+		// Build an index of the class path that we can then
+		// use destructively
+		MultiMap<String,Jar> packages = new MultiMap<String,Jar>();
+		for (Jar srce : getClasspath()) {
+			for (Entry<String,Map<String,Resource>> e : srce.getDirectories().entrySet()) {
+				if (e.getValue() != null)
+					packages.add(e.getKey(), srce);
+			}
+		}
+
+		Parameters privatePackages = getPrivatePackage();
+		if (isTrue(getProperty(Constants.UNDERTEST))) {
+			String h = getProperty(Constants.TESTPACKAGES, "test;presence:=optional");
+			privatePackages.putAll(parseHeader(h));
+		}
+
+		if (!privatePackages.isEmpty()) {
+			Instructions privateFilter = new Instructions(privatePackages);
+			Set<Instruction> unused = doExpand(dot, packages, privateFilter);
+
+			if (!unused.isEmpty()) {
+				warning("Unused Private-Package instructions, no such package(s) on the class path: %s", unused);
+			}
+		}
+
+		Parameters exportedPackage = getExportPackage();
+		if (!exportedPackage.isEmpty()) {
+			Instructions exportedFilter = new Instructions(exportedPackage);
+
+			// We ignore unused instructions for exports, they should show
+			// up as errors during analysis. Otherwise any overlapping
+			// packages with the private packages should show up as
+			// unused
+
+			doExpand(dot, packages, exportedFilter);
+		}
+	}
+
+	/**
+	 * Destructively filter the packages from the build up index. This index is
+	 * used by the Export Package as well as the Private Package
+	 * 
+	 * @param jar
+	 * @param name
+	 * @param instructions
+	 */
+	private Set<Instruction> doExpand(Jar jar, MultiMap<String,Jar> index, Instructions filter) {
+		Set<Instruction> unused = Create.set();
+
+		for (Entry<Instruction,Attrs> e : filter.entrySet()) {
+			Instruction instruction = e.getKey();
+			if (instruction.isDuplicate())
+				continue;
+
+			Attrs directives = e.getValue();
+
+			// We can optionally filter on the
+			// source of the package. We assume
+			// they all match but this can be overridden
+			// on the instruction
+			Instruction from = new Instruction(directives.get(FROM_DIRECTIVE, "*"));
+
+			boolean used = false;
+
+			for (Iterator<Entry<String,List<Jar>>> entry = index.entrySet().iterator(); entry.hasNext();) {
+				Entry<String,List<Jar>> p = entry.next();
+
+				String directory = p.getKey();
+				PackageRef packageRef = getPackageRef(directory);
+
+				// Skip * and meta data, we're talking packages!
+				if (packageRef.isMetaData() && instruction.isAny())
+					continue;
+
+				if (!instruction.matches(packageRef.getFQN()))
+					continue;
+
+				// Ensure it is never matched again
+				entry.remove();
+
+				// ! effectively removes it from consideration by others (this
+				// includes exports)
+				if (instruction.isNegated())
+					continue;
+
+				// Do the from: directive, filters on the JAR type
+				List<Jar> providers = filterFrom(from, p.getValue());
+				if (providers.isEmpty())
+					continue;
+
+				int splitStrategy = getSplitStrategy(directives.get(SPLIT_PACKAGE_DIRECTIVE));
+				copyPackage(jar, providers, directory, splitStrategy);
+
+				used = true;
+			}
+
+			if (!used && !isTrue(directives.get("optional:")))
+				unused.add(instruction);
+		}
+		return unused;
+	}
+
+	/**
+	 * @param from
+	 * @return
+	 */
+	private List<Jar> filterFrom(Instruction from, List<Jar> providers) {
+		if (from.isAny())
+			return providers;
+
+		List<Jar> np = new ArrayList<Jar>();
+		for (Iterator<Jar> i = providers.iterator(); i.hasNext();) {
+			Jar j = i.next();
+			if (from.matches(j.getName())) {
+				np.add(j);
+			}
+		}
+		return np;
+	}
+
+	/**
+	 * Copy the package from the providers based on the split package strategy.
+	 * 
+	 * @param dest
+	 * @param providers
+	 * @param directory
+	 * @param splitStrategy
+	 */
+	private void copyPackage(Jar dest, List<Jar> providers, String path, int splitStrategy) {
+		switch (splitStrategy) {
+			case SPLIT_MERGE_LAST :
+				for (Jar srce : providers) {
+					copy(dest, srce, path, true);
+				}
+				break;
+
+			case SPLIT_MERGE_FIRST :
+				for (Jar srce : providers) {
+					copy(dest, srce, path, false);
+				}
+				break;
+
+			case SPLIT_ERROR :
+				error(diagnostic(path, providers));
+				break;
+
+			case SPLIT_FIRST :
+				copy(dest, providers.get(0), path, false);
+				break;
+
+			default :
+				if (providers.size() > 1)
+					warning("%s", diagnostic(path, providers));
+				for (Jar srce : providers) {
+					copy(dest, srce, path, false);
+				}
+				break;
+		}
+	}
+
+	/**
+	 * Cop
+	 * 
+	 * @param dest
+	 * @param srce
+	 * @param path
+	 * @param overwriteResource
+	 */
+	private void copy(Jar dest, Jar srce, String path, boolean overwrite) {
+		trace("copy d=" + dest + " s=" + srce +" p="+ path);
+		dest.copy(srce, path, overwrite);
+		
+		// bnd.info sources must be preprocessed
+		String bndInfoPath = path + "/bnd.info";
+		Resource r = dest.getResource(bndInfoPath);
+		if ( r != null && !(r instanceof PreprocessResource)) {
+			trace("preprocessing bnd.info");
+			PreprocessResource pp = new PreprocessResource(this, r);
+			dest.putResource(bndInfoPath, pp);
+		}
+		
+		if (hasSources()) {
+			String srcPath = "OSGI-OPT/src/" + path;
+			Map<String,Resource> srcContents = srce.getDirectories().get(srcPath);
+			if (srcContents != null) {
+				dest.addDirectory(srcContents, overwrite);
+			}
+		}
+	}
+
+	/**
+	 * Analyze the classpath for a split package
+	 * 
+	 * @param pack
+	 * @param classpath
+	 * @param source
+	 * @return
+	 */
+	private String diagnostic(String pack, List<Jar> culprits) {
+		// Default is like merge-first, but with a warning
+		return "Split package, multiple jars provide the same package:"
+				+ pack
+				+ "\nUse Import/Export Package directive -split-package:=(merge-first|merge-last|error|first) to get rid of this warning\n"
+				+ "Package found in   " + culprits + "\n" //
+				+ "Class path         " + getClasspath();
+	}
+
+	private int getSplitStrategy(String type) {
+		if (type == null)
+			return SPLIT_DEFAULT;
+
+		if (type.equals("merge-last"))
+			return SPLIT_MERGE_LAST;
+
+		if (type.equals("merge-first"))
+			return SPLIT_MERGE_FIRST;
+
+		if (type.equals("error"))
+			return SPLIT_ERROR;
+
+		if (type.equals("first"))
+			return SPLIT_FIRST;
+
+		error("Invalid strategy for split-package: " + type);
+		return SPLIT_DEFAULT;
+	}
+
+	/**
+	 * Matches the instructions against a package.
+	 * 
+	 * @param instructions
+	 *            The list of instructions
+	 * @param pack
+	 *            The name of the package
+	 * @param unused
+	 *            The total list of patterns, matched patterns are removed
+	 * @param source
+	 *            The name of the source container, can be filtered upon with
+	 *            the from: directive.
+	 * @return
+	 */
+	private Instruction matches(Instructions instructions, String pack, Set<Instruction> unused, String source) {
+		for (Entry<Instruction,Attrs> entry : instructions.entrySet()) {
+			Instruction pattern = entry.getKey();
+
+			// It is possible to filter on the source of the
+			// package with the from: directive. This is an
+			// instruction that must match the name of the
+			// source class path entry.
+
+			String from = entry.getValue().get(FROM_DIRECTIVE);
+			if (from != null) {
+				Instruction f = new Instruction(from);
+				if (!f.matches(source) || f.isNegated())
+					continue;
+			}
+
+			// Now do the normal
+			// matching
+			if (pattern.matches(pack)) {
+				if (unused != null)
+					unused.remove(pattern);
+				return pattern;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Parse the Bundle-Includes header. Files in the bundles Include header are
+	 * included in the jar. The source can be a directory or a file.
+	 * 
+	 * @throws IOException
+	 * @throws FileNotFoundException
+	 */
+	private void doIncludeResources(Jar jar) throws Exception {
+		String includes = getProperty("Bundle-Includes");
+		if (includes == null) {
+			includes = getProperty(INCLUDERESOURCE);
+			if (includes == null || includes.length() == 0)
+				includes = getProperty("Include-Resource");
+		} else
+			warning("Please use -includeresource instead of Bundle-Includes");
+
+		doIncludeResource(jar, includes);
+
+	}
+
+	private void doIncludeResource(Jar jar, String includes) throws Exception {
+		Parameters clauses = parseHeader(includes);
+		doIncludeResource(jar, clauses);
+	}
+
+	private void doIncludeResource(Jar jar, Parameters clauses) throws ZipException, IOException, Exception {
+		for (Entry<String,Attrs> entry : clauses.entrySet()) {
+			doIncludeResource(jar, entry.getKey(), entry.getValue());
+		}
+	}
+
+	private void doIncludeResource(Jar jar, String name, Map<String,String> extra) throws ZipException, IOException,
+			Exception {
+
+		boolean preprocess = false;
+		boolean absentIsOk = false;
+
+		if (name.startsWith("{") && name.endsWith("}")) {
+			preprocess = true;
+			name = name.substring(1, name.length() - 1).trim();
+		}
+
+		String parts[] = name.split("\\s*=\\s*");
+		String source = parts[0];
+		String destination = parts[0];
+		if (parts.length == 2)
+			source = parts[1];
+
+		if (source.startsWith("-")) {
+			source = source.substring(1);
+			absentIsOk = true;
+		}
+
+		if (source.startsWith("@")) {
+			extractFromJar(jar, source.substring(1), parts.length == 1 ? "" : destination, absentIsOk);
+		} else if (extra.containsKey("cmd")) {
+			doCommand(jar, source, destination, extra, preprocess, absentIsOk);
+		} else if (extra.containsKey(LITERAL_ATTRIBUTE)) {
+			String literal = extra.get(LITERAL_ATTRIBUTE);
+			Resource r = new EmbeddedResource(literal.getBytes("UTF-8"), 0);
+			String x = extra.get("extra");
+			if (x != null)
+				r.setExtra(x);
+			jar.putResource(name, r);
+		} else {
+			File sourceFile;
+			String destinationPath;
+
+			sourceFile = getFile(source);
+			if (parts.length == 1) {
+				// Directories should be copied to the root
+				// but files to their file name ...
+				if (sourceFile.isDirectory())
+					destinationPath = "";
+				else
+					destinationPath = sourceFile.getName();
+			} else {
+				destinationPath = parts[0];
+			}
+			// Handle directories
+			if (sourceFile.isDirectory()) {
+				destinationPath = doResourceDirectory(jar, extra, preprocess, sourceFile, destinationPath);
+				return;
+			}
+
+			// destinationPath = checkDestinationPath(destinationPath);
+
+			if (!sourceFile.exists()) {
+				if (absentIsOk)
+					return;
+
+				noSuchFile(jar, name, extra, source, destinationPath);
+			} else
+				copy(jar, destinationPath, sourceFile, preprocess, extra);
+		}
+	}
+
+	/**
+	 * It is possible in Include-Resource to use a system command that generates
+	 * the contents, this is indicated with {@code cmd} attribute. The command
+	 * can be repeated for a number of source files with the {@code for}
+	 * attribute which indicates a list of repetitions, often down with the
+	 * {@link Macro#_lsa(String[])} or {@link Macro#_lsb(String[])} macro. The
+	 * repetition will repeat the given command for each item. The @} macro can
+	 * be used to replace the current item. If no {@code for} is given, the
+	 * source is used as the only item. If the destination contains a macro,
+	 * each iteration will create a new file, otherwise the destination name is
+	 * used. The execution of the command is delayed until the JAR is actually
+	 * written to the file system for performance reasons.
+	 * 
+	 * @param jar
+	 * @param source
+	 * @param destination
+	 * @param extra
+	 * @param preprocess
+	 * @param absentIsOk
+	 */
+	private void doCommand(Jar jar, String source, String destination, Map<String,String> extra, boolean preprocess,
+			boolean absentIsOk) {
+		String repeat = extra.get("for"); // TODO constant
+		if (repeat == null)
+			repeat = source;
+
+		Collection<String> requires = split(extra.get("requires"));
+		long lastModified = 0;
+		for (String required : requires) {
+			File file = getFile(required);
+			if (!file.isFile()) {
+				error("Include-Resource.cmd for %s, requires %s, but no such file %s", source, required,
+						file.getAbsoluteFile());
+			} else
+				lastModified = Math.max(lastModified, file.lastModified());
+		}
+
+		String cmd = extra.get("cmd");
+
+		Collection<String> items = Processor.split(repeat);
+
+		CombinedResource cr = null;
+
+		if (!destination.contains("${@}")) {
+			cr = new CombinedResource();
+			cr.lastModified = lastModified;
+		}
+		trace("last modified requires %s", lastModified);
+
+		for (String item : items) {
+			setProperty("@", item);
+			try {
+				String path = getReplacer().process(destination);
+				String command = getReplacer().process(cmd);
+				File file = getFile(item);
+				if ( file.exists())
+					lastModified = Math.max(lastModified, file.lastModified());
+				
+				Resource r = new CommandResource(command, this, lastModified, getBase());
+
+				if (preprocess)
+					r = new PreprocessResource(this, r);
+
+				if (cr == null)
+					jar.putResource(path, r);
+				else
+					cr.addResource(r);
+			}
+			finally {
+				unsetProperty("@");
+			}
+		}
+
+		// Add last so the correct modification date is used
+		// to update the modified time.
+		if (cr != null)
+			jar.putResource(destination, cr);
+		
+		updateModified(lastModified, "Include-Resource: cmd");
+	}
+
+	private String doResourceDirectory(Jar jar, Map<String,String> extra, boolean preprocess, File sourceFile,
+			String destinationPath) throws Exception {
+		String filter = extra.get("filter:");
+		boolean flatten = isTrue(extra.get("flatten:"));
+		boolean recursive = true;
+		String directive = extra.get("recursive:");
+		if (directive != null) {
+			recursive = isTrue(directive);
+		}
+
+		Instruction.Filter iFilter = null;
+		if (filter != null) {
+			iFilter = new Instruction.Filter(new Instruction(filter), recursive, getDoNotCopy());
+		} else {
+			iFilter = new Instruction.Filter(null, recursive, getDoNotCopy());
+		}
+
+		Map<String,File> files = newMap();
+		resolveFiles(sourceFile, iFilter, recursive, destinationPath, files, flatten);
+
+		for (Map.Entry<String,File> entry : files.entrySet()) {
+			copy(jar, entry.getKey(), entry.getValue(), preprocess, extra);
+		}
+		return destinationPath;
+	}
+
+	private void resolveFiles(File dir, FileFilter filter, boolean recursive, String path, Map<String,File> files,
+			boolean flatten) {
+
+		if (doNotCopy(dir.getName())) {
+			return;
+		}
+
+		File[] fs = dir.listFiles(filter);
+		for (File file : fs) {
+			if (file.isDirectory()) {
+				if (recursive) {
+					String nextPath;
+					if (flatten)
+						nextPath = path;
+					else
+						nextPath = appendPath(path, file.getName());
+
+					resolveFiles(file, filter, recursive, nextPath, files, flatten);
+				}
+				// Directories are ignored otherwise
+			} else {
+				String p = appendPath(path, file.getName());
+				if (files.containsKey(p))
+					warning("Include-Resource overwrites entry %s from file %s", p, file);
+				files.put(p, file);
+			}
+		}
+		if (fs.length == 0) {
+			File empty = new File(dir, Constants.EMPTY_HEADER);
+			files.put(appendPath(path, empty.getName()), empty);
+		}
+	}
+
+	private void noSuchFile(Jar jar, @SuppressWarnings("unused") String clause, Map<String,String> extra, String source, String destinationPath)
+			throws Exception {
+		Jar src = getJarFromName(source, "Include-Resource " + source);
+		if (src != null) {
+			// Do not touch the manifest so this also
+			// works for signed files.
+			src.setDoNotTouchManifest();
+			JarResource jarResource = new JarResource(src);
+			jar.putResource(destinationPath, jarResource);
+		} else {
+			Resource lastChance = make.process(source);
+			if (lastChance != null) {
+				String x = extra.get("extra");
+				if (x != null)
+					lastChance.setExtra(x);
+				jar.putResource(destinationPath, lastChance);
+			} else
+				error("Input file does not exist: " + source);
+		}
+	}
+
+	/**
+	 * Extra resources from a Jar and add them to the given jar. The clause is
+	 * the
+	 * 
+	 * @param jar
+	 * @param clauses
+	 * @param i
+	 * @throws ZipException
+	 * @throws IOException
+	 */
+	private void extractFromJar(Jar jar, String source, String destination, boolean absentIsOk) throws ZipException,
+			IOException {
+		// Inline all resources and classes from another jar
+		// optionally appended with a modified regular expression
+		// like @zip.jar!/META-INF/MANIFEST.MF
+		int n = source.lastIndexOf("!/");
+		Instruction instr = null;
+		if (n > 0) {
+			instr = new Instruction(source.substring(n + 2));
+			source = source.substring(0, n);
+		}
+
+		// Pattern filter = null;
+		// if (n > 0) {
+		// String fstring = source.substring(n + 2);
+		// source = source.substring(0, n);
+		// filter = wildcard(fstring);
+		// }
+		Jar sub = getJarFromName(source, "extract from jar");
+		if (sub == null) {
+			if (absentIsOk)
+				return;
+
+			error("Can not find JAR file " + source);
+		} else {
+			addAll(jar, sub, instr, destination);
+		}
+	}
+
+	/**
+	 * Add all the resources in the given jar that match the given filter.
+	 * 
+	 * @param sub
+	 *            the jar
+	 * @param filter
+	 *            a pattern that should match the resoures in sub to be added
+	 */
+	public boolean addAll(Jar to, Jar sub, Instruction filter) {
+		return addAll(to, sub, filter, "");
+	}
+
+	/**
+	 * Add all the resources in the given jar that match the given filter.
+	 * 
+	 * @param sub
+	 *            the jar
+	 * @param filter
+	 *            a pattern that should match the resoures in sub to be added
+	 */
+	public boolean addAll(Jar to, Jar sub, Instruction filter, String destination) {
+		boolean dupl = false;
+		for (String name : sub.getResources().keySet()) {
+			if ("META-INF/MANIFEST.MF".equals(name))
+				continue;
+
+			if (filter == null || filter.matches(name) != filter.isNegated())
+				dupl |= to.putResource(Processor.appendPath(destination, name), sub.getResource(name), true);
+		}
+		return dupl;
+	}
+
+	private void copy(Jar jar, String path, File from, boolean preprocess, Map<String,String> extra) throws Exception {
+		if (doNotCopy(from.getName()))
+			return;
+
+		if (from.isDirectory()) {
+
+			File files[] = from.listFiles();
+			for (int i = 0; i < files.length; i++) {
+				copy(jar, appendPath(path, files[i].getName()), files[i], preprocess, extra);
+			}
+		} else {
+			if (from.exists()) {
+				Resource resource = new FileResource(from);
+				if (preprocess) {
+					resource = new PreprocessResource(this, resource);
+				}
+				String x = extra.get("extra");
+				if (x != null)
+					resource.setExtra(x);
+				if (path.endsWith("/"))
+					path = path + from.getName();
+				jar.putResource(path, resource);
+
+				if (isTrue(extra.get(LIB_DIRECTIVE))) {
+					setProperty(BUNDLE_CLASSPATH, append(getProperty(BUNDLE_CLASSPATH), path));
+				}
+			} else if (from.getName().equals(Constants.EMPTY_HEADER)) {
+				jar.putResource(path, new EmbeddedResource(new byte[0], 0));
+			} else {
+				error("Input file does not exist: " + from);
+			}
+		}
+	}
+
+	public void setSourcepath(File[] files) {
+		for (int i = 0; i < files.length; i++)
+			addSourcepath(files[i]);
+	}
+
+	public void addSourcepath(File cp) {
+		if (!cp.exists())
+			warning("File on sourcepath that does not exist: " + cp);
+
+		sourcePath.add(cp);
+	}
+
+	@Override
+	public void close() {
+		super.close();
+	}
+
+	/**
+	 * Build Multiple jars. If the -sub command is set, we filter the file with
+	 * the given patterns.
+	 * 
+	 * @return
+	 * @throws Exception
+	 */
+	public Jar[] builds() throws Exception {
+		begin();
+
+		// Are we acting as a conduit for another JAR?
+		String conduit = getProperty(CONDUIT);
+		if (conduit != null) {
+			Parameters map = parseHeader(conduit);
+			Jar[] result = new Jar[map.size()];
+			int n = 0;
+			for (String file : map.keySet()) {
+				Jar c = new Jar(getFile(file));
+				addClose(c);
+				String name = map.get(file).get("name");
+				if (name != null)
+					c.setName(name);
+
+				result[n++] = c;
+			}
+			return result;
+		}
+
+		List<Jar> result = new ArrayList<Jar>();
+		List<Builder> builders;
+
+		builders = getSubBuilders();
+
+		for (Builder builder : builders) {
+			try {
+				Jar jar = builder.build();
+				jar.setName(builder.getBsn());
+				result.add(jar);
+			}
+			catch (Exception e) {
+				e.printStackTrace();
+				error("Sub Building " + builder.getBsn(), e);
+			}
+			if (builder != this)
+				getInfo(builder, builder.getBsn() + ": ");
+		}
+		return result.toArray(new Jar[result.size()]);
+	}
+
+	/**
+	 * Answer a list of builders that represent this file or a list of files
+	 * specified in -sub. This list can be empty. These builders represents to
+	 * be created artifacts and are each scoped to such an artifacts. The
+	 * builders can be used to build the bundles or they can be used to find out
+	 * information about the to be generated bundles.
+	 * 
+	 * @return List of 0..n builders representing artifacts.
+	 * @throws Exception
+	 */
+	public List<Builder> getSubBuilders() throws Exception {
+		String sub = getProperty(SUB);
+		if (sub == null || sub.trim().length() == 0 || EMPTY_HEADER.equals(sub))
+			return Arrays.asList(this);
+
+		List<Builder> builders = new ArrayList<Builder>();
+		if (isTrue(getProperty(NOBUNDLES)))
+			return builders;
+
+		Parameters subsMap = parseHeader(sub);
+		for (Iterator<String> i = subsMap.keySet().iterator(); i.hasNext();) {
+			File file = getFile(i.next());
+			if (file.isFile() && !file.getName().startsWith(".")) {
+				builders.add(getSubBuilder(file));
+				i.remove();
+			}
+		}
+
+		Instructions instructions = new Instructions(subsMap);
+
+		List<File> members = new ArrayList<File>(Arrays.asList(getBase().listFiles()));
+
+		nextFile: while (members.size() > 0) {
+
+			File file = members.remove(0);
+
+			// Check if the file is one of our parents
+			Processor p = this;
+			while (p != null) {
+				if (file.equals(p.getPropertiesFile()))
+					continue nextFile;
+				p = p.getParent();
+			}
+
+			for (Iterator<Instruction> i = instructions.keySet().iterator(); i.hasNext();) {
+
+				Instruction instruction = i.next();
+				if (instruction.matches(file.getName())) {
+
+					if (!instruction.isNegated()) {
+						builders.add(getSubBuilder(file));
+					}
+
+					// Because we matched (even though we could be negated)
+					// we skip any remaining searches
+					continue nextFile;
+				}
+			}
+		}
+		return builders;
+	}
+
+	public Builder getSubBuilder(File file) throws Exception {
+		Builder builder = getSubBuilder();
+		if (builder != null) {
+			builder.setProperties(file);
+			addClose(builder);
+		}
+		return builder;
+	}
+
+	public Builder getSubBuilder() throws Exception {
+		Builder builder = new Builder(this);
+		builder.setBase(getBase());
+
+		for (Jar file : getClasspath()) {
+			builder.addClasspath(file);
+		}
+
+		return builder;
+	}
+
+	/**
+	 * A macro to convert a maven version to an OSGi version
+	 */
+
+	public String _maven_version(String args[]) {
+		if (args.length > 2)
+			error("${maven_version} macro receives too many arguments " + Arrays.toString(args));
+		else if (args.length < 2)
+			error("${maven_version} macro has no arguments, use ${maven_version;1.2.3-SNAPSHOT}");
+		else {
+			return cleanupVersion(args[1]);
+		}
+		return null;
+	}
+
+	public String _permissions(String args[]) {
+		StringBuilder sb = new StringBuilder();
+
+		for (String arg : args) {
+			if ("packages".equals(arg) || "all".equals(arg)) {
+				for (PackageRef imp : getImports().keySet()) {
+					if (!imp.isJava()) {
+						sb.append("(org.osgi.framework.PackagePermission \"");
+						sb.append(imp);
+						sb.append("\" \"import\")\r\n");
+					}
+				}
+				for (PackageRef exp : getExports().keySet()) {
+					sb.append("(org.osgi.framework.PackagePermission \"");
+					sb.append(exp);
+					sb.append("\" \"export\")\r\n");
+				}
+			} else if ("admin".equals(arg) || "all".equals(arg)) {
+				sb.append("(org.osgi.framework.AdminPermission)");
+			} else if ("permissions".equals(arg))
+				;
+			else
+				error("Invalid option in ${permissions}: %s", arg);
+		}
+		return sb.toString();
+	}
+
+	/**
+     * 
+     */
+	public void removeBundleSpecificHeaders() {
+		Set<String> set = new HashSet<String>(Arrays.asList(BUNDLE_SPECIFIC_HEADERS));
+		setForceLocal(set);
+	}
+
+	/**
+	 * Check if the given resource is in scope of this bundle. That is, it
+	 * checks if the Include-Resource includes this resource or if it is a class
+	 * file it is on the class path and the Export-Package or Private-Package
+	 * include this resource.
+	 * 
+	 * @param f
+	 * @return
+	 */
+	public boolean isInScope(Collection<File> resources) throws Exception {
+		Parameters clauses = parseHeader(getProperty(Constants.EXPORT_PACKAGE));
+		clauses.putAll(parseHeader(getProperty(Constants.PRIVATE_PACKAGE)));
+		if (isTrue(getProperty(Constants.UNDERTEST))) {
+			clauses.putAll(parseHeader(getProperty(Constants.TESTPACKAGES, "test;presence:=optional")));
+		}
+
+		Collection<String> ir = getIncludedResourcePrefixes();
+
+		Instructions instructions = new Instructions(clauses);
+
+		for (File r : resources) {
+			String cpEntry = getClasspathEntrySuffix(r);
+
+			if (cpEntry != null) {
+
+				if (cpEntry.equals("")) // Meaning we actually have a CPE
+					return true;
+
+				String pack = Descriptors.getPackage(cpEntry);
+				Instruction i = matches(instructions, pack, null, r.getName());
+				if (i != null)
+					return !i.isNegated();
+			}
+
+			// Check if this resource starts with one of the I-C header
+			// paths.
+			String path = r.getAbsolutePath();
+			for (String p : ir) {
+				if (path.startsWith(p))
+					return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Extra the paths for the directories and files that are used in the
+	 * Include-Resource header.
+	 * 
+	 * @return
+	 */
+	private Collection<String> getIncludedResourcePrefixes() {
+		List<String> prefixes = new ArrayList<String>();
+		Parameters includeResource = getIncludeResource();
+		for (Entry<String,Attrs> p : includeResource.entrySet()) {
+			if (p.getValue().containsKey("literal"))
+				continue;
+
+			Matcher m = IR_PATTERN.matcher(p.getKey());
+			if (m.matches()) {
+				File f = getFile(m.group(1));
+				prefixes.add(f.getAbsolutePath());
+			}
+		}
+		return prefixes;
+	}
+
+	/**
+	 * Answer the string of the resource that it has in the container. It is
+	 * possible that the resource is a classpath entry. In that case an empty
+	 * string is returned.
+	 * 
+	 * @param resource
+	 *            The resource to look for
+	 * @return A suffix on the classpath or "" if the resource is a class path
+	 *         entry
+	 * @throws Exception
+	 */
+	public String getClasspathEntrySuffix(File resource) throws Exception {
+		for (Jar jar : getClasspath()) {
+			File source = jar.getSource();
+			if (source != null) {
+
+				source = source.getCanonicalFile();
+				String sourcePath = source.getAbsolutePath();
+				String resourcePath = resource.getAbsolutePath();
+				if (sourcePath.equals(resourcePath))
+					return ""; // Matches a classpath entry
+
+				if (resourcePath.startsWith(sourcePath)) {
+					// Make sure that the path name is translated correctly
+					// i.e. on Windows the \ must be translated to /
+					String filePath = resourcePath.substring(sourcePath.length() + 1);
+
+					return filePath.replace(File.separatorChar, '/');
+				}
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * doNotCopy The doNotCopy variable maintains a patter for files that should
+	 * not be copied. There is a default {@link #DEFAULT_DO_NOT_COPY} but this
+	 * ca be overridden with the {@link Constants#DONOTCOPY} property.
+	 */
+
+	public boolean doNotCopy(String v) {
+		return getDoNotCopy().matcher(v).matches();
+	}
+
+	public Pattern getDoNotCopy() {
+		if (xdoNotCopy == null) {
+			String string = null;
+			try {
+				string = getProperty(DONOTCOPY, DEFAULT_DO_NOT_COPY);
+				xdoNotCopy = Pattern.compile(string);
+			}
+			catch (Exception e) {
+				error("Invalid value for %s, value is %s", DONOTCOPY, string);
+				xdoNotCopy = Pattern.compile(DEFAULT_DO_NOT_COPY);
+			}
+		}
+		return xdoNotCopy;
+	}
+
+	/**
+	 */
+
+	static MakeBnd			makeBnd				= new MakeBnd();
+	static MakeCopy			makeCopy			= new MakeCopy();
+	static ServiceComponent	serviceComponent	= new ServiceComponent();
+	static DSAnnotations	dsAnnotations		= new DSAnnotations();
+	static MetatypePlugin	metatypePlugin		= new MetatypePlugin();
+
+	@Override
+	protected void setTypeSpecificPlugins(Set<Object> list) {
+		list.add(makeBnd);
+		list.add(makeCopy);
+		list.add(serviceComponent);
+		list.add(dsAnnotations);
+		list.add(metatypePlugin);
+		super.setTypeSpecificPlugins(list);
+	}
+
+	/**
+	 * Diff this bundle to another bundle for the given packages.
+	 * 
+	 * @throws Exception
+	 */
+
+	public void doDiff(@SuppressWarnings("unused") Jar dot) throws Exception {
+		Parameters diffs = parseHeader(getProperty("-diff"));
+		if (diffs.isEmpty())
+			return;
+
+		trace("diff %s", diffs);
+
+		if (tree == null)
+			tree = differ.tree(this);
+
+		for (Entry<String,Attrs> entry : diffs.entrySet()) {
+			String path = entry.getKey();
+			File file = getFile(path);
+			if (!file.isFile()) {
+				error("Diffing against %s that is not a file", file);
+				continue;
+			}
+
+			boolean full = entry.getValue().get("--full") != null;
+			boolean warning = entry.getValue().get("--warning") != null;
+
+			Tree other = differ.tree(file);
+			Diff api = tree.diff(other).get("<api>");
+			Instructions instructions = new Instructions(entry.getValue().get("--pack"));
+
+			trace("diff against %s --full=%s --pack=%s --warning=%s", file, full, instructions);
+			for (Diff p : api.getChildren()) {
+				String pname = p.getName();
+				if (p.getType() == Type.PACKAGE && instructions.matches(pname)) {
+					if (p.getDelta() != Delta.UNCHANGED) {
+
+						if (!full)
+							if (warning)
+								warning("Differ %s", p);
+							else
+								error("Differ %s", p);
+						else {
+							if (warning)
+								warning("Diff found a difference in %s for packages %s", file, instructions);
+							else
+								error("Diff found a difference in %s for packages %s", file, instructions);
+							show(p, "", warning);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * Show the diff recursively
+	 * 
+	 * @param p
+	 * @param i
+	 */
+	private void show(Diff p, String indent, boolean warning) {
+		Delta d = p.getDelta();
+		if (d == Delta.UNCHANGED)
+			return;
+
+		if (warning)
+			warning("%s%s", indent, p);
+		else
+			error("%s%s", indent, p);
+
+		indent = indent + " ";
+		switch (d) {
+			case CHANGED :
+			case MAJOR :
+			case MINOR :
+			case MICRO :
+				break;
+
+			default :
+				return;
+		}
+		for (Diff c : p.getChildren())
+			show(c, indent, warning);
+	}
+
+	
+	public void addSourcepath(Collection<File> sourcepath) {
+		for (File f : sourcepath) {
+			addSourcepath(f);
+		}
+	}
+
+	/**
+	 * Base line against a previous version. Should be overridden in the ProjectBuilder where we have access to the repos
+	 * 
+	 * @throws Exception
+	 */
+
+	protected void doBaseline(Jar dot) throws Exception {}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/BundleId.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/BundleId.java
new file mode 100644
index 0000000..67f9b4a
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/BundleId.java
@@ -0,0 +1,44 @@
+package aQute.bnd.osgi;
+
+/**
+ * Holds the bundle bsn + version pair
+ */
+public class BundleId implements Comparable<BundleId> {
+	final String	bsn;
+	final String	version;
+
+	public BundleId(String bsn, String version) {
+		this.bsn = bsn.trim();
+		this.version = version.trim();
+	}
+
+	public String getVersion() {
+		return version;
+	}
+
+	public String getBsn() {
+		return bsn;
+	}
+
+	public boolean isValid() {
+		return Verifier.isVersion(version) && Verifier.isBsn(bsn);
+	}
+
+	@Override
+	public boolean equals(Object o) {
+		return this == o || ((o instanceof BundleId) && compareTo((BundleId) o) == 0);
+	}
+
+	@Override
+	public int hashCode() {
+		return bsn.hashCode() ^ version.hashCode();
+	}
+
+	public int compareTo(BundleId other) {
+		int result = bsn.compareTo(other.bsn);
+		if (result != 0)
+			return result;
+
+		return version.compareTo(other.version);
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/ClassDataCollector.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/ClassDataCollector.java
new file mode 100644
index 0000000..17aa62e
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/ClassDataCollector.java
@@ -0,0 +1,83 @@
+package aQute.bnd.osgi;
+
+import aQute.bnd.osgi.Descriptors.TypeRef;
+
+ at SuppressWarnings("unused")
+public class ClassDataCollector {
+	public void classBegin(int access, TypeRef name) {}
+
+	public boolean classStart(int access, TypeRef className) {
+		classBegin(access, className);
+		return true;
+	}
+
+	public void extendsClass(TypeRef zuper) throws Exception {}
+
+	public void implementsInterfaces(TypeRef[] interfaces) throws Exception {}
+
+	public void addReference(TypeRef ref) {}
+
+	public void annotation(Annotation annotation) {}
+
+	public void parameter(int p) {}
+
+	public void method(Clazz.MethodDef defined) {}
+
+	public void field(Clazz.FieldDef defined) {}
+
+	public void classEnd() throws Exception {}
+
+	public void deprecated() throws Exception {}
+
+	/**
+	 * The EnclosingMethod attribute
+	 * 
+	 * @param cName
+	 *            The name of the enclosing class, never null. Name is with
+	 *            slashes.
+	 * @param mName
+	 *            The name of the enclosing method in the class with cName or
+	 *            null
+	 * @param mDescriptor
+	 *            The descriptor of this type
+	 */
+	public void enclosingMethod(TypeRef cName, String mName, String mDescriptor) {
+
+	}
+
+	/**
+	 * The InnerClass attribute
+	 * 
+	 * @param innerClass
+	 *            The name of the inner class (with slashes). Can be null.
+	 * @param outerClass
+	 *            The name of the outer class (with slashes) Can be null.
+	 * @param innerName
+	 *            The name inside the outer class, can be null.
+	 * @param modifiers
+	 *            The access flags
+	 * @throws Exception
+	 */
+	public void innerClass(TypeRef innerClass, TypeRef outerClass, String innerName, int innerClassAccessFlags)
+			throws Exception {}
+
+	public void signature(String signature) {}
+
+	public void constant(Object object) {}
+
+	public void memberEnd() {}
+
+	public void version(int minor, int major) {}
+
+	public void referenceMethod(int access, TypeRef className, String method, String descriptor) {}
+
+	/**
+	 * A reference to a type from method or field. The modifiers indicate the
+	 * access level of the parent method/field.
+	 * 
+	 * @param typeRef
+	 * @param modifiers
+	 */
+	public void referTo(TypeRef typeRef, int modifiers) {}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/Clazz.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/Clazz.java
new file mode 100755
index 0000000..391bf45
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/Clazz.java
@@ -0,0 +1,1737 @@
+package aQute.bnd.osgi;
+
+import java.io.*;
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.nio.*;
+import java.util.*;
+import java.util.regex.*;
+
+import aQute.bnd.osgi.Descriptors.Descriptor;
+import aQute.bnd.osgi.Descriptors.PackageRef;
+import aQute.bnd.osgi.Descriptors.TypeRef;
+import aQute.libg.generics.*;
+
+public class Clazz {
+
+	static Pattern	METHOD_DESCRIPTOR	= Pattern.compile("\\((.*)\\)(.+)");
+
+	public class ClassConstant {
+		int	cname;
+
+		public ClassConstant(int class_index) {
+			this.cname = class_index;
+		}
+
+		public String getName() {
+			return (String) pool[cname];
+		}
+	}
+
+	public static enum JAVA {
+		JDK1_1(45, "JRE-1.1"), JDK1_2(46, "J2SE-1.2"), //
+		JDK1_3(47, "J2SE-1.3"), //
+		JDK1_4(48, "J2SE-1.4"), //
+		J2SE5(49, "J2SE-1.5"), //
+		J2SE6(50, "JavaSE-1.6"), //
+		OpenJDK7(51, "JavaSE-1.7"), //
+		UNKNOWN(Integer.MAX_VALUE, "<>")//
+		;
+
+		final int		major;
+		final String	ee;
+
+		JAVA(int major, String ee) {
+			this.major = major;
+			this.ee = ee;
+		}
+
+		static JAVA format(int n) {
+			for (JAVA e : JAVA.values())
+				if (e.major == n)
+					return e;
+			return UNKNOWN;
+		}
+
+		public int getMajor() {
+			return major;
+		}
+
+		public boolean hasAnnotations() {
+			return major >= J2SE5.major;
+		}
+
+		public boolean hasGenerics() {
+			return major >= J2SE5.major;
+		}
+
+		public boolean hasEnums() {
+			return major >= J2SE5.major;
+		}
+
+		public static JAVA getJava(int major, @SuppressWarnings("unused")
+		int minor) {
+			for (JAVA j : JAVA.values()) {
+				if (j.major == major)
+					return j;
+			}
+			return UNKNOWN;
+		}
+
+		public String getEE() {
+			return ee;
+		}
+	}
+
+	public static enum QUERY {
+		IMPLEMENTS, EXTENDS, IMPORTS, NAMED, ANY, VERSION, CONCRETE, ABSTRACT, PUBLIC, ANNOTATED, RUNTIMEANNOTATIONS, CLASSANNOTATIONS;
+
+	}
+
+	public final static EnumSet<QUERY>	HAS_ARGUMENT	= EnumSet.of(QUERY.IMPLEMENTS, QUERY.EXTENDS, QUERY.IMPORTS,
+																QUERY.NAMED, QUERY.VERSION, QUERY.ANNOTATED);
+
+	/**
+	 * <pre>
+	 * ACC_PUBLIC 0x0001 Declared public; may be accessed from outside its
+	 * package. 
+	 * ACC_FINAL 0x0010 Declared final; no subclasses allowed.
+	 * ACC_SUPER 0x0020 Treat superclass methods specially when invoked by the
+	 * invokespecial instruction. 
+	 * ACC_INTERFACE 0x0200 Is an interface, not a
+	 * class. 
+	 * ACC_ABSTRACT 0x0400 Declared abstract; may not be instantiated.
+	 * </pre>
+	 * 
+	 * @param mod
+	 */
+	final static int					ACC_PUBLIC		= 0x0001;												// Declared
+	// public;
+	// may
+	// be
+	// accessed
+	// from outside its package.
+	final static int					ACC_FINAL		= 0x0010;												// Declared
+	// final;
+	// no
+	// subclasses
+	// allowed.
+	final static int					ACC_SUPER		= 0x0020;												// Treat
+	// superclass
+	// methods
+	// specially when invoked by the
+	// invokespecial instruction.
+	final static int					ACC_INTERFACE	= 0x0200;												// Is
+	// an
+	// interface,
+	// not
+	// a
+	// classs
+	final static int					ACC_ABSTRACT	= 0x0400;												// Declared
+
+	// a thing not in the source code
+	final static int					ACC_SYNTHETIC	= 0x1000;
+	final static int					ACC_ANNOTATION	= 0x2000;
+	final static int					ACC_ENUM		= 0x4000;
+
+	static protected class Assoc {
+		Assoc(byte tag, int a, int b) {
+			this.tag = tag;
+			this.a = a;
+			this.b = b;
+		}
+
+		byte	tag;
+		int		a;
+		int		b;
+	}
+
+	public abstract class Def {
+
+		final int		access;
+		Set<TypeRef>	annotations;
+
+		public Def(int access) {
+			this.access = access;
+		}
+
+		public int getAccess() {
+			return access;
+		}
+
+		public boolean isEnum() {
+			return (access & ACC_ENUM) != 0;
+		}
+
+		public boolean isPublic() {
+			return Modifier.isPublic(access);
+		}
+
+		public boolean isAbstract() {
+			return Modifier.isAbstract(access);
+		}
+
+		public boolean isProtected() {
+			return Modifier.isProtected(access);
+		}
+
+		public boolean isFinal() {
+			return Modifier.isFinal(access) || Clazz.this.isFinal();
+		}
+
+		public boolean isStatic() {
+			return Modifier.isStatic(access);
+		}
+
+		public boolean isPrivate() {
+			return Modifier.isPrivate(access);
+		}
+
+		public boolean isNative() {
+			return Modifier.isNative(access);
+		}
+
+		public boolean isTransient() {
+			return Modifier.isTransient(access);
+		}
+
+		public boolean isVolatile() {
+			return Modifier.isVolatile(access);
+		}
+
+		public boolean isInterface() {
+			return Modifier.isInterface(access);
+		}
+
+		public boolean isSynthetic() {
+			return (access & ACC_SYNTHETIC) != 0;
+		}
+
+		void addAnnotation(Annotation a) {
+			if (annotations == null)
+				annotations = Create.set();
+			annotations.add(analyzer.getTypeRef(a.name.getBinary()));
+		}
+
+		public Collection<TypeRef> getAnnotations() {
+			return annotations;
+		}
+
+		public TypeRef getOwnerType() {
+			return className;
+		}
+
+		public abstract String getName();
+
+		public abstract TypeRef getType();
+
+		public abstract TypeRef[] getPrototype();
+
+		public Object getClazz() {
+			return Clazz.this;
+		}
+	}
+
+	public class FieldDef extends Def {
+		final String		name;
+		final Descriptor	descriptor;
+		String				signature;
+		Object				constant;
+		boolean				deprecated;
+
+		public boolean isDeprecated() {
+			return deprecated;
+		}
+
+		public void setDeprecated(boolean deprecated) {
+			this.deprecated = deprecated;
+		}
+
+		public FieldDef(int access, String name, String descriptor) {
+			super(access);
+			this.name = name;
+			this.descriptor = analyzer.getDescriptor(descriptor);
+		}
+
+		@Override
+		public String getName() {
+			return name;
+		}
+
+		@Override
+		public TypeRef getType() {
+			return descriptor.getType();
+		}
+
+		public TypeRef getContainingClass() {
+			return getClassName();
+		}
+
+		public Descriptor getDescriptor() {
+			return descriptor;
+		}
+
+		public void setConstant(Object o) {
+			this.constant = o;
+		}
+
+		public Object getConstant() {
+			return this.constant;
+		}
+
+		// TODO change to use proper generics
+		public String getGenericReturnType() {
+			String use = descriptor.toString();
+			if (signature != null)
+				use = signature;
+
+			Matcher m = METHOD_DESCRIPTOR.matcher(use);
+			if (!m.matches())
+				throw new IllegalArgumentException("Not a valid method descriptor: " + descriptor);
+
+			String returnType = m.group(2);
+			return objectDescriptorToFQN(returnType);
+		}
+
+		@Override
+		public TypeRef[] getPrototype() {
+			return null;
+		}
+
+		public String getSignature() {
+			return signature;
+		}
+
+		@Override
+		public String toString() {
+			return name;
+		}
+	}
+
+	public class MethodDef extends FieldDef {
+		public MethodDef(int access, String method, String descriptor) {
+			super(access, method, descriptor);
+		}
+
+		public boolean isConstructor() {
+			return name.equals("<init>") || name.equals("<clinit>");
+		}
+
+		@Override
+		public TypeRef[] getPrototype() {
+			return descriptor.getPrototype();
+		}
+	}
+
+	public class TypeDef extends Def {
+		TypeRef	type;
+		boolean	interf;
+
+		public TypeDef(TypeRef type, boolean interf) {
+			super(Modifier.PUBLIC);
+			this.type = type;
+			this.interf = interf;
+		}
+
+		public TypeRef getReference() {
+			return type;
+		}
+
+		public boolean getImplements() {
+			return interf;
+		}
+
+		@Override
+		public String getName() {
+			if (interf)
+				return "<implements>";
+			return "<extends>";
+		}
+
+		@Override
+		public TypeRef getType() {
+			return type;
+		}
+
+		@Override
+		public TypeRef[] getPrototype() {
+			return null;
+		}
+	}
+
+	final static byte	SkipTable[]	= { //
+			0, // 0 non existent
+			-1, // 1 CONSTANT_utf8 UTF 8, handled in
+			// method
+			-1, // 2
+			4, // 3 CONSTANT_Integer
+			4, // 4 CONSTANT_Float
+			8, // 5 CONSTANT_Long (index +=2!)
+			8, // 6 CONSTANT_Double (index +=2!)
+			-1, // 7 CONSTANT_Class
+			2, // 8 CONSTANT_String
+			4, // 9 CONSTANT_FieldRef
+			4, // 10 CONSTANT_MethodRef
+			4, // 11 CONSTANT_InterfaceMethodRef
+			4, // 12 CONSTANT_NameAndType
+			-1, // 13 Not defined
+			-1, // 14 Not defined
+			3, // 15 CONSTANT_MethodHandle
+			2, // 16 CONSTANT_MethodType
+			-1, // 17 Not defined
+			4, // 18 CONSTANT_InvokeDynamic
+									};
+
+	boolean				hasRuntimeAnnotations;
+	boolean				hasClassAnnotations;
+
+	TypeRef				className;
+	Object				pool[];
+	int					intPool[];
+	Set<PackageRef>		imports		= Create.set();
+	String				path;
+	int					minor		= 0;
+	int					major		= 0;
+	int					innerAccess	= -1;
+	int					accessx		= 0;
+	String				sourceFile;
+	Set<TypeRef>		xref;
+	Set<TypeRef>		annotations;
+	int					forName		= 0;
+	int					class$		= 0;
+	TypeRef[]			interfaces;
+	TypeRef				zuper;
+	ClassDataCollector	cd			= null;
+	Resource			resource;
+	FieldDef			last		= null;
+	boolean				deprecated;
+	Set<PackageRef>		api;
+	final Analyzer		analyzer;
+
+	public Clazz(Analyzer analyzer, String path, Resource resource) {
+		this.path = path;
+		this.resource = resource;
+		this.analyzer = analyzer;
+	}
+
+	public Set<TypeRef> parseClassFile() throws Exception {
+		return parseClassFileWithCollector(null);
+	}
+
+	public Set<TypeRef> parseClassFile(InputStream in) throws Exception {
+		return parseClassFile(in, null);
+	}
+
+	public Set<TypeRef> parseClassFileWithCollector(ClassDataCollector cd) throws Exception {
+		InputStream in = resource.openInputStream();
+		try {
+			return parseClassFile(in, cd);
+		}
+		finally {
+			in.close();
+		}
+	}
+
+	public Set<TypeRef> parseClassFile(InputStream in, ClassDataCollector cd) throws Exception {
+		DataInputStream din = new DataInputStream(in);
+		try {
+			this.cd = cd;
+			return parseClassFile(din);
+		}
+		finally {
+			cd = null;
+			din.close();
+		}
+	}
+
+	Set<TypeRef> parseClassFile(DataInputStream in) throws Exception {
+		xref = new HashSet<TypeRef>();
+
+		boolean crawl = cd != null; // Crawl the byte code if we have a
+		// collector
+		int magic = in.readInt();
+		if (magic != 0xCAFEBABE)
+			throw new IOException("Not a valid class file (no CAFEBABE header)");
+
+		minor = in.readUnsignedShort(); // minor version
+		major = in.readUnsignedShort(); // major version
+		if (cd != null)
+			cd.version(minor, major);
+		int count = in.readUnsignedShort();
+		pool = new Object[count];
+		intPool = new int[count];
+
+		process: for (int poolIndex = 1; poolIndex < count; poolIndex++) {
+			byte tag = in.readByte();
+			switch (tag) {
+				case 0 :
+					break process;
+				case 1 :
+					constantUtf8(in, poolIndex);
+					break;
+
+				case 3 :
+					constantInteger(in, poolIndex);
+					break;
+
+				case 4 :
+					constantFloat(in, poolIndex);
+					break;
+
+				// For some insane optimization reason are
+				// the long and the double two entries in the
+				// constant pool. See 4.4.5
+				case 5 :
+					constantLong(in, poolIndex);
+					poolIndex++;
+					break;
+
+				case 6 :
+					constantDouble(in, poolIndex);
+					poolIndex++;
+					break;
+
+				case 7 :
+					constantClass(in, poolIndex);
+					break;
+
+				case 8 :
+					constantString(in, poolIndex);
+					break;
+
+				case 10 : // Method ref
+				case 11 : // Interface Method ref
+					methodRef(in, poolIndex);
+					break;
+
+				// Name and Type
+				case 12 :
+					nameAndType(in, poolIndex, tag);
+					break;
+
+				// We get the skip count for each record type
+				// from the SkipTable. This will also automatically
+				// abort when
+				default :
+					if (tag == 2)
+						throw new IOException("Invalid tag " + tag);
+					in.skipBytes(SkipTable[tag]);
+					break;
+			}
+		}
+
+		pool(pool, intPool);
+
+		// All name& type and class constant records contain descriptors we must
+		// treat
+		// as references, though not API
+
+		for (Object o : pool) {
+			if (o == null)
+				continue;
+
+			if (o instanceof Assoc && ((Assoc) o).tag == 12) {
+				referTo(((Assoc) o).b, 0); // Descriptor
+			} else if (o instanceof ClassConstant) {
+				String binaryClassName = (String) pool[((ClassConstant) o).cname];
+				TypeRef typeRef = analyzer.getTypeRef(binaryClassName);
+				referTo(typeRef, 0);
+			}
+		}
+
+		/*
+		 * Parse after the constant pool, code thanks to Hans Christian
+		 * Falkenberg
+		 */
+
+		accessx = in.readUnsignedShort(); // access
+		if (Modifier.isPublic(accessx))
+			api = new HashSet<PackageRef>();
+
+		int this_class = in.readUnsignedShort();
+		className = analyzer.getTypeRef((String) pool[intPool[this_class]]);
+		referTo(className, Modifier.PUBLIC);
+
+		try {
+
+			if (cd != null) {
+				if (!cd.classStart(accessx, className))
+					return null;
+			}
+
+			int super_class = in.readUnsignedShort();
+			String superName = (String) pool[intPool[super_class]];
+			if (superName != null) {
+				zuper = analyzer.getTypeRef(superName);
+			}
+
+			if (zuper != null) {
+				referTo(zuper, accessx);
+				if (cd != null)
+					cd.extendsClass(zuper);
+			}
+
+			int interfacesCount = in.readUnsignedShort();
+			if (interfacesCount > 0) {
+				interfaces = new TypeRef[interfacesCount];
+				for (int i = 0; i < interfacesCount; i++) {
+					interfaces[i] = analyzer.getTypeRef((String) pool[intPool[in.readUnsignedShort()]]);
+					referTo(interfaces[i], accessx);
+				}
+				if (cd != null)
+					cd.implementsInterfaces(interfaces);
+			}
+
+			int fieldsCount = in.readUnsignedShort();
+			for (int i = 0; i < fieldsCount; i++) {
+				int access_flags = in.readUnsignedShort(); // skip access flags
+				int name_index = in.readUnsignedShort();
+				int descriptor_index = in.readUnsignedShort();
+
+				// Java prior to 1.5 used a weird
+				// static variable to hold the com.X.class
+				// result construct. If it did not find it
+				// it would create a variable class$com$X
+				// that would be used to hold the class
+				// object gotten with Class.forName ...
+				// Stupidly, they did not actively use the
+				// class name for the field type, so bnd
+				// would not see a reference. We detect
+				// this case and add an artificial descriptor
+				String name = pool[name_index].toString(); // name_index
+				if (name.startsWith("class$")) {
+					crawl = true;
+				}
+				if (cd != null)
+					cd.field(last = new FieldDef(access_flags, name, pool[descriptor_index].toString()));
+
+				referTo(descriptor_index, access_flags);
+				doAttributes(in, ElementType.FIELD, false, access_flags);
+			}
+
+			//
+			// Check if we have to crawl the code to find
+			// the ldc(_w) <string constant> invokestatic Class.forName
+			// if so, calculate the method ref index so we
+			// can do this efficiently
+			//
+			if (crawl) {
+				forName = findMethodReference("java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;");
+				class$ = findMethodReference(className.getBinary(), "class$", "(Ljava/lang/String;)Ljava/lang/Class;");
+			} else if (major == 48) {
+				forName = findMethodReference("java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;");
+				if (forName > 0) {
+					crawl = true;
+					class$ = findMethodReference(className.getBinary(), "class$",
+							"(Ljava/lang/String;)Ljava/lang/Class;");
+				}
+			}
+
+			// There are some serious changes in the
+			// class file format. So we do not do any crawling
+			// it has also become less important
+			if (major >= JAVA.OpenJDK7.major)
+				crawl = false;
+
+			//
+			// Handle the methods
+			//
+			int methodCount = in.readUnsignedShort();
+			for (int i = 0; i < methodCount; i++) {
+				int access_flags = in.readUnsignedShort();
+				int name_index = in.readUnsignedShort();
+				int descriptor_index = in.readUnsignedShort();
+				String name = pool[name_index].toString();
+				String descriptor = pool[descriptor_index].toString();
+				if (cd != null) {
+					MethodDef mdef = new MethodDef(access_flags, name, descriptor);
+					last = mdef;
+					cd.method(mdef);
+				}
+				referTo(descriptor_index, access_flags);
+
+				if ("<init>".equals(name)) {
+					doAttributes(in, ElementType.CONSTRUCTOR, crawl, access_flags);
+				} else {
+					doAttributes(in, ElementType.METHOD, crawl, access_flags);
+				}
+			}
+			if (cd != null)
+				cd.memberEnd();
+
+			doAttributes(in, ElementType.TYPE, false, accessx);
+
+			//
+			// Parse all the descriptors we found
+			//
+
+			Set<TypeRef> xref = this.xref;
+			reset();
+			return xref;
+		}
+		finally {
+			if (cd != null)
+				cd.classEnd();
+		}
+	}
+
+	private void constantFloat(DataInputStream in, int poolIndex) throws IOException {
+		if (cd != null)
+			pool[poolIndex] = in.readFloat(); // ALU
+		else
+			in.skipBytes(4);
+	}
+
+	private void constantInteger(DataInputStream in, int poolIndex) throws IOException {
+		intPool[poolIndex] = in.readInt();
+		if (cd != null)
+			pool[poolIndex] = intPool[poolIndex];
+	}
+
+	protected void pool(@SuppressWarnings("unused")
+	Object[] pool, @SuppressWarnings("unused")
+	int[] intPool) {}
+
+	/**
+	 * @param in
+	 * @param poolIndex
+	 * @param tag
+	 * @throws IOException
+	 */
+	protected void nameAndType(DataInputStream in, int poolIndex, byte tag) throws IOException {
+		int name_index = in.readUnsignedShort();
+		int descriptor_index = in.readUnsignedShort();
+		pool[poolIndex] = new Assoc(tag, name_index, descriptor_index);
+	}
+
+	/**
+	 * @param in
+	 * @param poolIndex
+	 * @param tag
+	 * @throws IOException
+	 */
+	private void methodRef(DataInputStream in, int poolIndex) throws IOException {
+		int class_index = in.readUnsignedShort();
+		int name_and_type_index = in.readUnsignedShort();
+		pool[poolIndex] = new Assoc((byte) 10, class_index, name_and_type_index);
+	}
+
+	/**
+	 * @param in
+	 * @param poolIndex
+	 * @throws IOException
+	 */
+	private void constantString(DataInputStream in, int poolIndex) throws IOException {
+		int string_index = in.readUnsignedShort();
+		intPool[poolIndex] = string_index;
+	}
+
+	/**
+	 * @param in
+	 * @param poolIndex
+	 * @throws IOException
+	 */
+	protected void constantClass(DataInputStream in, int poolIndex) throws IOException {
+		int class_index = in.readUnsignedShort();
+		intPool[poolIndex] = class_index;
+		ClassConstant c = new ClassConstant(class_index);
+		pool[poolIndex] = c;
+	}
+
+	/**
+	 * @param in
+	 * @throws IOException
+	 */
+	protected void constantDouble(DataInputStream in, int poolIndex) throws IOException {
+		if (cd != null)
+			pool[poolIndex] = in.readDouble();
+		else
+			in.skipBytes(8);
+	}
+
+	/**
+	 * @param in
+	 * @throws IOException
+	 */
+	protected void constantLong(DataInputStream in, int poolIndex) throws IOException {
+		if (cd != null) {
+			pool[poolIndex] = in.readLong();
+		} else
+			in.skipBytes(8);
+	}
+
+	/**
+	 * @param in
+	 * @param poolIndex
+	 * @throws IOException
+	 */
+	protected void constantUtf8(DataInputStream in, int poolIndex) throws IOException {
+		// CONSTANT_Utf8
+
+		String name = in.readUTF();
+		pool[poolIndex] = name;
+	}
+
+	/**
+	 * Find a method reference in the pool that points to the given class,
+	 * methodname and descriptor.
+	 * 
+	 * @param clazz
+	 * @param methodname
+	 * @param descriptor
+	 * @return index in constant pool
+	 */
+	private int findMethodReference(String clazz, String methodname, String descriptor) {
+		for (int i = 1; i < pool.length; i++) {
+			if (pool[i] instanceof Assoc) {
+				Assoc methodref = (Assoc) pool[i];
+				if (methodref.tag == 10) {
+					// Method ref
+					int class_index = methodref.a;
+					int class_name_index = intPool[class_index];
+					if (clazz.equals(pool[class_name_index])) {
+						int name_and_type_index = methodref.b;
+						Assoc name_and_type = (Assoc) pool[name_and_type_index];
+						if (name_and_type.tag == 12) {
+							// Name and Type
+							int name_index = name_and_type.a;
+							int type_index = name_and_type.b;
+							if (methodname.equals(pool[name_index])) {
+								if (descriptor.equals(pool[type_index])) {
+									return i;
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+		return -1;
+	}
+
+	/**
+	 * Called for each attribute in the class, field, or method.
+	 * 
+	 * @param in
+	 *            The stream
+	 * @param access_flags
+	 * @throws Exception
+	 */
+	private void doAttributes(DataInputStream in, ElementType member, boolean crawl, int access_flags) throws Exception {
+		int attributesCount = in.readUnsignedShort();
+		for (int j = 0; j < attributesCount; j++) {
+			// skip name CONSTANT_Utf8 pointer
+			doAttribute(in, member, crawl, access_flags);
+		}
+	}
+
+	/**
+	 * Process a single attribute, if not recognized, skip it.
+	 * 
+	 * @param in
+	 *            the data stream
+	 * @param access_flags
+	 * @throws Exception
+	 */
+	private void doAttribute(DataInputStream in, ElementType member, boolean crawl, int access_flags) throws Exception {
+		int attribute_name_index = in.readUnsignedShort();
+		String attributeName = (String) pool[attribute_name_index];
+		long attribute_length = in.readInt();
+		attribute_length &= 0xFFFFFFFF;
+		if ("Deprecated".equals(attributeName)) {
+			if (cd != null)
+				cd.deprecated();
+		} else if ("RuntimeVisibleAnnotations".equals(attributeName))
+			doAnnotations(in, member, RetentionPolicy.RUNTIME, access_flags);
+		else if ("RuntimeVisibleParameterAnnotations".equals(attributeName))
+			doParameterAnnotations(in, member, RetentionPolicy.RUNTIME, access_flags);
+		else if ("RuntimeInvisibleAnnotations".equals(attributeName))
+			doAnnotations(in, member, RetentionPolicy.CLASS, access_flags);
+		else if ("RuntimeInvisibleParameterAnnotations".equals(attributeName))
+			doParameterAnnotations(in, member, RetentionPolicy.CLASS, access_flags);
+		else if ("InnerClasses".equals(attributeName))
+			doInnerClasses(in);
+		else if ("EnclosingMethod".equals(attributeName))
+			doEnclosingMethod(in);
+		else if ("SourceFile".equals(attributeName))
+			doSourceFile(in);
+		else if ("Code".equals(attributeName) && crawl)
+			doCode(in);
+		else if ("Signature".equals(attributeName))
+			doSignature(in, member, access_flags);
+		else if ("ConstantValue".equals(attributeName))
+			doConstantValue(in);
+		else if ("AnnotationDefault".equals(attributeName))
+			doElementValue(in, member, RetentionPolicy.RUNTIME, cd!=null, access_flags);
+		else if ("Exceptions".equals(attributeName))
+			doExceptions(in, access_flags);
+		else {
+			if (attribute_length > 0x7FFFFFFF) {
+				throw new IllegalArgumentException("Attribute > 2Gb");
+			}
+			in.skipBytes((int) attribute_length);
+		}
+	}
+
+	/**
+	 * <pre>
+	 * EnclosingMethod_attribute { 
+	 * 	u2 attribute_name_index; 
+	 * 	u4 attribute_length; 
+	 * 	u2 class_index
+	 * 	u2 method_index;
+	 * }
+	 * </pre>
+	 * 
+	 * @param in
+	 * @throws IOException
+	 */
+	private void doEnclosingMethod(DataInputStream in) throws IOException {
+		int cIndex = in.readShort();
+		int mIndex = in.readShort();
+
+		if (cd != null) {
+			int nameIndex = intPool[cIndex];
+			TypeRef cName = analyzer.getTypeRef((String) pool[nameIndex]);
+
+			String mName = null;
+			String mDescriptor = null;
+
+			if (mIndex != 0) {
+				Assoc nameAndType = (Assoc) pool[mIndex];
+				mName = (String) pool[nameAndType.a];
+				mDescriptor = (String) pool[nameAndType.b];
+			}
+			cd.enclosingMethod(cName, mName, mDescriptor);
+		}
+	}
+
+	/**
+	 * <pre>
+	 * InnerClasses_attribute {
+	 * 	u2 attribute_name_index; 
+	 * 	u4 attribute_length; 
+	 * 	u2 number_of_classes; {	
+	 * 		u2 inner_class_info_index;
+	 * 		u2 outer_class_info_index; 
+	 * 		u2 inner_name_index; 
+	 * 		u2 inner_class_access_flags;
+	 * 	} classes[number_of_classes];
+	 * }
+	 * </pre>
+	 * 
+	 * @param in
+	 * @throws Exception
+	 */
+	private void doInnerClasses(DataInputStream in) throws Exception {
+		int number_of_classes = in.readShort();
+		for (int i = 0; i < number_of_classes; i++) {
+			int inner_class_info_index = in.readShort();
+			int outer_class_info_index = in.readShort();
+			int inner_name_index = in.readShort();
+			int inner_class_access_flags = in.readShort() & 0xFFFF;
+
+			if (cd != null) {
+				TypeRef innerClass = null;
+				TypeRef outerClass = null;
+				String innerName = null;
+
+				if (inner_class_info_index != 0) {
+					int nameIndex = intPool[inner_class_info_index];
+					innerClass = analyzer.getTypeRef((String) pool[nameIndex]);
+				}
+
+				if (outer_class_info_index != 0) {
+					int nameIndex = intPool[outer_class_info_index];
+					outerClass = analyzer.getTypeRef((String) pool[nameIndex]);
+				}
+
+				if (inner_name_index != 0)
+					innerName = (String) pool[inner_name_index];
+
+				cd.innerClass(innerClass, outerClass, innerName, inner_class_access_flags);
+			}
+		}
+	}
+
+	/**
+	 * Handle a signature
+	 * 
+	 * <pre>
+	 * Signature_attribute { 
+	 *     u2 attribute_name_index; 
+	 *     u4 attribute_length; 
+	 *     u2 signature_index; 
+	 *     }
+	 * </pre>
+	 * 
+	 * @param member
+	 * @param access_flags
+	 */
+
+	void doSignature(DataInputStream in, ElementType member, int access_flags) throws IOException {
+		int signature_index = in.readUnsignedShort();
+		String signature = (String) pool[signature_index];
+
+		parseDescriptor(signature, access_flags);
+
+		if (last != null)
+			last.signature = signature;
+
+		if (cd != null)
+			cd.signature(signature);
+	}
+
+	/**
+	 * Handle a constant value call the data collector with it
+	 */
+	void doConstantValue(DataInputStream in) throws IOException {
+		int constantValue_index = in.readUnsignedShort();
+		if (cd == null)
+			return;
+
+		Object object = pool[constantValue_index];
+		if (object == null)
+			object = pool[intPool[constantValue_index]];
+
+		last.constant = object;
+		cd.constant(object);
+	}
+
+	void doExceptions(DataInputStream in, int access_flags) throws IOException {
+		int exception_count = in.readUnsignedShort();
+		for (int i = 0; i < exception_count; i++) {
+			int index = in.readUnsignedShort();
+			if (api != null && (Modifier.isPublic(access_flags) || Modifier.isProtected(access_flags))) {
+				ClassConstant cc = (ClassConstant) pool[index];
+				String descr = (String) pool[cc.cname];
+
+				TypeRef clazz = analyzer.getTypeRef(descr);
+				referTo(clazz, access_flags);
+			}
+		}
+	}
+
+	/**
+	 * <pre>
+	 * Code_attribute {
+	 * 		u2 attribute_name_index;
+	 * 		u4 attribute_length;
+	 * 		u2 max_stack;
+	 * 		u2 max_locals;
+	 * 		u4 code_length;
+	 * 		u1 code[code_length];
+	 * 		u2 exception_table_length;
+	 * 		{    	u2 start_pc;
+	 * 		      	u2 end_pc;
+	 * 		      	u2  handler_pc;
+	 * 		      	u2  catch_type;
+	 * 		}	exception_table[exception_table_length];
+	 * 		u2 attributes_count;
+	 * 		attribute_info attributes[attributes_count];
+	 * 	}
+	 * </pre>
+	 * 
+	 * @param in
+	 * @param pool
+	 * @throws Exception
+	 */
+	private void doCode(DataInputStream in) throws Exception {
+		/* int max_stack = */in.readUnsignedShort();
+		/* int max_locals = */in.readUnsignedShort();
+		int code_length = in.readInt();
+		byte code[] = new byte[code_length];
+		in.readFully(code);
+		crawl(code);
+		int exception_table_length = in.readUnsignedShort();
+		in.skipBytes(exception_table_length * 8);
+		doAttributes(in, ElementType.METHOD, false, 0);
+	}
+
+	/**
+	 * We must find Class.forName references ...
+	 * 
+	 * @param code
+	 */
+	protected void crawl(byte[] code) {
+		ByteBuffer bb = ByteBuffer.wrap(code);
+		bb.order(ByteOrder.BIG_ENDIAN);
+		int lastReference = -1;
+
+		while (bb.remaining() > 0) {
+			int instruction = 0xFF & bb.get();
+			switch (instruction) {
+				case OpCodes.ldc :
+					lastReference = 0xFF & bb.get();
+					break;
+
+				case OpCodes.ldc_w :
+					lastReference = 0xFFFF & bb.getShort();
+					break;
+
+				case OpCodes.invokespecial : {
+					int mref = 0xFFFF & bb.getShort();
+					if (cd != null)
+						getMethodDef(0, mref);
+					break;
+				}
+
+				case OpCodes.invokevirtual : {
+					int mref = 0xFFFF & bb.getShort();
+					if (cd != null)
+						getMethodDef(0, mref);
+					break;
+				}
+
+				case OpCodes.invokeinterface : {
+					int mref = 0xFFFF & bb.getShort();
+					if (cd != null)
+						getMethodDef(0, mref);
+					break;
+				}
+
+				case OpCodes.invokestatic : {
+					int methodref = 0xFFFF & bb.getShort();
+					if (cd != null)
+						getMethodDef(0, methodref);
+
+					if ((methodref == forName || methodref == class$) && lastReference != -1
+							&& pool[intPool[lastReference]] instanceof String) {
+						String fqn = (String) pool[intPool[lastReference]];
+						if (!fqn.equals("class") && fqn.indexOf('.') > 0) {
+							TypeRef clazz = analyzer.getTypeRefFromFQN(fqn);
+							referTo(clazz, 0);
+						}
+						lastReference = -1;
+					}
+					break;
+				}
+
+				case OpCodes.tableswitch :
+					// Skip to place divisible by 4
+					while ((bb.position() & 0x3) != 0)
+						bb.get();
+					/* int deflt = */
+					bb.getInt();
+					int low = bb.getInt();
+					int high = bb.getInt();
+					try {
+						bb.position(bb.position() + (high - low + 1) * 4);
+					}
+					catch (Exception e) {
+						// TODO Auto-generated catch block
+						e.printStackTrace();
+					}
+					lastReference = -1;
+					break;
+
+				case OpCodes.lookupswitch :
+					// Skip to place divisible by 4
+					while ((bb.position() & 0x3) != 0)
+						bb.get();
+					/* deflt = */
+					bb.getInt();
+					int npairs = bb.getInt();
+					bb.position(bb.position() + npairs * 8);
+					lastReference = -1;
+					break;
+
+				default :
+					lastReference = -1;
+					bb.position(bb.position() + OpCodes.OFFSETS[instruction]);
+			}
+		}
+	}
+
+	private void doSourceFile(DataInputStream in) throws IOException {
+		int sourcefile_index = in.readUnsignedShort();
+		this.sourceFile = pool[sourcefile_index].toString();
+	}
+
+	private void doParameterAnnotations(DataInputStream in, ElementType member, RetentionPolicy policy, int access_flags)
+			throws IOException {
+		int num_parameters = in.readUnsignedByte();
+		for (int p = 0; p < num_parameters; p++) {
+			if (cd != null)
+				cd.parameter(p);
+			doAnnotations(in, member, policy, access_flags);
+		}
+	}
+
+	private void doAnnotations(DataInputStream in, ElementType member, RetentionPolicy policy, int access_flags)
+			throws IOException {
+		int num_annotations = in.readUnsignedShort(); // # of annotations
+		for (int a = 0; a < num_annotations; a++) {
+			if (cd == null)
+				doAnnotation(in, member, policy, false, access_flags);
+			else {
+				Annotation annotion = doAnnotation(in, member, policy, true, access_flags);
+				cd.annotation(annotion);
+			}
+		}
+	}
+
+	private Annotation doAnnotation(DataInputStream in, ElementType member, RetentionPolicy policy, boolean collect,
+			int access_flags) throws IOException {
+		int type_index = in.readUnsignedShort();
+		if (annotations == null)
+			annotations = new HashSet<TypeRef>();
+
+		TypeRef tr = analyzer.getTypeRef(pool[type_index].toString());
+		annotations.add(tr);
+
+		TypeRef name = analyzer.getTypeRef((String) pool[type_index]);
+		if (policy == RetentionPolicy.RUNTIME) {
+			referTo(type_index, 0);
+			hasRuntimeAnnotations = true;
+			if (api != null && (Modifier.isPublic(access_flags) || Modifier.isProtected(access_flags)))
+				api.add(name.getPackageRef());
+		} else {
+			hasClassAnnotations = true;
+		}
+		int num_element_value_pairs = in.readUnsignedShort();
+		Map<String,Object> elements = null;
+		for (int v = 0; v < num_element_value_pairs; v++) {
+			int element_name_index = in.readUnsignedShort();
+			String element = (String) pool[element_name_index];
+			Object value = doElementValue(in, member, policy, collect, access_flags);
+			if (collect) {
+				if (elements == null)
+					elements = new LinkedHashMap<String,Object>();
+				elements.put(element, value);
+			}
+		}
+		if (collect)
+			return new Annotation(name, elements, member, policy);
+		return null;
+	}
+
+	private Object doElementValue(DataInputStream in, ElementType member, RetentionPolicy policy, boolean collect,
+			int access_flags) throws IOException {
+		char tag = (char) in.readUnsignedByte();
+		switch (tag) {
+			case 'B' : // Byte
+			case 'C' : // Character
+			case 'I' : // Integer
+			case 'S' : // Short
+				int const_value_index = in.readUnsignedShort();
+				return intPool[const_value_index];
+
+			case 'D' : // Double
+			case 'F' : // Float
+			case 's' : // String
+			case 'J' : // Long
+				const_value_index = in.readUnsignedShort();
+				return pool[const_value_index];
+
+			case 'Z' : // Boolean
+				const_value_index = in.readUnsignedShort();
+				return pool[const_value_index] == null || pool[const_value_index].equals(0) ? false : true;
+
+			case 'e' : // enum constant
+				int type_name_index = in.readUnsignedShort();
+				if (policy == RetentionPolicy.RUNTIME) {
+					referTo(type_name_index, 0);
+					if (api != null && (Modifier.isPublic(access_flags) || Modifier.isProtected(access_flags))) {
+						TypeRef name = analyzer.getTypeRef((String) pool[type_name_index]);
+						api.add(name.getPackageRef());
+					}
+				}
+				int const_name_index = in.readUnsignedShort();
+				return pool[const_name_index];
+
+			case 'c' : // Class
+				int class_info_index = in.readUnsignedShort();
+				if (policy == RetentionPolicy.RUNTIME) {
+					referTo(class_info_index, 0);
+					if (api != null && (Modifier.isPublic(access_flags) || Modifier.isProtected(access_flags))) {
+						TypeRef name = analyzer.getTypeRef((String) pool[class_info_index]);
+						api.add(name.getPackageRef());
+					}
+				}
+				return pool[class_info_index];
+
+			case '@' : // Annotation type
+				return doAnnotation(in, member, policy, collect, access_flags);
+
+			case '[' : // Array
+				int num_values = in.readUnsignedShort();
+				Object[] result = new Object[num_values];
+				for (int i = 0; i < num_values; i++) {
+					result[i] = doElementValue(in, member, policy, collect, access_flags);
+				}
+				return result;
+
+			default :
+				throw new IllegalArgumentException("Invalid value for Annotation ElementValue tag " + tag);
+		}
+	}
+
+	/**
+	 * Add a new package reference.
+	 * 
+	 * @param packageRef
+	 *            A '.' delimited package name
+	 */
+	void referTo(TypeRef typeRef, int modifiers) {
+		if (xref != null)
+			xref.add(typeRef);
+		if (typeRef.isPrimitive())
+			return;
+
+		PackageRef packageRef = typeRef.getPackageRef();
+		if (packageRef.isPrimitivePackage())
+			return;
+
+		imports.add(packageRef);
+
+		if (api != null && (Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers)))
+			api.add(packageRef);
+
+		if (cd != null)
+			cd.referTo(typeRef, modifiers);
+
+	}
+
+	void referTo(int index, int modifiers) {
+		String descriptor = (String) pool[index];
+		parseDescriptor(descriptor, modifiers);
+	}
+
+	/**
+	 * This method parses a descriptor and adds the package of the descriptor to
+	 * the referenced packages. The syntax of the descriptor is:
+	 * 
+	 * <pre>
+	 *   descriptor ::= ( '(' reference * ')' )? reference
+	 *   reference  ::= 'L' classname ( '<' references '>' )? ';' | 'B' | 'Z' | ... | '+' | '-' | '['
+	 * </pre>
+	 * 
+	 * This methods uses heavy recursion to parse the descriptor and a roving
+	 * pointer to limit the creation of string objects.
+	 * 
+	 * @param descriptor
+	 *            The to be parsed descriptor
+	 * @param rover
+	 *            The pointer to start at
+	 */
+
+	public void parseDescriptor(String descriptor, int modifiers) {
+		// Some descriptors are weird, they start with a generic
+		// declaration that contains ':', not sure what they mean ...
+		int rover = 0;
+		if (descriptor.charAt(0) == '<') {
+			rover = parseFormalTypeParameters(descriptor, rover, modifiers);
+		}
+
+		if (descriptor.charAt(rover) == '(') {
+			rover = parseReferences(descriptor, rover + 1, ')', modifiers);
+			rover++;
+		}
+		parseReferences(descriptor, rover, (char) 0, modifiers);
+	}
+
+	/**
+	 * Parse a sequence of references. A sequence ends with a given character or
+	 * when the string ends.
+	 * 
+	 * @param descriptor
+	 *            The whole descriptor.
+	 * @param rover
+	 *            The index in the descriptor
+	 * @param delimiter
+	 *            The end character or 0
+	 * @return the last index processed, one character after the delimeter
+	 */
+	int parseReferences(String descriptor, int rover, char delimiter, int modifiers) {
+		int r = rover;
+		while (r < descriptor.length() && descriptor.charAt(r) != delimiter) {
+			r = parseReference(descriptor, r, modifiers);
+		}
+		return r;
+	}
+
+	/**
+	 * Parse a single reference. This can be a single character or an object
+	 * reference when it starts with 'L'.
+	 * 
+	 * @param descriptor
+	 *            The descriptor
+	 * @param rover
+	 *            The place to start
+	 * @return The return index after the reference
+	 */
+	int parseReference(String descriptor, int rover, int modifiers) {
+		int r = rover;
+		char c = descriptor.charAt(r);
+		while (c == '[')
+			c = descriptor.charAt(++r);
+
+		if (c == '<') {
+			r = parseReferences(descriptor, r + 1, '>', modifiers);
+		} else if (c == 'T') {
+			// Type variable name
+			r++;
+			while (descriptor.charAt(r) != ';')
+				r++;
+		} else if (c == 'L') {
+			StringBuilder sb = new StringBuilder();
+			r++;
+			while ((c = descriptor.charAt(r)) != ';') {
+				if (c == '<') {
+					r = parseReferences(descriptor, r + 1, '>', modifiers);
+				} else
+					sb.append(c);
+				r++;
+			}
+			TypeRef ref = analyzer.getTypeRef(sb.toString());
+			if (cd != null)
+				cd.addReference(ref);
+
+			referTo(ref, modifiers);
+		} else {
+			if ("+-*BCDFIJSZV".indexOf(c) < 0)
+				;// System.err.println("Should not skip: " + c);
+		}
+
+		// this skips a lot of characters
+		// [, *, +, -, B, etc.
+
+		return r + 1;
+	}
+
+	/**
+	 * FormalTypeParameters
+	 * 
+	 * @param descriptor
+	 * @param index
+	 * @return
+	 */
+	private int parseFormalTypeParameters(String descriptor, int index, int modifiers) {
+		index++;
+		while (descriptor.charAt(index) != '>') {
+			// Skip IDENTIFIER
+			index = descriptor.indexOf(':', index) + 1;
+			if (index == 0)
+				throw new IllegalArgumentException("Expected IDENTIFIER: " + descriptor);
+
+			// ClassBound? InterfaceBounds
+
+			char c = descriptor.charAt(index);
+
+			// Class Bound?
+			if (c == 'L' || c == 'T') {
+				index = parseReference(descriptor, index, modifiers); // class
+																		// reference
+				c = descriptor.charAt(index);
+			}
+
+			// Interface Bounds
+			while (c == ':') {
+				index++;
+				index = parseReference(descriptor, index, modifiers);
+				c = descriptor.charAt(index);
+			} // for each interface
+
+		} // for each formal parameter
+		return index + 1; // skip >
+	}
+
+	public Set<PackageRef> getReferred() {
+		return imports;
+	}
+
+	public String getAbsolutePath() {
+		return path;
+	}
+
+	public String getSourceFile() {
+		return sourceFile;
+	}
+
+	/**
+	 * .class construct for different compilers sun 1.1 Detect static variable
+	 * class$com$acme$MyClass 1.2 " 1.3 " 1.4 " 1.5 ldc_w (class) 1.6 " eclipse
+	 * 1.1 class$0, ldc (string), invokestatic Class.forName 1.2 " 1.3 " 1.5 ldc
+	 * (class) 1.6 " 1.5 and later is not an issue, sun pre 1.5 is easy to
+	 * detect the static variable that decodes the class name. For eclipse, the
+	 * class$0 gives away we have a reference encoded in a string.
+	 * compilerversions/compilerversions.jar contains test versions of all
+	 * versions/compilers.
+	 */
+
+	public void reset() {
+		pool = null;
+		intPool = null;
+		xref = null;
+	}
+
+	public boolean is(QUERY query, Instruction instr, Analyzer analyzer) throws Exception {
+		switch (query) {
+			case ANY :
+				return true;
+
+			case NAMED :
+				if (instr.matches(getClassName().getDottedOnly()))
+					return !instr.isNegated();
+				return false;
+
+			case VERSION :
+				String v = major + "." + minor;
+				if (instr.matches(v))
+					return !instr.isNegated();
+				return false;
+
+			case IMPLEMENTS :
+				for (int i = 0; interfaces != null && i < interfaces.length; i++) {
+					if (instr.matches(interfaces[i].getDottedOnly()))
+						return !instr.isNegated();
+				}
+				break;
+
+			case EXTENDS :
+				if (zuper == null)
+					return false;
+
+				if (instr.matches(zuper.getDottedOnly()))
+					return !instr.isNegated();
+				break;
+
+			case PUBLIC :
+				return Modifier.isPublic(accessx);
+
+			case CONCRETE :
+				return !Modifier.isAbstract(accessx);
+
+			case ANNOTATED :
+				if (annotations == null)
+					return false;
+
+				for (TypeRef annotation : annotations) {
+					if (instr.matches(annotation.getFQN()))
+						return !instr.isNegated();
+				}
+
+				return false;
+
+			case RUNTIMEANNOTATIONS :
+				return hasRuntimeAnnotations;
+			case CLASSANNOTATIONS :
+				return hasClassAnnotations;
+
+			case ABSTRACT :
+				return Modifier.isAbstract(accessx);
+
+			case IMPORTS :
+				for (PackageRef imp : imports) {
+					if (instr.matches(imp.getFQN()))
+						return !instr.isNegated();
+				}
+		}
+
+		if (zuper == null)
+			return false;
+
+		Clazz clazz = analyzer.findClass(zuper);
+		if (clazz == null)
+			return false;
+
+		return clazz.is(query, instr, analyzer);
+	}
+
+	@Override
+	public String toString() {
+		return className.getFQN();
+	}
+
+	/**
+	 * Called when crawling the byte code and a method reference is found
+	 */
+	void getMethodDef(int access, int methodRefPoolIndex) {
+		if (methodRefPoolIndex == 0)
+			return;
+
+		Object o = pool[methodRefPoolIndex];
+		if (o != null && o instanceof Assoc) {
+			Assoc assoc = (Assoc) o;
+			if (assoc.tag == 10) {
+				int string_index = intPool[assoc.a];
+				TypeRef className = analyzer.getTypeRef((String) pool[string_index]);
+				int name_and_type_index = assoc.b;
+				Assoc name_and_type = (Assoc) pool[name_and_type_index];
+				if (name_and_type.tag == 12) {
+					// Name and Type
+					int name_index = name_and_type.a;
+					int type_index = name_and_type.b;
+					String method = (String) pool[name_index];
+					String descriptor = (String) pool[type_index];
+					cd.referenceMethod(access, className, method, descriptor);
+				} else
+					throw new IllegalArgumentException(
+							"Invalid class file (or parsing is wrong), assoc is not type + name (12)");
+			} else
+				throw new IllegalArgumentException(
+						"Invalid class file (or parsing is wrong), Assoc is not method ref! (10)");
+		} else
+			throw new IllegalArgumentException("Invalid class file (or parsing is wrong), Not an assoc at a method ref");
+	}
+
+	public boolean isPublic() {
+		return Modifier.isPublic(accessx);
+	}
+
+	public boolean isProtected() {
+		return Modifier.isProtected(accessx);
+	}
+
+	public boolean isEnum() {
+		return zuper != null && zuper.getBinary().equals("java/lang/Enum");
+	}
+
+	public JAVA getFormat() {
+		return JAVA.format(major);
+
+	}
+
+	public static String objectDescriptorToFQN(String string) {
+		if (string.startsWith("L") && string.endsWith(";"))
+			return string.substring(1, string.length() - 1).replace('/', '.');
+
+		switch (string.charAt(0)) {
+			case 'V' :
+				return "void";
+			case 'B' :
+				return "byte";
+			case 'C' :
+				return "char";
+			case 'I' :
+				return "int";
+			case 'S' :
+				return "short";
+			case 'D' :
+				return "double";
+			case 'F' :
+				return "float";
+			case 'J' :
+				return "long";
+			case 'Z' :
+				return "boolean";
+			case '[' : // Array
+				return objectDescriptorToFQN(string.substring(1)) + "[]";
+		}
+		throw new IllegalArgumentException("Invalid type character in descriptor " + string);
+	}
+
+	public static String unCamel(String id) {
+		StringBuilder out = new StringBuilder();
+		for (int i = 0; i < id.length(); i++) {
+			char c = id.charAt(i);
+			if (c == '_' || c == '$' || c == '.') {
+				if (out.length() > 0 && !Character.isWhitespace(out.charAt(out.length() - 1)))
+					out.append(' ');
+				continue;
+			}
+
+			int n = i;
+			while (n < id.length() && Character.isUpperCase(id.charAt(n))) {
+				n++;
+			}
+			if (n == i)
+				out.append(id.charAt(i));
+			else {
+				boolean tolower = (n - i) == 1;
+				if (i > 0 && !Character.isWhitespace(out.charAt(out.length() - 1)))
+					out.append(' ');
+
+				for (; i < n;) {
+					if (tolower)
+						out.append(Character.toLowerCase(id.charAt(i)));
+					else
+						out.append(id.charAt(i));
+					i++;
+				}
+				i--;
+			}
+		}
+		if (id.startsWith("."))
+			out.append(" *");
+		out.replace(0, 1, Character.toUpperCase(out.charAt(0)) + "");
+		return out.toString();
+	}
+
+	public boolean isInterface() {
+		return Modifier.isInterface(accessx);
+	}
+
+	public boolean isAbstract() {
+		return Modifier.isAbstract(accessx);
+	}
+
+	public int getAccess() {
+		if (innerAccess == -1)
+			return accessx;
+		return innerAccess;
+	}
+
+	public TypeRef getClassName() {
+		return className;
+	}
+
+	/**
+	 * To provide an enclosing instance
+	 * 
+	 * @param access
+	 * @param name
+	 * @param descriptor
+	 * @return
+	 */
+	public MethodDef getMethodDef(int access, String name, String descriptor) {
+		return new MethodDef(access, name, descriptor);
+	}
+
+	public TypeRef getSuper() {
+		return zuper;
+	}
+
+	public String getFQN() {
+		return className.getFQN();
+	}
+
+	public TypeRef[] getInterfaces() {
+		return interfaces;
+	}
+
+	public void setInnerAccess(int access) {
+		innerAccess = access;
+	}
+
+	public boolean isFinal() {
+		return Modifier.isFinal(accessx);
+	}
+
+	public void setDeprecated(boolean b) {
+		deprecated = b;
+	}
+
+	public boolean isDeprecated() {
+		return deprecated;
+	}
+
+	public boolean isAnnotation() {
+		return (accessx & ACC_ANNOTATION) != 0;
+	}
+
+	public Set<PackageRef> getAPIUses() {
+		if (api == null)
+			return Collections.emptySet();
+		return api;
+	}
+
+	public Clazz.TypeDef getExtends(TypeRef type) {
+		return new TypeDef(type, false);
+	}
+
+	public Clazz.TypeDef getImplements(TypeRef type) {
+		return new TypeDef(type, true);
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/CombinedResource.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/CombinedResource.java
new file mode 100644
index 0000000..1b10348
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/CombinedResource.java
@@ -0,0 +1,34 @@
+package aQute.bnd.osgi;
+
+import java.io.*;
+import java.util.*;
+
+public class CombinedResource extends WriteResource {
+	final List<Resource>	resources		= new ArrayList<Resource>();
+	long					lastModified	= 0;
+
+	@Override
+	public void write(final OutputStream out) throws IOException, Exception {
+		OutputStream unclosable = new FilterOutputStream(out) {
+			@Override
+			public void close() {
+				// Ignore
+			}
+		};
+		for (Resource r : resources) {
+			r.write(unclosable);
+			unclosable.flush();
+		}
+	}
+
+	@Override
+	public long lastModified() {
+		return lastModified;
+	}
+
+	public void addResource(Resource r) {
+		lastModified = Math.max(lastModified, r.lastModified());
+		resources.add(r);
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/CommandResource.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/CommandResource.java
new file mode 100644
index 0000000..19c1a21
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/CommandResource.java
@@ -0,0 +1,51 @@
+package aQute.bnd.osgi;
+
+import java.io.*;
+
+import aQute.libg.command.*;
+
+public class CommandResource extends WriteResource {
+	final long		lastModified;
+	final Builder	domain;
+	final String	command;
+	final File wd;
+
+	public CommandResource(String command, Builder domain, long lastModified, File wd) {
+		this.lastModified = lastModified;
+		this.domain = domain;
+		this.command = command;
+		this.wd = wd;
+	}
+
+	@Override
+	public void write(OutputStream out) throws IOException, Exception {
+		StringBuilder errors = new StringBuilder();
+		StringBuilder stdout = new StringBuilder();
+			domain.trace("executing command %s", command);
+			Command cmd = new Command("sh");
+			cmd.setCwd(wd);
+			cmd.inherit();
+			String oldpath = cmd.var("PATH");
+
+			String path = domain.getProperty("-PATH");
+			if (path != null) {
+				path = path.replaceAll("\\s*,\\s*", File.pathSeparator);
+				path = path.replaceAll("\\$\\{@\\}", oldpath);
+				cmd.var("PATH", path);
+				domain.trace("PATH: %s", path);
+			}
+			OutputStreamWriter osw = new OutputStreamWriter(out, "UTF-8");
+			int result = cmd.execute(command, stdout, errors);
+			osw.append(stdout);
+			osw.flush();
+			if (result != 0) {
+				throw new Exception("executing command failed" + command + "\n"+ stdout + "\n" + errors);
+			}
+	}
+
+	@Override
+	public long lastModified() {
+		return lastModified;
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/Constants.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/Constants.java
new file mode 100644
index 0000000..9e9a388
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/Constants.java
@@ -0,0 +1,325 @@
+package aQute.bnd.osgi;
+
+import java.nio.charset.*;
+import java.util.*;
+import java.util.regex.*;
+
+public interface Constants {
+	/*
+	 * Defined in OSGi
+	 */
+	/**
+	 * @syntax Bundle-ActivationPolicy ::= policy ( ’;’ directive )* policy ::=
+	 *         ’lazy’
+	 */
+	String							BND_ADDXMLTOTEST							= "Bnd-AddXMLToTest";
+	String							BUNDLE_ACTIVATIONPOLICY						= "Bundle-ActivationPolicy";
+	String							BUNDLE_ACTIVATOR							= "Bundle-Activator";
+	String							BUNDLE_BLUEPRINT							= "Bundle-Copyright";
+	String							BUNDLE_CATEGORY								= "Bundle-Category";
+	String							BUNDLE_CLASSPATH							= "Bundle-ClassPath";
+	String							BUNDLE_CONTACTADDRESS						= "Bundle-ContactAddress";
+	String							BUNDLE_COPYRIGHT							= "Bundle-Copyright";
+	String							BUNDLE_DESCRIPTION							= "Bundle-Description";
+	String							BUNDLE_DOCURL								= "Bundle-DocURL";
+	String							BUNDLE_ICON									= "Bundle-Icon";
+	String							BUNDLE_LICENSE								= "Bundle-License";
+	String							BUNDLE_LOCALIZATION							= "Bundle-Localization";
+	String							BUNDLE_MANIFESTVERSION						= "Bundle-ManifestVersion";
+	String							BUNDLE_NAME									= "Bundle-Name";
+	String							BUNDLE_NATIVECODE							= "Bundle-NativeCode";
+	String							BUNDLE_REQUIREDEXECUTIONENVIRONMENT			= "Bundle-RequiredExecutionEnvironment";
+	String							BUNDLE_SYMBOLICNAME							= "Bundle-SymbolicName";
+	String							BUNDLE_UPDATELOCATION						= "Bundle-UpdateLocation";
+	String							BUNDLE_VENDOR								= "Bundle-Vendor";
+	String							BUNDLE_VERSION								= "Bundle-Version";
+	String							DYNAMICIMPORT_PACKAGE						= "DynamicImport-Package";
+	String							EXPORT_PACKAGE								= "Export-Package";
+	String							EXPORT_SERVICE								= "Export-Service";
+	String							FRAGMENT_HOST								= "Fragment-Host";
+	String							IMPORT_PACKAGE								= "Import-Package";
+	String							IMPORT_SERVICE								= "Import-Service";
+	String							PROVIDE_CAPABILITY							= "Provide-Capability";
+	String							REQUIRE_BUNDLE								= "Require-Bundle";
+	String							REQUIRE_CAPABILITY							= "Require-Capability";
+	String							SERVICE_COMPONENT							= "Service-Component";
+
+	String							PRIVATE_PACKAGE								= "Private-Package";
+	String							IGNORE_PACKAGE								= "Ignore-Package";
+	String							INCLUDE_RESOURCE							= "Include-Resource";
+	String							CONDITIONAL_PACKAGE							= "Conditional-Package";
+	String							BND_LASTMODIFIED							= "Bnd-LastModified";
+	String							CREATED_BY									= "Created-By";
+	String							TOOL										= "Tool";
+	String							TESTCASES									= "Test-Cases";
+	/**
+	 * @deprecated Use {@link Constants#TESTCASES}.
+	 */
+	@Deprecated
+	String							TESTSUITES									= "Test-Suites";
+	String							SIGNATURE_TEST								= "-signaturetest";
+
+	String							headers[]									= {
+			BUNDLE_ACTIVATOR, BUNDLE_CONTACTADDRESS, BUNDLE_COPYRIGHT, BUNDLE_DESCRIPTION, BUNDLE_DOCURL,
+			BUNDLE_LOCALIZATION, BUNDLE_NATIVECODE, BUNDLE_VENDOR, BUNDLE_VERSION, BUNDLE_LICENSE, BUNDLE_CLASSPATH,
+			SERVICE_COMPONENT, EXPORT_PACKAGE, IMPORT_PACKAGE, BUNDLE_LOCALIZATION, BUNDLE_MANIFESTVERSION,
+			BUNDLE_NAME, BUNDLE_NATIVECODE, BUNDLE_REQUIREDEXECUTIONENVIRONMENT, BUNDLE_SYMBOLICNAME, BUNDLE_VERSION,
+			FRAGMENT_HOST, PRIVATE_PACKAGE, IGNORE_PACKAGE, INCLUDE_RESOURCE, REQUIRE_BUNDLE, IMPORT_SERVICE,
+			EXPORT_SERVICE, CONDITIONAL_PACKAGE, BND_LASTMODIFIED, TESTCASES, SIGNATURE_TEST, REQUIRE_CAPABILITY,
+			PROVIDE_CAPABILITY, BUNDLE_ICON
+																				};
+
+	String							BASELINE									= "-baseline";
+	String							BASELINEREPO								= "-baselinerepo";
+	String							BUILDPATH									= "-buildpath";
+	String							BUILDPACKAGES								= "-buildpackages";
+	String							BUMPPOLICY									= "-bumppolicy";
+	String							CONDUIT										= "-conduit";
+	String							COMPILER_SOURCE								= "-source";
+	String							COMPILER_TARGET								= "-target";
+	String							DEPENDSON									= "-dependson";
+	String							DEPLOY										= "-deploy";
+	String							DEPLOYREPO									= "-deployrepo";
+	String							DIGESTS										= "-digests";
+	String							DSANNOTATIONS								= "-dsannotations";
+	String							DONOTCOPY									= "-donotcopy";
+	String							DEBUG										= "-debug";
+	String							EXPERIMENTS									= "-experiments";
+	String							EXPORT_CONTENTS								= "-exportcontents";
+	String							FAIL_OK										= "-failok";
+	String							INCLUDE										= "-include";
+	String							INCLUDERESOURCE								= "-includeresource";
+	String							MAKE										= "-make";
+	String							METATYPE									= "-metatype";
+	String							MANIFEST									= "-manifest";
+	String							PROFILE										= "-profile";
+	String							SAVEMANIFEST								= "-savemanifest";
+	String							NAMESECTION									= "-namesection";
+	String							NODEFAULTVERSION							= "-nodefaultversion";
+	String							NOEXTRAHEADERS								= "-noextraheaders";
+	String							NOMANIFEST									= "-nomanifest";
+	String							NOUSES										= "-nouses";
+	String							NOBUNDLES									= "-nobundles";
+	String							PEDANTIC									= "-pedantic";
+	String							PLUGIN										= "-plugin";
+	String							PLUGINPATH									= "-pluginpath";
+	String							POM											= "-pom";
+	String							RELEASEREPO									= "-releaserepo";
+	String							REMOVEHEADERS								= "-removeheaders";
+	String							RESOURCEONLY								= "-resourceonly";
+	String							SOURCES										= "-sources";
+	String							SOURCEPATH									= "-sourcepath";
+	String							SUB											= "-sub";
+	String							RUNPROPERTIES								= "-runproperties";
+	String							RUNSYSTEMPACKAGES							= "-runsystempackages";
+	String							RUNSYSTEMCAPABILITIES						= "-runsystemcapabilities";
+	String							RUNBUNDLES									= "-runbundles";
+	String							RUNREPOS									= "-runrepos";
+
+	/**
+	 * @deprecated This is for support of the legacy OBR requirement format, use
+	 *             {@link #RUNREQUIRES} for new format.
+	 */
+	@Deprecated
+	String							RUNREQUIRE									= "-runrequire";
+
+	String							RUNREQUIRES									= "-runrequires";
+
+	String							RUNEE										= "-runee";
+	String							RUNPATH										= "-runpath";
+	String							RUNSTORAGE									= "-runstorage";
+	String							RUNBUILDS									= "-runbuilds";
+	String							RUNPATH_MAIN_DIRECTIVE						= "main:";
+	String							RUNPATH_LAUNCHER_DIRECTIVE					= "launcher:";
+	String							RUNVM										= "-runvm";
+	String							RUNPROGRAMARGS								= "-runprogramargs";
+	String							RUNTRACE									= "-runtrace";
+	String							RUNFRAMEWORK								= "-runframework";
+	String							RUNFW										= "-runfw";
+	String							RUNTIMEOUT									= "-runtimeout";
+	String							SNAPSHOT									= "-snapshot";
+	String							RUNFRAMEWORK_SERVICES						= "services";
+	String							RUNFRAMEWORK_NONE							= "none";
+	String							REPORTNEWER									= "-reportnewer";
+	String							SIGN										= "-sign";
+	String							TESTPACKAGES								= "-testpackages";
+	String							TESTREPORT									= "-testreport";
+	String							TESTPATH									= "-testpath";
+	String							TESTCONTINUOUS								= "-testcontinuous";
+	String							UNDERTEST									= "-undertest";
+	String							VERBOSE										= "-verbose";
+	String							PROVIDER_POLICY								= "-provider-policy";
+	String							CONSUMER_POLICY								= "-consumer-policy";
+	String							WAB											= "-wab";
+	String							WABLIB										= "-wablib";
+	String							REQUIRE_BND									= "-require-bnd";
+
+	// Deprecated
+	String							CLASSPATH									= "-classpath";
+	String							OUTPUT										= "-output";
+
+	String							options[]									= {
+			BASELINE, BUILDPATH, BUMPPOLICY, CONDUIT, CLASSPATH, CONSUMER_POLICY, DEPENDSON, DONOTCOPY, EXPORT_CONTENTS, FAIL_OK,
+			INCLUDE, INCLUDERESOURCE, MAKE, MANIFEST, NOEXTRAHEADERS, NOUSES, NOBUNDLES, PEDANTIC, PLUGIN, POM,
+			PROVIDER_POLICY, REMOVEHEADERS, RESOURCEONLY, SOURCES, SOURCEPATH, SOURCES, SOURCEPATH, SUB, RUNBUNDLES,
+			RUNPATH, RUNSYSTEMPACKAGES, RUNSYSTEMCAPABILITIES, RUNPROPERTIES, REPORTNEWER, UNDERTEST, TESTPATH, TESTPACKAGES, TESTREPORT,
+			VERBOSE, NOMANIFEST, DEPLOYREPO, RELEASEREPO, SAVEMANIFEST, RUNVM, RUNPROGRAMARGS, WAB, WABLIB, RUNFRAMEWORK, RUNFW, RUNTRACE,
+			TESTCONTINUOUS, SNAPSHOT, NAMESECTION, DIGESTS, DSANNOTATIONS, EXPERIMENTS, BASELINE, BASELINEREPO, PROFILE
+																				};
+
+	// Ignore bundle specific headers. These bundles do not make
+	// a lot of sense to inherit
+	String[]						BUNDLE_SPECIFIC_HEADERS						= new String[] {
+			INCLUDE_RESOURCE, BUNDLE_ACTIVATOR, BUNDLE_CLASSPATH, BUNDLE_NAME, BUNDLE_NATIVECODE, BUNDLE_SYMBOLICNAME,
+			IMPORT_PACKAGE, EXPORT_PACKAGE, DYNAMICIMPORT_PACKAGE, FRAGMENT_HOST, REQUIRE_BUNDLE, PRIVATE_PACKAGE,
+			EXPORT_CONTENTS, TESTCASES, NOMANIFEST, SIGNATURE_TEST, WAB, WABLIB, REQUIRE_CAPABILITY,
+			PROVIDE_CAPABILITY, DSANNOTATIONS, SERVICE_COMPONENT
+																				};
+
+	char							DUPLICATE_MARKER							= '~';
+	String							SPECIFICATION_VERSION						= "specification-version";
+	String							SPLIT_PACKAGE_DIRECTIVE						= "-split-package:";
+	String							IMPORT_DIRECTIVE							= "-import:";
+	String							NO_IMPORT_DIRECTIVE							= "-noimport:";
+	String							REMOVE_ATTRIBUTE_DIRECTIVE					= "-remove-attribute:";
+	String							LIB_DIRECTIVE								= "lib:";
+	String							NOANNOTATIONS								= "-noannotations";
+	String							COMMAND_DIRECTIVE							= "command:";
+	String							USES_DIRECTIVE								= "uses:";
+	String							MANDATORY_DIRECTIVE							= "mandatory:";
+	String							INCLUDE_DIRECTIVE							= "include:";
+	String							PROVIDE_DIRECTIVE							= "provide:";
+	String							EXCLUDE_DIRECTIVE							= "exclude:";
+	String							PRESENCE_DIRECTIVE							= "presence:";
+	String							PRIVATE_DIRECTIVE							= "private:";
+	String							SINGLETON_DIRECTIVE							= "singleton:";
+	String							EXTENSION_DIRECTIVE							= "extension:";
+	String							VISIBILITY_DIRECTIVE						= "visibility:";
+	String							FRAGMENT_ATTACHMENT_DIRECTIVE				= "fragment-attachment:";
+	String							RESOLUTION_DIRECTIVE						= "resolution:";
+	String							PATH_DIRECTIVE								= "path:";
+	String							SIZE_ATTRIBUTE								= "size";
+	String							LINK_ATTRIBUTE								= "link";
+	String							LITERAL_ATTRIBUTE							= "literal";
+	String							NAME_ATTRIBUTE								= "name";
+	String							DESCRIPTION_ATTRIBUTE						= "description";
+	String							OSNAME_ATTRIBUTE							= "osname";
+	String							OSVERSION_ATTRIBUTE							= "osversion";
+	String							PROCESSOR_ATTRIBUTE							= "processor";
+	String							LANGUAGE_ATTRIBUTE							= "language";
+	String							SELECTION_FILTER_ATTRIBUTE					= "selection-filter";
+	String							BLUEPRINT_WAIT_FOR_DEPENDENCIES_ATTRIBUTE	= "blueprint.wait-for-dependencies";
+	String							BLUEPRINT_TIMEOUT_ATTRIBUTE					= "blueprint.timeout";
+	String							VERSION_ATTRIBUTE							= "version";
+	String							BUNDLE_SYMBOLIC_NAME_ATTRIBUTE				= "bundle-symbolic-name";
+	String							BUNDLE_VERSION_ATTRIBUTE					= "bundle-version";
+	String							FROM_DIRECTIVE								= "from:";
+
+	String							KEYSTORE_LOCATION_DIRECTIVE					= "keystore:";
+	String							KEYSTORE_PROVIDER_DIRECTIVE					= "provider:";
+	String							KEYSTORE_PASSWORD_DIRECTIVE					= "password:";
+	String							SIGN_PASSWORD_DIRECTIVE						= "sign-password:";
+
+	String							NONE										= "none";
+
+	String							directives[]								= {
+			SPLIT_PACKAGE_DIRECTIVE, NO_IMPORT_DIRECTIVE, IMPORT_DIRECTIVE, RESOLUTION_DIRECTIVE, INCLUDE_DIRECTIVE,
+			USES_DIRECTIVE, EXCLUDE_DIRECTIVE, KEYSTORE_LOCATION_DIRECTIVE, KEYSTORE_PROVIDER_DIRECTIVE,
+			KEYSTORE_PASSWORD_DIRECTIVE, SIGN_PASSWORD_DIRECTIVE, COMMAND_DIRECTIVE, NOANNOTATIONS, LIB_DIRECTIVE,
+			RUNPATH_LAUNCHER_DIRECTIVE, FROM_DIRECTIVE, PRIVATE_DIRECTIVE, LITERAL_ATTRIBUTE
+
+																				// TODO
+																				};
+
+	String							USES_USES									= "<<USES>>";
+	String							CURRENT_USES								= "@uses";
+	String							IMPORT_REFERENCE							= "reference";
+	String							IMPORT_PRIVATE								= "private";
+	String[]						importDirectives							= {
+			IMPORT_REFERENCE, IMPORT_PRIVATE
+																				};
+
+	static final Pattern			VALID_PROPERTY_TYPES						= Pattern
+																						.compile("(String|Long|Double|Float|Integer|Byte|Character|Boolean|Short)");
+
+	String							DEFAULT_BND_EXTENSION						= ".bnd";
+	String							DEFAULT_JAR_EXTENSION						= ".jar";
+	String							DEFAULT_BAR_EXTENSION						= ".bar";
+	String							DEFAULT_BNDRUN_EXTENSION					= ".bndrun";
+	String[]						METAPACKAGES								= {
+			"META-INF", "OSGI-INF", "OSGI-OPT"
+																				};
+
+	String							CURRENT_VERSION								= "@";
+	String							CURRENT_PACKAGE								= "@package";
+
+	String							BUILDFILES									= "buildfiles";
+
+	String							EMPTY_HEADER								= "<<EMPTY>>";
+
+	String							EMBEDDED_REPO								= "/embedded-repo.jar";
+	String							LAUNCHER_PLUGIN								= "Launcher-Plugin";
+	String							TESTER_PLUGIN								= "Tester-Plugin";
+
+	String							DEFAULT_LAUNCHER_BSN						= "biz.aQute.launcher";
+	String							DEFAULT_TESTER_BSN							= "biz.aQute.junit";
+
+	String							DEFAULT_DO_NOT_COPY							= "CVS|\\.svn|\\.git|\\.DS_Store";
+
+	Charset							DEFAULT_CHARSET								= Charset.forName("UTF8");
+	String							VERSION_FILTER								= "version";
+	String							PROVIDER_TYPE_DIRECTIVE						= "x-provider-type:";
+	/**
+	 * Component constants
+	 */
+	public final static String		NAMESPACE_STEM								= "http://www.osgi.org/xmlns/scr";
+	public final static String		JIDENTIFIER									= "<<identifier>>";
+	public final static String		COMPONENT_NAME								= "name:";
+	public final static String		COMPONENT_FACTORY							= "factory:";
+	public final static String		COMPONENT_SERVICEFACTORY					= "servicefactory:";
+	public final static String		COMPONENT_IMMEDIATE							= "immediate:";
+	public final static String		COMPONENT_ENABLED							= "enabled:";
+	public final static String		COMPONENT_DYNAMIC							= "dynamic:";
+	public final static String		COMPONENT_MULTIPLE							= "multiple:";
+	public final static String		COMPONENT_GREEDY							= "greedy:";
+	public final static String		COMPONENT_PROVIDE							= "provide:";
+	public final static String		COMPONENT_OPTIONAL							= "optional:";
+	public final static String		COMPONENT_PROPERTIES						= "properties:";
+	public final static String		COMPONENT_IMPLEMENTATION					= "implementation:";
+	public final static String		COMPONENT_DESIGNATE							= "designate:";
+	public final static String		COMPONENT_DESIGNATEFACTORY					= "designateFactory:";
+	public final static String		COMPONENT_DESCRIPTORS						= ".descriptors:";
+
+	// v1.1.0
+	public final static String		COMPONENT_VERSION							= "version:";
+	public final static String		COMPONENT_CONFIGURATION_POLICY				= "configuration-policy:";
+	public final static String		COMPONENT_MODIFIED							= "modified:";
+	public final static String		COMPONENT_ACTIVATE							= "activate:";
+	public final static String		COMPONENT_DEACTIVATE						= "deactivate:";
+
+	public final static String		COMPONENT_NAMESPACE							= "xmlns:";
+
+	final static Map<String,String>	EMPTY										= Collections.emptyMap();
+
+	public final static String[]	componentDirectives							= new String[] {
+			COMPONENT_FACTORY, COMPONENT_IMMEDIATE, COMPONENT_ENABLED, COMPONENT_DYNAMIC, COMPONENT_MULTIPLE,
+			COMPONENT_PROVIDE, COMPONENT_OPTIONAL, COMPONENT_PROPERTIES, COMPONENT_IMPLEMENTATION,
+			COMPONENT_SERVICEFACTORY, COMPONENT_VERSION, COMPONENT_CONFIGURATION_POLICY, COMPONENT_MODIFIED,
+			COMPONENT_ACTIVATE, COMPONENT_DEACTIVATE, COMPONENT_NAME, COMPONENT_DESCRIPTORS, COMPONENT_DESIGNATE,
+			COMPONENT_DESIGNATEFACTORY, COMPONENT_GREEDY, COMPONENT_NAMESPACE
+																				};
+
+	public final static Set<String>	SET_COMPONENT_DIRECTIVES					= new HashSet<String>(
+																						Arrays.asList(componentDirectives));
+
+	public final static Set<String>	SET_COMPONENT_DIRECTIVES_1_1				= //
+																				new HashSet<String>(Arrays.asList(
+																						COMPONENT_VERSION,
+																						COMPONENT_CONFIGURATION_POLICY,
+																						COMPONENT_MODIFIED,
+																						COMPONENT_ACTIVATE,
+																						COMPONENT_DEACTIVATE));
+
+	public final static Set<String>	SET_COMPONENT_DIRECTIVES_1_2				= new HashSet<String>(
+																						Arrays.asList(COMPONENT_GREEDY));
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/Descriptors.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/Descriptors.java
new file mode 100644
index 0000000..de4601e
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/Descriptors.java
@@ -0,0 +1,567 @@
+package aQute.bnd.osgi;
+
+import java.util.*;
+
+import aQute.libg.generics.*;
+
+public class Descriptors {
+	Map<String,TypeRef>		typeRefCache		= Create.map();
+	Map<String,Descriptor>	descriptorCache		= Create.map();
+	Map<String,PackageRef>	packageCache		= Create.map();
+
+	// MUST BE BEFORE PRIMITIVES, THEY USE THE DEFAULT PACKAGE!!
+	final static PackageRef	DEFAULT_PACKAGE		= new PackageRef();
+	final static PackageRef	PRIMITIVE_PACKAGE	= new PackageRef();
+
+	final static TypeRef	VOID				= new ConcreteRef("V", "void", PRIMITIVE_PACKAGE);
+	final static TypeRef	BOOLEAN				= new ConcreteRef("Z", "boolean", PRIMITIVE_PACKAGE);
+	final static TypeRef	BYTE				= new ConcreteRef("B", "byte", PRIMITIVE_PACKAGE);
+	final static TypeRef	CHAR				= new ConcreteRef("C", "char", PRIMITIVE_PACKAGE);
+	final static TypeRef	SHORT				= new ConcreteRef("S", "short", PRIMITIVE_PACKAGE);
+	final static TypeRef	INTEGER				= new ConcreteRef("I", "int", PRIMITIVE_PACKAGE);
+	final static TypeRef	LONG				= new ConcreteRef("J", "long", PRIMITIVE_PACKAGE);
+	final static TypeRef	DOUBLE				= new ConcreteRef("D", "double", PRIMITIVE_PACKAGE);
+	final static TypeRef	FLOAT				= new ConcreteRef("F", "float", PRIMITIVE_PACKAGE);
+
+	{
+		packageCache.put("", DEFAULT_PACKAGE);
+	}
+
+	public interface TypeRef extends Comparable<TypeRef> {
+		String getBinary();
+
+		String getFQN();
+
+		String getPath();
+
+		boolean isPrimitive();
+
+		TypeRef getComponentTypeRef();
+
+		TypeRef getClassRef();
+
+		PackageRef getPackageRef();
+
+		String getShortName();
+
+		boolean isJava();
+
+		boolean isObject();
+
+		String getSourcePath();
+
+		String getDottedOnly();
+
+	}
+
+	public static class PackageRef implements Comparable<PackageRef> {
+		final String	binaryName;
+		final String	fqn;
+		final boolean	java;
+
+		PackageRef(String binaryName) {
+			this.binaryName = fqnToBinary(binaryName);
+			this.fqn = binaryToFQN(binaryName);
+			this.java = this.fqn.startsWith("java."); // &&
+														// !this.fqn.equals("java.sql)"
+
+			// For some reason I excluded java.sql but the classloader will
+			// delegate anyway. So lost the understanding why I did it??
+		}
+
+		PackageRef() {
+			this.binaryName = "";
+			this.fqn = ".";
+			this.java = false;
+		}
+
+		public PackageRef getDuplicate() {
+			return new PackageRef(binaryName + Constants.DUPLICATE_MARKER);
+		}
+
+		public String getFQN() {
+			return fqn;
+		}
+
+		public String getBinary() {
+			return binaryName;
+		}
+
+		public String getPath() {
+			return binaryName;
+		}
+
+		public boolean isJava() {
+			return java;
+		}
+
+		@Override
+		public String toString() {
+			return fqn;
+		}
+
+		boolean isDefaultPackage() {
+			return this.fqn.equals(".");
+		}
+
+		boolean isPrimitivePackage() {
+			return this == PRIMITIVE_PACKAGE;
+		}
+
+		public int compareTo(PackageRef other) {
+			return fqn.compareTo(other.fqn);
+		}
+
+		@Override
+		public boolean equals(Object o) {
+			assert o instanceof PackageRef;
+			return o == this;
+		}
+
+		@Override
+		public int hashCode() {
+			return super.hashCode();
+		}
+
+		/**
+		 * Decide if the package is a metadata package.
+		 * 
+		 * @param pack
+		 * @return
+		 */
+		public boolean isMetaData() {
+			if (isDefaultPackage())
+				return true;
+
+			for (int i = 0; i < Constants.METAPACKAGES.length; i++) {
+				if (fqn.startsWith(Constants.METAPACKAGES[i]))
+					return true;
+			}
+			return false;
+		}
+
+	}
+
+	// We "intern" the
+	private static class ConcreteRef implements TypeRef {
+		final String		binaryName;
+		final String		fqn;
+		final boolean		primitive;
+		final PackageRef	packageRef;
+
+		ConcreteRef(PackageRef packageRef, String binaryName) {
+			if (packageRef.getFQN().length() < 2)
+				System.err.println("in default pack? " + binaryName);
+			this.binaryName = binaryName;
+			this.fqn = binaryToFQN(binaryName);
+			this.primitive = false;
+			this.packageRef = packageRef;
+		}
+
+		ConcreteRef(String binaryName, String fqn, PackageRef pref) {
+			this.binaryName = binaryName;
+			this.fqn = fqn;
+			this.primitive = true;
+			this.packageRef = pref;
+		}
+
+		public String getBinary() {
+			return binaryName;
+		}
+
+		public String getPath() {
+			return binaryName + ".class";
+		}
+
+		public String getSourcePath() {
+			return binaryName + ".java";
+		}
+
+		public String getFQN() {
+			return fqn;
+		}
+
+		public String getDottedOnly() {
+			return fqn.replace('$', '.');
+		}
+
+		public boolean isPrimitive() {
+			return primitive;
+		}
+
+		public TypeRef getComponentTypeRef() {
+			return null;
+		}
+
+		public TypeRef getClassRef() {
+			return this;
+		}
+
+		public PackageRef getPackageRef() {
+			return packageRef;
+		}
+
+		public String getShortName() {
+			int n = binaryName.lastIndexOf('/');
+			return binaryName.substring(n + 1);
+		}
+
+		public boolean isJava() {
+			return packageRef.isJava();
+		}
+
+		@Override
+		public String toString() {
+			return fqn;
+		}
+
+		public boolean isObject() {
+			return fqn.equals("java.lang.Object");
+		}
+
+		@Override
+		public boolean equals(Object other) {
+			assert other instanceof TypeRef;
+			return this == other;
+		}
+
+		public int compareTo(TypeRef other) {
+			if (this == other)
+				return 0;
+			return fqn.compareTo(other.getFQN());
+		}
+
+		@Override
+		public int hashCode() {
+			return super.hashCode();
+		}
+
+	}
+
+	private static class ArrayRef implements TypeRef {
+		final TypeRef	component;
+
+		ArrayRef(TypeRef component) {
+			this.component = component;
+		}
+
+		public String getBinary() {
+			return "[" + component.getBinary();
+		}
+
+		public String getFQN() {
+			return component.getFQN() + "[]";
+		}
+
+		public String getPath() {
+			return component.getPath();
+		}
+
+		public String getSourcePath() {
+			return component.getSourcePath();
+		}
+
+		public boolean isPrimitive() {
+			return false;
+		}
+
+		public TypeRef getComponentTypeRef() {
+			return component;
+		}
+
+		public TypeRef getClassRef() {
+			return component.getClassRef();
+		}
+
+		@Override
+		public boolean equals(Object other) {
+			if (other == null || other.getClass() != getClass())
+				return false;
+
+			return component.equals(((ArrayRef) other).component);
+		}
+
+		public PackageRef getPackageRef() {
+			return component.getPackageRef();
+		}
+
+		public String getShortName() {
+			return component.getShortName() + "[]";
+		}
+
+		public boolean isJava() {
+			return component.isJava();
+		}
+
+		@Override
+		public String toString() {
+			return component.toString() + "[]";
+		}
+
+		public boolean isObject() {
+			return false;
+		}
+
+		public String getDottedOnly() {
+			return component.getDottedOnly();
+		}
+
+		public int compareTo(TypeRef other) {
+			if (this == other)
+				return 0;
+
+			return getFQN().compareTo(other.getFQN());
+		}
+
+		@Override
+		public int hashCode() {
+			return super.hashCode();
+		}
+
+	}
+
+	public TypeRef getTypeRef(String binaryClassName) {
+		assert !binaryClassName.endsWith(".class");
+
+		TypeRef ref = typeRefCache.get(binaryClassName);
+		if (ref != null)
+			return ref;
+
+		if (binaryClassName.startsWith("[")) {
+			ref = getTypeRef(binaryClassName.substring(1));
+			ref = new ArrayRef(ref);
+		} else {
+			if (binaryClassName.length() == 1) {
+				switch (binaryClassName.charAt(0)) {
+					case 'V' :
+						return VOID;
+					case 'B' :
+						return BYTE;
+					case 'C' :
+						return CHAR;
+					case 'I' :
+						return INTEGER;
+					case 'S' :
+						return SHORT;
+					case 'D' :
+						return DOUBLE;
+					case 'F' :
+						return FLOAT;
+					case 'J' :
+						return LONG;
+					case 'Z' :
+						return BOOLEAN;
+				}
+				// falls trough for other 1 letter class names
+			}
+			if (binaryClassName.startsWith("L") && binaryClassName.endsWith(";")) {
+				binaryClassName = binaryClassName.substring(1, binaryClassName.length() - 1);
+			}
+			ref = typeRefCache.get(binaryClassName);
+			if (ref != null)
+				return ref;
+
+			PackageRef pref;
+			int n = binaryClassName.lastIndexOf('/');
+			if (n < 0)
+				pref = DEFAULT_PACKAGE;
+			else
+				pref = getPackageRef(binaryClassName.substring(0, n));
+
+			ref = new ConcreteRef(pref, binaryClassName);
+		}
+
+		typeRefCache.put(binaryClassName, ref);
+		return ref;
+	}
+
+	public PackageRef getPackageRef(String binaryPackName) {
+		if (binaryPackName.indexOf('.') >= 0) {
+			binaryPackName = binaryPackName.replace('.', '/');
+		}
+		PackageRef ref = packageCache.get(binaryPackName);
+		if (ref != null)
+			return ref;
+
+		ref = new PackageRef(binaryPackName);
+		packageCache.put(binaryPackName, ref);
+		return ref;
+	}
+
+	public Descriptor getDescriptor(String descriptor) {
+		Descriptor d = descriptorCache.get(descriptor);
+		if (d != null)
+			return d;
+		d = new Descriptor(descriptor);
+		descriptorCache.put(descriptor, d);
+		return d;
+	}
+
+	public class Descriptor {
+		final TypeRef	type;
+		final TypeRef[]	prototype;
+		final String	descriptor;
+
+		Descriptor(String descriptor) {
+			this.descriptor = descriptor;
+			int index = 0;
+			List<TypeRef> types = Create.list();
+			if (descriptor.charAt(index) == '(') {
+				index++;
+				while (descriptor.charAt(index) != ')') {
+					index = parse(types, descriptor, index);
+				}
+				index++; // skip )
+				prototype = types.toArray(new TypeRef[types.size()]);
+				types.clear();
+			} else
+				prototype = null;
+
+			index = parse(types, descriptor, index);
+			type = types.get(0);
+		}
+
+		int parse(List<TypeRef> types, String descriptor, int index) {
+			char c;
+			StringBuilder sb = new StringBuilder();
+			while ((c = descriptor.charAt(index++)) == '[') {
+				sb.append('[');
+			}
+
+			switch (c) {
+				case 'L' :
+					while ((c = descriptor.charAt(index++)) != ';') {
+						// TODO
+						sb.append(c);
+					}
+					break;
+
+				case 'V' :
+				case 'B' :
+				case 'C' :
+				case 'I' :
+				case 'S' :
+				case 'D' :
+				case 'F' :
+				case 'J' :
+				case 'Z' :
+					sb.append(c);
+					break;
+
+				default :
+					throw new IllegalArgumentException("Invalid type in descriptor: " + c + " from " + descriptor + "["
+							+ index + "]");
+			}
+			types.add(getTypeRef(sb.toString()));
+			return index;
+		}
+
+		public TypeRef getType() {
+			return type;
+		}
+
+		public TypeRef[] getPrototype() {
+			return prototype;
+		}
+
+		@Override
+		public boolean equals(Object other) {
+			if (other == null || other.getClass() != getClass())
+				return false;
+
+			return Arrays.equals(prototype, ((Descriptor) other).prototype) && type == ((Descriptor) other).type;
+		}
+
+		@Override
+		public int hashCode() {
+			return prototype == null ? type.hashCode() : type.hashCode() ^ Arrays.hashCode(prototype);
+		}
+
+		@Override
+		public String toString() {
+			return descriptor;
+		}
+	}
+
+	/**
+	 * Return the short name of a FQN
+	 */
+
+	public static String getShortName(String fqn) {
+		assert fqn.indexOf('/') < 0;
+
+		int n = fqn.lastIndexOf('.');
+		if (n >= 0) {
+			return fqn.substring(n + 1);
+		}
+		return fqn;
+	}
+
+	public static String binaryToFQN(String binary) {
+		StringBuilder sb = new StringBuilder();
+		for (int i = 0, l = binary.length(); i < l; i++) {
+			char c = binary.charAt(i);
+
+			if (c == '/')
+				sb.append('.');
+			else
+				sb.append(c);
+		}
+		String result = sb.toString();
+		assert result.length() > 0;
+		return result;
+	}
+
+	public static String fqnToBinary(String binary) {
+		return binary.replace('.', '/');
+	}
+
+	public static String getPackage(String binaryNameOrFqn) {
+		int n = binaryNameOrFqn.lastIndexOf('/');
+		if (n >= 0)
+			return binaryNameOrFqn.substring(0, n).replace('/', '.');
+
+		n = binaryNameOrFqn.lastIndexOf(".");
+		if (n >= 0)
+			return binaryNameOrFqn.substring(0, n);
+
+		return ".";
+	}
+
+	public static String fqnToPath(String s) {
+		return fqnToBinary(s) + ".class";
+	}
+
+	public TypeRef getTypeRefFromFQN(String fqn) {
+		if (fqn.equals("boolean"))
+			return BOOLEAN;
+
+		if (fqn.equals("byte"))
+			return BOOLEAN;
+
+		if (fqn.equals("char"))
+			return CHAR;
+
+		if (fqn.equals("short"))
+			return SHORT;
+
+		if (fqn.equals("int"))
+			return INTEGER;
+
+		if (fqn.equals("long"))
+			return LONG;
+
+		if (fqn.equals("float"))
+			return FLOAT;
+
+		if (fqn.equals("double"))
+			return DOUBLE;
+
+		return getTypeRef(fqnToBinary(fqn));
+	}
+
+	public TypeRef getTypeRefFromPath(String path) {
+		assert path.endsWith(".class");
+		return getTypeRef(path.substring(0, path.length() - 6));
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/Domain.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/Domain.java
new file mode 100644
index 0000000..e904aa8
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/Domain.java
@@ -0,0 +1,376 @@
+package aQute.bnd.osgi;
+
+import static aQute.bnd.osgi.Constants.*;
+
+import java.io.*;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.jar.*;
+
+import aQute.bnd.header.*;
+import aQute.bnd.version.*;
+import aQute.lib.converter.*;
+import aQute.service.reporter.*;
+
+/**
+ * This class abstracts domains that have properties holding OSGi meta data. It
+ * provides access to the keys, the set method and the get method. It then
+ * provides convenient methods to access these properties via semantic methods.
+ */
+public abstract class Domain implements Iterable<String> {
+	final Properties	translation	= new Properties();
+
+	public abstract String get(String key);
+
+	public String get(String key, String deflt) {
+		String result = get(key);
+		if (result != null)
+			return result;
+		return deflt;
+	}
+
+	public String translate(String key) {
+		return translate(key, null);
+	}
+	
+	
+	public String translate(String key, String deflt) {
+		String value = get(key);
+		if ( value == null)
+			return deflt;
+		
+		if ( value.indexOf('%')>=0) {
+			value = value.trim().substring(1);
+			return translation.getProperty(value,value);
+		}
+		return null;
+	}
+
+	public abstract void set(String key, String value);
+
+	public abstract Iterator<String> iterator();
+
+	public static Domain domain(final Manifest manifest) {
+		Attributes attrs = manifest.getMainAttributes();
+		return domain(attrs);
+	}
+
+	public static Domain domain(final Attributes attrs) {
+		return new Domain() {
+
+			@Override
+			public String get(String key) {
+				return attrs.getValue(key);
+			}
+
+			@Override
+			public void set(String key, String value) {
+				attrs.putValue(key, value);
+			}
+
+			@Override
+			public Iterator<String> iterator() {
+				final Iterator<Object> it = attrs.keySet().iterator();
+
+				return new Iterator<String>() {
+
+					public boolean hasNext() {
+						return it.hasNext();
+					}
+
+					public String next() {
+						return it.next().toString();
+					}
+
+					public void remove() {
+						it.remove();
+					}
+				};
+			}
+		};
+	}
+
+	public static Domain domain(final Processor processor) {
+		return new Domain() {
+
+			@Override
+			public String get(String key) {
+				return processor.getProperty(key);
+			}
+
+			@Override
+			public String get(String key, String deflt) {
+				return processor.getProperty(key, deflt);
+			}
+
+			@Override
+			public void set(String key, String value) {
+				processor.setProperty(key, value);
+			}
+
+			@Override
+			public Iterator<String> iterator() {
+				final Iterator<String> it = processor.getPropertyKeys(true).iterator();
+
+				return new Iterator<String>() {
+					String	current;
+
+					public boolean hasNext() {
+						return it.hasNext();
+					}
+
+					public String next() {
+						return current = it.next().toString();
+					}
+
+					public void remove() {
+						processor.getProperties().remove(current);
+					}
+				};
+			}
+		};
+	}
+
+	public static Domain domain(final Map<String,String> map) {
+		return new Domain() {
+
+			@Override
+			public String get(String key) {
+				return map.get(key);
+			}
+
+			@Override
+			public void set(String key, String value) {
+				map.put(key, value);
+			}
+
+			@Override
+			public Iterator<String> iterator() {
+				return map.keySet().iterator();
+			}
+		};
+	}
+
+	public Parameters getParameters(String key, Reporter reporter) {
+		return new Parameters(get(key), reporter);
+	}
+
+	public Parameters getParameters(String key) {
+		return new Parameters(get(key));
+	}
+
+	public Parameters getParameters(String key, String deflt) {
+		return new Parameters(get(key, deflt));
+	}
+
+	public Parameters getParameters(String key, String deflt, Reporter reporter) {
+		return new Parameters(get(key, deflt), reporter);
+	}
+	
+	
+	public Parameters getRequireBundle() {
+		return getParameters(Constants.REQUIRE_BUNDLE);
+	}
+
+
+
+	public Parameters getImportPackage() {
+		return getParameters(IMPORT_PACKAGE);
+	}
+
+	public Parameters getExportPackage() {
+		return getParameters(EXPORT_PACKAGE);
+	}
+
+	public Parameters getBundleClassPath() {
+		return getParameters(BUNDLE_CLASSPATH);
+	}
+
+	public Parameters getPrivatePackage() {
+		return getParameters(PRIVATE_PACKAGE);
+	}
+
+	public Parameters getIncludeResource() {
+		Parameters ic = getParameters(INCLUDE_RESOURCE);
+		ic.putAll(getParameters(INCLUDERESOURCE));
+		ic.putAll(getParameters(WAB));
+		return ic;
+	}
+
+	public Parameters getDynamicImportPackage() {
+		return getParameters(DYNAMICIMPORT_PACKAGE);
+	}
+
+	public Parameters getExportContents() {
+		return getParameters(EXPORT_CONTENTS);
+	}
+
+	public String getBundleActivator() {
+		return get(BUNDLE_ACTIVATOR);
+	}
+
+	public void setPrivatePackage(String s) {
+		if (s != null)
+			set(PRIVATE_PACKAGE, s);
+	}
+
+	public void setIncludeResource(String s) {
+		if (s != null)
+			set(INCLUDE_RESOURCE, s);
+	}
+
+	public void setBundleActivator(String s) {
+		if (s != null)
+			set(BUNDLE_ACTIVATOR, s);
+	}
+
+	public void setExportPackage(String s) {
+		if (s != null)
+			set(EXPORT_PACKAGE, s);
+	}
+
+	public void setImportPackage(String s) {
+		if (s != null)
+			set(IMPORT_PACKAGE, s);
+	}
+
+	public void setBundleClasspath(String s) {
+		if (s != null)
+			set(BUNDLE_CLASSPATH, s);
+	}
+
+	public Parameters getBundleClasspath() {
+		return getParameters(BUNDLE_CLASSPATH);
+	}
+
+	public void setBundleRequiredExecutionEnvironment(String s) {
+		if (s != null)
+			set(BUNDLE_REQUIREDEXECUTIONENVIRONMENT, s);
+	}
+
+	public Parameters getBundleRequiredExecutionEnvironment() {
+		return getParameters(BUNDLE_REQUIREDEXECUTIONENVIRONMENT);
+	}
+
+	public void setSources(boolean b) {
+		if (b)
+			set(SOURCES, "true");
+		else
+			set(SOURCES, "false");
+	}
+
+	public boolean isSources() {
+		return Processor.isTrue(get(SOURCES));
+	}
+
+	public Map.Entry<String,Attrs> getBundleSymbolicName() {
+		Parameters p = getParameters(BUNDLE_SYMBOLICNAME);
+		if (p.isEmpty())
+			return null;
+		return p.entrySet().iterator().next();
+	}
+
+	public Map.Entry<String,Attrs> getFragmentHost() {
+		Parameters p = getParameters(FRAGMENT_HOST);
+		if (p.isEmpty())
+			return null;
+		return p.entrySet().iterator().next();
+	}
+
+	public void setBundleSymbolicName(String s) {
+		set(BUNDLE_SYMBOLICNAME, s);
+	}
+
+	public String getBundleVersion() {
+		return get(BUNDLE_VERSION);
+	}
+
+	public void setBundleVersion(String version) {
+		Version v = new Version(version);
+		set(BUNDLE_VERSION, v.toString());
+	}
+
+	public void setBundleVersion(Version version) {
+		set(BUNDLE_VERSION, version.toString());
+	}
+
+	public void setFailOk(boolean b) {
+		set(FAIL_OK, b + "");
+	}
+
+	public boolean isFailOk() {
+		return Processor.isTrue(get(FAIL_OK));
+	}
+
+	/**
+	 * Find an icon with the requested size in the list of icons.
+	 * 
+	 * @param requestedSize
+	 *            the number of pixels desired
+	 * @return null or a the selected URI (which may be relative)
+	 */
+	public String getIcon(int requestedSize) throws Exception {
+		String spec = get(Constants.BUNDLE_ICON);
+		if (spec == null)
+			return null;
+
+		Parameters p = OSGiHeader.parseHeader(spec);
+		int dist = Integer.MAX_VALUE;
+		String selected = null;
+
+		for (Entry<String,Attrs> e : p.entrySet()) {
+			String url = e.getKey();
+			if (selected == null)
+				selected = url;
+			if (e.getValue() != null) {
+				String s = e.getValue().get("size");
+				if (s != null) {
+					int size = Converter.cnv(Integer.class, s);
+					if (size != 0 && Math.abs(requestedSize - size) < dist) {
+						dist = Math.abs(requestedSize - size);
+						selected = url;
+					}
+				}
+			}
+		}
+		return selected;
+	}
+
+	public void setConditionalPackage(String string) {
+		set(CONDITIONAL_PACKAGE, string);
+
+	}
+
+	public void setTranslation(Jar jar) throws Exception {
+
+		Manifest m = jar.getManifest();
+		if (m == null)
+			return;
+
+		String path = m.getMainAttributes().getValue(Constants.BUNDLE_LOCALIZATION);
+		if (path == null)
+			path = org.osgi.framework.Constants.BUNDLE_LOCALIZATION_DEFAULT_BASENAME;
+
+		path += ".properties";
+
+		Resource propsResource = jar.getResource(path);
+		if (propsResource != null) {
+			InputStream in = propsResource.openInputStream();
+			try {
+				translation.load(in);
+			}
+			finally {
+				in.close();
+			}
+		}
+	}
+
+	public Parameters getRequireCapability() {
+		return getParameters(Constants.REQUIRE_CAPABILITY);
+	}
+
+	public Parameters getProvideCapability() {
+		return getParameters(Constants.PROVIDE_CAPABILITY);
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/EmbeddedResource.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/EmbeddedResource.java
new file mode 100755
index 0000000..ae3c449
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/EmbeddedResource.java
@@ -0,0 +1,100 @@
+package aQute.bnd.osgi;
+
+import java.io.*;
+import java.util.zip.*;
+
+import aQute.lib.io.*;
+
+public class EmbeddedResource implements Resource {
+	byte	data[];
+	long	lastModified;
+	String	extra;
+
+	public EmbeddedResource(byte data[], long lastModified) {
+		this.data = data;
+		this.lastModified = lastModified;
+	}
+
+	public InputStream openInputStream() throws FileNotFoundException {
+		return new ByteArrayInputStream(data);
+	}
+
+	public void write(OutputStream out) throws IOException {
+		out.write(data);
+	}
+
+	@Override
+	public String toString() {
+		return ":" + data.length + ":";
+	}
+
+	public static void build(Jar jar, InputStream in, long lastModified) throws IOException {
+		ZipInputStream jin = new ZipInputStream(in);
+		ZipEntry entry = jin.getNextEntry();
+		while (entry != null) {
+			if (!entry.isDirectory()) {
+				byte data[] = collect(jin);
+				jar.putResource(entry.getName(), new EmbeddedResource(data, lastModified), true);
+			}
+			entry = jin.getNextEntry();
+		}
+		IO.drain(in);
+		jin.close();
+	}
+
+	/**
+	 * Convenience method to turn an inputstream into a byte array. The method
+	 * uses a recursive algorithm to minimize memory usage.
+	 * 
+	 * @param in
+	 *            stream with data
+	 * @param offset
+	 *            where we are in the stream
+	 * @returns byte array filled with data
+	 */
+	static byte[] collect(InputStream in) throws IOException {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		copy(in, out);
+		return out.toByteArray();
+	}
+
+	static void copy(InputStream in, OutputStream out) throws IOException {
+		int available = in.available();
+		if (available <= 10000)
+			available = 64000;
+		byte[] buffer = new byte[available];
+		int size;
+		while ((size = in.read(buffer)) > 0)
+			out.write(buffer, 0, size);
+	}
+
+	public long lastModified() {
+		return lastModified;
+	}
+
+	public static void build(Jar sub, Resource resource) throws Exception {
+		InputStream in = resource.openInputStream();
+		try {
+			build(sub, in, resource.lastModified());
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}
+		finally {
+			in.close();
+		}
+	}
+
+	public String getExtra() {
+		return extra;
+	}
+
+	public void setExtra(String extra) {
+		this.extra = extra;
+	}
+
+	public long size() {
+		return data.length;
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/FileResource.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/FileResource.java
new file mode 100755
index 0000000..66635d1
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/FileResource.java
@@ -0,0 +1,79 @@
+package aQute.bnd.osgi;
+
+import java.io.*;
+import java.util.regex.*;
+
+public class FileResource implements Resource {
+	File	file;
+	String	extra;
+
+	public FileResource(File file) {
+		this.file = file;
+	}
+
+	public InputStream openInputStream() throws FileNotFoundException {
+		return new FileInputStream(file);
+	}
+
+	public static void build(Jar jar, File directory, Pattern doNotCopy) {
+		traverse(jar, directory.getAbsolutePath().length(), directory, doNotCopy);
+	}
+
+	@Override
+	public String toString() {
+		return ":" + file.getName() + ":";
+	}
+
+	public void write(OutputStream out) throws Exception {
+		copy(this, out);
+	}
+
+	static synchronized void copy(Resource resource, OutputStream out) throws Exception {
+		InputStream in = resource.openInputStream();
+		try {
+			byte buffer[] = new byte[20000];
+			int size = in.read(buffer);
+			while (size > 0) {
+				out.write(buffer, 0, size);
+				size = in.read(buffer);
+			}
+		}
+		finally {
+			in.close();
+		}
+	}
+
+	static void traverse(Jar jar, int rootlength, File directory, Pattern doNotCopy) {
+		if (doNotCopy != null && doNotCopy.matcher(directory.getName()).matches())
+			return;
+		jar.updateModified(directory.lastModified(), "Dir change");
+
+		File files[] = directory.listFiles();
+		for (int i = 0; i < files.length; i++) {
+			if (files[i].isDirectory())
+				traverse(jar, rootlength, files[i], doNotCopy);
+			else {
+				String path = files[i].getAbsolutePath().substring(rootlength + 1);
+				if (File.separatorChar != '/')
+					path = path.replace(File.separatorChar, '/');
+				jar.putResource(path, new FileResource(files[i]), true);
+			}
+		}
+	}
+
+	public long lastModified() {
+		return file.lastModified();
+	}
+
+	public String getExtra() {
+		return extra;
+	}
+
+	public void setExtra(String extra) {
+		this.extra = extra;
+	}
+
+	public long size() {
+		return (int) file.length();
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/Instruction.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/Instruction.java
new file mode 100755
index 0000000..d350c8a
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/Instruction.java
@@ -0,0 +1,185 @@
+package aQute.bnd.osgi;
+
+import java.io.*;
+import java.util.regex.*;
+
+public class Instruction {
+
+	public static class Filter implements FileFilter {
+
+		private Instruction	instruction;
+		private boolean		recursive;
+		private Pattern		doNotCopy;
+
+		public Filter(Instruction instruction, boolean recursive, Pattern doNotCopy) {
+			this.instruction = instruction;
+			this.recursive = recursive;
+			this.doNotCopy = doNotCopy;
+		}
+
+		public Filter(Instruction instruction, boolean recursive) {
+			this(instruction, recursive, Pattern.compile(Constants.DEFAULT_DO_NOT_COPY));
+		}
+
+		public boolean isRecursive() {
+			return recursive;
+		}
+
+		public boolean accept(File pathname) {
+			if (doNotCopy != null && doNotCopy.matcher(pathname.getName()).matches()) {
+				return false;
+			}
+
+			if (pathname.isDirectory() && isRecursive()) {
+				return true;
+			}
+
+			if (instruction == null) {
+				return true;
+			}
+			return !instruction.isNegated() == instruction.matches(pathname.getName());
+		}
+	}
+
+	transient Pattern	pattern;
+	transient boolean	optional;
+
+	final String		input;
+	final String		match;
+	final boolean		negated;
+	final boolean		duplicate;
+	final boolean		literal;
+	final boolean		any;
+
+	public Instruction(String input) {
+		this.input = input;
+
+		String s = Processor.removeDuplicateMarker(input);
+		duplicate = !s.equals(input);
+
+		if (s.startsWith("!")) {
+			negated = true;
+			s = s.substring(1);
+		} else
+			negated = false;
+
+		if (input.equals("*")) {
+			any = true;
+			literal = false;
+			match = null;
+			return;
+		}
+
+		any = false;
+		if (s.startsWith("=")) {
+			match = s.substring(1);
+			literal = true;
+		} else {
+			boolean wildcards = false;
+
+			StringBuilder sb = new StringBuilder();
+			loop: for (int c = 0; c < s.length(); c++) {
+				switch (s.charAt(c)) {
+					case '.' :
+						// If we end in a wildcard .* then we need to
+						// also include the last full package. I.e.
+						// com.foo.* includes com.foo (unlike OSGi)
+						if (c == s.length() - 2 && '*' == s.charAt(c + 1)) {
+							sb.append("(\\..*)?");
+							wildcards = true;
+							break loop;
+						}
+						sb.append("\\.");
+
+						break;
+					case '*' :
+						sb.append(".*");
+						wildcards = true;
+						break;
+					case '$' :
+						sb.append("\\$");
+						break;
+					case '?' :
+						sb.append(".?");
+						wildcards = true;
+						break;
+					case '|' :
+						sb.append('|');
+						wildcards = true;
+						break;
+					default :
+						sb.append(s.charAt(c));
+						break;
+				}
+			}
+
+			if (!wildcards) {
+				literal = true;
+				match = s;
+			} else {
+				literal = false;
+				match = sb.toString();
+			}
+		}
+
+	}
+
+	public boolean matches(String value) {
+		if (any)
+			return true;
+
+		if (literal)
+			return match.equals(value);
+		return getMatcher(value).matches();
+	}
+
+	public boolean isNegated() {
+		return negated;
+	}
+
+	public String getPattern() {
+		return match;
+	}
+
+	public String getInput() {
+		return input;
+	}
+
+	@Override
+	public String toString() {
+		return input;
+	}
+
+	public Matcher getMatcher(String value) {
+		if (pattern == null) {
+			pattern = Pattern.compile(match);
+		}
+		return pattern.matcher(value);
+	}
+
+	public void setOptional() {
+		optional = true;
+	}
+
+	public boolean isOptional() {
+		return optional;
+	}
+
+	public boolean isLiteral() {
+		return literal;
+	}
+
+	public String getLiteral() {
+		assert literal;
+		return match;
+	}
+
+	public boolean isDuplicate() {
+		return duplicate;
+	}
+
+	public boolean isAny() {
+		return any;
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/Instructions.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/Instructions.java
new file mode 100644
index 0000000..b157f88
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/Instructions.java
@@ -0,0 +1,222 @@
+package aQute.bnd.osgi;
+
+import java.util.*;
+
+import aQute.bnd.header.*;
+
+public class Instructions implements Map<Instruction,Attrs> {
+	private LinkedHashMap<Instruction,Attrs>	map;
+	static Map<Instruction,Attrs>				EMPTY	= Collections.emptyMap();
+
+	public Instructions(Instructions other) {
+		if (other.map != null && !other.map.isEmpty()) {
+			map = new LinkedHashMap<Instruction,Attrs>(other.map);
+		}
+	}
+
+	public Instructions(Collection<String> other) {
+		if (other != null)
+			for (String s : other) {
+				put(new Instruction(s), null);
+			}
+	}
+
+	public Instructions() {}
+
+	public Instructions(Parameters contained) {
+		append(contained);
+	}
+
+	public Instructions(String h) {
+		this(new Parameters(h));
+	}
+
+	public void clear() {
+		map.clear();
+	}
+
+	public boolean containsKey(Instruction name) {
+		if (map == null)
+			return false;
+
+		return map.containsKey(name);
+	}
+
+	@Deprecated
+	public boolean containsKey(Object name) {
+		assert name instanceof Instruction;
+		if (map == null)
+			return false;
+
+		return map.containsKey(name);
+	}
+
+	public boolean containsValue(Attrs value) {
+		if (map == null)
+			return false;
+
+		return map.containsValue(value);
+	}
+
+	@Deprecated
+	public boolean containsValue(Object value) {
+		assert value instanceof Attrs;
+		if (map == null)
+			return false;
+
+		return map.containsValue(value);
+	}
+
+	public Set<java.util.Map.Entry<Instruction,Attrs>> entrySet() {
+		if (map == null)
+			return EMPTY.entrySet();
+
+		return map.entrySet();
+	}
+
+	@Deprecated
+	public Attrs get(Object key) {
+		assert key instanceof Instruction;
+		if (map == null)
+			return null;
+
+		return map.get(key);
+	}
+
+	public Attrs get(Instruction key) {
+		if (map == null)
+			return null;
+
+		return map.get(key);
+	}
+
+	public boolean isEmpty() {
+		return map == null || map.isEmpty();
+	}
+
+	public Set<Instruction> keySet() {
+		if (map == null)
+			return EMPTY.keySet();
+
+		return map.keySet();
+	}
+
+	public Attrs put(Instruction key, Attrs value) {
+		if (map == null)
+			map = new LinkedHashMap<Instruction,Attrs>();
+
+		return map.put(key, value);
+	}
+
+	public void putAll(Map< ? extends Instruction, ? extends Attrs> map) {
+		if (this.map == null) {
+			if (map.isEmpty())
+				return;
+			this.map = new LinkedHashMap<Instruction,Attrs>();
+		}
+		this.map.putAll(map);
+	}
+
+	@Deprecated
+	public Attrs remove(Object var0) {
+		assert var0 instanceof Instruction;
+		if (map == null)
+			return null;
+
+		return map.remove(var0);
+	}
+
+	public Attrs remove(Instruction var0) {
+		if (map == null)
+			return null;
+		return map.remove(var0);
+	}
+
+	public int size() {
+		if (map == null)
+			return 0;
+		return map.size();
+	}
+
+	public Collection<Attrs> values() {
+		if (map == null)
+			return EMPTY.values();
+
+		return map.values();
+	}
+
+	@Override
+	public String toString() {
+		return map == null ? "{}" : map.toString();
+	}
+
+	public void append(Parameters other) {
+		for (Map.Entry<String,Attrs> e : other.entrySet()) {
+			put(new Instruction(e.getKey()), e.getValue());
+		}
+	}
+
+	public <T> Collection<T> select(Collection<T> set, boolean emptyIsAll) {
+		return select(set, null, emptyIsAll);
+	}
+
+	public <T> Collection<T> select(Collection<T> set, Set<Instruction> unused, boolean emptyIsAll) {
+		List<T> input = new ArrayList<T>(set);
+		if (emptyIsAll && isEmpty())
+			return input;
+
+		List<T> result = new ArrayList<T>();
+
+		for (Instruction instruction : keySet()) {
+			boolean used = false;
+			for (Iterator<T> o = input.iterator(); o.hasNext();) {
+				T oo = o.next();
+				String s = oo.toString();
+				if (instruction.matches(s)) {
+					if (!instruction.isNegated())
+						result.add(oo);
+					o.remove();
+					used = true;
+				}
+			}
+			if (!used && unused != null)
+				unused.add(instruction);
+		}
+		return result;
+	}
+
+	public <T> Collection<T> reject(Collection<T> set) {
+		List<T> input = new ArrayList<T>(set);
+		List<T> result = new ArrayList<T>();
+
+		for (Instruction instruction : keySet()) {
+			for (Iterator<T> o = input.iterator(); o.hasNext();) {
+				T oo = o.next();
+				String s = oo.toString();
+				if (instruction.matches(s)) {
+					if (instruction.isNegated())
+						result.add(oo);
+					o.remove();
+				} else
+					result.add(oo);
+
+			}
+		}
+		return result;
+	}
+
+	public boolean matches(String value) {
+		if (size() == 0)
+			return true;
+
+		for (Instruction i : keySet()) {
+			if (i.matches(value)) {
+				if (i.isNegated())
+					return false; // we deny this one explicitly
+				return true; // we allow it explicitly
+			}
+		}
+		return false;
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/Jar.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/Jar.java
new file mode 100755
index 0000000..9ee4048
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/Jar.java
@@ -0,0 +1,861 @@
+package aQute.bnd.osgi;
+
+import static aQute.lib.io.IO.*;
+
+import java.io.*;
+import java.net.*;
+import java.security.*;
+import java.util.*;
+import java.util.jar.*;
+import java.util.regex.*;
+import java.util.zip.*;
+
+import aQute.lib.base64.*;
+import aQute.lib.io.*;
+import aQute.service.reporter.*;
+
+public class Jar implements Closeable {
+	public enum Compression {
+		DEFLATE, STORE
+	}
+
+	public static final Object[]			EMPTY_ARRAY	= new Jar[0];
+	final Map<String,Resource>				resources	= new TreeMap<String,Resource>();
+	final Map<String,Map<String,Resource>>	directories	= new TreeMap<String,Map<String,Resource>>();
+	Manifest								manifest;
+	boolean									manifestFirst;
+	String									name;
+	File									source;
+	ZipFile									zipFile;
+	long									lastModified;
+	String									lastModifiedReason;
+	Reporter								reporter;
+	boolean									doNotTouchManifest;
+	boolean									nomanifest;
+	Compression								compression	= Compression.DEFLATE;
+	boolean									closed;
+	String[]								algorithms;
+
+	public Jar(String name) {
+		this.name = name;
+	}
+
+	public Jar(String name, File dirOrFile, Pattern doNotCopy) throws ZipException, IOException {
+		this(name);
+		source = dirOrFile;
+		if (dirOrFile.isDirectory())
+			FileResource.build(this, dirOrFile, doNotCopy);
+		else if (dirOrFile.isFile()) {
+			zipFile = ZipResource.build(this, dirOrFile);
+		} else {
+			throw new IllegalArgumentException("A Jar can only accept a valid file or directory: " + dirOrFile);
+		}
+	}
+
+	public Jar(String name, InputStream in, long lastModified) throws IOException {
+		this(name);
+		EmbeddedResource.build(this, in, lastModified);
+	}
+
+	public Jar(String name, String path) throws IOException {
+		this(name);
+		File f = new File(path);
+		InputStream in = new FileInputStream(f);
+		EmbeddedResource.build(this, in, f.lastModified());
+		in.close();
+	}
+
+	public Jar(File f) throws IOException {
+		this(getName(f), f, null);
+	}
+
+	/**
+	 * Make the JAR file name the project name if we get a src or bin directory.
+	 * 
+	 * @param f
+	 * @return
+	 */
+	private static String getName(File f) {
+		f = f.getAbsoluteFile();
+		String name = f.getName();
+		if (name.equals("bin") || name.equals("src"))
+			return f.getParentFile().getName();
+		if (name.endsWith(".jar"))
+			name = name.substring(0, name.length() - 4);
+		return name;
+	}
+
+	public Jar(String string, InputStream resourceAsStream) throws IOException {
+		this(string, resourceAsStream, 0);
+	}
+
+	public Jar(String string, File file) throws ZipException, IOException {
+		this(string, file, Pattern.compile(Constants.DEFAULT_DO_NOT_COPY));
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	@Override
+	public String toString() {
+		return "Jar:" + name;
+	}
+
+	public boolean putResource(String path, Resource resource) {
+		check();
+		return putResource(path, resource, true);
+	}
+
+	public boolean putResource(String path, Resource resource, boolean overwrite) {
+		check();
+		updateModified(resource.lastModified(), path);
+		while (path.startsWith("/"))
+			path = path.substring(1);
+
+		if (path.equals("META-INF/MANIFEST.MF")) {
+			manifest = null;
+			if (resources.isEmpty())
+				manifestFirst = true;
+		}
+		String dir = getDirectory(path);
+		Map<String,Resource> s = directories.get(dir);
+		if (s == null) {
+			s = new TreeMap<String,Resource>();
+			directories.put(dir, s);
+			int n = dir.lastIndexOf('/');
+			while (n > 0) {
+				String dd = dir.substring(0, n);
+				if (directories.containsKey(dd))
+					break;
+				directories.put(dd, null);
+				n = dd.lastIndexOf('/');
+			}
+		}
+		boolean duplicate = s.containsKey(path);
+		if (!duplicate || overwrite) {
+			resources.put(path, resource);
+			s.put(path, resource);
+		}
+		return duplicate;
+	}
+
+	public Resource getResource(String path) {
+		check();
+		if (resources == null)
+			return null;
+		return resources.get(path);
+	}
+
+	private String getDirectory(String path) {
+		check();
+		int n = path.lastIndexOf('/');
+		if (n < 0)
+			return "";
+
+		return path.substring(0, n);
+	}
+
+	public Map<String,Map<String,Resource>> getDirectories() {
+		check();
+		return directories;
+	}
+
+	public Map<String,Resource> getResources() {
+		check();
+		return resources;
+	}
+
+	public boolean addDirectory(Map<String,Resource> directory, boolean overwrite) {
+		check();
+		boolean duplicates = false;
+		if (directory == null)
+			return false;
+
+		for (Map.Entry<String,Resource> entry : directory.entrySet()) {
+			String key = entry.getKey();
+			if (!key.endsWith(".java")) {
+				duplicates |= putResource(key, entry.getValue(), overwrite);
+			}
+		}
+		return duplicates;
+	}
+
+	public Manifest getManifest() throws Exception {
+		check();
+		if (manifest == null) {
+			Resource manifestResource = getResource("META-INF/MANIFEST.MF");
+			if (manifestResource != null) {
+				InputStream in = manifestResource.openInputStream();
+				manifest = new Manifest(in);
+				in.close();
+			}
+		}
+		return manifest;
+	}
+
+	public boolean exists(String path) {
+		check();
+		return resources.containsKey(path);
+	}
+
+	public void setManifest(Manifest manifest) {
+		check();
+		manifestFirst = true;
+		this.manifest = manifest;
+	}
+
+	public void setManifest(File file) throws IOException {
+		check();
+		FileInputStream fin = new FileInputStream(file);
+		try {
+			Manifest m = new Manifest(fin);
+			setManifest(m);
+		}
+		finally {
+			fin.close();
+		}
+	}
+
+	public void write(File file) throws Exception {
+		check();
+		try {
+			OutputStream out = new FileOutputStream(file);
+			try {
+				write(out);
+			}
+			finally {
+				IO.close(out);
+			}
+			return;
+
+		}
+		catch (Exception t) {
+			file.delete();
+			throw t;
+		}
+	}
+
+	public void write(String file) throws Exception {
+		check();
+		write(new File(file));
+	}
+
+	public void write(OutputStream out) throws Exception {
+		check();
+
+		if (!doNotTouchManifest && !nomanifest && algorithms != null) {
+
+			// ok, we have a request to create digests
+			// of the resources. Since we have to output
+			// the manifest first, we have a slight problem.
+			// We can also not make multiple passes over the resource
+			// because some resources are not idempotent and/or can
+			// take significant time. So we just copy the jar
+			// to a temporary file, read it in again, calculate
+			// the checksums and save.
+
+			String[] algs = algorithms;
+			algorithms = null;
+			try {
+				File f = File.createTempFile(getName(), ".jar");
+				System.out.println("Created tmp file " + f);
+				write(f);
+				Jar tmp = new Jar(f);
+				try {
+					tmp.calcChecksums(algorithms);
+					tmp.write(out);
+				}
+				finally {
+					f.delete();
+					tmp.close();
+				}
+			}
+			finally {
+				algorithms = algs;
+			}
+			return;
+		}
+
+		ZipOutputStream jout = nomanifest || doNotTouchManifest ? new ZipOutputStream(out) : new JarOutputStream(out);
+
+		switch (compression) {
+			case STORE :
+				jout.setMethod(ZipOutputStream.DEFLATED);
+				break;
+
+			default :
+				// default is DEFLATED
+		}
+
+		Set<String> done = new HashSet<String>();
+
+		Set<String> directories = new HashSet<String>();
+		if (doNotTouchManifest) {
+			Resource r = getResource("META-INF/MANIFEST.MF");
+			if (r != null) {
+				writeResource(jout, directories, "META-INF/MANIFEST.MF", r);
+				done.add("META-INF/MANIFEST.MF");
+			}
+		} else
+			doManifest(done, jout);
+
+		for (Map.Entry<String,Resource> entry : getResources().entrySet()) {
+			// Skip metainf contents
+			if (!done.contains(entry.getKey()))
+				writeResource(jout, directories, entry.getKey(), entry.getValue());
+		}
+		jout.finish();
+	}
+
+	private void doManifest(Set<String> done, ZipOutputStream jout) throws Exception {
+		check();
+		if (nomanifest)
+			return;
+
+		JarEntry ze = new JarEntry("META-INF/MANIFEST.MF");
+
+		jout.putNextEntry(ze);
+		writeManifest(jout);
+		jout.closeEntry();
+		done.add(ze.getName());
+	}
+
+	/**
+	 * Cleanup the manifest for writing. Cleaning up consists of adding a space
+	 * after any \n to prevent the manifest to see this newline as a delimiter.
+	 * 
+	 * @param out
+	 *            Output
+	 * @throws IOException
+	 */
+
+	public void writeManifest(OutputStream out) throws Exception {
+		check();
+		writeManifest(getManifest(), out);
+	}
+
+	public static void writeManifest(Manifest manifest, OutputStream out) throws IOException {
+		if (manifest == null)
+			return;
+
+		manifest = clean(manifest);
+		outputManifest(manifest, out);
+	}
+
+	/**
+	 * Unfortunately we have to write our own manifest :-( because of a stupid
+	 * bug in the manifest code. It tries to handle UTF-8 but the way it does it
+	 * it makes the bytes platform dependent. So the following code outputs the
+	 * manifest. A Manifest consists of
+	 * 
+	 * <pre>
+	 *   'Manifest-Version: 1.0\r\n'
+	 *   main-attributes *
+	 *   \r\n
+	 *   name-section
+	 *   
+	 *   main-attributes ::= attributes
+	 *   attributes      ::= key ': ' value '\r\n'
+	 *   name-section    ::= 'Name: ' name '\r\n' attributes
+	 * </pre>
+	 * 
+	 * Lines in the manifest should not exceed 72 bytes (! this is where the
+	 * manifest screwed up as well when 16 bit unicodes were used).
+	 * <p>
+	 * As a bonus, we can now sort the manifest!
+	 */
+	static byte[]	CONTINUE	= new byte[] {
+			'\r', '\n', ' '
+								};
+
+	/**
+	 * Main function to output a manifest properly in UTF-8.
+	 * 
+	 * @param manifest
+	 *            The manifest to output
+	 * @param out
+	 *            The output stream
+	 * @throws IOException
+	 *             when something fails
+	 */
+	public static void outputManifest(Manifest manifest, OutputStream out) throws IOException {
+		writeEntry(out, "Manifest-Version", "1.0");
+		attributes(manifest.getMainAttributes(), out);
+
+		TreeSet<String> keys = new TreeSet<String>();
+		for (Object o : manifest.getEntries().keySet())
+			keys.add(o.toString());
+
+		for (String key : keys) {
+			write(out, 0, "\r\n");
+			writeEntry(out, "Name", key);
+			attributes(manifest.getAttributes(key), out);
+		}
+		out.flush();
+	}
+
+	/**
+	 * Write out an entry, handling proper unicode and line length constraints
+	 */
+	private static void writeEntry(OutputStream out, String name, String value) throws IOException {
+		int n = write(out, 0, name + ": ");
+		write(out, n, value);
+		write(out, 0, "\r\n");
+	}
+
+	/**
+	 * Convert a string to bytes with UTF8 and then output in max 72 bytes
+	 * 
+	 * @param out
+	 *            the output string
+	 * @param i
+	 *            the current width
+	 * @param s
+	 *            the string to output
+	 * @return the new width
+	 * @throws IOException
+	 *             when something fails
+	 */
+	private static int write(OutputStream out, int i, String s) throws IOException {
+		byte[] bytes = s.getBytes("UTF8");
+		return write(out, i, bytes);
+	}
+
+	/**
+	 * Write the bytes but ensure that the line length does not exceed 72
+	 * characters. If it is more than 70 characters, we just put a cr/lf +
+	 * space.
+	 * 
+	 * @param out
+	 *            The output stream
+	 * @param width
+	 *            The nr of characters output in a line before this method
+	 *            started
+	 * @param bytes
+	 *            the bytes to output
+	 * @return the nr of characters in the last line
+	 * @throws IOException
+	 *             if something fails
+	 */
+	private static int write(OutputStream out, int width, byte[] bytes) throws IOException {
+		int w = width;
+		for (int i = 0; i < bytes.length; i++) {
+			if (w >= 72) { // we need to add the \n\r!
+				out.write(CONTINUE);
+				w = 1;
+			}
+			out.write(bytes[i]);
+			w++;
+		}
+		return w;
+	}
+
+	/**
+	 * Output an Attributes map. We will sort this map before outputing.
+	 * 
+	 * @param value
+	 *            the attrbutes
+	 * @param out
+	 *            the output stream
+	 * @throws IOException
+	 *             when something fails
+	 */
+	private static void attributes(Attributes value, OutputStream out) throws IOException {
+		TreeMap<String,String> map = new TreeMap<String,String>(String.CASE_INSENSITIVE_ORDER);
+		for (Map.Entry<Object,Object> entry : value.entrySet()) {
+			map.put(entry.getKey().toString(), entry.getValue().toString());
+		}
+
+		map.remove("Manifest-Version"); // get rid of
+		// manifest
+		// version
+		for (Map.Entry<String,String> entry : map.entrySet()) {
+			writeEntry(out, entry.getKey(), entry.getValue());
+		}
+	}
+
+	private static Manifest clean(Manifest org) {
+
+		Manifest result = new Manifest();
+		for (Map.Entry< ? , ? > entry : org.getMainAttributes().entrySet()) {
+			String nice = clean((String) entry.getValue());
+			result.getMainAttributes().put(entry.getKey(), nice);
+		}
+		for (String name : org.getEntries().keySet()) {
+			Attributes attrs = result.getAttributes(name);
+			if (attrs == null) {
+				attrs = new Attributes();
+				result.getEntries().put(name, attrs);
+			}
+
+			for (Map.Entry< ? , ? > entry : org.getAttributes(name).entrySet()) {
+				String nice = clean((String) entry.getValue());
+				attrs.put(entry.getKey(), nice);
+			}
+		}
+		return result;
+	}
+
+	private static String clean(String s) {
+		if (s.indexOf('\n') < 0)
+			return s;
+
+		StringBuilder sb = new StringBuilder(s);
+		for (int i = 0; i < sb.length(); i++) {
+			if (sb.charAt(i) == '\n')
+				sb.insert(++i, ' ');
+		}
+		return sb.toString();
+	}
+
+	private void writeResource(ZipOutputStream jout, Set<String> directories, String path, Resource resource)
+			throws Exception {
+		if (resource == null)
+			return;
+		try {
+			createDirectories(directories, jout, path);
+			if (path.endsWith(Constants.EMPTY_HEADER))
+				return;
+			ZipEntry ze = new ZipEntry(path);
+			ze.setMethod(ZipEntry.DEFLATED);
+			long lastModified = resource.lastModified();
+			if (lastModified == 0L) {
+				lastModified = System.currentTimeMillis();
+			}
+			ze.setTime(lastModified);
+			if (resource.getExtra() != null)
+				ze.setExtra(resource.getExtra().getBytes("UTF-8"));
+			jout.putNextEntry(ze);
+			resource.write(jout);
+			jout.closeEntry();
+		}
+		catch (Exception e) {
+			throw new Exception("Problem writing resource " + path, e);
+		}
+	}
+
+	void createDirectories(Set<String> directories, ZipOutputStream zip, String name) throws IOException {
+		int index = name.lastIndexOf('/');
+		if (index > 0) {
+			String path = name.substring(0, index);
+			if (directories.contains(path))
+				return;
+			createDirectories(directories, zip, path);
+			ZipEntry ze = new ZipEntry(path + '/');
+			zip.putNextEntry(ze);
+			zip.closeEntry();
+			directories.add(path);
+		}
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * Add all the resources in the given jar that match the given filter.
+	 * 
+	 * @param sub
+	 *            the jar
+	 * @param filter
+	 *            a pattern that should match the resoures in sub to be added
+	 */
+	public boolean addAll(Jar sub, Instruction filter) {
+		return addAll(sub, filter, "");
+	}
+
+	/**
+	 * Add all the resources in the given jar that match the given filter.
+	 * 
+	 * @param sub
+	 *            the jar
+	 * @param filter
+	 *            a pattern that should match the resoures in sub to be added
+	 */
+	public boolean addAll(Jar sub, Instruction filter, String destination) {
+		check();
+		boolean dupl = false;
+		for (String name : sub.getResources().keySet()) {
+			if ("META-INF/MANIFEST.MF".equals(name))
+				continue;
+
+			if (filter == null || filter.matches(name) != filter.isNegated())
+				dupl |= putResource(Processor.appendPath(destination, name), sub.getResource(name), true);
+		}
+		return dupl;
+	}
+
+	public void close() {
+		this.closed = true;
+		if (zipFile != null)
+			try {
+				zipFile.close();
+			}
+			catch (IOException e) {
+				// Ignore
+			}
+		resources.clear();
+		directories.clear();
+		manifest = null;
+		source = null;
+	}
+
+	public long lastModified() {
+		return lastModified;
+	}
+
+	public void updateModified(long time, String reason) {
+		if (time > lastModified) {
+			lastModified = time;
+			lastModifiedReason = reason;
+		}
+	}
+
+	public void setReporter(Reporter reporter) {
+		this.reporter = reporter;
+	}
+
+	public boolean hasDirectory(String path) {
+		check();
+		return directories.get(path) != null;
+	}
+
+	public List<String> getPackages() {
+		check();
+		List<String> list = new ArrayList<String>(directories.size());
+
+		for (Map.Entry<String,Map<String,Resource>> i : directories.entrySet()) {
+			if (i.getValue() != null) {
+				String path = i.getKey();
+				String pack = path.replace('/', '.');
+				list.add(pack);
+			}
+		}
+		return list;
+	}
+
+	public File getSource() {
+		check();
+		return source;
+	}
+
+	public boolean addAll(Jar src) {
+		check();
+		return addAll(src, null);
+	}
+
+	public boolean rename(String oldPath, String newPath) {
+		check();
+		Resource resource = remove(oldPath);
+		if (resource == null)
+			return false;
+
+		return putResource(newPath, resource);
+	}
+
+	public Resource remove(String path) {
+		check();
+		Resource resource = resources.remove(path);
+		String dir = getDirectory(path);
+		Map<String,Resource> mdir = directories.get(dir);
+		// must be != null
+		mdir.remove(path);
+		return resource;
+	}
+
+	/**
+	 * Make sure nobody touches the manifest! If the bundle is signed, we do not
+	 * want anybody to touch the manifest after the digests have been
+	 * calculated.
+	 */
+	public void setDoNotTouchManifest() {
+		doNotTouchManifest = true;
+	}
+
+	/**
+	 * Calculate the checksums and set them in the manifest.
+	 */
+
+	public void calcChecksums(String algorithms[]) throws Exception {
+		check();
+		if (algorithms == null)
+			algorithms = new String[] {
+					"SHA", "MD5"
+			};
+
+		Manifest m = getManifest();
+		if (m == null) {
+			m = new Manifest();
+			setManifest(m);
+		}
+
+		MessageDigest digests[] = new MessageDigest[algorithms.length];
+		int n = 0;
+		for (String algorithm : algorithms)
+			digests[n++] = MessageDigest.getInstance(algorithm);
+
+		byte buffer[] = new byte[30000];
+
+		for (Map.Entry<String,Resource> entry : resources.entrySet()) {
+
+			// Skip the manifest
+			if (entry.getKey().equals("META-INF/MANIFEST.MF"))
+				continue;
+
+			Resource r = entry.getValue();
+			Attributes attributes = m.getAttributes(entry.getKey());
+			if (attributes == null) {
+				attributes = new Attributes();
+				getManifest().getEntries().put(entry.getKey(), attributes);
+			}
+			InputStream in = r.openInputStream();
+			try {
+				for (MessageDigest d : digests)
+					d.reset();
+				int size = in.read(buffer);
+				while (size > 0) {
+					for (MessageDigest d : digests)
+						d.update(buffer, 0, size);
+					size = in.read(buffer);
+				}
+			}
+			finally {
+				in.close();
+			}
+			for (MessageDigest d : digests)
+				attributes.putValue(d.getAlgorithm() + "-Digest", Base64.encodeBase64(d.digest()));
+		}
+	}
+
+	Pattern	BSN	= Pattern.compile("\\s*([-\\w\\d\\._]+)\\s*;?.*");
+
+	public String getBsn() throws Exception {
+		check();
+		Manifest m = getManifest();
+		if (m == null)
+			return null;
+
+		String s = m.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
+		if (s == null)
+			return null;
+
+		Matcher matcher = BSN.matcher(s);
+		if (matcher.matches()) {
+			return matcher.group(1);
+		}
+		return null;
+	}
+
+	public String getVersion() throws Exception {
+		check();
+		Manifest m = getManifest();
+		if (m == null)
+			return null;
+
+		String s = m.getMainAttributes().getValue(Constants.BUNDLE_VERSION);
+		if (s == null)
+			return null;
+
+		return s.trim();
+	}
+
+	/**
+	 * Expand the JAR file to a directory.
+	 * 
+	 * @param dir
+	 *            the dst directory, is not required to exist
+	 * @throws Exception
+	 *             if anything does not work as expected.
+	 */
+	public void expand(File dir) throws Exception {
+		check();
+		dir = dir.getAbsoluteFile();
+		if (!dir.exists() && !dir.mkdirs()) {
+			throw new IOException("Could not create directory " + dir);
+		}
+		if (!dir.isDirectory()) {
+			throw new IllegalArgumentException("Not a dir: " + dir.getAbsolutePath());
+		}
+
+		for (Map.Entry<String,Resource> entry : getResources().entrySet()) {
+			File f = getFile(dir, entry.getKey());
+			File fp = f.getParentFile();
+			if (!fp.exists() && !fp.mkdirs()) {
+				throw new IOException("Could not create directory " + fp);
+			}
+			IO.copy(entry.getValue().openInputStream(), f);
+		}
+	}
+
+	/**
+	 * Make sure we have a manifest
+	 * 
+	 * @throws Exception
+	 */
+	public void ensureManifest() throws Exception {
+		if (getManifest() != null)
+			return;
+		manifest = new Manifest();
+	}
+
+	/**
+	 * Answer if the manifest was the first entry
+	 */
+
+	public boolean isManifestFirst() {
+		return manifestFirst;
+	}
+
+	public void copy(Jar srce, String path, boolean overwrite) {
+		check();
+		addDirectory(srce.getDirectories().get(path), overwrite);
+	}
+
+	public void setCompression(Compression compression) {
+		this.compression = compression;
+	}
+
+	public Compression hasCompression() {
+		return this.compression;
+	}
+
+	void check() {
+		if (closed)
+			throw new RuntimeException("Already closed " + name);
+	}
+
+	/**
+	 * Return a data uri from the JAR. The data must be less than 32k
+	 * 
+	 * @param jar
+	 *            The jar to load the data from
+	 * @param path
+	 *            the path in the jar
+	 * @param mime
+	 *            the mime type
+	 * @return a URI or null if conversion could not take place
+	 */
+
+	public URI getDataURI(String path, String mime, int max) throws Exception {
+		Resource r = getResource(path);
+
+		if (r.size() >= max || r.size() <= 0)
+			return null;
+
+		byte[] data = new byte[(int) r.size()];
+		DataInputStream din = new DataInputStream(r.openInputStream());
+		try {
+			din.readFully(data);
+			String encoded = Base64.encodeBase64(data);
+			return new URI("data:" + mime + ";base64," + encoded);
+		}
+		finally {
+			din.close();
+		}
+	}
+
+	public void setDigestAlgorithms(String[] algorithms) {
+		this.algorithms = algorithms;
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/JarResource.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/JarResource.java
new file mode 100755
index 0000000..1734fc9
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/JarResource.java
@@ -0,0 +1,38 @@
+package aQute.bnd.osgi;
+
+import java.io.*;
+
+public class JarResource extends WriteResource {
+	Jar		jar;
+	long	size	= -1;
+
+	public JarResource(Jar jar) {
+		this.jar = jar;
+	}
+
+	@Override
+	public long lastModified() {
+		return jar.lastModified();
+	}
+
+	@Override
+	public void write(OutputStream out) throws Exception {
+		try {
+			jar.write(out);
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+			throw e;
+		}
+	}
+
+	public Jar getJar() {
+		return jar;
+	}
+
+	@Override
+	public String toString() {
+		return ":" + jar.getName() + ":";
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/Macro.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/Macro.java
new file mode 100755
index 0000000..6146a00
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/Macro.java
@@ -0,0 +1,990 @@
+package aQute.bnd.osgi;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.net.*;
+import java.text.*;
+import java.util.*;
+import java.util.regex.*;
+
+import aQute.bnd.version.*;
+import aQute.lib.collections.*;
+import aQute.lib.io.*;
+
+/**
+ * Provide a macro processor. This processor can replace variables in strings
+ * based on a properties and a domain. The domain can implement functions that
+ * start with a "_" and take args[], the names of these functions are available
+ * as functions in the macro processor (without the _). Macros can nest to any
+ * depth but may not contain loops. Add POSIX macros: ${#parameter} String
+ * length. ${parameter%word} Remove smallest suffix pattern. ${parameter%%word}
+ * Remove largest suffix pattern. ${parameter#word} Remove smallest prefix
+ * pattern. ${parameter##word} Remove largest prefix pattern.
+ */
+public class Macro {
+	Processor	domain;
+	Object		targets[];
+	boolean		flattening;
+
+	public Macro(Processor domain, Object... targets) {
+		this.domain = domain;
+		this.targets = targets;
+		if (targets != null) {
+			for (Object o : targets) {
+				assert o != null;
+			}
+		}
+	}
+
+	public String process(String line, Processor source) {
+		return process(line, new Link(source, null, line));
+	}
+
+	String process(String line, Link link) {
+		StringBuilder sb = new StringBuilder();
+		process(line, 0, '\u0000', '\u0000', sb, link);
+		return sb.toString();
+	}
+
+	int process(CharSequence org, int index, char begin, char end, StringBuilder result, Link link) {
+		StringBuilder line = new StringBuilder(org);
+		int nesting = 1;
+
+		StringBuilder variable = new StringBuilder();
+		outer: while (index < line.length()) {
+			char c1 = line.charAt(index++);
+			if (c1 == end) {
+				if (--nesting == 0) {
+					result.append(replace(variable.toString(), link));
+					return index;
+				}
+			} else if (c1 == begin)
+				nesting++;
+			else if (c1 == '\\' && index < line.length() - 1 && line.charAt(index) == '$') {
+				// remove the escape backslash and interpret the dollar
+				// as a
+				// literal
+				index++;
+				variable.append('$');
+				continue outer;
+			} else if (c1 == '$' && index < line.length() - 2) {
+				char c2 = line.charAt(index);
+				char terminator = getTerminator(c2);
+				if (terminator != 0) {
+					index = process(line, index + 1, c2, terminator, variable, link);
+					continue outer;
+				}
+			} else if (c1 == '.' && index < line.length() && line.charAt(index) == '/') {
+				// Found the sequence ./
+				if (index == 1 || Character.isWhitespace(line.charAt(index - 2))) {
+					// make sure it is preceded by whitespace or starts at begin
+					index++;
+					variable.append(domain.getBase().getAbsolutePath());
+					variable.append('/');
+					continue outer;
+				}
+			}
+			variable.append(c1);
+		}
+		result.append(variable);
+		return index;
+	}
+
+	public static char getTerminator(char c) {
+		switch (c) {
+			case '(' :
+				return ')';
+			case '[' :
+				return ']';
+			case '{' :
+				return '}';
+			case '<' :
+				return '>';
+			case '\u00ab' : // Guillemet double << >>
+				return '\u00bb';
+			case '\u2039' : // Guillemet single
+				return '\u203a';
+		}
+		return 0;
+	}
+
+	protected String replace(String key, Link link) {
+		if (link != null && link.contains(key))
+			return "${infinite:" + link.toString() + "}";
+
+		if (key != null) {
+			key = key.trim();
+			if (key.length() > 0) {
+				Processor source = domain;
+				String value = null;
+
+				if (key.indexOf(';') < 0) {
+					Instruction ins = new Instruction(key);
+					if (!ins.isLiteral()) {
+						SortedList<String> sortedList = SortedList.fromIterator(domain.iterator());
+						StringBuilder sb = new StringBuilder();
+						String del = "";
+						for (String k : sortedList) {
+							if (ins.matches(k)) {
+								String v = replace(k, new Link(source, link, key));
+								if (v != null) {
+									sb.append(del);
+									del = ",";
+									sb.append(v);
+								}
+							}
+						}
+						return sb.toString();
+					}
+				}
+				while (value == null && source != null) {
+					value = source.getProperties().getProperty(key);
+					source = source.getParent();
+				}
+
+				if (value != null)
+					return process(value, new Link(source, link, key));
+
+				value = doCommands(key, link);
+				if (value != null)
+					return process(value, new Link(source, link, key));
+
+				if (key != null && key.trim().length() > 0) {
+					value = System.getProperty(key);
+					if (value != null)
+						return value;
+				}
+				if (!flattening && !key.equals("@"))
+					domain.warning("No translation found for macro: " + key);
+			} else {
+				domain.warning("Found empty macro key");
+			}
+		} else {
+			domain.warning("Found null macro key");
+		}
+		return "${" + key + "}";
+	}
+
+	/**
+	 * Parse the key as a command. A command consist of parameters separated by
+	 * ':'.
+	 * 
+	 * @param key
+	 * @return
+	 */
+	static Pattern	commands	= Pattern.compile("(?<!\\\\);");
+
+	private String doCommands(String key, Link source) {
+		String[] args = commands.split(key);
+		if (args == null || args.length == 0)
+			return null;
+
+		for (int i = 0; i < args.length; i++)
+			if (args[i].indexOf('\\') >= 0)
+				args[i] = args[i].replaceAll("\\\\;", ";");
+
+		if (args[0].startsWith("^")) {
+			String varname = args[0].substring(1).trim();
+
+			Processor parent = source.start.getParent();
+			if (parent != null)
+				return parent.getProperty(varname);
+			return null;
+		}
+
+		Processor rover = domain;
+		while (rover != null) {
+			String result = doCommand(rover, args[0], args);
+			if (result != null)
+				return result;
+
+			rover = rover.getParent();
+		}
+
+		for (int i = 0; targets != null && i < targets.length; i++) {
+			String result = doCommand(targets[i], args[0], args);
+			if (result != null)
+				return result;
+		}
+
+		return doCommand(this, args[0], args);
+	}
+
+	private String doCommand(Object target, String method, String[] args) {
+		if (target == null)
+			; // System.err.println("Huh? Target should never be null " +
+		// domain);
+		else {
+			String cname = "_" + method.replaceAll("-", "_");
+			try {
+				Method m = target.getClass().getMethod(cname, new Class[] {
+					String[].class
+				});
+				Object result = m.invoke(target, new Object[] {
+					args
+				});
+				return result == null ? null : result.toString();
+			}
+			catch (NoSuchMethodException e) {
+				// Ignore
+			}
+			catch (InvocationTargetException e) {
+				if (e.getCause() instanceof IllegalArgumentException) {
+					domain.error("%s, for cmd: %s, arguments; %s", e.getCause().getMessage(), method,
+							Arrays.toString(args));
+				} else {
+					domain.warning("Exception in replace: %s", e.getCause());
+					e.getCause().printStackTrace();
+				}
+			}
+			catch (Exception e) {
+				domain.warning("Exception in replace: " + e + " method=" + method);
+				e.printStackTrace();
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Return a unique list where the duplicates are removed.
+	 * 
+	 * @param args
+	 * @return
+	 */
+	static String	_uniqHelp	= "${uniq;<list> ...}";
+
+	public String _uniq(String args[]) {
+		verifyCommand(args, _uniqHelp, null, 1, Integer.MAX_VALUE);
+		Set<String> set = new LinkedHashSet<String>();
+		for (int i = 1; i < args.length; i++) {
+			Processor.split(args[i], set);
+		}
+		return Processor.join(set, ",");
+	}
+
+	public String _pathseparator(String args[]) {
+		return File.pathSeparator;
+	}
+
+	public String _separator(String args[]) {
+		return File.separator;
+	}
+
+	public String _filter(String args[]) {
+		return filter(args, false);
+	}
+
+	public String _filterout(String args[]) {
+		return filter(args, true);
+
+	}
+
+	static String	_filterHelp	= "${%s;<list>;<regex>}";
+
+	String filter(String[] args, boolean include) {
+		verifyCommand(args, String.format(_filterHelp, args[0]), null, 3, 3);
+
+		Collection<String> list = new ArrayList<String>(Processor.split(args[1]));
+		Pattern pattern = Pattern.compile(args[2]);
+
+		for (Iterator<String> i = list.iterator(); i.hasNext();) {
+			if (pattern.matcher(i.next()).matches() == include)
+				i.remove();
+		}
+		return Processor.join(list);
+	}
+
+	static String	_sortHelp	= "${sort;<list>...}";
+
+	public String _sort(String args[]) {
+		verifyCommand(args, _sortHelp, null, 2, Integer.MAX_VALUE);
+
+		List<String> result = new ArrayList<String>();
+		for (int i = 1; i < args.length; i++) {
+			Processor.split(args[i], result);
+		}
+		Collections.sort(result);
+		return Processor.join(result);
+	}
+
+	static String	_joinHelp	= "${join;<list>...}";
+
+	public String _join(String args[]) {
+
+		verifyCommand(args, _joinHelp, null, 1, Integer.MAX_VALUE);
+
+		List<String> result = new ArrayList<String>();
+		for (int i = 1; i < args.length; i++) {
+			Processor.split(args[i], result);
+		}
+		return Processor.join(result);
+	}
+
+	static String	_ifHelp	= "${if;<condition>;<iftrue> [;<iffalse>] }";
+
+	public String _if(String args[]) {
+		verifyCommand(args, _ifHelp, null, 3, 4);
+		String condition = args[1].trim();
+		if (!condition.equalsIgnoreCase("false"))
+			if (condition.length() != 0)
+				return args[2];
+
+		if (args.length > 3)
+			return args[3];
+		return "";
+	}
+
+	public final static String	_nowHelp	= "${now;pattern|'long'}, returns current time";
+
+	public Object _now(String args[]) {
+		verifyCommand(args, _nowHelp, null, 1, 2);
+		Date now = new Date();
+
+		if (args.length == 2) {
+			if ("long".equals(args[1]))
+				return now.getTime();
+
+			DateFormat df = new SimpleDateFormat(args[1]);
+			return df.format(now);
+		}
+		return new Date();
+	}
+
+	public final static String	_fmodifiedHelp	= "${fmodified;<list of filenames>...}, return latest modification date";
+
+	public String _fmodified(String args[]) throws Exception {
+		verifyCommand(args, _fmodifiedHelp, null, 2, Integer.MAX_VALUE);
+
+		long time = 0;
+		Collection<String> names = new ArrayList<String>();
+		for (int i = 1; i < args.length; i++) {
+			Processor.split(args[i], names);
+		}
+		for (String name : names) {
+			File f = new File(name);
+			if (f.exists() && f.lastModified() > time)
+				time = f.lastModified();
+		}
+		return "" + time;
+	}
+
+	public String _long2date(String args[]) {
+		try {
+			return new Date(Long.parseLong(args[1])).toString();
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}
+		return "not a valid long";
+	}
+
+	public String _literal(String args[]) {
+		if (args.length != 2)
+			throw new RuntimeException("Need a value for the ${literal;<value>} macro");
+		return "${" + args[1] + "}";
+	}
+
+	public String _def(String args[]) {
+		if (args.length != 2)
+			throw new RuntimeException("Need a value for the ${def;<value>} macro");
+
+		return domain.getProperty(args[1], "");
+	}
+
+	/**
+	 * replace ; <list> ; regex ; replace
+	 * 
+	 * @param args
+	 * @return
+	 */
+	public String _replace(String args[]) {
+		if (args.length != 4) {
+			domain.warning("Invalid nr of arguments to replace " + Arrays.asList(args));
+			return null;
+		}
+
+		String list[] = args[1].split("\\s*,\\s*");
+		StringBuilder sb = new StringBuilder();
+		String del = "";
+		for (int i = 0; i < list.length; i++) {
+			String element = list[i].trim();
+			if (!element.equals("")) {
+				sb.append(del);
+				sb.append(element.replaceAll(args[2], args[3]));
+				del = ", ";
+			}
+		}
+
+		return sb.toString();
+	}
+
+	public String _warning(String args[]) {
+		for (int i = 1; i < args.length; i++) {
+			domain.warning(process(args[i]));
+		}
+		return "";
+	}
+
+	public String _error(String args[]) {
+		for (int i = 1; i < args.length; i++) {
+			domain.error(process(args[i]));
+		}
+		return "";
+	}
+
+	/**
+	 * toclassname ; <path>.class ( , <path>.class ) *
+	 * 
+	 * @param args
+	 * @return
+	 */
+	static String	_toclassnameHelp	= "${classname;<list of class names>}, convert class paths to FQN class names ";
+
+	public String _toclassname(String args[]) {
+		verifyCommand(args, _toclassnameHelp, null, 2, 2);
+		Collection<String> paths = Processor.split(args[1]);
+
+		List<String> names = new ArrayList<String>(paths.size());
+		for (String path : paths) {
+			if (path.endsWith(".class")) {
+				String name = path.substring(0, path.length() - 6).replace('/', '.');
+				names.add(name);
+			} else if (path.endsWith(".java")) {
+				String name = path.substring(0, path.length() - 5).replace('/', '.');
+				names.add(name);
+			} else {
+				domain.warning("in toclassname, " + args[1] + " is not a class path because it does not end in .class");
+			}
+		}
+		return Processor.join(names, ",");
+	}
+
+	/**
+	 * toclassname ; <path>.class ( , <path>.class ) *
+	 * 
+	 * @param args
+	 * @return
+	 */
+
+	static String	_toclasspathHelp	= "${toclasspath;<list>[;boolean]}, convert a list of class names to paths";
+
+	public String _toclasspath(String args[]) {
+		verifyCommand(args, _toclasspathHelp, null, 2, 3);
+		boolean cl = true;
+		if (args.length > 2)
+			cl = Boolean.valueOf(args[2]);
+
+		Collection<String> names = Processor.split(args[1]);
+		Collection<String> paths = new ArrayList<String>(names.size());
+		for (String name : names) {
+			String path = name.replace('.', '/') + (cl ? ".class" : "");
+			paths.add(path);
+		}
+		return Processor.join(paths, ",");
+	}
+
+	public String _dir(String args[]) {
+		if (args.length < 2) {
+			domain.warning("Need at least one file name for ${dir;...}");
+			return null;
+		}
+		String del = "";
+		StringBuilder sb = new StringBuilder();
+		for (int i = 1; i < args.length; i++) {
+			File f = domain.getFile(args[i]);
+			if (f.exists() && f.getParentFile().exists()) {
+				sb.append(del);
+				sb.append(f.getParentFile().getAbsolutePath());
+				del = ",";
+			}
+		}
+		return sb.toString();
+
+	}
+
+	public String _basename(String args[]) {
+		if (args.length < 2) {
+			domain.warning("Need at least one file name for ${basename;...}");
+			return null;
+		}
+		String del = "";
+		StringBuilder sb = new StringBuilder();
+		for (int i = 1; i < args.length; i++) {
+			File f = domain.getFile(args[i]);
+			if (f.exists() && f.getParentFile().exists()) {
+				sb.append(del);
+				sb.append(f.getName());
+				del = ",";
+			}
+		}
+		return sb.toString();
+
+	}
+
+	public String _isfile(String args[]) {
+		if (args.length < 2) {
+			domain.warning("Need at least one file name for ${isfile;...}");
+			return null;
+		}
+		boolean isfile = true;
+		for (int i = 1; i < args.length; i++) {
+			File f = new File(args[i]).getAbsoluteFile();
+			isfile &= f.isFile();
+		}
+		return isfile ? "true" : "false";
+
+	}
+
+	public String _isdir(String args[]) {
+		if (args.length < 2) {
+			domain.warning("Need at least one file name for ${isdir;...}");
+			return null;
+		}
+		boolean isdir = true;
+		for (int i = 1; i < args.length; i++) {
+			File f = new File(args[i]).getAbsoluteFile();
+			isdir &= f.isDirectory();
+		}
+		return isdir ? "true" : "false";
+
+	}
+
+	public String _tstamp(String args[]) {
+		String format = "yyyyMMddHHmm";
+		long now = System.currentTimeMillis();
+		TimeZone tz = TimeZone.getTimeZone("UTC");
+
+		if (args.length > 1) {
+			format = args[1];
+		}
+		if (args.length > 2) {
+			tz = TimeZone.getTimeZone(args[2]);
+		}
+		if (args.length > 3) {
+			now = Long.parseLong(args[3]);
+		}
+		if (args.length > 4) {
+			domain.warning("Too many arguments for tstamp: " + Arrays.toString(args));
+		}
+
+		SimpleDateFormat sdf = new SimpleDateFormat(format);
+		sdf.setTimeZone(tz);
+
+		return sdf.format(new Date(now));
+	}
+
+	/**
+	 * Wildcard a directory. The lists can contain Instruction that are matched
+	 * against the given directory ${lsr;<dir>;<list>(;<list>)*}
+	 * ${lsa;<dir>;<list>(;<list>)*}
+	 * 
+	 * @author aqute
+	 */
+
+	public String _lsr(String args[]) {
+		return ls(args, true);
+	}
+
+	public String _lsa(String args[]) {
+		return ls(args, false);
+	}
+
+	String ls(String args[], boolean relative) {
+		if (args.length < 2)
+			throw new IllegalArgumentException("the ${ls} macro must at least have a directory as parameter");
+
+		File dir = domain.getFile(args[1]);
+		if (!dir.isAbsolute())
+			throw new IllegalArgumentException("the ${ls} macro directory parameter is not absolute: " + dir);
+
+		if (!dir.exists())
+			throw new IllegalArgumentException("the ${ls} macro directory parameter does not exist: " + dir);
+
+		if (!dir.isDirectory())
+			throw new IllegalArgumentException(
+					"the ${ls} macro directory parameter points to a file instead of a directory: " + dir);
+
+		Collection<File> files = new ArrayList<File>(new SortedList<File>(dir.listFiles()));
+
+		for (int i = 2; i < args.length; i++) {
+			Instructions filters = new Instructions(args[i]);
+			files = filters.select(files, true);
+		}
+
+		List<String> result = new ArrayList<String>();
+		for (File file : files)
+			result.add(relative ? file.getName() : file.getAbsolutePath());
+
+		return Processor.join(result, ",");
+	}
+
+	public String _currenttime(String args[]) {
+		return Long.toString(System.currentTimeMillis());
+	}
+
+	/**
+	 * Modify a version to set a version policy. Thed policy is a mask that is
+	 * mapped to a version.
+	 * 
+	 * <pre>
+	 * +           increment
+	 * -           decrement
+	 * =           maintain
+	 * ˜           discard
+	 * 
+	 * ==+      = maintain major, minor, increment micro, discard qualifier
+	 * ˜˜˜=     = just get the qualifier
+	 * version="[${version;==;${@}},${version;=+;${@}})"
+	 * </pre>
+	 * 
+	 * @param args
+	 * @return
+	 */
+	final static String		MASK_STRING			= "[\\-+=~0123456789]{0,3}[=~]?";
+	final static Pattern	MASK				= Pattern.compile(MASK_STRING);
+	final static String		_versionHelp		= "${version;<mask>;<version>}, modify a version\n"
+														+ "<mask> ::= [ M [ M [ M [ MQ ]]]\n"
+														+ "M ::= '+' | '-' | MQ\n" + "MQ ::= '~' | '='";
+	final static Pattern	_versionPattern[]	= new Pattern[] {
+			null, null, MASK, Verifier.VERSION
+												};
+
+	public String _version(String args[]) {
+		verifyCommand(args, _versionHelp, null, 2, 3);
+
+		String mask = args[1];
+
+		Version version = null;
+		if (args.length >= 3)
+			version = new Version(args[2]);
+
+		return version(version, mask);
+	}
+
+	String version(Version version, String mask) {
+		if (version == null) {
+			String v = domain.getProperty("@");
+			if (v == null) {
+				domain.error(
+						"No version specified for ${version} or ${range} and no implicit version ${@} either, mask=%s",
+						mask);
+				v = "0";
+			}
+			version = new Version(v);
+		}
+
+		StringBuilder sb = new StringBuilder();
+		String del = "";
+
+		for (int i = 0; i < mask.length(); i++) {
+			char c = mask.charAt(i);
+			String result = null;
+			if (c != '~') {
+				if (i == 3) {
+					result = version.getQualifier();
+				} else if (Character.isDigit(c)) {
+					// Handle masks like +00, =+0
+					result = String.valueOf(c);
+				} else {
+					int x = version.get(i);
+					switch (c) {
+						case '+' :
+							x++;
+							break;
+						case '-' :
+							x--;
+							break;
+						case '=' :
+							break;
+					}
+					result = Integer.toString(x);
+				}
+				if (result != null) {
+					sb.append(del);
+					del = ".";
+					sb.append(result);
+				}
+			}
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * Schortcut for version policy
+	 * 
+	 * <pre>
+	 * -provide-policy : ${policy;[==,=+)}
+	 * -consume-policy : ${policy;[==,+)}
+	 * </pre>
+	 * 
+	 * @param args
+	 * @return
+	 */
+
+	static Pattern	RANGE_MASK		= Pattern.compile("(\\[|\\()(" + MASK_STRING + "),(" + MASK_STRING + ")(\\]|\\))");
+	static String	_rangeHelp		= "${range;<mask>[;<version>]}, range for version, if version not specified lookyp ${@}\n"
+											+ "<mask> ::= [ M [ M [ M [ MQ ]]]\n"
+											+ "M ::= '+' | '-' | MQ\n"
+											+ "MQ ::= '~' | '='";
+	static Pattern	_rangePattern[]	= new Pattern[] {
+			null, RANGE_MASK
+									};
+
+	public String _range(String args[]) {
+		verifyCommand(args, _rangeHelp, _rangePattern, 2, 3);
+		Version version = null;
+		if (args.length >= 3)
+			version = new Version(args[2]);
+		else {
+			String v = domain.getProperty("@");
+			if (v == null)
+				return null;
+			version = new Version(v);
+		}
+		String spec = args[1];
+
+		Matcher m = RANGE_MASK.matcher(spec);
+		m.matches();
+		String floor = m.group(1);
+		String floorMask = m.group(2);
+		String ceilingMask = m.group(3);
+		String ceiling = m.group(4);
+
+		String left = version(version, floorMask);
+		String right = version(version, ceilingMask);
+		StringBuilder sb = new StringBuilder();
+		sb.append(floor);
+		sb.append(left);
+		sb.append(",");
+		sb.append(right);
+		sb.append(ceiling);
+
+		String s = sb.toString();
+		VersionRange vr = new VersionRange(s);
+		if (!(vr.includes(vr.getHigh()) || vr.includes(vr.getLow()))) {
+			domain.error("${range} macro created an invalid range %s from %s and mask %s", s, version, spec);
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * System command. Execute a command and insert the result.
+	 * 
+	 * @param args
+	 * @param help
+	 * @param patterns
+	 * @param low
+	 * @param high
+	 */
+	public String system_internal(boolean allowFail, String args[]) throws Exception {
+		verifyCommand(args, "${" + (allowFail ? "system-allow-fail" : "system")
+				+ ";<command>[;<in>]}, execute a system command", null, 2, 3);
+		String command = args[1];
+		String input = null;
+
+		if (args.length > 2) {
+			input = args[2];
+		}
+
+		Process process = Runtime.getRuntime().exec(command, null, domain.getBase());
+		if (input != null) {
+			process.getOutputStream().write(input.getBytes("UTF-8"));
+		}
+		process.getOutputStream().close();
+
+		String s = IO.collect(process.getInputStream(), "UTF-8");
+		int exitValue = process.waitFor();
+		if (exitValue != 0)
+			return exitValue + "";
+
+		if (!allowFail && (exitValue != 0)) {
+			domain.error("System command " + command + " failed with " + exitValue);
+		}
+		return s.trim();
+	}
+
+	public String _system(String args[]) throws Exception {
+		return system_internal(false, args);
+	}
+
+	public String _system_allow_fail(String args[]) throws Exception {
+		String result = "";
+		try {
+			result = system_internal(true, args);
+		}
+		catch (Throwable t) {
+			/* ignore */
+		}
+		return result;
+	}
+
+	public String _env(String args[]) {
+		verifyCommand(args, "${env;<name>}, get the environmet variable", null, 2, 2);
+
+		try {
+			return System.getenv(args[1]);
+		}
+		catch (Throwable t) {
+			return null;
+		}
+	}
+
+	/**
+	 * Get the contents of a file.
+	 * 
+	 * @param in
+	 * @return
+	 * @throws IOException
+	 */
+
+	public String _cat(String args[]) throws IOException {
+		verifyCommand(args, "${cat;<in>}, get the content of a file", null, 2, 2);
+		File f = domain.getFile(args[1]);
+		if (f.isFile()) {
+			return IO.collect(f);
+		} else if (f.isDirectory()) {
+			return Arrays.toString(f.list());
+		} else {
+			try {
+				URL url = new URL(args[1]);
+				return IO.collect(url, "UTF-8");
+			}
+			catch (MalformedURLException mfue) {
+				// Ignore here
+			}
+			return null;
+		}
+	}
+
+	public static void verifyCommand(String args[], String help, Pattern[] patterns, int low, int high) {
+		String message = "";
+		if (args.length > high) {
+			message = "too many arguments";
+		} else if (args.length < low) {
+			message = "too few arguments";
+		} else {
+			for (int i = 0; patterns != null && i < patterns.length && i < args.length; i++) {
+				if (patterns[i] != null) {
+					Matcher m = patterns[i].matcher(args[i]);
+					if (!m.matches())
+						message += String.format("Argument %s (%s) does not match %s%n", i, args[i],
+								patterns[i].pattern());
+				}
+			}
+		}
+		if (message.length() != 0) {
+			StringBuilder sb = new StringBuilder();
+			String del = "${";
+			for (String arg : args) {
+				sb.append(del);
+				sb.append(arg);
+				del = ";";
+			}
+			sb.append("}, is not understood. ");
+			sb.append(message);
+			throw new IllegalArgumentException(sb.toString());
+		}
+	}
+
+	// Helper class to track expansion of variables
+	// on the stack.
+	static class Link {
+		Link		previous;
+		String		key;
+		Processor	start;
+
+		public Link(Processor start, Link previous, String key) {
+			this.previous = previous;
+			this.key = key;
+			this.start = start;
+		}
+
+		public boolean contains(String key) {
+			if (this.key.equals(key))
+				return true;
+
+			if (previous == null)
+				return false;
+
+			return previous.contains(key);
+		}
+
+		@Override
+		public String toString() {
+			StringBuilder sb = new StringBuilder();
+			String del = "[";
+			for (Link r = this; r != null; r = r.previous) {
+				sb.append(del);
+				sb.append(r.key);
+				del = ",";
+			}
+			sb.append("]");
+			return sb.toString();
+		}
+	}
+
+	/**
+	 * Take all the properties and translate them to actual values. This method
+	 * takes the set properties and traverse them over all entries, including
+	 * the default properties for that properties. The values no longer contain
+	 * macros.
+	 * 
+	 * @return A new Properties with the flattened values
+	 */
+	public Properties getFlattenedProperties() {
+		// Some macros only work in a lower processor, so we
+		// do not report unknown macros while flattening
+		flattening = true;
+		try {
+			Properties flattened = new Properties();
+			Properties source = domain.getProperties();
+			for (Enumeration< ? > e = source.propertyNames(); e.hasMoreElements();) {
+				String key = (String) e.nextElement();
+				if (!key.startsWith("_"))
+					if (key.startsWith("-"))
+						flattened.put(key, source.getProperty(key));
+					else
+						flattened.put(key, process(source.getProperty(key)));
+			}
+			return flattened;
+		}
+		finally {
+			flattening = false;
+		}
+	}
+
+	public final static String	_fileHelp	= "${file;<base>;<paths>...}, create correct OS dependent path";
+
+	public String _osfile(String args[]) {
+		verifyCommand(args, _fileHelp, null, 3, 3);
+		File base = new File(args[1]);
+		File f = Processor.getFile(base, args[2]);
+		return f.getAbsolutePath();
+	}
+
+	public String _path(String args[]) {
+		List<String> list = new ArrayList<String>();
+		for (int i = 1; i < args.length; i++) {
+			list.addAll(Processor.split(args[i]));
+		}
+		return Processor.join(list, File.pathSeparator);
+	}
+
+	public static Properties getParent(Properties p) {
+		try {
+			Field f = Properties.class.getDeclaredField("defaults");
+			f.setAccessible(true);
+			return (Properties) f.get(p);
+		}
+		catch (Exception e) {
+			Field[] fields = Properties.class.getFields();
+			System.err.println(Arrays.toString(fields));
+			return null;
+		}
+	}
+
+	public String process(String line) {
+		return process(line, domain);
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/OpCodes.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/OpCodes.java
new file mode 100755
index 0000000..4299556
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/OpCodes.java
@@ -0,0 +1,1250 @@
+package aQute.bnd.osgi;
+
+public class OpCodes {
+	final static short	nop				= 0x00;			// [No change]
+															// performs
+															// no
+	// operation
+	final static short	aconst_null		= 0x01;			// ? null pushes a
+															// null
+	// reference onto the stack
+	final static short	iconst_m1		= 0x02;			// ? -1 loads the
+															// int
+															// value -1
+	// onto the stack
+	final static short	iconst_0		= 0x03;			// ? 0 loads the int
+															// value 0
+	// onto the stack
+	final static short	iconst_1		= 0x04;			// ? 1 loads the int
+															// value 1
+	// onto the stack
+	final static short	iconst_2		= 0x05;			// ? 2 loads the int
+															// value 2
+	// onto the stack
+	final static short	iconst_3		= 0x06;			// ? 3 loads the int
+															// value 3
+	// onto the stack
+	final static short	iconst_4		= 0x07;			// ? 4 loads the int
+															// value 4
+	// onto the stack
+	final static short	iconst_5		= 0x08;			// ? 5 loads the int
+															// value 5
+	// onto the stack
+	final static short	lconst_0		= 0x09;			// ? 0L pushes the
+															// long
+															// 0 onto
+	// the stack
+	final static short	bipush			= 0x10;			// byte ? value
+															// pushes a
+															// byte
+	// onto the stack as an integer
+	// value
+	final static short	sipush			= 0x11;			// byte1, byte2 ?
+															// value
+															// pushes a
+	// signed integer (byte1 << 8 +
+	// byte2) onto the stack
+	final static short	ldc				= 0x12;			// index ? value
+															// pushes
+															// a
+	// constant #index from a
+	// constant pool (String, int,
+	// float or class type) onto the
+	// stack
+	final static short	ldc_w			= 0x13;			// indexbyte1,
+															// indexbyte2 ?
+	// value pushes a constant
+	// #index from a constant pool
+	// (String, int, float or class
+	// type) onto the stack (wide
+	// index is constructed as
+	// indexbyte1 << 8 + indexbyte2)
+	final static short	ldc2_w			= 0x14;			// indexbyte1,
+															// indexbyte2 ?
+	// value pushes a constant
+	// #index from a constant pool
+	// (double or long) onto the
+	// stack (wide index is
+	// constructed as indexbyte1 <<
+	// 8 + indexbyte2)
+	final static short	iload			= 0x15;			// index ? value
+															// loads
+															// an int
+	// value from a variable #index
+	final static short	lload			= 0x16;			// index ? value
+															// load a
+															// long
+	// value from a local variable
+	// #index
+	final static short	fload			= 0x17;			// index ? value
+															// loads a
+															// float
+	// value from a local variable
+	// #index
+	final static short	dload			= 0x18;			// index ? value
+															// loads a
+															// double
+	// value from a local variable
+	// #index
+	final static short	aload			= 0x19;			// index ? objectref
+															// loads a
+	// reference onto the stack from
+	// a local variable #index
+	final static short	lload_2			= 0x20;			// ? value load a
+															// long
+															// value
+	// from a local variable 2
+	final static short	lload_3			= 0x21;			// ? value load a
+															// long
+															// value
+	// from a local variable 3
+	final static short	fload_0			= 0x22;			// ? value loads a
+															// float
+															// value
+	// from local variable 0
+	final static short	fload_1			= 0x23;			// ? value loads a
+															// float
+															// value
+	// from local variable 1
+	final static short	fload_2			= 0x24;			// ? value loads a
+															// float
+															// value
+	// from local variable 2
+	final static short	fload_3			= 0x25;			// ? value loads a
+															// float
+															// value
+	// from local variable 3
+	final static short	dload_0			= 0x26;			// ? value loads a
+															// double from
+	// local variable 0
+	final static short	dload_1			= 0x27;			// ? value loads a
+															// double from
+	// local variable 1
+	final static short	dload_2			= 0x28;			// ? value loads a
+															// double from
+	// local variable 2
+	final static short	dload_3			= 0x29;			// ? value loads a
+															// double from
+	// local variable 3
+	final static short	faload			= 0x30;			// arrayref, index ?
+															// value loads
+	// a float from an array
+	final static short	daload			= 0x31;			// arrayref, index ?
+															// value loads
+	// a double from an array
+	final static short	aaload			= 0x32;			// arrayref, index ?
+															// value loads
+	// onto the stack a reference
+	// from an array
+	final static short	baload			= 0x33;			// arrayref, index ?
+															// value loads
+	// a byte or Boolean value from
+	// an array
+	final static short	caload			= 0x34;			// arrayref, index ?
+															// value loads
+	// a char from an array
+	final static short	saload			= 0x35;			// arrayref, index ?
+															// value load
+	// short from array
+	final static short	istore			= 0x36;			// index value ?
+															// store
+															// int value
+	// into variable #index
+	final static short	lstore			= 0x37;			// index value ?
+															// store a
+															// long
+	// value in a local variable
+	// #index
+	final static short	fstore			= 0x38;			// index value ?
+															// stores
+															// a float
+	// value into a local variable
+	// #index
+	final static short	dstore			= 0x39;			// index value ?
+															// stores
+															// a double
+	// value into a local variable
+	// #index
+	final static short	lstore_1		= 0x40;			// value ? store a
+															// long
+															// value in
+	// a local variable 1
+	final static short	lstore_2		= 0x41;			// value ? store a
+															// long
+															// value in
+	// a local variable 2
+	final static short	lstore_3		= 0x42;			// value ? store a
+															// long
+															// value in
+	// a local variable 3
+	final static short	fstore_0		= 0x43;			// value ? stores a
+															// float value
+	// into local variable 0
+	final static short	fstore_1		= 0x44;			// value ? stores a
+															// float value
+	// into local variable 1
+	final static short	fstore_2		= 0x45;			// value ? stores a
+															// float value
+	// into local variable 2
+	final static short	fstore_3		= 0x46;			// value ? stores a
+															// float value
+	// into local variable 3
+	final static short	dstore_0		= 0x47;			// value ? stores a
+															// double into
+	// local variable 0
+	final static short	dstore_1		= 0x48;			// value ? stores a
+															// double into
+	// local variable 1
+	final static short	dstore_2		= 0x49;			// value ? stores a
+															// double into
+	// local variable 2
+	final static short	lastore			= 0x50;			// arrayref, index,
+															// value ?
+	// store a long to an array
+	final static short	fastore			= 0x51;			// arreyref, index,
+															// value ?
+	// stores a float in an array
+	final static short	dastore			= 0x52;			// arrayref, index,
+															// value ?
+	// stores a double into an array
+	final static short	aastore			= 0x53;			// arrayref, index,
+															// value ?
+	// stores into a reference to an
+	// array
+	final static short	bastore			= 0x54;			// arrayref, index,
+															// value ?
+	// stores a byte or Boolean
+	// value into an array
+	final static short	castore			= 0x55;			// arrayref, index,
+															// value ?
+	// stores a char into an array
+	final static short	sastore			= 0x56;			// arrayref, index,
+															// value ?
+	// store short to array
+	final static short	pop				= 0x57;			// value ? discards
+															// the
+															// top
+	// value on the stack
+	final static short	pop2			= 0x58;			// {value2, value1}
+															// ?
+															// discards
+	// the top two values on the
+	// stack (or one value, if it is
+	// a double or long)
+	final static short	dup				= 0x59;			// value ? value,
+															// value
+	// duplicates the value on top
+	// of the stack
+	final static short	iadd			= 0x60;			// value1, value2 ?
+															// result adds
+	// two ints together
+	final static short	ladd			= 0x61;			// value1, value2 ?
+															// result add
+	// two longs
+	final static short	fadd			= 0x62;			// value1, value2 ?
+															// result adds
+	// two floats
+	final static short	dadd			= 0x63;			// value1, value2 ?
+															// result adds
+	// two doubles
+	final static short	isub			= 0x64;			// value1, value2 ?
+															// result int
+	// subtract
+	final static short	lsub			= 0x65;			// value1, value2 ?
+															// result
+	// subtract two longs
+	final static short	fsub			= 0x66;			// value1, value2 ?
+															// result
+	// subtracts two floats
+	final static short	dsub			= 0x67;			// value1, value2 ?
+															// result
+	// subtracts a double from
+	// another
+	final static short	imul			= 0x68;			// value1, value2 ?
+															// result
+	// multiply two integers
+	final static short	lmul			= 0x69;			// value1, value2 ?
+															// result
+	// multiplies two longs
+	final static short	irem			= 0x70;			// value1, value2 ?
+															// result
+	// logical int remainder
+	final static short	lrem			= 0x71;			// value1, value2 ?
+															// result
+	// remainder of division of two
+	// longs
+	final static short	frem			= 0x72;			// value1, value2 ?
+															// result gets
+	// the remainder from a division
+	// between two floats
+	final static short	drem			= 0x73;			// value1, value2 ?
+															// result gets
+	// the remainder from a division
+	// between two doubles
+	final static short	ineg			= 0x74;			// value ? result
+															// negate
+															// int
+	final static short	lneg			= 0x75;			// value ? result
+															// negates a long
+	final static short	fneg			= 0x76;			// value ? result
+															// negates a
+	// float
+	final static short	dneg			= 0x77;			// value ? result
+															// negates a
+	// double
+	final static short	ishl			= 0x78;			// value1, value2 ?
+															// result int
+	// shift left
+	final static short	lshl			= 0x79;			// value1, value2 ?
+															// result
+	// bitwise shift left of a long
+	// value1 by value2 positions
+	final static short	ior				= 0x80;			// value1, value2 ?
+															// result
+	// logical int or
+	final static short	lor				= 0x81;			// value1, value2 ?
+															// result
+	// bitwise or of two longs
+	final static short	ixor			= 0x82;			// value1, value2 ?
+															// result int
+	// xor
+	final static short	lxor			= 0x83;			// value1, value2 ?
+															// result
+	// bitwise exclusive or of two
+	// longs
+	final static short	iinc			= 0x84;			// index, const [No
+															// change]
+	// increment local variable
+	// #index by signed byte const
+	final static short	i2l				= 0x85;			// value ? result
+															// converts an
+	// int into a long
+	final static short	i2f				= 0x86;			// value ? result
+															// converts an
+	// int into a float
+	final static short	i2d				= 0x87;			// value ? result
+															// converts an
+	// int into a double
+	final static short	l2i				= 0x88;			// value ? result
+															// converts a
+	// long to an int
+	final static short	l2f				= 0x89;			// value ? result
+															// converts a
+	// long to a float
+	final static short	d2f				= 0x90;			// value ? result
+															// converts a
+	// double to a float
+	final static short	i2b				= 0x91;			// value ? result
+															// converts an
+	// int into a byte
+	final static short	i2c				= 0x92;			// value ? result
+															// converts an
+	// int into a character
+	final static short	i2s				= 0x93;			// value ? result
+															// converts an
+	// int into a short
+	final static short	lcmp			= 0x94;			// value1, value2 ?
+															// result
+	// compares two longs values
+	final static short	fcmpl			= 0x95;			// value1, value2 ?
+															// result
+	// compares two floats
+	final static short	fcmpg			= 0x96;			// value1, value2 ?
+															// result
+	// compares two floats
+	final static short	dcmpl			= 0x97;			// value1, value2 ?
+															// result
+	// compares two doubles
+	final static short	dcmpg			= 0x98;			// value1, value2 ?
+															// result
+	// compares two doubles
+	final static short	ifeq			= 0x99;			// branchbyte1,
+															// branchbyte2
+	// value ? if value is 0, branch
+	// to instruction at
+	// branchoffset (signed short
+	// constructed from unsigned
+	// bytes branchbyte1 << 8 +
+	// branchbyte2)
+	final static short	lconst_1		= 0x0a;			// ? 1L pushes the
+															// long
+															// 1 onto
+	// the stack
+	final static short	fconst_0		= 0x0b;			// ? 0.0f pushes
+															// 0.0f on
+															// the
+	// stack
+	final static short	fconst_1		= 0x0c;			// ? 1.0f pushes
+															// 1.0f on
+															// the
+	// stack
+	final static short	fconst_2		= 0x0d;			// ? 2.0f pushes
+															// 2.0f on
+															// the
+	// stack
+	final static short	dconst_0		= 0x0e;			// ? 0.0 pushes the
+															// constant 0.0
+	// onto the stack
+	final static short	dconst_1		= 0x0f;			// ? 1.0 pushes the
+															// constant 1.0
+	// onto the stack
+	final static short	iload_0			= 0x1a;			// ? value loads an
+															// int
+															// value
+	// from variable 0
+	final static short	iload_1			= 0x1b;			// ? value loads an
+															// int
+															// value
+	// from variable 1
+	final static short	iload_2			= 0x1c;			// ? value loads an
+															// int
+															// value
+	// from variable 2
+	final static short	iload_3			= 0x1d;			// ? value loads an
+															// int
+															// value
+	// from variable 3
+	final static short	lload_0			= 0x1e;			// ? value load a
+															// long
+															// value
+	// from a local variable 0
+	final static short	lload_1			= 0x1f;			// ? value load a
+															// long
+															// value
+	// from a local variable 1
+	final static short	aload_0			= 0x2a;			// ? objectref loads
+															// a
+															// reference
+	// onto the stack from local
+	// variable 0
+	final static short	aload_1			= 0x2b;			// ? objectref loads
+															// a
+															// reference
+	// onto the stack from local
+	// variable 1
+	final static short	aload_2			= 0x2c;			// ? objectref loads
+															// a
+															// reference
+	// onto the stack from local
+	// variable 2
+	final static short	aload_3			= 0x2d;			// ? objectref loads
+															// a
+															// reference
+	// onto the stack from local
+	// variable 3
+	final static short	iaload			= 0x2e;			// arrayref, index ?
+															// value loads
+	// an int from an array
+	final static short	laload			= 0x2f;			// arrayref, index ?
+															// value load
+	// a long from an array
+	final static short	astore			= 0x3a;			// index objectref ?
+															// stores a
+	// reference into a local
+	// variable #index
+	final static short	istore_0		= 0x3b;			// value ? store int
+															// value into
+	// variable 0
+	final static short	istore_1		= 0x3c;			// value ? store int
+															// value into
+	// variable 1
+	final static short	istore_2		= 0x3d;			// value ? store int
+															// value into
+	// variable 2
+	final static short	istore_3		= 0x3e;			// value ? store int
+															// value into
+	// variable 3
+	final static short	lstore_0		= 0x3f;			// value ? store a
+															// long
+															// value in
+	// a local variable 0
+	final static short	dstore_3		= 0x4a;			// value ? stores a
+															// double into
+	// local variable 3
+	final static short	astore_0		= 0x4b;			// objectref ?
+															// stores a
+	// reference into local variable
+	// 0
+	final static short	astore_1		= 0x4c;			// objectref ?
+															// stores a
+	// reference into local variable
+	// 1
+	final static short	astore_2		= 0x4d;			// objectref ?
+															// stores a
+	// reference into local variable
+	// 2
+	final static short	astore_3		= 0x4e;			// objectref ?
+															// stores a
+	// reference into local variable
+	// 3
+	final static short	iastore			= 0x4f;			// arrayref, index,
+															// value ?
+	// stores an int into an array
+	final static short	dup_x1			= 0x5a;			// value2, value1 ?
+															// value1,
+	// value2, value1 inserts a copy
+	// of the top value into the
+	// stack two values from the top
+	final static short	dup_x2			= 0x5b;			// value3, value2,
+															// value1 ?
+	// value1, value3, value2,
+	// value1 inserts a copy of the
+	// top value into the stack two
+	// (if value2 is double or long
+	// it takes up the entry of
+	// value3, too) or three values
+	// (if value2 is neither double
+	// nor long) from the top
+	final static short	dup2			= 0x5c;			// {value2, value1}
+															// ?
+															// {value2,
+	// value1}, {value2, value1}
+	// duplicate top two stack words
+	// (two values, if value1 is not
+	// double nor long; a single
+	// value, if value1 is double or
+	// long)
+	final static short	dup2_x1			= 0x5d;			// value3, {value2,
+															// value1} ?
+	// {value2, value1}, value3,
+	// {value2, value1} duplicate
+	// two words and insert beneath
+	// third word (see explanation
+	// above)
+	final static short	dup2_x2			= 0x5e;			// {value4, value3},
+															// {value2,
+	// value1} ? {value2, value1},
+	// {value4, value3}, {value2,
+	// value1} duplicate two words
+	// and insert beneath fourth
+	// word
+	final static short	swap			= 0x5f;			// value2, value1 ?
+															// value1,
+	// value2 swaps two top words on
+	// the stack (note that value1
+	// and value2 must not be double
+	// or long)
+	final static short	fmul			= 0x6a;			// value1, value2 ?
+															// result
+	// multiplies two floats
+	final static short	dmul			= 0x6b;			// value1, value2 ?
+															// result
+	// multiplies two doubles
+	final static short	idiv			= 0x6c;			// value1, value2 ?
+															// result
+	// divides two integers
+	final static short	ldiv			= 0x6d;			// value1, value2 ?
+															// result
+	// divide two longs
+	final static short	fdiv			= 0x6e;			// value1, value2 ?
+															// result
+	// divides two floats
+	final static short	ddiv			= 0x6f;			// value1, value2 ?
+															// result
+	// divides two doubles
+	final static short	ishr			= 0x7a;			// value1, value2 ?
+															// result int
+	// shift right
+	final static short	lshr			= 0x7b;			// value1, value2 ?
+															// result
+	// bitwise shift right of a long
+	// value1 by value2 positions
+	final static short	iushr			= 0x7c;			// value1, value2 ?
+															// result int
+	// shift right
+	final static short	lushr			= 0x7d;			// value1, value2 ?
+															// result
+	// bitwise shift right of a long
+	// value1 by value2 positions,
+	// unsigned
+	final static short	iand			= 0x7e;			// value1, value2 ?
+															// result
+	// performs a logical and on two
+	// integers
+	final static short	land			= 0x7f;			// value1, value2 ?
+															// result
+	// bitwise and of two longs
+	final static short	l2d				= 0x8a;			// value ? result
+															// converts a
+	// long to a double
+	final static short	f2i				= 0x8b;			// value ? result
+															// converts a
+	// float to an int
+	final static short	f2l				= 0x8c;			// value ? result
+															// converts a
+	// float to a long
+	final static short	f2d				= 0x8d;			// value ? result
+															// converts a
+	// float to a double
+	final static short	d2i				= 0x8e;			// value ? result
+															// converts a
+	// double to an int
+	final static short	d2l				= 0x8f;			// value ? result
+															// converts a
+	// double to a long
+	final static short	ifne			= 0x9a;			// branchbyte1,
+															// branchbyte2
+	// value ? if value is not 0,
+	// branch to instruction at
+	// branchoffset (signed short
+	// constructed from unsigned
+	// bytes branchbyte1 << 8 +
+	// branchbyte2)
+	final static short	iflt			= 0x9b;			// branchbyte1,
+															// branchbyte2
+	// value ? if value is less than
+	// 0, branch to instruction at
+	// branchoffset (signed short
+	// constructed from unsigned
+	// bytes branchbyte1 << 8 +
+	// branchbyte2)
+	final static short	ifge			= 0x9c;			// branchbyte1,
+															// branchbyte2
+	// value ? if value is greater
+	// than or equal to 0, branch to
+	// instruction at branchoffset
+	// (signed short constructed
+	// from unsigned bytes
+	// branchbyte1 << 8 +
+	// branchbyte2)
+	final static short	ifgt			= 0x9d;			// branchbyte1,
+															// branchbyte2
+	// value ? if value is greater
+	// than 0, branch to instruction
+	// at branchoffset (signed short
+	// constructed from unsigned
+	// bytes branchbyte1 << 8 +
+	// branchbyte2)
+	final static short	ifle			= 0x9e;			// branchbyte1,
+															// branchbyte2
+	// value ? if value is less than
+	// or equal to 0, branch to
+	// instruction at branchoffset
+	// (signed short constructed
+	// from unsigned bytes
+	// branchbyte1 << 8 +
+	// branchbyte2)
+	final static short	if_icmpeq		= 0x9f;			// branchbyte1,
+															// branchbyte2
+	// value1, value2 ? if ints are
+	// equal, branch to instruction
+	// at branchoffset (signed short
+	// constructed from unsigned
+	// bytes branchbyte1 << 8 +
+	// branchbyte2)
+	final static short	if_icmpne		= 0xa0;			// branchbyte1,
+															// branchbyte2
+	// value1, value2 ? if ints are
+	// not equal, branch to
+	// instruction at branchoffset
+	// (signed short constructed
+	// from unsigned bytes
+	// branchbyte1 << 8 +
+	// branchbyte2)
+	final static short	if_icmplt		= 0xa1;			// branchbyte1,
+															// branchbyte2
+	// value1, value2 ? if value1 is
+	// less than value2, branch to
+	// instruction at branchoffset
+	// (signed short constructed
+	// from unsigned bytes
+	// branchbyte1 << 8 +
+	// branchbyte2)
+	final static short	if_icmpge		= 0xa2;			// branchbyte1,
+															// branchbyte2
+	// value1, value2 ? if value1 is
+	// greater than or equal to
+	// value2, branch to instruction
+	// at branchoffset (signed short
+	// constructed from unsigned
+	// bytes branchbyte1 << 8 +
+	// branchbyte2)
+	final static short	if_icmpgt		= 0xa3;			// branchbyte1,
+															// branchbyte2
+	// value1, value2 ? if value1 is
+	// greater than value2, branch
+	// to instruction at
+	// branchoffset (signed short
+	// constructed from unsigned
+	// bytes branchbyte1 << 8 +
+	// branchbyte2)
+	final static short	if_icmple		= 0xa4;			// branchbyte1,
+															// branchbyte2
+	// value1, value2 ? if value1 is
+	// less than or equal to value2,
+	// branch to instruction at
+	// branchoffset (signed short
+	// constructed from unsigned
+	// bytes branchbyte1 << 8 +
+	// branchbyte2)
+	final static short	if_acmpeq		= 0xa5;			// branchbyte1,
+															// branchbyte2
+	// value1, value2 ? if
+	// references are equal, branch
+	// to instruction at
+	// branchoffset (signed short
+	// constructed from unsigned
+	// bytes branchbyte1 << 8 +
+	// branchbyte2)
+	final static short	if_acmpne		= 0xa6;			// branchbyte1,
+															// branchbyte2
+	// value1, value2 ? if
+	// references are not equal,
+	// branch to instruction at
+	// branchoffset (signed short
+	// constructed from unsigned
+	// bytes branchbyte1 << 8 +
+	// branchbyte2)
+	final static short	goto_			= 0xa7;			// branchbyte1,
+															// branchbyte2 [no
+	// change] goes to another
+	// instruction at branchoffset
+	// (signed short constructed
+	// from unsigned bytes
+	// branchbyte1 << 8 +
+	// branchbyte2)
+	final static short	jsr				= 0xa8;			// branchbyte1,
+															// branchbyte2 ?
+	// address jump to subroutine at
+	// branchoffset (signed short
+	// constructed from unsigned
+	// bytes branchbyte1 << 8 +
+	// branchbyte2) and place the
+	// return address on the stack
+	final static short	ret				= 0xa9;			// index [No change]
+															// continue
+	// execution from address taken
+	// from a local variable #index
+	// (the asymmetry with jsr is
+	// intentional)
+	final static short	tableswitch		= 0xaa;			// [0-3 bytes
+															// padding],
+	// defaultbyte1, defaultbyte2,
+	// defaultbyte3, defaultbyte4,
+	// lowbyte1, lowbyte2, lowbyte3,
+	// lowbyte4, highbyte1,
+	// highbyte2, highbyte3,
+	// highbyte4, jump offsets...
+	// index ? continue execution
+	// from an address in the table
+	// at offset index
+	final static short	lookupswitch	= 0xab;			// <0-3 bytes
+															// padding>,
+	// defaultbyte1, defaultbyte2,
+	// defaultbyte3, defaultbyte4,
+	// npairs1, npairs2, npairs3,
+	// npairs4, match-offset
+	// pairs... key ? a target
+	// address is looked up from a
+	// table using a key and
+	// execution continues from the
+	// instruction at that address
+	final static short	ireturn			= 0xac;			// value ? [empty]
+															// returns an
+	// integer from a method
+	final static short	lreturn			= 0xad;			// value ? [empty]
+															// returns a
+	// long value
+	final static short	freturn			= 0xae;			// value ? [empty]
+															// returns a
+	// float
+	final static short	dreturn			= 0xaf;			// value ? [empty]
+															// returns a
+	// double from a method
+	final static short	areturn			= 0xb0;			// objectref ?
+															// [empty]
+															// returns a
+	// reference from a method
+	final static short	return_			= 0xb1;			// ? [empty] return
+															// void
+															// from
+	// method
+	final static short	getstatic		= 0xb2;			// index1, index2 ?
+															// value gets a
+	// static field value of a
+	// class, where the field is
+	// identified by field reference
+	// in the constant pool index
+	// (index1 << 8 + index2)
+	final static short	putstatic		= 0xb3;			// indexbyte1,
+															// indexbyte2 value
+	// ? set static field to value
+	// in a class, where the field
+	// is identified by a field
+	// reference index in constant
+	// pool (indexbyte1 << 8 +
+	// indexbyte2)
+	final static short	getfield		= 0xb4;			// index1, index2
+															// objectref ?
+	// value gets a field value of
+	// an object objectref, where
+	// the field is identified by
+	// field reference in the
+	// constant pool index (index1
+	// << 8 + index2)
+	final static short	putfield		= 0xb5;			// indexbyte1,
+															// indexbyte2
+	// objectref, value ? set field
+	// to value in an object
+	// objectref, where the field is
+	// identified by a field
+	// reference index in constant
+	// pool (indexbyte1 << 8 +
+	// indexbyte2)
+	final static short	invokevirtual	= 0xb6;			// indexbyte1,
+															// indexbyte2
+	// objectref, [arg1, arg2, ...]
+	// ? invoke virtual method on
+	// object objectref, where the
+	// method is identified by
+	// method reference index in
+	// constant pool (indexbyte1 <<
+	// 8 + indexbyte2)
+	final static short	invokespecial	= 0xb7;			// indexbyte1,
+															// indexbyte2
+	// objectref, [arg1, arg2, ...]
+	// ? invoke instance method on
+	// object objectref, where the
+	// method is identified by
+	// method reference index in
+	// constant pool (indexbyte1 <<
+	// 8 + indexbyte2)
+	final static short	invokestatic	= 0xb8;			// indexbyte1,
+															// indexbyte2 [arg1,
+	// arg2, ...] ? invoke a static
+	// method, where the method is
+	// identified by method
+	// reference index in constant
+	// pool (indexbyte1 << 8 +
+	// indexbyte2)
+	final static short	invokeinterface	= 0xb9;			// indexbyte1,
+															// indexbyte2,
+	// count, 0 objectref, [arg1,
+	// arg2, ...] ? invokes an
+	// interface method on object
+	// objectref, where the
+	// interface method is
+	// identified by method
+	// reference index in constant
+	// pool (indexbyte1 << 8 +
+	// indexbyte2)
+	final static short	xxxunusedxxx	= 0xba;			// this opcode is
+															// reserved "for
+	// historical reasons"
+	final static short	new_			= 0xbb;			// indexbyte1,
+															// indexbyte2 ?
+	// objectref creates new object
+	// of type identified by class
+	// reference in constant pool
+	// index (indexbyte1 << 8 +
+	// indexbyte2)
+	final static short	newarray		= 0xbc;			// atype count ?
+															// arrayref
+	// creates new array with count
+	// elements of primitive type
+	// identified by atype
+	final static short	anewarray		= 0xbd;			// indexbyte1,
+															// indexbyte2 count
+	// ? arrayref creates a new
+	// array of references of length
+	// count and component type
+	// identified by the class
+	// reference index (indexbyte1
+	// << 8 + indexbyte2) in the
+	// constant pool
+	final static short	arraylength		= 0xbe;			// arrayref ? length
+															// gets the
+	// length of an array
+	final static short	athrow			= 0xbf;			// objectref ?
+															// [empty],
+	// objectref throws an error or
+	// exception (notice that the
+	// rest of the stack is cleared,
+	// leaving only a reference to
+	// the Throwable)
+	final static short	checkcast		= 0xc0;			// indexbyte1,
+															// indexbyte2
+	// objectref ? objectref checks
+	// whether an objectref is of a
+	// certain type, the class
+	// reference of which is in the
+	// constant pool at index
+	// (indexbyte1 << 8 +
+	// indexbyte2)
+	final static short	instanceof_		= 0xc1;			// indexbyte1,
+															// indexbyte2
+	// objectref ? result determines
+	// if an object objectref is of
+	// a given type, identified by
+	// class reference index in
+	// constant pool (indexbyte1 <<
+	// 8 + indexbyte2)
+	final static short	monitorenter	= 0xc2;			// objectref ? enter
+															// monitor for
+	// object ("grab the lock" -
+	// start of synchronized()
+	// section)
+	final static short	monitorexit		= 0xc3;			// objectref ? exit
+															// monitor for
+	// object ("release the lock" -
+	// end of synchronized()
+	// section)
+	final static short	wide			= 0xc4;			// opcode,
+															// indexbyte1,
+	// indexbyte2
+	final static short	multianewarray	= 0xc5;			// indexbyte1,
+															// indexbyte2,
+	// dimensions count1,
+	// [count2,...] ? arrayref
+	// create a new array of
+	// dimensions dimensions with
+	// elements of type identified
+	// by class reference in
+	// constant pool index
+	// (indexbyte1 << 8 +
+	// indexbyte2); the sizes of
+	// each dimension is identified
+	// by count1, [count2, etc]
+	final static short	ifnull			= 0xc6;			// branchbyte1,
+															// branchbyte2
+	// value ? if value is null,
+	// branch to instruction at
+	// branchoffset (signed short
+	// constructed from unsigned
+	// bytes branchbyte1 << 8 +
+	// branchbyte2)
+	final static short	ifnonnull		= 0xc7;			// branchbyte1,
+															// branchbyte2
+	// value ? if value is not null,
+	// branch to instruction at
+	// branchoffset (signed short
+	// constructed from unsigned
+	// bytes branchbyte1 << 8 +
+	// branchbyte2)
+	final static short	goto_w			= 0xc8;			// branchbyte1,
+															// branchbyte2,
+	// branchbyte3, branchbyte4 [no
+	// change] goes to another
+	// instruction at branchoffset
+	// (signed int constructed from
+	// unsigned bytes branchbyte1 <<
+	// 24 + branchbyte2 << 16 +
+	// branchbyte3 << 8 +
+	// branchbyte4)
+	final static short	jsr_w			= 0xc9;			// branchbyte1,
+															// branchbyte2,
+	// branchbyte3, branchbyte4 ?
+	// address jump to subroutine at
+	// branchoffset (signed int
+	// constructed from unsigned
+	// bytes branchbyte1 << 24 +
+	// branchbyte2 << 16 +
+	// branchbyte3 << 8 +
+	// branchbyte4) and place the
+	// return address on the stack
+	final static short	breakpoint		= 0xca;			// reserved for
+															// breakpoints in
+	// Java debuggers; should not
+	// appear in any class file
+	final static short	impdep1			= 0xfe;			// reserved for
+	// implementation-dependent
+	// operations within debuggers;
+	// should not appear in any
+	// class file
+	final static short	impdep2			= 0xff;			// reserved for
+	// implementation-dependent
+	// operations within debuggers;
+	// should not appear in any
+	// class file
+
+	final static byte	OFFSETS[]		= new byte[256];
+
+	static {
+		OFFSETS[bipush] = 1; // byte ? value pushes a byte onto the
+		// stack as an integer value
+		OFFSETS[sipush] = 2; // byte1, byte2 ? value pushes a signed
+		// integer (byte1 << 8 + byte2) onto the
+		// stack
+		OFFSETS[ldc] = 1; // index ? value pushes a constant
+		// #index from a constant pool (String,
+		// int, float or class type) onto the
+		// stack
+		OFFSETS[ldc_w] = 2; // indexbyte1, indexbyte2 ? value pushes
+		// a constant #index from a constant
+		// pool (String, int, float or class
+		// type) onto the stack (wide index is
+		// constructed as indexbyte1 << 8 +
+		// indexbyte2)
+		OFFSETS[ldc2_w] = 2; // indexbyte1, indexbyte2 ? value pushes
+		// a constant #index from a constant
+		// pool (double or long) onto the stack
+		// (wide index is constructed as
+		// indexbyte1 << 8 + indexbyte2)
+		OFFSETS[iload] = 1; // index ? value loads an int value from
+		// a variable #index
+		OFFSETS[lload] = 1; // index ? value load a long value from
+		// a local variable #index
+		OFFSETS[fload] = 1; // index ? value loads a float value
+		// from a local variable #index
+		OFFSETS[dload] = 1; // index ? value loads a double value
+		// from a local variable #index
+		OFFSETS[aload] = 1; // index ? objectref loads a reference
+		// onto the stack from a local variable
+		// #index
+		OFFSETS[istore] = 1; // index value ? store int value into
+		// variable #index
+		OFFSETS[lstore] = 1; // index value ? store a long value in a
+		// local variable #index
+		OFFSETS[fstore] = 1; // index value ? stores a float value
+		// into a local variable #index
+		OFFSETS[dstore] = 1; // index value ? stores a double value
+		// into a local variable #index
+		OFFSETS[iinc] = 2; // index, const [No change] increment
+		// local variable #index by signed byte
+		// const
+		OFFSETS[ifeq] = 2; // branchbyte1, branchbyte2 value ? if
+		// value is 0, branch to instruction at
+		// branchoffset (signed short
+		// constructed from unsigned bytes
+		// branchbyte1 << 8 + branchbyte2)
+		OFFSETS[astore] = 1; // index objectref ? stores a reference
+		// into a local variable #index
+		OFFSETS[ifne] = 2; // branchbyte1, branchbyte2 value ? if
+		// value is not 0, branch to instruction
+		// at branchoffset (signed short
+		// constructed from unsigned bytes
+		// branchbyte1 << 8 + branchbyte2)
+		OFFSETS[iflt] = 2; // branchbyte1, branchbyte2 value ? if
+		// value is less than 0, branch to
+		// instruction at branchoffset (signed
+		// short constructed from unsigned bytes
+		// branchbyte1 << 8 + branchbyte2)
+		OFFSETS[ifge] = 2; // branchbyte1, branchbyte2 value ? if
+		// value is greater than or equal to 0,
+		// branch to instruction at branchoffset
+		// (signed short constructed from
+		// unsigned bytes branchbyte1 << 8 +
+		// branchbyte2)
+		OFFSETS[ifgt] = 2; // branchbyte1, branchbyte2 value ? if
+		// value is greater than 0, branch to
+		// instruction at branchoffset (signed
+		// short constructed from unsigned bytes
+		// branchbyte1 << 8 + branchbyte2)
+		OFFSETS[ifle] = 2; // branchbyte1, branchbyte2 value ? if
+		// value is less than or equal to 0,
+		// branch to instruction at branchoffset
+		// (signed short constructed from
+		// unsigned bytes branchbyte1 << 8 +
+		// branchbyte2)
+		OFFSETS[if_icmpeq] = 2; // branchbyte1, branchbyte2 value1,
+		// value2 ? if ints are equal,
+		// branch to instruction at
+		// branchoffset (signed short
+		// constructed from unsigned bytes
+		// branchbyte1 << 8 + branchbyte2)
+		OFFSETS[if_icmpne] = 2; // branchbyte1, branchbyte2 value1,
+		// value2 ? if ints are not equal,
+		// branch to instruction at
+		// branchoffset (signed short
+		// constructed from unsigned bytes
+		// branchbyte1 << 8 + branchbyte2)
+		OFFSETS[if_icmplt] = 2; // branchbyte1, branchbyte2 value1,
+		// value2 ? if value1 is less than
+		// value2, branch to instruction at
+		// branchoffset (signed short
+		// constructed from unsigned bytes
+		// branchbyte1 << 8 + branchbyte2)
+		OFFSETS[if_icmpge] = 2; // branchbyte1, branchbyte2 value1,
+		// value2 ? if value1 is greater
+		// than or equal to value2, branch
+		// to instruction at branchoffset
+		// (signed short constructed from
+		// unsigned bytes branchbyte1 << 8 +
+		// branchbyte2)
+		OFFSETS[if_icmpgt] = 2; // branchbyte1, branchbyte2 value1,
+		// value2 ? if value1 is greater
+		// than value2, branch to
+		// instruction at branchoffset
+		// (signed short constructed from
+		// unsigned bytes branchbyte1 << 8 +
+		// branchbyte2)
+		OFFSETS[if_icmple] = 2; // branchbyte1, branchbyte2 value1,
+		// value2 ? if value1 is less than
+		// or equal to value2, branch to
+		// instruction at branchoffset
+		// (signed short constructed from
+		// unsigned bytes branchbyte1 << 8 +
+		// branchbyte2)
+		OFFSETS[if_acmpeq] = 2; // branchbyte1, branchbyte2 value1,
+		// value2 ? if references are equal,
+		// branch to instruction at
+		// branchoffset (signed short
+		// constructed from unsigned bytes
+		// branchbyte1 << 8 + branchbyte2)
+		OFFSETS[if_acmpne] = 2; // branchbyte1, branchbyte2 value1,
+		// value2 ? if references are not
+		// equal, branch to instruction at
+		// branchoffset (signed short
+		// constructed from unsigned bytes
+		// branchbyte1 << 8 + branchbyte2)
+		OFFSETS[goto_] = 2; // branchbyte1, branchbyte2 [no change]
+		// goes to another instruction at
+		// branchoffset (signed short
+		// constructed from unsigned bytes
+		// branchbyte1 << 8 + branchbyte2)
+		OFFSETS[jsr] = 2; // branchbyte1, branchbyte2 ? address
+		// jump to subroutine at branchoffset
+		// (signed short constructed from
+		// unsigned bytes branchbyte1 << 8 +
+		// branchbyte2) and place the return
+		// address on the stack
+		OFFSETS[ret] = 1; // index [No change] continue execution
+		// from address taken from a local
+		// variable #index (the asymmetry with
+		// jsr is intentional)
+		OFFSETS[tableswitch] = -1; // [0-3 bytes padding],
+		// defaultbyte1, defaultbyte2,
+		// defaultbyte3, defaultbyte4,
+		// lowbyte1, lowbyte2, lowbyte3,
+		// lowbyte4, highbyte1,
+		// highbyte2, highbyte3,
+		// highbyte4, jump offsets...
+		// index ? continue execution
+		// from an address in the table
+		// at offset index
+		OFFSETS[lookupswitch] = -1; // <0-3 bytes padding>,
+		// defaultbyte1, defaultbyte2,
+		// defaultbyte3, defaultbyte4,
+		// npairs1, npairs2, npairs3,
+		// npairs4, match-offset
+		// pairs... key ? a target
+		// address is looked up from a
+		// table using a key and
+		// execution continues from the
+		// instruction at that address
+		OFFSETS[getstatic] = 2; // index1, index2 ? value gets a
+		// static field value of a class,
+		// where the field is identified by
+		// field reference in the constant
+		// pool index (index1 << 8 + index2)
+		OFFSETS[putstatic] = 2; // indexbyte1, indexbyte2 value ?
+		// set static field to value in a
+		// class, where the field is
+		// identified by a field reference
+		// index in constant pool
+		// (indexbyte1 << 8 + indexbyte2)
+		OFFSETS[getfield] = 2; // index1, index2 objectref ? value
+		// gets a field value of an object
+		// objectref, where the field is
+		// identified by field reference in
+		// the constant pool index (index1
+		// << 8 + index2)
+		OFFSETS[putfield] = 2; // indexbyte1, indexbyte2 objectref,
+		// value ? set field to value in an
+		// object objectref, where the field
+		// is identified by a field
+		// reference index in constant pool
+		// (indexbyte1 << 8 + indexbyte2)
+		OFFSETS[invokevirtual] = 2; // indexbyte1, indexbyte2
+		// objectref, [arg1, arg2, ...]
+		// ? invoke virtual method on
+		// object objectref, where the
+		// method is identified by
+		// method reference index in
+		// constant pool (indexbyte1 <<
+		// 8 + indexbyte2)
+		OFFSETS[invokespecial] = 2; // indexbyte1, indexbyte2
+		// objectref, [arg1, arg2, ...]
+		// ? invoke instance method on
+		// object objectref, where the
+		// method is identified by
+		// method reference index in
+		// constant pool (indexbyte1 <<
+		// 8 + indexbyte2)
+		OFFSETS[invokestatic] = 2; // indexbyte1, indexbyte2 [arg1,
+		// arg2, ...] ? invoke a static
+		// method, where the method is
+		// identified by method
+		// reference index in constant
+		// pool (indexbyte1 << 8 +
+		// indexbyte2)
+		OFFSETS[invokeinterface] = 2; // indexbyte1, indexbyte2,
+		// count, 0 objectref,
+		// [arg1, arg2, ...] ?
+		// invokes an interface
+		// method on object
+		// objectref, where the
+		// interface method is
+		// identified by method
+		// reference index in
+		// constant pool (indexbyte1
+		// << 8 + indexbyte2)
+		OFFSETS[new_] = 2; // indexbyte1, indexbyte2 ? objectref
+		// creates new object of type identified
+		// by class reference in constant pool
+		// index (indexbyte1 << 8 + indexbyte2)
+		OFFSETS[newarray] = 1; // atype count ? arrayref creates
+		// new array with count elements of
+		// primitive type identified by
+		// atype
+		OFFSETS[anewarray] = 2; // indexbyte1, indexbyte2 count ?
+		// arrayref creates a new array of
+		// references of length count and
+		// component type identified by the
+		// class reference index (indexbyte1
+		// << 8 + indexbyte2) in the
+		// constant pool
+		OFFSETS[checkcast] = 2; // indexbyte1, indexbyte2 objectref
+		// ? objectref checks whether an
+		// objectref is of a certain type,
+		// the class reference of which is
+		// in the constant pool at index
+		// (indexbyte1 << 8 + indexbyte2)
+		OFFSETS[instanceof_] = 2; // indexbyte1, indexbyte2 objectref
+		// ? result determines if an object
+		// objectref is of a given type,
+		// identified by class reference
+		// index in constant pool
+		// (indexbyte1 << 8 + indexbyte2)
+		OFFSETS[wide] = 3; // opcode, indexbyte1, indexbyte2
+		OFFSETS[multianewarray] = 3; // indexbyte1, indexbyte2,
+		// dimensions count1,
+		// [count2,...] ? arrayref
+		// create a new array of
+		// dimensions dimensions with
+		// elements of type identified
+		// by class reference in
+		// constant pool index
+		// (indexbyte1 << 8 +
+		// indexbyte2); the sizes of
+		// each dimension is identified
+		// by count1, [count2, etc]
+		OFFSETS[ifnull] = 2; // branchbyte1, branchbyte2 value ? if
+		// value is null, branch to instruction
+		// at branchoffset (signed short
+		// constructed from unsigned bytes
+		// branchbyte1 << 8 + branchbyte2)
+		OFFSETS[ifnonnull] = 2; // branchbyte1, branchbyte2 value ?
+		// if value is not null, branch to
+		// instruction at branchoffset
+		// (signed short constructed from
+		// unsigned bytes branchbyte1 << 8 +
+		// branchbyte2)
+		OFFSETS[goto_w] = 4; // branchbyte1, branchbyte2,
+		// branchbyte3, branchbyte4 [no change]
+		// goes to another instruction at
+		// branchoffset (signed int constructed
+		// from unsigned bytes branchbyte1 << 24
+		// + branchbyte2 << 16 + branchbyte3 <<
+		// 8 + branchbyte4)
+		OFFSETS[jsr_w] = 4; // branchbyte1, branchbyte2,
+		// branchbyte3, branchbyte4 ? address
+		// jump to subroutine at branchoffset
+		// (signed int constructed from unsigned
+		// bytes branchbyte1 << 24 + branchbyte2
+		// << 16 + branchbyte3 << 8 +
+		// branchbyte4) and place the return
+		// address on the stack
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/Packages.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/Packages.java
new file mode 100644
index 0000000..a7f6290
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/Packages.java
@@ -0,0 +1,235 @@
+package aQute.bnd.osgi;
+
+import java.util.*;
+
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.Descriptors.PackageRef;
+
+public class Packages implements Map<PackageRef,Attrs> {
+	private LinkedHashMap<PackageRef,Attrs>	map;
+	static Map<PackageRef,Attrs>			EMPTY	= Collections.emptyMap();
+
+	public Packages(Packages other) {
+		if (other.map != null) {
+			map = new LinkedHashMap<Descriptors.PackageRef,Attrs>(other.map);
+		}
+	}
+
+	public Packages() {}
+
+	public void clear() {
+		if (map != null)
+			map.clear();
+	}
+
+	public boolean containsKey(PackageRef name) {
+		if (map == null)
+			return false;
+
+		return map.containsKey(name);
+	}
+
+	@Deprecated
+	public boolean containsKey(Object name) {
+		assert name instanceof PackageRef;
+		if (map == null)
+			return false;
+
+		return map.containsKey(name);
+	}
+
+	public boolean containsValue(Attrs value) {
+		if (map == null)
+			return false;
+
+		return map.containsValue(value);
+	}
+
+	@Deprecated
+	public boolean containsValue(Object value) {
+		assert value instanceof Attrs;
+		if (map == null)
+			return false;
+
+		return map.containsValue(value);
+	}
+
+	public Set<java.util.Map.Entry<PackageRef,Attrs>> entrySet() {
+		if (map == null)
+			return EMPTY.entrySet();
+
+		return map.entrySet();
+	}
+
+	@Deprecated
+	public Attrs get(Object key) {
+		assert key instanceof PackageRef;
+		if (map == null)
+			return null;
+
+		return map.get(key);
+	}
+
+	public Attrs get(PackageRef key) {
+		if (map == null)
+			return null;
+
+		return map.get(key);
+	}
+
+	public boolean isEmpty() {
+		return map == null || map.isEmpty();
+	}
+
+	public Set<PackageRef> keySet() {
+		if (map == null)
+			return EMPTY.keySet();
+
+		return map.keySet();
+	}
+
+	public Attrs put(PackageRef ref) {
+		Attrs attrs = get(ref);
+		if (attrs != null)
+			return attrs;
+
+		attrs = new Attrs();
+		put(ref, attrs);
+		return attrs;
+	}
+
+	public Attrs put(PackageRef key, Attrs value) {
+		if (map == null)
+			map = new LinkedHashMap<PackageRef,Attrs>();
+
+		return map.put(key, value);
+	}
+
+	public void putAll(Map< ? extends PackageRef, ? extends Attrs> map) {
+		if (this.map == null) {
+			if (map.isEmpty())
+				return;
+			this.map = new LinkedHashMap<PackageRef,Attrs>();
+		}
+		this.map.putAll(map);
+	}
+
+	public void putAllIfAbsent(Map<PackageRef, ? extends Attrs> map) {
+		for (Map.Entry<PackageRef, ? extends Attrs> entry : map.entrySet()) {
+			if (!containsKey(entry.getKey()))
+				put(entry.getKey(), entry.getValue());
+		}
+	}
+
+	@Deprecated
+	public Attrs remove(Object var0) {
+		assert var0 instanceof PackageRef;
+		if (map == null)
+			return null;
+
+		return map.remove(var0);
+	}
+
+	public Attrs remove(PackageRef var0) {
+		if (map == null)
+			return null;
+		return map.remove(var0);
+	}
+
+	public int size() {
+		if (map == null)
+			return 0;
+		return map.size();
+	}
+
+	public Collection<Attrs> values() {
+		if (map == null)
+			return EMPTY.values();
+
+		return map.values();
+	}
+
+	public Attrs getByFQN(String s) {
+		if (map == null)
+			return null;
+
+		for (Map.Entry<PackageRef,Attrs> pr : map.entrySet()) {
+			if (pr.getKey().getFQN().equals(s))
+				return pr.getValue();
+		}
+		return null;
+	}
+
+	public Attrs getByBinaryName(String s) {
+		if (map == null)
+			return null;
+
+		for (Map.Entry<PackageRef,Attrs> pr : map.entrySet()) {
+			if (pr.getKey().getBinary().equals(s))
+				pr.getValue();
+		}
+		return null;
+	}
+
+	public boolean containsFQN(String s) {
+		return getByFQN(s) != null;
+	}
+
+	public boolean containsBinaryName(String s) {
+		return getByFQN(s) != null;
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		append(sb);
+		return sb.toString();
+	}
+
+	public void append(StringBuilder sb) {
+		String del = "";
+		for (Map.Entry<PackageRef,Attrs> s : entrySet()) {
+			sb.append(del);
+			sb.append(s.getKey());
+			if (!s.getValue().isEmpty()) {
+				sb.append(';');
+				s.getValue().append(sb);
+			}
+			del = ",";
+		}
+	}
+
+	public void merge(PackageRef ref, boolean unique, Attrs... attrs) {
+		if (unique) {
+			while (containsKey(ref))
+				ref = ref.getDuplicate();
+		}
+
+		Attrs org = put(ref);
+		for (Attrs a : attrs) {
+			if (a != null)
+				org.putAll(a);
+		}
+	}
+
+	public Attrs get(PackageRef packageRef, Attrs deflt) {
+		Attrs mine = get(packageRef);
+		if (mine != null)
+			return mine;
+
+		return deflt;
+	}
+
+	@Override
+	@Deprecated
+	public boolean equals(Object other) {
+		return super.equals(other);
+	}
+
+	@Override
+	@Deprecated
+	public int hashCode() {
+		return super.hashCode();
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/PreprocessResource.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/PreprocessResource.java
new file mode 100644
index 0000000..c1f847c
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/PreprocessResource.java
@@ -0,0 +1,46 @@
+package aQute.bnd.osgi;
+
+import java.io.*;
+
+public class PreprocessResource extends AbstractResource {
+	final Resource	resource;
+	final Processor	processor;
+
+	public PreprocessResource(Processor processor, Resource r) {
+		super(r.lastModified());
+		this.processor = processor;
+		this.resource = r;
+		setExtra(resource.getExtra());
+	}
+
+	@Override
+	protected byte[] getBytes() throws Exception {
+		ByteArrayOutputStream bout = new ByteArrayOutputStream(2000);
+		OutputStreamWriter osw = new OutputStreamWriter(bout, Constants.DEFAULT_CHARSET);
+		PrintWriter pw = new PrintWriter(osw);
+		InputStream in = null;
+		BufferedReader rdr = null;
+		try {
+			in = resource.openInputStream();
+			rdr = new BufferedReader(new InputStreamReader(in, "UTF8"));
+			String line = rdr.readLine();
+			while (line != null) {
+				line = processor.getReplacer().process(line);
+				pw.println(line);
+				line = rdr.readLine();
+			}
+			pw.flush();
+			byte[] data = bout.toByteArray();
+			return data;
+
+		}
+		finally {
+			if (rdr != null) {
+				rdr.close();
+			}
+			if (in != null) {
+				in.close();
+			}
+		}
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/Processor.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/Processor.java
new file mode 100755
index 0000000..1e6c802
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/Processor.java
@@ -0,0 +1,1780 @@
+package aQute.bnd.osgi;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.concurrent.*;
+import java.util.jar.*;
+import java.util.regex.*;
+
+import aQute.bnd.header.*;
+import aQute.bnd.service.*;
+import aQute.bnd.version.*;
+import aQute.lib.collections.*;
+import aQute.lib.io.*;
+import aQute.libg.generics.*;
+import aQute.service.reporter.*;
+
+public class Processor extends Domain implements Reporter, Registry, Constants, Closeable {
+
+	static ThreadLocal<Processor>	current			= new ThreadLocal<Processor>();
+	static ExecutorService			executor		= Executors.newCachedThreadPool();
+	static Random					random			= new Random();
+
+	// TODO handle include files out of date
+	// TODO make splitter skip eagerly whitespace so trim is not necessary
+	public final static String		LIST_SPLITTER	= "\\s*,\\s*";
+	final List<String>				errors			= new ArrayList<String>();
+	final List<String>				warnings		= new ArrayList<String>();
+	final Set<Object>				basicPlugins	= new HashSet<Object>();
+	private final Set<Closeable>	toBeClosed		= new HashSet<Closeable>();
+	Set<Object>						plugins;
+
+	boolean							pedantic;
+	boolean							trace;
+	boolean							exceptions;
+	boolean							fileMustExist	= true;
+
+	private File					base			= new File("").getAbsoluteFile();
+
+	Properties						properties;
+	String							profile;
+	private Macro					replacer;
+	private long					lastModified;
+	private File					propertiesFile;
+	private boolean					fixup			= true;
+	long							modified;
+	Processor						parent;
+	List<File>						included;
+
+	CL								pluginLoader;
+	Collection<String>				filter;
+	HashSet<String>					missingCommand;
+
+	public Processor() {
+		properties = new Properties();
+	}
+
+	public Processor(Properties parent) {
+		properties = new Properties(parent);
+	}
+
+	public Processor(Processor child) {
+		this(child.properties);
+		this.parent = child;
+	}
+
+	public void setParent(Processor processor) {
+		this.parent = processor;
+		Properties ext = new Properties(processor.properties);
+		ext.putAll(this.properties);
+		this.properties = ext;
+	}
+
+	public Processor getParent() {
+		return parent;
+	}
+
+	public Processor getTop() {
+		if (parent == null)
+			return this;
+		return parent.getTop();
+	}
+
+	public void getInfo(Reporter processor, String prefix) {
+		if (isFailOk())
+			addAll(warnings, processor.getErrors(), prefix);
+		else
+			addAll(errors, processor.getErrors(), prefix);
+		addAll(warnings, processor.getWarnings(), prefix);
+
+		processor.getErrors().clear();
+		processor.getWarnings().clear();
+	}
+
+	public void getInfo(Reporter processor) {
+		getInfo(processor, "");
+	}
+
+	private <T> void addAll(List<String> to, List< ? extends T> from, String prefix) {
+		for (T x : from) {
+			to.add(prefix + x);
+		}
+	}
+
+	/**
+	 * A processor can mark itself current for a thread.
+	 * 
+	 * @return
+	 */
+	private Processor current() {
+		Processor p = current.get();
+		if (p == null)
+			return this;
+		return p;
+	}
+
+	public SetLocation warning(String string, Object... args) {
+		Processor p = current();
+		String s = formatArrays(string, args);
+		if (!p.warnings.contains(s))
+			p.warnings.add(s);
+		p.signal();
+		return location(s);
+	}
+
+	public SetLocation error(String string, Object... args) {
+		Processor p = current();
+		try {
+			if (p.isFailOk())
+				return p.warning(string, args);
+			String s = formatArrays(string, args == null ? new Object[0] : args);
+			if (!p.errors.contains(s))
+				p.errors.add(s);
+			return location(s);
+		}
+		finally {
+			p.signal();
+		}
+	}
+
+	public void progress(float progress, String format, Object... args) {
+		format = String.format("[%2d] %s", (int) progress, format);
+		trace(format, args);
+	}
+
+	public void progress(String format, Object... args) {
+		progress(-1f, format, args);
+	}
+
+	public SetLocation exception(Throwable t, String format, Object... args) {
+		return error(format, t, args);
+	}
+
+	public SetLocation error(String string, Throwable t, Object... args) {
+		Processor p = current();
+		try {
+			if (p.exceptions)
+				t.printStackTrace();
+			if (p.isFailOk()) {
+				return p.warning(string + ": " + t, args);
+			}
+			p.errors.add("Exception: " + t.getMessage());
+			String s = formatArrays(string, args == null ? new Object[0] : args);
+			if (!p.errors.contains(s))
+				p.errors.add(s);
+			return location(s);
+		}
+		finally {
+			p.signal();
+		}
+	}
+
+	public void signal() {}
+
+	public List<String> getWarnings() {
+		return warnings;
+	}
+
+	public List<String> getErrors() {
+		return errors;
+	}
+
+	/**
+	 * Standard OSGi header parser.
+	 * 
+	 * @param value
+	 * @return
+	 */
+	static public Parameters parseHeader(String value, Processor logger) {
+		return new Parameters(value, logger);
+	}
+
+	public Parameters parseHeader(String value) {
+		return new Parameters(value, this);
+	}
+
+	public void addClose(Closeable jar) {
+		assert jar != null;
+		toBeClosed.add(jar);
+	}
+
+	public void removeClose(Closeable jar) {
+		assert jar != null;
+		toBeClosed.remove(jar);
+	}
+
+	public boolean isPedantic() {
+		return current().pedantic;
+	}
+
+	public void setPedantic(boolean pedantic) {
+		this.pedantic = pedantic;
+	}
+
+	public void use(Processor reporter) {
+		setPedantic(reporter.isPedantic());
+		setTrace(reporter.isTrace());
+		setBase(reporter.getBase());
+		setFailOk(reporter.isFailOk());
+	}
+
+	public static File getFile(File base, String file) {
+		return IO.getFile(base, file);
+	}
+
+	public File getFile(String file) {
+		return getFile(base, file);
+	}
+
+	/**
+	 * Return a list of plugins that implement the given class.
+	 * 
+	 * @param clazz
+	 *            Each returned plugin implements this class/interface
+	 * @return A list of plugins
+	 */
+	public <T> List<T> getPlugins(Class<T> clazz) {
+		List<T> l = new ArrayList<T>();
+		Set<Object> all = getPlugins();
+		for (Object plugin : all) {
+			if (clazz.isInstance(plugin))
+				l.add(clazz.cast(plugin));
+		}
+		return l;
+	}
+
+	/**
+	 * Returns the first plugin it can find of the given type.
+	 * 
+	 * @param <T>
+	 * @param clazz
+	 * @return
+	 */
+	public <T> T getPlugin(Class<T> clazz) {
+		Set<Object> all = getPlugins();
+		for (Object plugin : all) {
+			if (clazz.isInstance(plugin))
+				return clazz.cast(plugin);
+		}
+		return null;
+	}
+
+	/**
+	 * Return a list of plugins. Plugins are defined with the -plugin command.
+	 * They are class names, optionally associated with attributes. Plugins can
+	 * implement the Plugin interface to see these attributes. Any object can be
+	 * a plugin.
+	 * 
+	 * @return
+	 */
+	protected synchronized Set<Object> getPlugins() {
+		if (this.plugins != null)
+			return this.plugins;
+
+		missingCommand = new HashSet<String>();
+		Set<Object> list = new LinkedHashSet<Object>();
+
+		// The owner of the plugin is always in there.
+		list.add(this);
+		setTypeSpecificPlugins(list);
+
+		if (parent != null)
+			list.addAll(parent.getPlugins());
+
+		// We only use plugins now when they are defined on our level
+		// and not if it is in our parent. We inherit from our parent
+		// through the previous block.
+
+		if (properties.containsKey(PLUGIN)) {
+			String spe = getProperty(PLUGIN);
+			if (spe.equals(NONE))
+				return new LinkedHashSet<Object>();
+
+			String pluginPath = getProperty(PLUGINPATH);
+			loadPlugins(list, spe, pluginPath);
+		}
+
+		return this.plugins = list;
+	}
+
+	/**
+	 * @param list
+	 * @param spe
+	 */
+	protected void loadPlugins(Set<Object> list, String spe, String pluginPath) {
+		Parameters plugins = new Parameters(spe);
+		CL loader = getLoader();
+
+		// First add the plugin-specific paths from their path: directives
+		for (Entry<String,Attrs> entry : plugins.entrySet()) {
+			String key = removeDuplicateMarker(entry.getKey());
+			String path = entry.getValue().get(PATH_DIRECTIVE);
+			if (path != null) {
+				String parts[] = path.split("\\s*,\\s*");
+				try {
+					for (String p : parts) {
+						File f = getFile(p).getAbsoluteFile();
+						loader.add(f.toURI().toURL());
+					}
+				}
+				catch (Exception e) {
+					error("Problem adding path %s to loader for plugin %s. Exception: (%s)", path, key, e);
+				}
+			}
+		}
+
+		// Next add -pluginpath entries
+		if (pluginPath != null && pluginPath.length() > 0) {
+			StringTokenizer tokenizer = new StringTokenizer(pluginPath, ",");
+			while (tokenizer.hasMoreTokens()) {
+				String path = tokenizer.nextToken().trim();
+				try {
+					File f = getFile(path).getAbsoluteFile();
+					loader.add(f.toURI().toURL());
+				}
+				catch (Exception e) {
+					error("Problem adding path %s from global plugin path. Exception: %s", path, e);
+				}
+			}
+		}
+
+		// Load the plugins
+		for (Entry<String,Attrs> entry : plugins.entrySet()) {
+			String key = entry.getKey();
+
+			try {
+				trace("Using plugin %s", key);
+
+				// Plugins could use the same class with different
+				// parameters so we could have duplicate names Remove
+				// the ! added by the parser to make each name unique.
+				key = removeDuplicateMarker(key);
+
+				try {
+					Class< ? > c = loader.loadClass(key);
+					Object plugin = c.newInstance();
+					customize(plugin, entry.getValue());
+					if (plugin instanceof Closeable) {
+						addClose((Closeable) plugin);
+					}
+					list.add(plugin);
+				}
+				catch (Throwable t) {
+					// We can defer the error if the plugin specifies
+					// a command name. In that case, we'll verify that
+					// a bnd file does not contain any references to a
+					// plugin
+					// command. The reason this feature was added was
+					// to compile plugin classes with the same build.
+					String commands = entry.getValue().get(COMMAND_DIRECTIVE);
+					if (commands == null)
+						error("Problem loading the plugin: %s exception: (%s)", key, t);
+					else {
+						Collection<String> cs = split(commands);
+						missingCommand.addAll(cs);
+					}
+				}
+			}
+			catch (Throwable e) {
+				error("Problem loading the plugin: %s exception: (%s)", key, e);
+			}
+		}
+	}
+
+	protected void setTypeSpecificPlugins(Set<Object> list) {
+		list.add(executor);
+		list.add(random);
+		list.addAll(basicPlugins);
+	}
+
+	/**
+	 * @param plugin
+	 * @param entry
+	 */
+	protected <T> T customize(T plugin, Attrs map) {
+		if (plugin instanceof Plugin) {
+			if (map != null)
+				((Plugin) plugin).setProperties(map);
+
+			((Plugin) plugin).setReporter(this);
+		}
+		if (plugin instanceof RegistryPlugin) {
+			((RegistryPlugin) plugin).setRegistry(this);
+		}
+		return plugin;
+	}
+
+	@Override
+	public boolean isFailOk() {
+		String v = getProperty(Analyzer.FAIL_OK, null);
+		return v != null && v.equalsIgnoreCase("true");
+	}
+
+	public File getBase() {
+		return base;
+	}
+
+	public void setBase(File base) {
+		this.base = base;
+	}
+
+	public void clear() {
+		errors.clear();
+		warnings.clear();
+	}
+
+	public void trace(String msg, Object... parms) {
+		Processor p = current();
+		if (p.trace) {
+			System.err.printf("# " + msg + "%n", parms);
+		}
+	}
+
+	public <T> List<T> newList() {
+		return new ArrayList<T>();
+	}
+
+	public <T> Set<T> newSet() {
+		return new TreeSet<T>();
+	}
+
+	public static <K, V> Map<K,V> newMap() {
+		return new LinkedHashMap<K,V>();
+	}
+
+	public static <K, V> Map<K,V> newHashMap() {
+		return new LinkedHashMap<K,V>();
+	}
+
+	public <T> List<T> newList(Collection<T> t) {
+		return new ArrayList<T>(t);
+	}
+
+	public <T> Set<T> newSet(Collection<T> t) {
+		return new TreeSet<T>(t);
+	}
+
+	public <K, V> Map<K,V> newMap(Map<K,V> t) {
+		return new LinkedHashMap<K,V>(t);
+	}
+
+	public void close() {
+		for (Closeable c : toBeClosed) {
+			try {
+				c.close();
+			}
+			catch (IOException e) {
+				// Who cares?
+			}
+		}
+		toBeClosed.clear();
+	}
+
+	public String _basedir(@SuppressWarnings("unused")
+	String args[]) {
+		if (base == null)
+			throw new IllegalArgumentException("No base dir set");
+
+		return base.getAbsolutePath();
+	}
+
+	/**
+	 * Property handling ...
+	 * 
+	 * @return
+	 */
+
+	public Properties getProperties() {
+		if (fixup) {
+			fixup = false;
+			begin();
+		}
+
+		return properties;
+	}
+
+	public String getProperty(String key) {
+		return getProperty(key, null);
+	}
+
+	public void mergeProperties(File file, boolean override) {
+		if (file.isFile()) {
+			try {
+				Properties properties = loadProperties(file);
+				mergeProperties(properties, override);
+			}
+			catch (Exception e) {
+				error("Error loading properties file: " + file);
+			}
+		} else {
+			if (!file.exists())
+				error("Properties file does not exist: " + file);
+			else
+				error("Properties file must a file, not a directory: " + file);
+		}
+	}
+
+	public void mergeProperties(Properties properties, boolean override) {
+		for (Enumeration< ? > e = properties.propertyNames(); e.hasMoreElements();) {
+			String key = (String) e.nextElement();
+			String value = properties.getProperty(key);
+			if (override || !getProperties().containsKey(key))
+				setProperty(key, value);
+		}
+	}
+
+	public void setProperties(Properties properties) {
+		doIncludes(getBase(), properties);
+		this.properties.putAll(properties);
+	}
+
+	public void addProperties(File file) throws Exception {
+		addIncluded(file);
+		Properties p = loadProperties(file);
+		setProperties(p);
+	}
+
+	public void addProperties(Map< ? , ? > properties) {
+		for (Entry< ? , ? > entry : properties.entrySet()) {
+			setProperty(entry.getKey().toString(), entry.getValue() + "");
+		}
+	}
+
+	public synchronized void addIncluded(File file) {
+		if (included == null)
+			included = new ArrayList<File>();
+		included.add(file);
+	}
+
+	/**
+	 * Inspect the properties and if you find -includes parse the line included
+	 * manifest files or properties files. The files are relative from the given
+	 * base, this is normally the base for the analyzer.
+	 * 
+	 * @param ubase
+	 * @param p
+	 * @param done
+	 * @throws IOException
+	 * @throws IOException
+	 */
+
+	private void doIncludes(File ubase, Properties p) {
+		String includes = p.getProperty(INCLUDE);
+		if (includes != null) {
+			includes = getReplacer().process(includes);
+			p.remove(INCLUDE);
+			Collection<String> clauses = new Parameters(includes).keySet();
+
+			for (String value : clauses) {
+				boolean fileMustExist = true;
+				boolean overwrite = true;
+				while (true) {
+					if (value.startsWith("-")) {
+						fileMustExist = false;
+						value = value.substring(1).trim();
+					} else if (value.startsWith("~")) {
+						// Overwrite properties!
+						overwrite = false;
+						value = value.substring(1).trim();
+					} else
+						break;
+				}
+				try {
+					File file = getFile(ubase, value).getAbsoluteFile();
+					if (!file.isFile() && fileMustExist) {
+						error("Included file " + file + (file.exists() ? " does not exist" : " is directory"));
+					} else
+						doIncludeFile(file, overwrite, p);
+				}
+				catch (Exception e) {
+					if (fileMustExist)
+						error("Error in processing included file: " + value, e);
+				}
+			}
+		}
+	}
+
+	/**
+	 * @param file
+	 * @param parent
+	 * @param done
+	 * @param overwrite
+	 * @throws FileNotFoundException
+	 * @throws IOException
+	 */
+	public void doIncludeFile(File file, boolean overwrite, Properties target) throws Exception {
+		doIncludeFile(file, overwrite, target, null);
+	}
+
+	/**
+	 * @param file
+	 * @param parent
+	 * @param done
+	 * @param overwrite
+	 * @param extensionName
+	 * @throws FileNotFoundException
+	 * @throws IOException
+	 */
+	public void doIncludeFile(File file, boolean overwrite, Properties target, String extensionName) throws Exception {
+		if (included != null && included.contains(file)) {
+			error("Cyclic or multiple include of " + file);
+		} else {
+			addIncluded(file);
+			updateModified(file.lastModified(), file.toString());
+			InputStream in = new FileInputStream(file);
+			try {
+				Properties sub;
+				if (file.getName().toLowerCase().endsWith(".mf")) {
+					sub = getManifestAsProperties(in);
+				} else
+					sub = loadProperties(in, file.getAbsolutePath());
+
+				doIncludes(file.getParentFile(), sub);
+				// make sure we do not override properties
+				for (Map.Entry< ? , ? > entry : sub.entrySet()) {
+					String key = (String) entry.getKey();
+					String value = (String) entry.getValue();
+
+					if (overwrite || !target.containsKey(key)) {
+						target.setProperty(key, value);
+					} else if (extensionName != null) {
+						String extensionKey = extensionName + "." + key;
+						if (!target.containsKey(extensionKey))
+							target.setProperty(extensionKey, value);
+					}
+				}
+			}
+			finally {
+				IO.close(in);
+			}
+		}
+	}
+
+	public void unsetProperty(String string) {
+		getProperties().remove(string);
+
+	}
+
+	public boolean refresh() {
+		plugins = null; // We always refresh our plugins
+		
+		
+		if (propertiesFile == null)
+			return false;
+
+		boolean changed = updateModified(propertiesFile.lastModified(), "properties file");
+		if (included != null) {
+			for (File file : included) {
+				if (changed)
+					break;
+
+				changed |= !file.exists() || updateModified(file.lastModified(), "include file: " + file);
+			}
+		}
+
+		profile = getProperty(PROFILE); // Used in property access
+		
+		if (changed) {
+			forceRefresh();
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * 
+	 */
+	public void forceRefresh() {
+		included = null;
+		properties.clear();
+		setProperties(propertiesFile, base);
+		propertiesChanged();
+	}
+
+	public void propertiesChanged() {}
+
+	/**
+	 * Set the properties by file. Setting the properties this way will also set
+	 * the base for this analyzer. After reading the properties, this will call
+	 * setProperties(Properties) which will handle the includes.
+	 * 
+	 * @param propertiesFile
+	 * @throws FileNotFoundException
+	 * @throws IOException
+	 */
+	public void setProperties(File propertiesFile) throws IOException {
+		propertiesFile = propertiesFile.getAbsoluteFile();
+		setProperties(propertiesFile, propertiesFile.getParentFile());
+	}
+
+	public void setProperties(File propertiesFile, File base) {
+		this.propertiesFile = propertiesFile.getAbsoluteFile();
+		setBase(base);
+		try {
+			if (propertiesFile.isFile()) {
+				// System.err.println("Loading properties " + propertiesFile);
+				long modified = propertiesFile.lastModified();
+				if (modified > System.currentTimeMillis() + 100) {
+					System.err.println("Huh? This is in the future " + propertiesFile);
+					this.modified = System.currentTimeMillis();
+				} else
+					this.modified = modified;
+
+				included = null;
+				Properties p = loadProperties(propertiesFile);
+				setProperties(p);
+			} else {
+				if (fileMustExist) {
+					error("No such properties file: " + propertiesFile);
+				}
+			}
+		}
+		catch (IOException e) {
+			error("Could not load properties " + propertiesFile);
+		}
+	}
+
+	protected void begin() {
+		if (isTrue(getProperty(PEDANTIC)))
+			setPedantic(true);
+	}
+
+	public static boolean isTrue(String value) {
+		if (value == null)
+			return false;
+
+		return !"false".equalsIgnoreCase(value);
+	}
+
+	/**
+	 * Get a property without preprocessing it with a proper default
+	 * 
+	 * @param headerName
+	 * @param deflt
+	 * @return
+	 */
+
+	public String getUnprocessedProperty(String key, String deflt) {
+		return getProperties().getProperty(key, deflt);
+	}
+
+	/**
+	 * Get a property with preprocessing it with a proper default
+	 * 
+	 * @param headerName
+	 * @param deflt
+	 * @return
+	 */
+	public String getProperty(String key, String deflt) {
+
+		String value = null;
+
+		Instruction ins = new Instruction(key);
+		if (!ins.isLiteral()) {
+			// Handle a wildcard key, make sure they're sorted
+			// for consistency
+			SortedList<String> sortedList = SortedList.fromIterator(iterator());
+			StringBuilder sb = new StringBuilder();
+			String del = "";
+			for (String k : sortedList) {
+				if (ins.matches(k)) {
+					String v = getProperty(k, null);
+					if (v != null) {
+						sb.append(del);
+						del = ",";
+						sb.append(v);
+					}
+				}
+			}
+			if (sb.length() == 0)
+				return deflt;
+
+			return sb.toString();
+		}
+
+		Processor source = this;
+
+		// Use the key as is first, if found ok
+
+		if (filter != null && filter.contains(key)) {
+			value = (String) getProperties().get(key);
+		} else {
+			while (source != null) {
+				value = (String) source.getProperties().get(key);
+				if (value != null)
+					break;
+
+				source = source.getParent();
+			}
+		}
+
+		// Check if we found a value, if not, try to prefix
+		// it with a profile if found and search again. profiles
+		// are a simple name that is prefixed like [profile]. This
+		// allows different variables to be used in different profiles.
+
+		if (value == null && profile != null) {
+			String pkey = "[" + profile + "]" + key;
+			if (filter != null && filter.contains(key)) {
+				value = (String) getProperties().get(pkey);
+			} else {
+				while (source != null) {
+					value = (String) source.getProperties().get(pkey);
+					if (value != null)
+						break;
+
+					source = source.getParent();
+				}
+			}
+		}
+
+		if (value != null)
+			return getReplacer().process(value, source);
+		else if (deflt != null)
+			return getReplacer().process(deflt, this);
+		else
+			return null;
+	}
+
+	/**
+	 * Helper to load a properties file from disk.
+	 * 
+	 * @param file
+	 * @return
+	 * @throws IOException
+	 */
+	public Properties loadProperties(File file) throws IOException {
+		updateModified(file.lastModified(), "Properties file: " + file);
+		InputStream in = new FileInputStream(file);
+		try {
+			Properties p = loadProperties(in, file.getAbsolutePath());
+			return p;
+		}
+		finally {
+			in.close();
+		}
+	}
+
+	Properties loadProperties(InputStream in, String name) throws IOException {
+		int n = name.lastIndexOf('/');
+		if (n > 0)
+			name = name.substring(0, n);
+		if (name.length() == 0)
+			name = ".";
+
+		try {
+			Properties p = new Properties();
+			p.load(in);
+			return replaceAll(p, "\\$\\{\\.\\}", name);
+		}
+		catch (Exception e) {
+			error("Error during loading properties file: " + name + ", error:" + e);
+			return new Properties();
+		}
+	}
+
+	/**
+	 * Replace a string in all the values of the map. This can be used to
+	 * preassign variables that change. I.e. the base directory ${.} for a
+	 * loaded properties
+	 */
+
+	public static Properties replaceAll(Properties p, String pattern, String replacement) {
+		Properties result = new Properties();
+		for (Iterator<Map.Entry<Object,Object>> i = p.entrySet().iterator(); i.hasNext();) {
+			Map.Entry<Object,Object> entry = i.next();
+			String key = (String) entry.getKey();
+			String value = (String) entry.getValue();
+			value = value.replaceAll(pattern, replacement);
+			result.put(key, value);
+		}
+		return result;
+	}
+
+	/**
+	 * Print a standard Map based OSGi header.
+	 * 
+	 * @param exports
+	 *            map { name => Map { attribute|directive => value } }
+	 * @return the clauses
+	 * @throws IOException
+	 */
+	public static String printClauses(Map< ? , ? extends Map< ? , ? >> exports) throws IOException {
+		return printClauses(exports, false);
+	}
+
+	public static String printClauses(Map< ? , ? extends Map< ? , ? >> exports, @SuppressWarnings("unused")
+	boolean checkMultipleVersions) throws IOException {
+		StringBuilder sb = new StringBuilder();
+		String del = "";
+		for (Entry< ? , ? extends Map< ? , ? >> entry : exports.entrySet()) {
+			String name = entry.getKey().toString();
+			Map< ? , ? > clause = entry.getValue();
+
+			// We allow names to be duplicated in the input
+			// by ending them with '~'. This is necessary to use
+			// the package names as keys. However, we remove these
+			// suffixes in the output so that you can set multiple
+			// exports with different attributes.
+			String outname = removeDuplicateMarker(name);
+			sb.append(del);
+			sb.append(outname);
+			printClause(clause, sb);
+			del = ",";
+		}
+		return sb.toString();
+	}
+
+	public static void printClause(Map< ? , ? > map, StringBuilder sb) throws IOException {
+
+		for (Entry< ? , ? > entry : map.entrySet()) {
+			Object key = entry.getKey();
+			// Skip directives we do not recognize
+			if (key.equals(NO_IMPORT_DIRECTIVE) || key.equals(PROVIDE_DIRECTIVE) || key.equals(SPLIT_PACKAGE_DIRECTIVE)
+					|| key.equals(FROM_DIRECTIVE))
+				continue;
+
+			String value = ((String) entry.getValue()).trim();
+			sb.append(";");
+			sb.append(key);
+			sb.append("=");
+
+			quote(sb, value);
+		}
+	}
+
+	/**
+	 * @param sb
+	 * @param value
+	 * @return
+	 * @throws IOException
+	 */
+	public static boolean quote(Appendable sb, String value) throws IOException {
+		boolean clean = (value.length() >= 2 && value.charAt(0) == '"' && value.charAt(value.length() - 1) == '"')
+				|| Verifier.TOKEN.matcher(value).matches();
+		if (!clean)
+			sb.append("\"");
+		sb.append(value);
+		if (!clean)
+			sb.append("\"");
+		return clean;
+	}
+
+	public Macro getReplacer() {
+		if (replacer == null)
+			return replacer = new Macro(this, getMacroDomains());
+		return replacer;
+	}
+
+	/**
+	 * This should be overridden by subclasses to add extra macro command
+	 * domains on the search list.
+	 * 
+	 * @return
+	 */
+	protected Object[] getMacroDomains() {
+		return new Object[] {};
+	}
+
+	/**
+	 * Return the properties but expand all macros. This always returns a new
+	 * Properties object that can be used in any way.
+	 * 
+	 * @return
+	 */
+	public Properties getFlattenedProperties() {
+		return getReplacer().getFlattenedProperties();
+
+	}
+
+	/**
+	 * Return all inherited property keys
+	 * 
+	 * @return
+	 */
+	public Set<String> getPropertyKeys(boolean inherit) {
+		Set<String> result;
+		if (parent == null || !inherit) {
+			result = Create.set();
+		} else
+			result = parent.getPropertyKeys(inherit);
+		for (Object o : properties.keySet())
+			result.add(o.toString());
+
+		return result;
+	}
+
+	public boolean updateModified(long time, @SuppressWarnings("unused")
+	String reason) {
+		if (time > lastModified) {
+			lastModified = time;
+			return true;
+		}
+		return false;
+	}
+
+	public long lastModified() {
+		return lastModified;
+	}
+
+	/**
+	 * Add or override a new property.
+	 * 
+	 * @param key
+	 * @param value
+	 */
+	public void setProperty(String key, String value) {
+		checkheader: for (int i = 0; i < headers.length; i++) {
+			if (headers[i].equalsIgnoreCase(value)) {
+				value = headers[i];
+				break checkheader;
+			}
+		}
+		getProperties().put(key, value);
+	}
+
+	/**
+	 * Read a manifest but return a properties object.
+	 * 
+	 * @param in
+	 * @return
+	 * @throws IOException
+	 */
+	public static Properties getManifestAsProperties(InputStream in) throws IOException {
+		Properties p = new Properties();
+		Manifest manifest = new Manifest(in);
+		for (Iterator<Object> it = manifest.getMainAttributes().keySet().iterator(); it.hasNext();) {
+			Attributes.Name key = (Attributes.Name) it.next();
+			String value = manifest.getMainAttributes().getValue(key);
+			p.put(key.toString(), value);
+		}
+		return p;
+	}
+
+	public File getPropertiesFile() {
+		return propertiesFile;
+	}
+
+	public void setFileMustExist(boolean mustexist) {
+		fileMustExist = mustexist;
+	}
+
+	static public String read(InputStream in) throws Exception {
+		InputStreamReader ir = new InputStreamReader(in, "UTF8");
+		StringBuilder sb = new StringBuilder();
+
+		try {
+			char chars[] = new char[1000];
+			int size = ir.read(chars);
+			while (size > 0) {
+				sb.append(chars, 0, size);
+				size = ir.read(chars);
+			}
+		}
+		finally {
+			ir.close();
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * Join a list.
+	 * 
+	 * @param args
+	 * @return
+	 */
+	public static String join(Collection< ? > list, String delimeter) {
+		return join(delimeter, list);
+	}
+
+	public static String join(String delimeter, Collection< ? >... list) {
+		StringBuilder sb = new StringBuilder();
+		String del = "";
+		if (list != null) {
+			for (Collection< ? > l : list) {
+				for (Object item : l) {
+					sb.append(del);
+					sb.append(item);
+					del = delimeter;
+				}
+			}
+		}
+		return sb.toString();
+	}
+
+	public static String join(Object[] list, String delimeter) {
+		if (list == null)
+			return "";
+		StringBuilder sb = new StringBuilder();
+		String del = "";
+		for (Object item : list) {
+			sb.append(del);
+			sb.append(item);
+			del = delimeter;
+		}
+		return sb.toString();
+	}
+
+	public static String join(Collection< ? >... list) {
+		return join(",", list);
+	}
+
+	public static <T> String join(T list[]) {
+		return join(list, ",");
+	}
+
+	public static void split(String s, Collection<String> set) {
+
+		String elements[] = s.trim().split(LIST_SPLITTER);
+		for (String element : elements) {
+			if (element.length() > 0)
+				set.add(element);
+		}
+	}
+
+	public static Collection<String> split(String s) {
+		return split(s, LIST_SPLITTER);
+	}
+
+	public static Collection<String> split(String s, String splitter) {
+		if (s != null)
+			s = s.trim();
+		if (s == null || s.trim().length() == 0)
+			return Collections.emptyList();
+
+		return Arrays.asList(s.split(splitter));
+	}
+
+	public static String merge(String... strings) {
+		ArrayList<String> result = new ArrayList<String>();
+		for (String s : strings) {
+			if (s != null)
+				split(s, result);
+		}
+		return join(result);
+	}
+
+	public boolean isExceptions() {
+		return exceptions;
+	}
+
+	public void setExceptions(boolean exceptions) {
+		this.exceptions = exceptions;
+	}
+
+	/**
+	 * Make the file short if it is inside our base directory, otherwise long.
+	 * 
+	 * @param f
+	 * @return
+	 */
+	public String normalize(String f) {
+		if (f.startsWith(base.getAbsolutePath() + "/"))
+			return f.substring(base.getAbsolutePath().length() + 1);
+		return f;
+	}
+
+	public String normalize(File f) {
+		return normalize(f.getAbsolutePath());
+	}
+
+	public static String removeDuplicateMarker(String key) {
+		int i = key.length() - 1;
+		while (i >= 0 && key.charAt(i) == DUPLICATE_MARKER)
+			--i;
+
+		return key.substring(0, i + 1);
+	}
+
+	public static boolean isDuplicate(String name) {
+		return name.length() > 0 && name.charAt(name.length() - 1) == DUPLICATE_MARKER;
+	}
+
+	public void setTrace(boolean x) {
+		trace = x;
+	}
+
+	static class CL extends URLClassLoader {
+
+		CL() {
+			super(new URL[0], Processor.class.getClassLoader());
+		}
+
+		void add(URL url) {
+			URL urls[] = getURLs();
+			for (URL u : urls) {
+				if (u.equals(url))
+					return;
+			}
+			super.addURL(url);
+		}
+
+		@Override
+		public Class< ? > loadClass(String name) throws NoClassDefFoundError {
+			try {
+				Class< ? > c = super.loadClass(name);
+				return c;
+			}
+			catch (Throwable t) {
+				StringBuilder sb = new StringBuilder();
+				sb.append(name);
+				sb.append(" not found, parent:  ");
+				sb.append(getParent());
+				sb.append(" urls:");
+				sb.append(Arrays.toString(getURLs()));
+				sb.append(" exception:");
+				sb.append(t);
+				throw new NoClassDefFoundError(sb.toString());
+			}
+		}
+	}
+
+	private CL getLoader() {
+		if (pluginLoader == null) {
+			pluginLoader = new CL();
+		}
+		return pluginLoader;
+	}
+
+	/*
+	 * Check if this is a valid project.
+	 */
+	public boolean exists() {
+		return base != null && base.isDirectory() && propertiesFile != null && propertiesFile.isFile();
+	}
+
+	public boolean isOk() {
+		return isFailOk() || (getErrors().size() == 0);
+	}
+
+	public boolean check(String... pattern) throws IOException {
+		Set<String> missed = Create.set();
+
+		if (pattern != null) {
+			for (String p : pattern) {
+				boolean match = false;
+				Pattern pat = Pattern.compile(p);
+				for (Iterator<String> i = errors.iterator(); i.hasNext();) {
+					if (pat.matcher(i.next()).find()) {
+						i.remove();
+						match = true;
+					}
+				}
+				for (Iterator<String> i = warnings.iterator(); i.hasNext();) {
+					if (pat.matcher(i.next()).find()) {
+						i.remove();
+						match = true;
+					}
+				}
+				if (!match)
+					missed.add(p);
+
+			}
+		}
+		if (missed.isEmpty() && isPerfect())
+			return true;
+
+		if (!missed.isEmpty())
+			System.err.println("Missed the following patterns in the warnings or errors: " + missed);
+
+		report(System.err);
+		return false;
+	}
+
+	protected void report(Appendable out) throws IOException {
+		if (errors.size() > 0) {
+			out.append(String.format("-----------------%nErrors%n"));
+			for (int i = 0; i < errors.size(); i++) {
+				out.append(String.format("%03d: %s%n", i, errors.get(i)));
+			}
+		}
+		if (warnings.size() > 0) {
+			out.append(String.format("-----------------%nWarnings%n"));
+			for (int i = 0; i < warnings.size(); i++) {
+				out.append(String.format("%03d: %s%n", i, warnings.get(i)));
+			}
+		}
+	}
+
+	public boolean isPerfect() {
+		return getErrors().size() == 0 && getWarnings().size() == 0;
+	}
+
+	public void setForceLocal(Collection<String> local) {
+		filter = local;
+	}
+
+	/**
+	 * Answer if the name is a missing plugin's command name. If a bnd file
+	 * contains the command name of a plugin, and that plugin is not available,
+	 * then an error is reported during manifest calculation. This allows the
+	 * plugin to fail to load when it is not needed. We first get the plugins to
+	 * ensure it is properly initialized.
+	 * 
+	 * @param name
+	 * @return
+	 */
+	public boolean isMissingPlugin(String name) {
+		getPlugins();
+		return missingCommand != null && missingCommand.contains(name);
+	}
+
+	/**
+	 * Append two strings to for a path in a ZIP or JAR file. It is guaranteed
+	 * to return a string that does not start, nor ends with a '/', while it is
+	 * properly separated with slashes. Double slashes are properly removed.
+	 * 
+	 * <pre>
+	 *  "/" + "abc/def/" becomes "abc/def"
+	 *  
+	 * @param prefix
+	 * @param suffix
+	 * @return
+	 */
+	public static String appendPath(String... parts) {
+		StringBuilder sb = new StringBuilder();
+		boolean lastSlash = true;
+		for (String part : parts) {
+			for (int i = 0; i < part.length(); i++) {
+				char c = part.charAt(i);
+				if (c == '/') {
+					if (!lastSlash)
+						sb.append('/');
+					lastSlash = true;
+				} else {
+					sb.append(c);
+					lastSlash = false;
+				}
+			}
+
+			if (!lastSlash && sb.length() > 0) {
+				sb.append('/');
+				lastSlash = true;
+			}
+		}
+		if (lastSlash && sb.length() > 0)
+			sb.deleteCharAt(sb.length() - 1);
+
+		return sb.toString();
+	}
+
+	/**
+	 * Parse the a=b strings and return a map of them.
+	 * 
+	 * @param attrs
+	 * @param clazz
+	 * @return
+	 */
+	public static Attrs doAttrbutes(Object[] attrs, Clazz clazz, Macro macro) {
+		Attrs map = new Attrs();
+
+		if (attrs == null || attrs.length == 0)
+			return map;
+
+		for (Object a : attrs) {
+			String attr = (String) a;
+			int n = attr.indexOf("=");
+			if (n > 0) {
+				map.put(attr.substring(0, n), macro.process(attr.substring(n + 1)));
+			} else
+				throw new IllegalArgumentException(formatArrays(
+						"Invalid attribute on package-info.java in %s , %s. Must be <key>=<name> ", clazz, attr));
+		}
+		return map;
+	}
+
+	/**
+	 * This method is the same as String.format but it makes sure that any
+	 * arrays are transformed to strings.
+	 * 
+	 * @param string
+	 * @param parms
+	 * @return
+	 */
+	public static String formatArrays(String string, Object... parms) {
+		Object[] parms2 = parms;
+		Object[] output = new Object[parms.length];
+		for (int i = 0; i < parms.length; i++) {
+			output[i] = makePrintable(parms[i]);
+		}
+		return String.format(string, parms2);
+	}
+
+	/**
+	 * Check if the object is an array and turn it into a string if it is,
+	 * otherwise unchanged.
+	 * 
+	 * @param object
+	 *            the object to make printable
+	 * @return a string if it was an array or the original object
+	 */
+	public static Object makePrintable(Object object) {
+		if (object == null)
+			return object;
+
+		if (object.getClass().isArray()) {
+			Object[] array = (Object[]) object;
+			Object[] output = new Object[array.length];
+			for (int i = 0; i < array.length; i++) {
+				output[i] = makePrintable(array[i]);
+			}
+			return Arrays.toString(output);
+		}
+		return object;
+	}
+
+	public static String append(String... strings) {
+		List<String> result = Create.list();
+		for (String s : strings) {
+			result.addAll(split(s));
+		}
+		return join(result);
+	}
+
+	public synchronized Class< ? > getClass(String type, File jar) throws Exception {
+		CL cl = getLoader();
+		cl.add(jar.toURI().toURL());
+		return cl.loadClass(type);
+	}
+
+	public boolean isTrace() {
+		return current().trace;
+	}
+
+	public static long getDuration(String tm, long dflt) {
+		if (tm == null)
+			return dflt;
+
+		tm = tm.toUpperCase();
+		TimeUnit unit = TimeUnit.MILLISECONDS;
+		Matcher m = Pattern
+				.compile("\\s*(\\d+)\\s*(NANOSECONDS|MICROSECONDS|MILLISECONDS|SECONDS|MINUTES|HOURS|DAYS)?").matcher(
+						tm);
+		if (m.matches()) {
+			long duration = Long.parseLong(tm);
+			String u = m.group(2);
+			if (u != null)
+				unit = TimeUnit.valueOf(u);
+			duration = TimeUnit.MILLISECONDS.convert(duration, unit);
+			return duration;
+		}
+		return dflt;
+	}
+
+	/**
+	 * Generate a random string, which is guaranteed to be a valid Java
+	 * identifier (first character is an ASCII letter, subsequent characters are
+	 * ASCII letters or numbers). Takes an optional parameter for the length of
+	 * string to generate; default is 8 characters.
+	 */
+	public String _random(String[] args) {
+		int numchars = 8;
+		if (args.length > 1) {
+			try {
+				numchars = Integer.parseInt(args[1]);
+			}
+			catch (NumberFormatException e) {
+				throw new IllegalArgumentException("Invalid character count parameter in ${random} macro.");
+			}
+		}
+
+		synchronized (Processor.class) {
+			if (random == null)
+				random = new Random();
+		}
+
+		char[] letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
+		char[] alphanums = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
+
+		char[] array = new char[numchars];
+		for (int i = 0; i < numchars; i++) {
+			char c;
+			if (i == 0)
+				c = letters[random.nextInt(letters.length)];
+			else
+				c = alphanums[random.nextInt(alphanums.length)];
+			array[i] = c;
+		}
+
+		return new String(array);
+	}
+	
+	/**
+	 * <p>
+	 * Generates a Capability string, in the format specified by the OSGi
+	 * Provide-Capability header, representing the current native platform
+	 * according to OSGi RFC 188. For example on Windows7 running on an x86_64
+	 * processor it should generate the following:
+	 * </p>
+	 * 
+	 * <pre>
+	 * osgi.native;osgi.native.osname:List<String>="Windows7,Windows 7,Win32";osgi.native.osversion:Version=6.1.0;osgi.native.processor:List<String>="x86-64,amd64,em64t,x86_64"
+	 * </pre>
+	 * 
+	 * @param args
+	 *            Ignored; reserved for future use.
+	 */
+	public String _native_capability(String[] args) {
+		StringBuilder builder = new StringBuilder().append("osgi.native");
+		
+		try {
+			// Operating System name and version
+			String osnames;
+			Version osversion;
+			
+			String sysPropOsName = System.getProperty("os.name");
+			String sysPropOsVersion = System.getProperty("os.version");
+			if (sysPropOsName.startsWith("Windows")) {
+				if (sysPropOsVersion.startsWith("6.2")) {
+					osversion = new Version(6,2,0);
+					osnames = "Windows8,Windows 8,Win32"; 
+				} else if (sysPropOsVersion.startsWith("6.1")) {
+					osversion = new Version(6, 1, 0);
+					osnames = "Windows7,Windows 7,Win32";
+				} else if (sysPropOsName.startsWith("6.0")) {
+					osversion = new Version(6, 0, 0);
+					osnames = "WindowsVista,WinVista,Windows Vista,Win32";
+				} else if (sysPropOsName.startsWith("5.1")) {
+					osversion = new Version(5, 1, 0);
+					osnames = "WindowsXP,WinXP,Windows XP,Win32";
+				} else {
+					throw new IllegalArgumentException(String.format("Unrecognised or unsupported Windows version while processing ${native} macro: %s version %s. Supported: XP, Vista, Win7, Win8.", sysPropOsName, sysPropOsVersion));
+				}
+			} else if (sysPropOsName.startsWith("Mac OS X")) {
+				osnames = "MacOSX,Mac OS X";
+				osversion = new Version(sysPropOsVersion);
+			} else if (sysPropOsName.toLowerCase().startsWith("linux")) {
+				osnames = "Linux";
+				osversion = new Version(sysPropOsVersion);
+			} else if (sysPropOsName.startsWith("Solaris")) {
+				osnames = "Solaris";
+				osversion = new Version(sysPropOsVersion);
+			} else if (sysPropOsName.startsWith("AIX")) {
+				osnames = "AIX";
+				osversion = new Version(sysPropOsVersion);
+			} else if (sysPropOsName.startsWith("HP-UX")) {
+				osnames = "HPUX,hp-ux";
+				osversion = new Version(sysPropOsVersion);
+			} else {
+				throw new IllegalArgumentException(String.format("Unrecognised or unsupported OS while processing ${native} macro: %s version %s. Supported: Windows, Mac OS X, Linux, Solaris, AIX, HP-UX.", sysPropOsName, sysPropOsVersion));
+			}
+			
+			builder.append(";osgi.native.osname:List<String>=\"").append(osnames).append('"');
+			builder.append(";osgi.native.osversion:Version=").append(osversion.toString());
+			
+			// Processor
+			String processorNames;
+			
+			String arch = System.getProperty("os.arch");
+			if ("x86_64".equals(arch))
+				processorNames = "x86-64,amd64,em64t,x86_64";
+			else if ("x86".equals(arch))
+				processorNames = "x86,pentium,i386,i486,i586,i686";
+			else
+				throw new IllegalArgumentException(String.format("Unrecognised/unsupported processor name '%s' in ${native} macro.", arch));
+			builder.append(";osgi.native.processor:List<String>=\"").append(processorNames).append('"');
+			
+		} catch (SecurityException e) {
+			throw new IllegalArgumentException("Security error retrieving system properties while processing ${native} macro.");
+		}
+		
+		return builder.toString();
+	}
+
+	/**
+	 * Set the current command thread. This must be balanced with the
+	 * {@link #end(Processor)} method. The method returns the previous command
+	 * owner or null. The command owner will receive all warnings and error
+	 * reports.
+	 */
+
+	protected Processor beginHandleErrors(String message) {
+		trace("begin %s", message);
+		Processor previous = current.get();
+		current.set(this);
+		return previous;
+	}
+
+	/**
+	 * End a command. Will restore the previous command owner.
+	 * 
+	 * @param previous
+	 */
+	protected void endHandleErrors(Processor previous) {
+		trace("end");
+		current.set(previous);
+	}
+
+	public static Executor getExecutor() {
+		return executor;
+	}
+
+	/**
+	 * These plugins are added to the total list of plugins. The separation is
+	 * necessary because the list of plugins is refreshed now and then so we
+	 * need to be able to add them at any moment in time.
+	 * 
+	 * @param plugin
+	 */
+	public synchronized void addBasicPlugin(Object plugin) {
+		basicPlugins.add(plugin);
+		if (plugins != null)
+			plugins.add(plugin);
+	}
+
+	public synchronized void removeBasicPlugin(Object plugin) {
+		basicPlugins.remove(plugin);
+		if (plugins != null)
+			plugins.remove(plugin);
+	}
+
+	public List<File> getIncluded() {
+		return included;
+	}
+
+	/**
+	 * Overrides for the Domain class
+	 */
+	@Override
+	public String get(String key) {
+		return getProperty(key);
+	}
+
+	@Override
+	public String get(String key, String deflt) {
+		return getProperty(key, deflt);
+	}
+
+	@Override
+	public void set(String key, String value) {
+		getProperties().setProperty(key, value);
+	}
+
+	@Override
+	public Iterator<String> iterator() {
+		Set<String> keys = keySet();
+		final Iterator<String> it = keys.iterator();
+
+		return new Iterator<String>() {
+			String	current;
+
+			public boolean hasNext() {
+				return it.hasNext();
+			}
+
+			public String next() {
+				return current = it.next().toString();
+			}
+
+			public void remove() {
+				getProperties().remove(current);
+			}
+		};
+	}
+
+	public Set<String> keySet() {
+		Set<String> set;
+		if (parent == null)
+			set = Create.set();
+		else
+			set = parent.keySet();
+
+		for (Object o : properties.keySet())
+			set.add(o.toString());
+
+		return set;
+	}
+
+	/**
+	 * Printout of the status of this processor for toString()
+	 */
+
+	@Override
+	public String toString() {
+		try {
+			StringBuilder sb = new StringBuilder();
+			report(sb);
+			return sb.toString();
+		}
+		catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	/**
+	 * Utiltity to replace an extension
+	 * 
+	 * @param s
+	 * @param extension
+	 * @param newExtension
+	 * @return
+	 */
+	public String replaceExtension(String s, String extension, String newExtension) {
+		if (s.endsWith(extension))
+			s = s.substring(0, s.length() - extension.length());
+
+		return s + newExtension;
+	}
+
+	/**
+	 * Create a location object and add it to the locations
+	 * 
+	 * @param s
+	 * @return
+	 */
+	List<Location>	locations	= new ArrayList<Location>();
+
+	static class SetLocationImpl extends Location implements SetLocation {
+		public SetLocationImpl(String s) {
+			this.message = s;
+		}
+
+		public SetLocation file(String file) {
+			this.file = file;
+			return this;
+		}
+
+		public SetLocation header(String header) {
+			this.header = header;
+			return this;
+		}
+
+		public SetLocation context(String context) {
+			this.context = context;
+			return this;
+		}
+
+		public SetLocation method(String methodName) {
+			this.methodName = methodName;
+			return this;
+		}
+
+		public SetLocation line(int n) {
+			this.line = n;
+			return this;
+		}
+
+		public SetLocation reference(String reference) {
+			this.reference = reference;
+			return this;
+		}
+
+	}
+
+	private SetLocation location(String s) {
+		SetLocationImpl loc = new SetLocationImpl(s);
+		locations.add(loc);
+		return loc;
+	}
+
+	public Location getLocation(String msg) {
+		for (Location l : locations)
+			if ((l.message != null) && l.message.equals(msg))
+				return l;
+
+		return null;
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/Resource.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/Resource.java
new file mode 100755
index 0000000..8be81aa
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/Resource.java
@@ -0,0 +1,17 @@
+package aQute.bnd.osgi;
+
+import java.io.*;
+
+public interface Resource {
+	InputStream openInputStream() throws Exception;
+
+	void write(OutputStream out) throws Exception;
+
+	long lastModified();
+
+	void setExtra(String extra);
+
+	String getExtra();
+
+	long size() throws Exception;
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/URLResource.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/URLResource.java
new file mode 100755
index 0000000..5d47067
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/URLResource.java
@@ -0,0 +1,85 @@
+package aQute.bnd.osgi;
+
+import java.io.*;
+import java.net.*;
+
+import aQute.lib.io.*;
+
+public class URLResource implements Resource {
+	URL		url;
+	String	extra;
+	long	size	= -1;
+
+	public URLResource(URL url) {
+		this.url = url;
+	}
+
+	public InputStream openInputStream() throws IOException {
+		return url.openStream();
+	}
+
+	@Override
+	public String toString() {
+		return ":" + url.getPath() + ":";
+	}
+
+	public void write(OutputStream out) throws Exception {
+		IO.copy(this.openInputStream(), out);
+	}
+
+	public long lastModified() {
+		return -1;
+	}
+
+	public String getExtra() {
+		return extra;
+	}
+
+	public void setExtra(String extra) {
+		this.extra = extra;
+	}
+
+	public long size() throws Exception {
+		if (size >= 0)
+			return size;
+
+		try {
+			if (url.getProtocol().equals("file:")) {
+				File file = new File(url.getPath());
+				if (file.isFile())
+					return size = file.length();
+			} else {
+				URLConnection con = url.openConnection();
+				if (con instanceof HttpURLConnection) {
+					HttpURLConnection http = (HttpURLConnection) con;
+					http.setRequestMethod("HEAD");
+					http.connect();
+					String l = http.getHeaderField("Content-Length");
+					if (l != null) {
+						return size = Long.parseLong(l);
+					}
+				}
+			}
+		}
+		catch (Exception e) {
+			// Forget this exception, we do it the hard way
+		}
+		InputStream in = openInputStream();
+		DataInputStream din = null;
+		try {
+			din = new DataInputStream(in);
+			long result = din.skipBytes(Integer.MAX_VALUE);
+			while (in.read() >= 0) {
+				result += din.skipBytes(Integer.MAX_VALUE);
+			}
+			size = result;
+		}
+		finally {
+			if (din != null) {
+				din.close();
+			}
+		}
+		return size;
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/Verifier.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/Verifier.java
new file mode 100755
index 0000000..77b324d
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/Verifier.java
@@ -0,0 +1,915 @@
+package aQute.bnd.osgi;
+
+import java.io.*;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.jar.*;
+import java.util.regex.*;
+
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.Descriptors.PackageRef;
+import aQute.bnd.osgi.Descriptors.TypeRef;
+import aQute.lib.base64.*;
+import aQute.lib.io.*;
+import aQute.libg.cryptography.*;
+import aQute.libg.qtokens.*;
+
+public class Verifier extends Processor {
+
+	private final Jar		dot;
+	private final Manifest	manifest;
+	private final Domain	main;
+
+	private boolean			r3;
+	private boolean			usesRequire;
+
+	final static Pattern	EENAME	= Pattern.compile("CDC-1\\.0/Foundation-1\\.0" + "|CDC-1\\.1/Foundation-1\\.1"
+											+ "|OSGi/Minimum-1\\.[1-9]" + "|JRE-1\\.1" + "|J2SE-1\\.2" + "|J2SE-1\\.3"
+											+ "|J2SE-1\\.4" + "|J2SE-1\\.5" + "|JavaSE-1\\.6" + "|JavaSE-1\\.7"
+											+ "|PersonalJava-1\\.1" + "|PersonalJava-1\\.2"
+											+ "|CDC-1\\.0/PersonalBasis-1\\.0" + "|CDC-1\\.0/PersonalJava-1\\.0");
+
+	final static int		V1_1	= 45;
+	final static int		V1_2	= 46;
+	final static int		V1_3	= 47;
+	final static int		V1_4	= 48;
+	final static int		V1_5	= 49;
+	final static int		V1_6	= 50;
+	final static int		V1_7	= 51;
+	final static int		V1_8	= 52;
+
+	static class EE {
+		String	name;
+		int		target;
+
+		EE(String name, @SuppressWarnings("unused") int source, int target) {
+			this.name = name;
+			this.target = target;
+		}
+
+		@Override
+		public String toString() {
+			return name + "(" + target + ")";
+		}
+	}
+
+	final static EE[]			ees								= {
+			new EE("CDC-1.0/Foundation-1.0", V1_3, V1_1),
+			new EE("CDC-1.1/Foundation-1.1", V1_3, V1_2),
+			new EE("OSGi/Minimum-1.0", V1_3, V1_1),
+			new EE("OSGi/Minimum-1.1", V1_3, V1_2),
+			new EE("JRE-1.1", V1_1, V1_1), //
+			new EE("J2SE-1.2", V1_2, V1_1), //
+			new EE("J2SE-1.3", V1_3, V1_1), //
+			new EE("J2SE-1.4", V1_3, V1_2), //
+			new EE("J2SE-1.5", V1_5, V1_5), //
+			new EE("JavaSE-1.6", V1_6, V1_6), //
+			new EE("PersonalJava-1.1", V1_1, V1_1), //
+			new EE("JavaSE-1.7", V1_7, V1_7), //
+			new EE("PersonalJava-1.1", V1_1, V1_1), //
+			new EE("PersonalJava-1.2", V1_1, V1_1), new EE("CDC-1.0/PersonalBasis-1.0", V1_3, V1_1),
+			new EE("CDC-1.0/PersonalJava-1.0", V1_3, V1_1), new EE("CDC-1.1/PersonalBasis-1.1", V1_3, V1_2),
+			new EE("CDC-1.1/PersonalJava-1.1", V1_3, V1_2)
+																};
+
+	final static Pattern		CARDINALITY_PATTERN				= Pattern.compile("single|multiple");
+	final static Pattern		RESOLUTION_PATTERN				= Pattern.compile("optional|mandatory");
+	final static Pattern		BUNDLEMANIFESTVERSION			= Pattern.compile("2");
+	public final static String	SYMBOLICNAME_STRING				= "[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)*";
+	public final static Pattern	SYMBOLICNAME					= Pattern.compile(SYMBOLICNAME_STRING);
+
+	public final static String	VERSION_STRING					= "[0-9]{1,9}(\\.[0-9]{1,9}(\\.[0-9]{1,9}(\\.[0-9A-Za-z_-]+)?)?)?";
+	public final static Pattern	VERSION							= Pattern.compile(VERSION_STRING);
+	final static Pattern		FILTEROP						= Pattern.compile("=|<=|>=|~=");
+	public final static Pattern	VERSIONRANGE					= Pattern.compile("((\\(|\\[)"
+
+																+ VERSION_STRING + "," + VERSION_STRING + "(\\]|\\)))|"
+																		+ VERSION_STRING);
+	final static Pattern		FILE							= Pattern
+																		.compile("/?[^/\"\n\r\u0000]+(/[^/\"\n\r\u0000]+)*");
+	final static Pattern		WILDCARDPACKAGE					= Pattern
+																		.compile("((\\p{Alnum}|_)+(\\.(\\p{Alnum}|_)+)*(\\.\\*)?)|\\*");
+	public final static Pattern	ISO639							= Pattern.compile("[A-Z][A-Z]");
+	public final static Pattern	HEADER_PATTERN					= Pattern.compile("[A-Za-z0-9][-a-zA-Z0-9_]+");
+	public final static Pattern	TOKEN							= Pattern.compile("[-a-zA-Z0-9_]+");
+
+	public final static Pattern	NUMBERPATTERN					= Pattern.compile("\\d+");
+	public final static Pattern	PACKAGEPATTERN					= Pattern
+																		.compile("\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*(\\.\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*)*");
+	public final static Pattern	PATHPATTERN						= Pattern.compile(".*");
+	public final static Pattern	FQNPATTERN						= Pattern.compile(".*");
+	public final static Pattern	URLPATTERN						= Pattern.compile(".*");
+	public final static Pattern	ANYPATTERN						= Pattern.compile(".*");
+	public final static Pattern	FILTERPATTERN					= Pattern.compile(".*");
+	public final static Pattern	TRUEORFALSEPATTERN				= Pattern.compile("true|false|TRUE|FALSE");
+	public static final Pattern	WILDCARDNAMEPATTERN				= Pattern.compile(".*");
+	public static final Pattern	BUNDLE_ACTIVATIONPOLICYPATTERN	= Pattern.compile("lazy");
+
+	public final static String	EES[]							= {
+			"CDC-1.0/Foundation-1.0", "CDC-1.1/Foundation-1.1", "OSGi/Minimum-1.0", "OSGi/Minimum-1.1",
+			"OSGi/Minimum-1.2", "JRE-1.1", "J2SE-1.2", "J2SE-1.3", "J2SE-1.4", "J2SE-1.5", "JavaSE-1.6", "JavaSE-1.7",
+			"PersonalJava-1.1", "PersonalJava-1.2", "CDC-1.0/PersonalBasis-1.0", "CDC-1.0/PersonalJava-1.0"
+																};
+
+	public final static String	OSNAMES[]						= {
+			"AIX", // IBM
+			"DigitalUnix", // Compaq
+			"Embos", // Segger Embedded Software Solutions
+			"Epoc32", // SymbianOS Symbian OS
+			"FreeBSD", // Free BSD
+			"HPUX", // hp-ux Hewlett Packard
+			"IRIX", // Silicon Graphics
+			"Linux", // Open source
+			"MacOS", // Apple
+			"NetBSD", // Open source
+			"Netware", // Novell
+			"OpenBSD", // Open source
+			"OS2", // OS/2 IBM
+			"QNX", // procnto QNX
+			"Solaris", // Sun (almost an alias of SunOS)
+			"SunOS", // Sun Microsystems
+			"VxWorks", // WindRiver Systems
+			"Windows95", "Win32", "Windows98", "WindowsNT", "WindowsCE", "Windows2000", // Win2000
+			"Windows2003", // Win2003
+			"WindowsXP", "WindowsVista",
+																};
+
+	public final static String	PROCESSORNAMES[]				= { //
+			//
+			"68k", // Motorola 68000
+			"ARM_LE", // Intel Strong ARM. Deprecated because it does not
+			// specify the endianness. See the following two rows.
+			"arm_le", // Intel Strong ARM Little Endian mode
+			"arm_be", // Intel String ARM Big Endian mode
+			"Alpha", //
+			"ia64n",// Hewlett Packard 32 bit
+			"ia64w",// Hewlett Packard 64 bit mode
+			"Ignite", // psc1k PTSC
+			"Mips", // SGI
+			"PArisc", // Hewlett Packard
+			"PowerPC", // power ppc Motorola/IBM Power PC
+			"Sh4", // Hitachi
+			"Sparc", // SUN
+			"Sparcv9", // SUN
+			"S390", // IBM Mainframe 31 bit
+			"S390x", // IBM Mainframe 64-bit
+			"V850E", // NEC V850E
+			"x86", // pentium i386
+			"i486", // i586 i686 Intel& AMD 32 bit
+			"x86-64",
+																};
+
+	final Analyzer				analyzer;
+	private Instructions		dynamicImports;
+
+	public Verifier(Jar jar) throws Exception {
+		this.analyzer = new Analyzer(this);
+		this.analyzer.use(this);
+		addClose(analyzer);
+		this.analyzer.setJar(jar);
+		this.manifest = this.analyzer.calcManifest();
+		this.main = Domain.domain(manifest);
+		this.dot = jar;
+		getInfo(analyzer);
+	}
+
+	public Verifier(Analyzer analyzer) throws Exception {
+		this.analyzer = analyzer;
+		this.dot = analyzer.getJar();
+		this.manifest = dot.getManifest();
+		this.main = Domain.domain(manifest);
+	}
+
+	private void verifyHeaders() {
+		for (String h : main) {
+			if (!HEADER_PATTERN.matcher(h).matches())
+				error("Invalid Manifest header: " + h + ", pattern=" + HEADER_PATTERN);
+		}
+	}
+
+	/*
+	 * Bundle-NativeCode ::= nativecode ( ',' nativecode )* ( ’,’ optional) ?
+	 * nativecode ::= path ( ';' path )* // See 1.4.2 ( ';' parameter )+
+	 * optional ::= ’*’
+	 */
+	public void verifyNative() {
+		String nc = get("Bundle-NativeCode");
+		doNative(nc);
+	}
+
+	public void doNative(String nc) {
+		if (nc != null) {
+			QuotedTokenizer qt = new QuotedTokenizer(nc, ",;=", false);
+			char del;
+			do {
+				do {
+					String name = qt.nextToken();
+					if (name == null) {
+						error("Can not parse name from bundle native code header: " + nc);
+						return;
+					}
+					del = qt.getSeparator();
+					if (del == ';') {
+						if (dot != null && !dot.exists(name)) {
+							error("Native library not found in JAR: " + name);
+						}
+					} else {
+						String value = null;
+						if (del == '=')
+							value = qt.nextToken();
+
+						String key = name.toLowerCase();
+						if (key.equals("osname")) {
+							// ...
+						} else if (key.equals("osversion")) {
+							// verify version range
+							verify(value, VERSIONRANGE);
+						} else if (key.equals("language")) {
+							verify(value, ISO639);
+						} else if (key.equals("processor")) {
+							// verify(value, PROCESSORS);
+						} else if (key.equals("selection-filter")) {
+							// verify syntax filter
+							verifyFilter(value);
+						} else if (name.equals("*") && value == null) {
+							// Wildcard must be at end.
+							if (qt.nextToken() != null)
+								error("Bundle-Native code header may only END in wildcard: nc");
+						} else {
+							warning("Unknown attribute in native code: " + name + "=" + value);
+						}
+						del = qt.getSeparator();
+					}
+				} while (del == ';');
+			} while (del == ',');
+		}
+	}
+
+	public boolean verifyFilter(String value) {
+		String s = validateFilter(value);
+		if (s == null)
+			return true;
+
+		error(s);
+		return false;
+	}
+
+	public static String validateFilter(String value) {
+		try {
+			verifyFilter(value, 0);
+			return null;
+		}
+		catch (Exception e) {
+			return "Not a valid filter: " + value + e.getMessage();
+		}
+	}
+
+	private void verifyActivator() throws Exception {
+		String bactivator = main.get("Bundle-Activator");
+		if (bactivator != null) {
+			TypeRef ref = analyzer.getTypeRefFromFQN(bactivator);
+			if (analyzer.getClassspace().containsKey(ref))
+				return;
+
+			PackageRef packageRef = ref.getPackageRef();
+			if (packageRef.isDefaultPackage())
+				error("The Bundle Activator is not in the bundle and it is in the default package ");
+			else if (!analyzer.isImported(packageRef)) {
+				error("Bundle-Activator not found on the bundle class path nor in imports: " + bactivator);
+			}
+		}
+	}
+
+	private void verifyComponent() {
+		String serviceComponent = main.get("Service-Component");
+		if (serviceComponent != null) {
+			Parameters map = parseHeader(serviceComponent);
+			for (String component : map.keySet()) {
+				if (component.indexOf("*") < 0 && !dot.exists(component)) {
+					error("Service-Component entry can not be located in JAR: " + component);
+				} else {
+					// validate component ...
+				}
+			}
+		}
+	}
+
+	/**
+	 * Check for unresolved imports. These are referrals that are not imported
+	 * by the manifest and that are not part of our bundle class path. The are
+	 * calculated by removing all the imported packages and contained from the
+	 * referred packages.
+	 */
+	private void verifyUnresolvedReferences() {
+		Set<PackageRef> unresolvedReferences = new TreeSet<PackageRef>(analyzer.getReferred().keySet());
+		unresolvedReferences.removeAll(analyzer.getImports().keySet());
+		unresolvedReferences.removeAll(analyzer.getContained().keySet());
+
+		// Remove any java.** packages.
+		for (Iterator<PackageRef> p = unresolvedReferences.iterator(); p.hasNext();) {
+			PackageRef pack = p.next();
+			if (pack.isJava())
+				p.remove();
+			else {
+				// Remove any dynamic imports
+				if (isDynamicImport(pack))
+					p.remove();
+			}
+		}
+
+		if (!unresolvedReferences.isEmpty()) {
+			// Now we want to know the
+			// classes that are the culprits
+			Set<String> culprits = new HashSet<String>();
+			for (Clazz clazz : analyzer.getClassspace().values()) {
+				if (hasOverlap(unresolvedReferences, clazz.getReferred()))
+					culprits.add(clazz.getAbsolutePath());
+			}
+
+			error("Unresolved references to %s by class(es) %s on the Bundle-Classpath: %s", unresolvedReferences,
+					culprits, analyzer.getBundleClasspath().keySet());
+		}
+	}
+
+	/**
+	 * @param p
+	 * @param pack
+	 */
+	private boolean isDynamicImport(PackageRef pack) {
+		if (dynamicImports == null)
+			dynamicImports = new Instructions(main.getDynamicImportPackage());
+
+		return dynamicImports.matches(pack.getFQN());
+	}
+
+	private boolean hasOverlap(Set< ? > a, Set< ? > b) {
+		for (Iterator< ? > i = a.iterator(); i.hasNext();) {
+			if (b.contains(i.next()))
+				return true;
+		}
+		return false;
+	}
+
+	public void verify() throws Exception {
+		verifyHeaders();
+		verifyDirectives("Export-Package", "uses:|mandatory:|include:|exclude:|" + IMPORT_DIRECTIVE, PACKAGEPATTERN,
+				"package");
+		verifyDirectives("Import-Package", "resolution:", PACKAGEPATTERN, "package");
+		verifyDirectives("Require-Bundle", "visibility:|resolution:", SYMBOLICNAME, "bsn");
+		verifyDirectives("Fragment-Host", "extension:", SYMBOLICNAME, "bsn");
+		verifyDirectives("Provide-Capability", "effective:|uses:", null, null);
+		verifyDirectives("Require-Capability", "effective:|resolution:|filter:", null, null);
+		verifyDirectives("Bundle-SymbolicName", "singleton:|fragment-attachment:|mandatory:", SYMBOLICNAME, "bsn");
+
+		verifyManifestFirst();
+		verifyActivator();
+		verifyActivationPolicy();
+		verifyComponent();
+		verifyNative();
+		verifyUnresolvedReferences();
+		verifySymbolicName();
+		verifyListHeader("Bundle-RequiredExecutionEnvironment", EENAME, false);
+		verifyHeader("Bundle-ManifestVersion", BUNDLEMANIFESTVERSION, false);
+		verifyHeader("Bundle-Version", VERSION, true);
+		verifyListHeader("Bundle-Classpath", FILE, false);
+		verifyDynamicImportPackage();
+		verifyBundleClasspath();
+		verifyUses();
+		if (usesRequire) {
+			if (!getErrors().isEmpty()) {
+				getWarnings()
+						.add(0,
+								"Bundle uses Require Bundle, this can generate false errors because then not enough information is available without the required bundles");
+			}
+		}
+
+		verifyRequirements();
+		verifyCapabilities();
+	}
+
+	private void verifyRequirements() {
+		Parameters map = parseHeader(manifest.getMainAttributes().getValue(Constants.REQUIRE_CAPABILITY));
+		for (String key : map.keySet()) {
+			Attrs attrs = map.get(key);
+			verify(attrs, "filter:", FILTERPATTERN, false, "Requirement %s filter not correct", key);
+			verify(attrs, "cardinality:", CARDINALITY_PATTERN, false, "Requirement %s cardinality not correct", key);
+			verify(attrs, "resolution:", RESOLUTION_PATTERN, false, "Requirement %s resolution not correct", key);
+
+			if (key.equals("osgi.extender")) {
+				// No requirements on extender
+			} else if (key.equals("osgi.serviceloader")) {
+				verify(attrs, "register:", PACKAGEPATTERN, false,
+						"Service Loader extender register: directive not a fully qualified Java name");
+			} else if (key.equals("osgi.contract")) {
+
+			} else if (key.equals("osgi.service")) {
+
+			} else if (key.equals("osgi.ee")) {
+
+			} else if (key.startsWith("osgi.wiring.") || key.startsWith("osgi.identity")) {
+				error("osgi.wiring.* namespaces must not be specified with generic requirements/capabilities");
+			}
+
+			verifyAttrs(attrs);
+
+			if (attrs.containsKey("mandatory:"))
+				error("mandatory: directive is intended for Capabilities, not Requirement %s", key);
+
+			if (attrs.containsKey("uses:"))
+				error("uses: directive is intended for Capabilities, not Requirement %s", key);
+		}
+	}
+
+	/**
+	 * @param attrs
+	 */
+	void verifyAttrs(Attrs attrs) {
+		for (String a : attrs.keySet()) {
+			String v = attrs.get(a);
+
+			if (!a.endsWith(":")) {
+				Attrs.Type t = attrs.getType(a);
+				if ("version".equals(a)) {
+					if (t != Attrs.Type.VERSION)
+						error("Version attributes should always be of type version, it is %s", t);
+				} else
+					verifyType(t, v);
+			}
+		}
+	}
+
+	private void verifyCapabilities() {
+		Parameters map = parseHeader(manifest.getMainAttributes().getValue(Constants.PROVIDE_CAPABILITY));
+		for (String key : map.keySet()) {
+			Attrs attrs = map.get(key);
+			verify(attrs, "cardinality:", CARDINALITY_PATTERN, false, "Requirement %s cardinality not correct", key);
+			verify(attrs, "resolution:", RESOLUTION_PATTERN, false, "Requirement %s resolution not correct", key);
+
+			if (key.equals("osgi.extender")) {
+				verify(attrs, "osgi.extender", SYMBOLICNAME, true,
+						"Extender %s must always have the osgi.extender attribute set", key);
+				verify(attrs, "version", VERSION, true, "Extender %s must always have a version", key);
+			} else if (key.equals("osgi.serviceloader")) {
+				verify(attrs, "register:", PACKAGEPATTERN, false,
+						"Service Loader extender register: directive not a fully qualified Java name");
+			} else if (key.equals("osgi.contract")) {
+				verify(attrs, "osgi.contract", SYMBOLICNAME, true,
+						"Contracts %s must always have the osgi.contract attribute set", key);
+
+			} else if (key.equals("osgi.service")) {
+				verify(attrs, "objectClass", PACKAGEPATTERN, true,
+						"osgi.service %s must have the objectClass attribute set", key);
+
+			} else if (key.equals("osgi.ee")) {
+				// TODO
+			} else if (key.startsWith("osgi.wiring.") || key.startsWith("osgi.identity")) {
+				error("osgi.wiring.* namespaces must not be specified with generic requirements/capabilities");
+			}
+
+			verifyAttrs(attrs);
+
+			if (attrs.containsKey("filter:"))
+				error("filter: directive is intended for Requirements, not Capability %s", key);
+			if (attrs.containsKey("cardinality:"))
+				error("cardinality: directive is intended for Requirements, not Capability %s", key);
+			if (attrs.containsKey("resolution:"))
+				error("resolution: directive is intended for Requirements, not Capability %s", key);
+		}
+	}
+
+	private void verify(Attrs attrs, String ad, Pattern pattern, boolean mandatory, String msg, String... args) {
+		String v = attrs.get(ad);
+		if (v == null) {
+			if (mandatory)
+				error("Missing required attribute/directive %s", ad);
+		} else {
+			Matcher m = pattern.matcher(v);
+			if (!m.matches())
+				error(msg, (Object[]) args);
+		}
+	}
+
+	private void verifyType(@SuppressWarnings("unused") Attrs.Type type, @SuppressWarnings("unused") String string) {
+
+	}
+
+	/**
+	 * Verify if the header does not contain any other directives
+	 * 
+	 * @param header
+	 * @param directives
+	 */
+	private void verifyDirectives(String header, String directives, Pattern namePattern, String type) {
+		Pattern pattern = Pattern.compile(directives);
+		Parameters map = parseHeader(manifest.getMainAttributes().getValue(header));
+		for (Entry<String,Attrs> entry : map.entrySet()) {
+			String pname = removeDuplicateMarker(entry.getKey());
+
+			if (namePattern != null) {
+				if (!namePattern.matcher(pname).matches())
+					if (isPedantic())
+						error("Invalid %s name: '%s'", type, pname);
+					else
+						warning("Invalid %s name: '%s'", type, pname);
+			}
+
+			for (String key : entry.getValue().keySet()) {
+				if (key.endsWith(":")) {
+					if (!key.startsWith("x-")) {
+						Matcher m = pattern.matcher(key);
+						if (m.matches())
+							continue;
+
+						warning("Unknown directive %s in %s, allowed directives are %s, and 'x-*'.", key, header,
+								directives.replace('|', ','));
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * Verify the use clauses
+	 */
+	private void verifyUses() {
+		// Set<String> uses = Create.set();
+		// for ( Map<String,String> attrs : analyzer.getExports().values()) {
+		// if ( attrs.containsKey(Constants.USES_DIRECTIVE)) {
+		// String s = attrs.get(Constants.USES_DIRECTIVE);
+		// uses.addAll( split(s));
+		// }
+		// }
+		// uses.removeAll(analyzer.getExports().keySet());
+		// uses.removeAll(analyzer.getImports().keySet());
+		// if ( !uses.isEmpty())
+		// warning("Export-Package uses: directive contains packages that are not imported nor exported: %s",
+		// uses);
+	}
+
+	public boolean verifyActivationPolicy() {
+		String policy = main.get(Constants.BUNDLE_ACTIVATIONPOLICY);
+		if (policy == null)
+			return true;
+
+		return verifyActivationPolicy(policy);
+	}
+
+	public boolean verifyActivationPolicy(String policy) {
+		Parameters map = parseHeader(policy);
+		if (map.size() == 0)
+			warning("Bundle-ActivationPolicy is set but has no argument %s", policy);
+		else if (map.size() > 1)
+			warning("Bundle-ActivationPolicy has too many arguments %s", policy);
+		else {
+			Map<String,String> s = map.get("lazy");
+			if (s == null)
+				warning("Bundle-ActivationPolicy set but is not set to lazy: %s", policy);
+			else
+				return true;
+		}
+
+		return false;
+	}
+
+	public void verifyBundleClasspath() {
+		Parameters bcp = main.getBundleClassPath();
+		if (bcp.isEmpty() || bcp.containsKey("."))
+			return;
+
+		for (String path : bcp.keySet()) {
+			if (path.endsWith("/"))
+				error("A Bundle-ClassPath entry must not end with '/': %s", path);
+
+			if (dot.getDirectories().containsKey(path))
+				// We assume that any classes are in a directory
+				// and therefore do not care when the bundle is included
+				return;
+		}
+
+		for (String path : dot.getResources().keySet()) {
+			if (path.endsWith(".class")) {
+				warning("The Bundle-Classpath does not contain the actual bundle JAR (as specified with '.' in the Bundle-Classpath) but the JAR does contain classes. Is this intentional?");
+				return;
+			}
+		}
+	}
+
+	/**
+	 * <pre>
+	 *          DynamicImport-Package ::= dynamic-description
+	 *              ( ',' dynamic-description )*
+	 *              
+	 *          dynamic-description::= wildcard-names ( ';' parameter )*
+	 *          wildcard-names ::= wildcard-name ( ';' wildcard-name )*
+	 *          wildcard-name ::= package-name 
+	 *                         | ( package-name '.*' ) // See 1.4.2
+	 *                         | '*'
+	 * </pre>
+	 */
+	private void verifyDynamicImportPackage() {
+		verifyListHeader("DynamicImport-Package", WILDCARDPACKAGE, true);
+		String dynamicImportPackage = get("DynamicImport-Package");
+		if (dynamicImportPackage == null)
+			return;
+
+		Parameters map = main.getDynamicImportPackage();
+		for (String name : map.keySet()) {
+			name = name.trim();
+			if (!verify(name, WILDCARDPACKAGE))
+				error("DynamicImport-Package header contains an invalid package name: " + name);
+
+			Map<String,String> sub = map.get(name);
+			if (r3 && sub.size() != 0) {
+				error("DynamicPackage-Import has attributes on import: " + name
+						+ ". This is however, an <=R3 bundle and attributes on this header were introduced in R4. ");
+			}
+		}
+	}
+
+	private void verifyManifestFirst() {
+		if (!dot.isManifestFirst()) {
+			error("Invalid JAR stream: Manifest should come first to be compatible with JarInputStream, it was not");
+		}
+	}
+
+	private void verifySymbolicName() {
+		Parameters bsn = parseHeader(main.get(Analyzer.BUNDLE_SYMBOLICNAME));
+		if (!bsn.isEmpty()) {
+			if (bsn.size() > 1)
+				error("More than one BSN specified " + bsn);
+
+			String name = bsn.keySet().iterator().next();
+			if (!isBsn(name)) {
+				error("Symbolic Name has invalid format: " + name);
+			}
+		}
+	}
+
+	/**
+	 * @param name
+	 * @return
+	 */
+	public static boolean isBsn(String name) {
+		return SYMBOLICNAME.matcher(name).matches();
+	}
+
+	/**
+	 * <pre>
+	 *         filter ::= ’(’ filter-comp ’)’
+	 *         filter-comp ::= and | or | not | operation
+	 *         and ::= ’&’ filter-list
+	 *         or ::= ’|’ filter-list
+	 *         not ::= ’!’ filter
+	 *         filter-list ::= filter | filter filter-list
+	 *         operation ::= simple | present | substring
+	 *         simple ::= attr filter-type value
+	 *         filter-type ::= equal | approx | greater | less
+	 *         equal ::= ’=’
+	 *         approx ::= ’˜=’
+	 *         greater ::= ’>=’
+	 *         less ::= ’<=’
+	 *         present ::= attr ’=*’
+	 *         substring ::= attr ’=’ initial any final
+	 *         inital ::= () | value
+	 *         any ::= ’*’ star-value
+	 *         star-value ::= () | value ’*’ star-value
+	 *         final ::= () | value
+	 *         value ::= <see text>
+	 * </pre>
+	 * 
+	 * @param expr
+	 * @param index
+	 * @return
+	 */
+
+	public static int verifyFilter(String expr, int index) {
+		try {
+			while (Character.isWhitespace(expr.charAt(index)))
+				index++;
+
+			if (expr.charAt(index) != '(')
+				throw new IllegalArgumentException("Filter mismatch: expected ( at position " + index + " : " + expr);
+
+			index++; // skip (
+
+			while (Character.isWhitespace(expr.charAt(index)))
+				index++;
+
+			switch (expr.charAt(index)) {
+				case '!' :
+					index++; // skip !
+					while (Character.isWhitespace(expr.charAt(index)))
+						index++;
+
+					if (expr.charAt(index) != '(')
+						throw new IllegalArgumentException("Filter mismatch: ! (not) must have one sub expression "
+								+ index + " : " + expr);
+					while (Character.isWhitespace(expr.charAt(index)))
+						index++;
+
+					index = verifyFilter(expr, index);
+					while (Character.isWhitespace(expr.charAt(index)))
+						index++;
+					if (expr.charAt(index) != ')')
+						throw new IllegalArgumentException("Filter mismatch: expected ) at position " + index + " : "
+								+ expr);
+					return index + 1;
+
+				case '&' :
+				case '|' :
+					index++; // skip operator
+					while (Character.isWhitespace(expr.charAt(index)))
+						index++;
+					while (expr.charAt(index) == '(') {
+						index = verifyFilter(expr, index);
+						while (Character.isWhitespace(expr.charAt(index)))
+							index++;
+					}
+
+					if (expr.charAt(index) != ')')
+						throw new IllegalArgumentException("Filter mismatch: expected ) at position " + index + " : "
+								+ expr);
+					return index + 1; // skip )
+
+				default :
+					index = verifyFilterOperation(expr, index);
+					if (expr.charAt(index) != ')')
+						throw new IllegalArgumentException("Filter mismatch: expected ) at position " + index + " : "
+								+ expr);
+					return index + 1;
+			}
+		}
+		catch (IndexOutOfBoundsException e) {
+			throw new IllegalArgumentException("Filter mismatch: early EOF from " + index);
+		}
+	}
+
+	static private int verifyFilterOperation(String expr, int index) {
+		StringBuilder sb = new StringBuilder();
+		while ("=><~()".indexOf(expr.charAt(index)) < 0) {
+			sb.append(expr.charAt(index++));
+		}
+		String attr = sb.toString().trim();
+		if (attr.length() == 0)
+			throw new IllegalArgumentException("Filter mismatch: attr at index " + index + " is 0");
+		sb = new StringBuilder();
+		while ("=><~".indexOf(expr.charAt(index)) >= 0) {
+			sb.append(expr.charAt(index++));
+		}
+		String operator = sb.toString();
+		if (!verify(operator, FILTEROP))
+			throw new IllegalArgumentException("Filter error, illegal operator " + operator + " at index " + index);
+
+		sb = new StringBuilder();
+		while (")".indexOf(expr.charAt(index)) < 0) {
+			switch (expr.charAt(index)) {
+				case '\\' :
+					if ("\\)(*".indexOf(expr.charAt(index + 1)) >= 0)
+						index++;
+					else
+						throw new IllegalArgumentException("Filter error, illegal use of backslash at index " + index
+								+ ". Backslash may only be used before * or () or \\");
+			}
+			sb.append(expr.charAt(index++));
+		}
+		return index;
+	}
+
+	private boolean verifyHeader(String name, Pattern regex, boolean error) {
+		String value = manifest.getMainAttributes().getValue(name);
+		if (value == null)
+			return false;
+
+		QuotedTokenizer st = new QuotedTokenizer(value.trim(), ",");
+		for (Iterator<String> i = st.getTokenSet().iterator(); i.hasNext();) {
+			if (!verify(i.next(), regex)) {
+				String msg = "Invalid value for " + name + ", " + value + " does not match " + regex.pattern();
+				if (error)
+					error(msg);
+				else
+					warning(msg);
+			}
+		}
+		return true;
+	}
+
+	static private boolean verify(String value, Pattern regex) {
+		return regex.matcher(value).matches();
+	}
+
+	private boolean verifyListHeader(String name, Pattern regex, boolean error) {
+		String value = manifest.getMainAttributes().getValue(name);
+		if (value == null)
+			return false;
+
+		Parameters map = parseHeader(value);
+		for (String header : map.keySet()) {
+			if (!regex.matcher(header).matches()) {
+				String msg = "Invalid value for " + name + ", " + value + " does not match " + regex.pattern();
+				if (error)
+					error(msg);
+				else
+					warning(msg);
+			}
+		}
+		return true;
+	}
+
+	@Override
+	public String getProperty(String key, String deflt) {
+		if (properties == null)
+			return deflt;
+		return properties.getProperty(key, deflt);
+	}
+
+	public static boolean isVersion(String version) {
+		return VERSION.matcher(version).matches();
+	}
+
+	public static boolean isIdentifier(String value) {
+		if (value.length() < 1)
+			return false;
+
+		if (!Character.isJavaIdentifierStart(value.charAt(0)))
+			return false;
+
+		for (int i = 1; i < value.length(); i++) {
+			if (!Character.isJavaIdentifierPart(value.charAt(i)))
+				return false;
+		}
+		return true;
+	}
+
+	public static boolean isMember(String value, String[] matches) {
+		for (String match : matches) {
+			if (match.equals(value))
+				return true;
+		}
+		return false;
+	}
+
+	public static boolean isFQN(String name) {
+		if (name.length() == 0)
+			return false;
+		if (!Character.isJavaIdentifierStart(name.charAt(0)))
+			return false;
+
+		for (int i = 1; i < name.length(); i++) {
+			char c = name.charAt(i);
+			if (Character.isJavaIdentifierPart(c) || c == '$' || c == '.')
+				continue;
+
+			return false;
+		}
+
+		return true;
+	}
+
+	/**
+	 * Verify checksums
+	 */
+	/**
+	 * Verify the checksums from the manifest against the real thing.
+	 * 
+	 * @param all
+	 *            if each resources must be digested
+	 * @return true if ok
+	 * @throws Exception
+	 */
+
+	public void verifyChecksums(boolean all) throws Exception {
+		Manifest m = dot.getManifest();
+		if (m == null || m.getEntries().isEmpty()) {
+			if (all)
+				error("Verify checksums with all but no digests");
+			return;
+		}
+
+		List<String> missingDigest = new ArrayList<String>();
+
+		for (String path : dot.getResources().keySet()) {
+			if (path.equals("META-INF/MANIFEST.MF"))
+				continue;
+
+			Attributes a = m.getAttributes(path);
+			String digest = a.getValue("SHA1-Digest");
+			if (digest == null) {
+				if (!path.matches(""))
+					missingDigest.add(path);
+			} else {
+				byte[] d = Base64.decodeBase64(digest);
+				SHA1 expected = new SHA1(d);
+				Digester<SHA1> digester = SHA1.getDigester();
+				InputStream in = dot.getResource(path).openInputStream();
+				IO.copy(in, digester);
+				digester.digest();
+				if (!expected.equals(digester.digest())) {
+					error("Checksum mismatch %s, expected %s, got %s", path, expected, digester.digest());
+				}
+			}
+		}
+		if (missingDigest.size() > 0) {
+			error("Entries in the manifest are missing digests: %s", missingDigest);
+		}
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/WriteResource.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/WriteResource.java
new file mode 100644
index 0000000..ed72c41
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/WriteResource.java
@@ -0,0 +1,75 @@
+package aQute.bnd.osgi;
+
+import java.io.*;
+
+public abstract class WriteResource implements Resource {
+	String			extra;
+	volatile long	size	= -1;
+
+	public InputStream openInputStream() throws Exception {
+		PipedInputStream pin = new PipedInputStream();
+		final PipedOutputStream pout = new PipedOutputStream(pin);
+		Thread t = new Thread() {
+			@Override
+			public void run() {
+				try {
+					write(pout);
+					pout.flush();
+				}
+				catch (Exception e) {
+					e.printStackTrace();
+				}
+				finally {
+					try {
+						pout.close();
+					}
+					catch (IOException e) {
+						// Ignore
+					}
+				}
+			}
+		};
+		t.start();
+		return pin;
+	}
+
+	public abstract void write(OutputStream out) throws IOException, Exception;
+
+	public abstract long lastModified();
+
+	public String getExtra() {
+		return extra;
+	}
+
+	public void setExtra(String extra) {
+		this.extra = extra;
+	}
+
+	static class CountingOutputStream extends OutputStream {
+		long	size;
+
+		@Override
+		public void write(int var0) throws IOException {
+			size++;
+		}
+
+		@Override
+		public void write(byte[] buffer) throws IOException {
+			size += buffer.length;
+		}
+
+		@Override
+		public void write(byte[] buffer, int start, int length) throws IOException {
+			size += length;
+		}
+	}
+
+	public long size() throws IOException, Exception {
+		if (size == -1) {
+			CountingOutputStream cout = new CountingOutputStream();
+			write(cout);
+			size = cout.size;
+		}
+		return size;
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/ZipResource.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/ZipResource.java
new file mode 100755
index 0000000..1101945
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/ZipResource.java
@@ -0,0 +1,84 @@
+package aQute.bnd.osgi;
+
+import java.io.*;
+import java.util.*;
+import java.util.regex.*;
+import java.util.zip.*;
+
+public class ZipResource implements Resource {
+	ZipFile		zip;
+	ZipEntry	entry;
+	long		lastModified;
+	String		extra;
+
+	ZipResource(ZipFile zip, ZipEntry entry, long lastModified) throws UnsupportedEncodingException {
+		this.zip = zip;
+		this.entry = entry;
+		this.lastModified = lastModified;
+		byte[] data = entry.getExtra();
+		if (data != null)
+			this.extra = new String(data, "UTF-8");
+	}
+
+	public InputStream openInputStream() throws IOException {
+		return zip.getInputStream(entry);
+	}
+
+	@Override
+	public String toString() {
+		return ":" + zip.getName() + "(" + entry.getName() + "):";
+	}
+
+	public static ZipFile build(Jar jar, File file) throws ZipException, IOException {
+		return build(jar, file, null);
+	}
+
+	public static ZipFile build(Jar jar, File file, Pattern pattern) throws ZipException, IOException {
+
+		try {
+			ZipFile zip = new ZipFile(file);
+			nextEntry: for (Enumeration< ? extends ZipEntry> e = zip.entries(); e.hasMoreElements();) {
+				ZipEntry entry = e.nextElement();
+				if (pattern != null) {
+					Matcher m = pattern.matcher(entry.getName());
+					if (!m.matches())
+						continue nextEntry;
+				}
+				if (!entry.isDirectory()) {
+					long time = entry.getTime();
+					if (time <= 0)
+						time = file.lastModified();
+					jar.putResource(entry.getName(), new ZipResource(zip, entry, time), true);
+				}
+			}
+			return zip;
+		}
+		catch (ZipException ze) {
+			throw new ZipException("The JAR/ZIP file (" + file.getAbsolutePath() + ") seems corrupted, error: "
+					+ ze.getMessage());
+		}
+		catch (FileNotFoundException e) {
+			throw new IllegalArgumentException("Problem opening JAR: " + file.getAbsolutePath());
+		}
+	}
+
+	public void write(OutputStream out) throws Exception {
+		FileResource.copy(this, out);
+	}
+
+	public long lastModified() {
+		return lastModified;
+	}
+
+	public String getExtra() {
+		return extra;
+	}
+
+	public void setExtra(String extra) {
+		this.extra = extra;
+	}
+
+	public long size() {
+		return entry.getSize();
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/bnd.info b/biz.aQute.bndlib/src/aQute/bnd/osgi/bnd.info
new file mode 100644
index 0000000..ee80a6b
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/bnd.info
@@ -0,0 +1,2 @@
+version = ${Bundle-Version}
+lastmodified = ${now}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/eclipse/EclipseClasspath.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/eclipse/EclipseClasspath.java
new file mode 100755
index 0000000..3a9371c
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/eclipse/EclipseClasspath.java
@@ -0,0 +1,238 @@
+package aQute.bnd.osgi.eclipse;
+
+import java.io.*;
+import java.util.*;
+import java.util.regex.*;
+
+import javax.xml.parsers.*;
+
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+import aQute.service.reporter.*;
+
+/**
+ * Parse the Eclipse project information for the classpath. Unfortunately, it is
+ * impossible to read the variables. They are ignored but that can cause
+ * problems.
+ * 
+ * @version $Revision: 1.2 $
+ */
+public class EclipseClasspath {
+	static DocumentBuilderFactory	documentBuilderFactory	= DocumentBuilderFactory.newInstance();
+	DocumentBuilder					db;
+	File							project;
+	File							workspace;
+	Set<File>						sources					= new LinkedHashSet<File>();
+	Set<File>						allSources				= new LinkedHashSet<File>();
+
+	Set<File>						classpath				= new LinkedHashSet<File>();
+	List<File>						dependents				= new ArrayList<File>();
+	File							output;
+	boolean							recurse					= true;
+	Set<File>						exports					= new LinkedHashSet<File>();
+	Map<String,String>				properties				= new HashMap<String,String>();
+	Reporter						reporter;
+	int								options;
+	Set<File>						bootclasspath			= new LinkedHashSet<File>();
+
+	public final static int			DO_VARIABLES			= 1;
+
+	/**
+	 * Parse an Eclipse project structure to discover the classpath.
+	 * 
+	 * @param workspace
+	 *            Points to workspace
+	 * @param project
+	 *            Points to project
+	 * @throws ParserConfigurationException
+	 * @throws SAXException
+	 * @throws IOException
+	 */
+
+	public EclipseClasspath(Reporter reporter, File workspace, File project, @SuppressWarnings("unused") int options) throws Exception {
+		this.project = project.getCanonicalFile();
+		this.workspace = workspace.getCanonicalFile();
+		this.reporter = reporter;
+		db = documentBuilderFactory.newDocumentBuilder();
+		parse(this.project, true);
+		db = null;
+	}
+
+	public EclipseClasspath(Reporter reporter, File workspace, File project) throws Exception {
+		this(reporter, workspace, project, 0);
+	}
+
+	/**
+	 * Recursive routine to parse the files. If a sub project is detected, it is
+	 * parsed before the parsing continues. This should give the right order.
+	 * 
+	 * @param project
+	 *            Project directory
+	 * @param top
+	 *            If this is the top project
+	 * @throws ParserConfigurationException
+	 * @throws SAXException
+	 * @throws IOException
+	 */
+	void parse(File project, boolean top) throws ParserConfigurationException, SAXException, IOException {
+		File file = new File(project, ".classpath");
+		if (!file.exists())
+			throw new FileNotFoundException(".classpath file not found: " + file.getAbsolutePath());
+
+		Document doc = db.parse(file);
+		NodeList nodelist = doc.getDocumentElement().getElementsByTagName("classpathentry");
+
+		if (nodelist == null)
+			throw new IllegalArgumentException("Can not find classpathentry in classpath file");
+
+		for (int i = 0; i < nodelist.getLength(); i++) {
+			Node node = nodelist.item(i);
+			NamedNodeMap attrs = node.getAttributes();
+			String kind = get(attrs, "kind");
+			if ("src".equals(kind)) {
+				String path = get(attrs, "path");
+				// TODO boolean exported = "true".equalsIgnoreCase(get(attrs,
+				// "exported"));
+				if (path.startsWith("/")) {
+					// We have another project
+					File subProject = getFile(workspace, project, path);
+					if (recurse)
+						parse(subProject, false);
+					dependents.add(subProject.getCanonicalFile());
+				} else {
+					File src = getFile(workspace, project, path);
+					allSources.add(src);
+					if (top) {
+						// We only want the sources for our own project
+						// or we'll compile all at once. Not a good idea
+						// because project settings can differ.
+						sources.add(src);
+					}
+				}
+			} else if ("lib".equals(kind)) {
+				String path = get(attrs, "path");
+				boolean exported = "true".equalsIgnoreCase(get(attrs, "exported"));
+				if (top || exported) {
+					File jar = getFile(workspace, project, path);
+					if (jar.getName().startsWith("ee."))
+						bootclasspath.add(jar);
+					else
+						classpath.add(jar);
+					if (exported)
+						exports.add(jar);
+				}
+			} else if ("output".equals(kind)) {
+				String path = get(attrs, "path");
+				path = path.replace('/', File.separatorChar);
+				output = getFile(workspace, project, path);
+				classpath.add(output);
+				exports.add(output);
+			} else if ("var".equals(kind)) {
+				boolean exported = "true".equalsIgnoreCase(get(attrs, "exported"));
+				File lib = replaceVar(get(attrs, "path"));
+				File slib = replaceVar(get(attrs, "sourcepath"));
+				if (lib != null) {
+					classpath.add(lib);
+					if (exported)
+						exports.add(lib);
+				}
+				if (slib != null)
+					sources.add(slib);
+			} else if ("con".equals(kind)) {
+				// Should do something useful ...
+			}
+		}
+	}
+
+	private File getFile(File abs, File relative, String opath) {
+		String path = opath.replace('/', File.separatorChar);
+		File result = new File(path);
+		if (result.isAbsolute() && result.isFile()) {
+			return result;
+		}
+		if (path.startsWith(File.separator)) {
+			result = abs;
+			path = path.substring(1);
+		} else
+			result = relative;
+
+		StringTokenizer st = new StringTokenizer(path, File.separator);
+		while (st.hasMoreTokens()) {
+			String token = st.nextToken();
+			result = new File(result, token);
+		}
+
+		if (!result.exists())
+			System.err.println("File not found: project=" + project + " workspace=" + workspace + " path=" + opath
+					+ " file=" + result);
+		return result;
+	}
+
+	static Pattern	PATH	= Pattern.compile("([A-Z_]+)/(.*)");
+
+	private File replaceVar(String path) {
+		if ((options & DO_VARIABLES) == 0)
+			return null;
+
+		Matcher m = PATH.matcher(path);
+		if (m.matches()) {
+			String var = m.group(1);
+			String remainder = m.group(2);
+			String base = properties.get(var);
+			if (base != null) {
+				File b = new File(base);
+				File f = new File(b, remainder.replace('/', File.separatorChar));
+				return f;
+			}
+			reporter.error("Can't find replacement variable for: " + path);
+		} else
+			reporter.error("Cant split variable path: " + path);
+		return null;
+	}
+
+	private String get(NamedNodeMap map, String name) {
+		Node node = map.getNamedItem(name);
+		if (node == null)
+			return null;
+
+		return node.getNodeValue();
+	}
+
+	public Set<File> getClasspath() {
+		return classpath;
+	}
+
+	public Set<File> getSourcepath() {
+		return sources;
+	}
+
+	public File getOutput() {
+		return output;
+	}
+
+	public List<File> getDependents() {
+		return dependents;
+	}
+
+	public void setRecurse(boolean recurse) {
+		this.recurse = recurse;
+	}
+
+	public Set<File> getExports() {
+		return exports;
+	}
+
+	public void setProperties(Map<String,String> map) {
+		this.properties = map;
+	}
+
+	public Set<File> getBootclasspath() {
+		return bootclasspath;
+	}
+
+	public Set<File> getAllSources() {
+		return allSources;
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/packageinfo b/biz.aQute.bndlib/src/aQute/bnd/osgi/packageinfo
new file mode 100644
index 0000000..a2afe57
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/packageinfo
@@ -0,0 +1 @@
+version 2.1.0
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/CapReq.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/CapReq.java
new file mode 100644
index 0000000..d5fe2c6
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/CapReq.java
@@ -0,0 +1,103 @@
+package aQute.bnd.osgi.resource;
+
+import java.util.*;
+
+import org.osgi.resource.*;
+
+class CapReq implements Capability, Requirement {
+	
+	static enum MODE { Capability, Requirement }
+	
+	private final MODE mode;
+	private final String	namespace;
+	private final Resource	resource;
+	private final Map<String,String>	directives;
+	private final Map<String,Object>	attributes;
+
+	CapReq(MODE mode, String namespace, Resource resource, Map<String, String> directives, Map<String, Object> attributes) {
+		this.mode = mode;
+		this.namespace = namespace;
+		this.resource = resource;
+		this.directives = new HashMap<String,String>(directives);
+		this.attributes = new HashMap<String,Object>(attributes);
+	}
+
+	public String getNamespace() {
+		return namespace;
+	}
+
+	public Map<String,String> getDirectives() {
+		return Collections.unmodifiableMap(directives);
+	}
+
+	public Map<String,Object> getAttributes() {
+		return Collections.unmodifiableMap(attributes);
+	}
+
+	public Resource getResource() {
+		return resource;
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((attributes == null) ? 0 : attributes.hashCode());
+		result = prime * result + ((directives == null) ? 0 : directives.hashCode());
+		result = prime * result + ((mode == null) ? 0 : mode.hashCode());
+		result = prime * result + ((namespace == null) ? 0 : namespace.hashCode());
+		result = prime * result + ((resource == null) ? 0 : resource.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		CapReq other = (CapReq) obj;
+		if (attributes == null) {
+			if (other.attributes != null)
+				return false;
+		} else if (!attributes.equals(other.attributes))
+			return false;
+		if (directives == null) {
+			if (other.directives != null)
+				return false;
+		} else if (!directives.equals(other.directives))
+			return false;
+		if (mode != other.mode)
+			return false;
+		if (namespace == null) {
+			if (other.namespace != null)
+				return false;
+		} else if (!namespace.equals(other.namespace))
+			return false;
+		if (resource == null) {
+			if (other.resource != null)
+				return false;
+		} else if (!resource.equals(other.resource))
+			return false;
+		return true;
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder builder = new StringBuilder();
+		if (mode == MODE.Capability) {
+			Object value = attributes.get(namespace);
+			builder.append(namespace).append('=').append(value);
+		} else {
+			String filter = directives.get(Namespace.REQUIREMENT_FILTER_DIRECTIVE);
+			builder.append(filter);
+			if (Namespace.RESOLUTION_OPTIONAL.equals(directives.get(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE))) {
+				builder.append("%OPT");
+			}
+		}
+		return builder.toString();
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/CapReqBuilder.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/CapReqBuilder.java
new file mode 100644
index 0000000..593dd39
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/CapReqBuilder.java
@@ -0,0 +1,97 @@
+package aQute.bnd.osgi.resource;
+
+import java.util.*;
+
+import org.osgi.framework.namespace.*;
+import org.osgi.resource.*;
+
+import aQute.bnd.osgi.resource.CapReq.MODE;
+import aQute.libg.filters.*;
+
+public class CapReqBuilder {
+
+	private final String				namespace;
+	private Resource					resource;
+	private final Map<String,Object>	attributes	= new HashMap<String,Object>();
+	private final Map<String,String>	directives	= new HashMap<String,String>();
+
+	public CapReqBuilder(String namespace) {
+		this.namespace = namespace;
+	}
+
+	public static CapReqBuilder clone(Capability capability) {
+		CapReqBuilder builder = new CapReqBuilder(capability.getNamespace());
+		builder.addAttributes(capability.getAttributes());
+		builder.addDirectives(capability.getDirectives());
+		return builder;
+	}
+
+	public static CapReqBuilder clone(Requirement requirement) {
+		CapReqBuilder builder = new CapReqBuilder(requirement.getNamespace());
+		builder.addAttributes(requirement.getAttributes());
+		builder.addDirectives(requirement.getDirectives());
+		return builder;
+	}
+
+	public String getNamespace() {
+		return namespace;
+	}
+
+	public CapReqBuilder setResource(Resource resource) {
+		this.resource = resource;
+		return this;
+	}
+
+	public CapReqBuilder addAttribute(String name, Object value) {
+		if (value != null)
+			attributes.put(name, value);
+		return this;
+	}
+
+	public CapReqBuilder addAttributes(Map< ? extends String, ? extends Object> attributes) {
+		this.attributes.putAll(attributes);
+		return this;
+	}
+
+	public CapReqBuilder addDirective(String name, String value) {
+		if (value != null)
+			directives.put(name, value);
+		return this;
+	}
+
+	public CapReqBuilder addDirectives(Map< ? extends String, ? extends String> directives) {
+		this.directives.putAll(directives);
+		return this;
+	}
+
+	public Capability buildCapability() {
+		// TODO check the thrown exception
+		if (resource == null)
+			throw new IllegalStateException("Cannot build Capability with null Resource.");
+		return new CapReq(MODE.Capability, namespace, resource, directives, attributes);
+	}
+
+	public Requirement buildRequirement() {
+		// TODO check the thrown exception
+		if (resource == null)
+			throw new IllegalStateException("Cannot build Requirement with null Resource.");
+		return new CapReq(MODE.Requirement, namespace, resource, directives, attributes);
+	}
+
+	public Requirement buildSyntheticRequirement() {
+		return new CapReq(MODE.Requirement, namespace, null, directives, attributes);
+	}
+
+	public static final CapReqBuilder createPackageRequirement(String pkgName, String range) {
+		Filter filter;
+		SimpleFilter pkgNameFilter = new SimpleFilter(PackageNamespace.PACKAGE_NAMESPACE, pkgName);
+		if (range != null)
+			filter = new AndFilter().addChild(pkgNameFilter).addChild(
+					new LiteralFilter(Filters.fromVersionRange(range)));
+		else
+			filter = pkgNameFilter;
+
+		return new CapReqBuilder(PackageNamespace.PACKAGE_NAMESPACE).addDirective(
+				Namespace.REQUIREMENT_FILTER_DIRECTIVE, filter.toString());
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/Filters.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/Filters.java
new file mode 100644
index 0000000..f12e7c8
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/Filters.java
@@ -0,0 +1,64 @@
+package aQute.bnd.osgi.resource;
+
+import org.osgi.framework.namespace.*;
+
+import aQute.bnd.version.*;
+import aQute.libg.filters.*;
+
+public class Filters {
+	
+	public static final String DEFAULT_VERSION_ATTR = IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE;
+	
+	/**
+	 * Generate an LDAP-style version filter from a version range, e.g.
+	 * {@code [1.0,2.0)} generates {@code (&(version>=1.0)(!(version>=2.0))}
+	 * 
+	 * @param range
+	 * @return The generated filter.
+	 * @throws IllegalArgumentException
+	 *             If the supplied range is invalid.
+	 */
+	public static String fromVersionRange(String range) throws IllegalArgumentException {
+		return fromVersionRange(range, DEFAULT_VERSION_ATTR);
+	}
+
+	/**
+	 * Generate an LDAP-style version filter from a version range, using a
+	 * specific attribute name for the version; for example can be used to
+	 * generate a range using the {@code bundle-version} attribute such as
+	 * {@code (&(bundle-version>=1.0)(!(bundle-version>=2.0))}.
+	 * 
+	 * @param range
+	 * @param versionAttr
+	 * @return The generated filter
+	 * @throws IllegalArgumentException
+	 *             If the supplied range is invalid.
+	 */
+	public static String fromVersionRange(String range, String versionAttr) throws IllegalArgumentException {
+		if (range == null)
+			return null;
+		VersionRange parsedRange = new VersionRange(range);
+		
+		Filter left;
+		if (parsedRange.includeLow())
+			left = new SimpleFilter(versionAttr, Operator.GreaterThanOrEqual, parsedRange.getLow().toString());
+		else
+			left = new NotFilter(new SimpleFilter(versionAttr, Operator.LessThanOrEqual, parsedRange.getLow().toString()));
+		
+		Filter right;
+		if (!parsedRange.isRange())
+			right = null;
+		else if (parsedRange.includeHigh())
+			right = new SimpleFilter(versionAttr, Operator.LessThanOrEqual, parsedRange.getHigh().toString());
+		else
+			right = new NotFilter(new SimpleFilter(versionAttr, Operator.GreaterThanOrEqual, parsedRange.getHigh().toString()));
+		
+		Filter result;
+		if (right != null)
+			result = new AndFilter().addChild(left).addChild(right);
+		else
+			result = left;
+		
+		return result.toString();
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/ResourceBuilder.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/ResourceBuilder.java
new file mode 100644
index 0000000..69e95b0
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/ResourceBuilder.java
@@ -0,0 +1,55 @@
+package aQute.bnd.osgi.resource;
+
+import java.util.*;
+
+import org.osgi.resource.*;
+
+public class ResourceBuilder {
+
+	private final ResourceImpl		resource		= new ResourceImpl();
+	private final List<Capability>	capabilities	= new LinkedList<Capability>();
+	private final List<Requirement>	requirements	= new LinkedList<Requirement>();
+
+	private boolean					built			= false;
+
+	public ResourceBuilder addCapability(Capability capability) {
+		CapReqBuilder builder = CapReqBuilder.clone(capability);
+		return addCapability(builder);
+	}
+	
+	public ResourceBuilder addCapability(CapReqBuilder builder) {
+		if (built)
+			throw new IllegalStateException("Resource already built");
+
+		Capability cap = builder.setResource(resource).buildCapability();
+		capabilities.add(cap);
+
+		return this;
+	}
+	
+	public ResourceBuilder addRequirement(Requirement requirement) {
+		CapReqBuilder builder = CapReqBuilder.clone(requirement);
+		return addRequirement(builder);
+	}
+	
+	public ResourceBuilder addRequirement(CapReqBuilder builder) {
+		if (built)
+			throw new IllegalStateException("Resource already built");
+
+		Requirement req = builder.setResource(resource).buildRequirement();
+		requirements.add(req);
+
+		return this;
+	}
+
+	public Resource build() {
+		if (built)
+			throw new IllegalStateException("Resource already built");
+		built = true;
+
+		resource.setCapabilities(capabilities);
+		resource.setRequirements(requirements);
+		return resource;
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/ResourceImpl.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/ResourceImpl.java
new file mode 100644
index 0000000..f8c3a84
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/ResourceImpl.java
@@ -0,0 +1,73 @@
+package aQute.bnd.osgi.resource;
+
+import java.util.*;
+
+import org.osgi.framework.namespace.*;
+import org.osgi.resource.*;
+
+class ResourceImpl implements Resource {
+
+	private List<Capability>				allCapabilities;
+	private Map<String,List<Capability>>	capabilityMap;
+
+	private List<Requirement>				allRequirements;
+	private Map<String,List<Requirement>>	requirementMap;
+
+	void setCapabilities(List<Capability> capabilities) {
+		allCapabilities = capabilities;
+
+		capabilityMap = new HashMap<String,List<Capability>>();
+		for (Capability capability : capabilities) {
+			List<Capability> list = capabilityMap.get(capability.getNamespace());
+			if (list == null) {
+				list = new LinkedList<Capability>();
+				capabilityMap.put(capability.getNamespace(), list);
+			}
+			list.add(capability);
+		}
+	}
+
+	public List<Capability> getCapabilities(String namespace) {
+		return namespace == null ? allCapabilities : capabilityMap.get(namespace);
+	}
+
+	void setRequirements(List<Requirement> requirements) {
+		allRequirements = requirements;
+
+		requirementMap = new HashMap<String,List<Requirement>>();
+		for (Requirement requirement : requirements) {
+			List<Requirement> list = requirementMap.get(requirement.getNamespace());
+			if (list == null) {
+				list = new LinkedList<Requirement>();
+				requirementMap.put(requirement.getNamespace(), list);
+			}
+			list.add(requirement);
+		}
+	}
+
+	public List<Requirement> getRequirements(String namespace) {
+		return namespace == null ? allRequirements : requirementMap.get(namespace);
+	}
+
+	@Override
+	public String toString() {
+		final StringBuilder builder = new StringBuilder();
+		List<Capability> identities = getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE);
+		if (identities != null && identities.size() == 1) {
+			Capability idCap = identities.get(0);
+			Object id = idCap.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE);
+			Object version = idCap.getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+			
+			builder.append(id).append(" ver=").append(version);
+		} else {
+			// Generic toString
+			builder.append("ResourceImpl [caps=");
+			builder.append(allCapabilities);
+			builder.append(", reqs=");
+			builder.append(allRequirements);
+			builder.append("]");
+		}
+		return builder.toString();
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/packageinfo b/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/packageinfo
new file mode 100644
index 0000000..b1793a2
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/resource/packageinfo
@@ -0,0 +1 @@
+version 1.1.0
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/aQute/bnd/properties/BadLocationException.java b/biz.aQute.bndlib/src/aQute/bnd/properties/BadLocationException.java
new file mode 100644
index 0000000..30647db
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/properties/BadLocationException.java
@@ -0,0 +1,14 @@
+package aQute.bnd.properties;
+
+public class BadLocationException extends Exception {
+
+	private static final long	serialVersionUID	= 1L;
+
+	public BadLocationException() {
+		super();
+	}
+
+	public BadLocationException(String var0) {
+		super(var0);
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/properties/CopyOnWriteTextStore.java b/biz.aQute.bndlib/src/aQute/bnd/properties/CopyOnWriteTextStore.java
new file mode 100644
index 0000000..edcba0e
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/properties/CopyOnWriteTextStore.java
@@ -0,0 +1,147 @@
+package aQute.bnd.properties;
+
+/**
+ * Copy-on-write <code>ITextStore</code> wrapper.
+ * <p>
+ * This implementation uses an unmodifiable text store for the initial content.
+ * Upon first modification attempt, the unmodifiable store is replaced with a
+ * modifiable instance which must be supplied in the constructor.
+ * </p>
+ * <p>
+ * This class is not intended to be subclassed.
+ * </p>
+ * 
+ * @since 3.2
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class CopyOnWriteTextStore implements ITextStore {
+
+	/**
+	 * An unmodifiable String based text store. It is not possible to modify the
+	 * content other than using {@link #set}. Trying to {@link #replace} a text
+	 * range will throw an <code>UnsupportedOperationException</code>.
+	 */
+	private static class StringTextStore implements ITextStore {
+
+		/** Represents the content of this text store. */
+		private String	fText	= "";	//$NON-NLS-1$
+
+		/**
+		 * Create an empty text store.
+		 */
+		StringTextStore() {
+			super();
+		}
+
+		/**
+		 * Create a text store with initial content.
+		 * 
+		 * @param text
+		 *            the initial content
+		 */
+		StringTextStore(String text) {
+			super();
+			set(text);
+		}
+
+		/*
+		 * @see org.eclipse.jface.text.ITextStore#get(int)
+		 */
+		public char get(int offset) {
+			return fText.charAt(offset);
+		}
+
+		/*
+		 * @see org.eclipse.jface.text.ITextStore#get(int, int)
+		 */
+		public String get(int offset, int length) {
+			return fText.substring(offset, offset + length);
+		}
+
+		/*
+		 * @see org.eclipse.jface.text.ITextStore#getLength()
+		 */
+		public int getLength() {
+			return fText.length();
+		}
+
+		/*
+		 * @see org.eclipse.jface.text.ITextStore#replace(int, int,
+		 * java.lang.String)
+		 */
+		public void replace(int offset, int length, String text) {
+			// modification not supported
+			throw new UnsupportedOperationException();
+		}
+
+		/*
+		 * @see org.eclipse.jface.text.ITextStore#set(java.lang.String)
+		 */
+		public void set(String text) {
+			fText = text != null ? text : ""; //$NON-NLS-1$
+		}
+
+	}
+
+	/** The underlying "real" text store */
+	protected ITextStore		fTextStore	= new StringTextStore();
+
+	/** A modifiable <code>ITextStore</code> instance */
+	private final ITextStore	fModifiableTextStore;
+
+	/**
+	 * Creates an empty text store. The given text store will be used upon first
+	 * modification attempt.
+	 * 
+	 * @param modifiableTextStore
+	 *            a modifiable <code>ITextStore</code> instance, may not be
+	 *            <code>null</code>
+	 */
+	public CopyOnWriteTextStore(ITextStore modifiableTextStore) {
+		fTextStore = new StringTextStore();
+		fModifiableTextStore = modifiableTextStore;
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.ITextStore#get(int)
+	 */
+	public char get(int offset) {
+		return fTextStore.get(offset);
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.ITextStore#get(int, int)
+	 */
+	public String get(int offset, int length) {
+		return fTextStore.get(offset, length);
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.ITextStore#getLength()
+	 */
+	public int getLength() {
+		return fTextStore.getLength();
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.ITextStore#replace(int, int,
+	 * java.lang.String)
+	 */
+	public void replace(int offset, int length, String text) {
+		if (fTextStore != fModifiableTextStore) {
+			String content = fTextStore.get(0, fTextStore.getLength());
+			fTextStore = fModifiableTextStore;
+			fTextStore.set(content);
+		}
+		fTextStore.replace(offset, length, text);
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.ITextStore#set(java.lang.String)
+	 */
+	public void set(String text) {
+		fTextStore = new StringTextStore(text);
+		fModifiableTextStore.set(""); //$NON-NLS-1$
+	}
+
+}
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/aQute/bnd/properties/Document.java b/biz.aQute.bndlib/src/aQute/bnd/properties/Document.java
new file mode 100644
index 0000000..3818b72
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/properties/Document.java
@@ -0,0 +1,59 @@
+package aQute.bnd.properties;
+
+public class Document implements IDocument {
+
+	public final static String[]	DELIMITERS	= {
+			"\r", "\n", "\r\n"
+												};
+
+	private LineTracker				lineTracker	= new LineTracker();
+	private ITextStore				textStore	= new CopyOnWriteTextStore(new GapTextStore());
+
+	public Document(String text) {
+		setText(text);
+	}
+
+	public int getNumberOfLines() {
+		return lineTracker.getNumberOfLines();
+	}
+
+	public IRegion getLineInformation(int line) throws BadLocationException {
+		return lineTracker.getLineInformation(line);
+	}
+
+	public String get(int offset, int length) throws BadLocationException {
+		return textStore.get(offset, length);
+	}
+
+	public String getLineDelimiter(int line) throws BadLocationException {
+		return lineTracker.getLineDelimiter(line);
+	}
+
+	public int getLength() {
+		return textStore.getLength();
+	}
+
+	public void replace(int offset, int length, String text) throws BadLocationException {
+		textStore.replace(offset, length, text);
+		lineTracker.set(get());
+	}
+
+	public char getChar(int pos) {
+		return textStore.get(pos);
+	}
+
+	public void setText(String text) {
+		textStore.set(text);
+		lineTracker.set(text);
+	}
+
+	public String get() {
+		return textStore.get(0, textStore.getLength());
+	}
+
+	protected static class DelimiterInfo {
+		public int		delimiterIndex;
+		public int		delimiterLength;
+		public String	delimiter;
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/properties/GapTextStore.java b/biz.aQute.bndlib/src/aQute/bnd/properties/GapTextStore.java
new file mode 100644
index 0000000..a32c219
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/properties/GapTextStore.java
@@ -0,0 +1,419 @@
+package aQute.bnd.properties;
+
+/**
+ * Implements a gap managing text store. The gap text store relies on the
+ * assumption that consecutive changes to a document are co-located. The start
+ * of the gap is always moved to the location of the last change.
+ * <p>
+ * <strong>Performance:</strong> Typing-style changes perform in constant time
+ * unless re-allocation becomes necessary. Generally, a change that does not
+ * cause re-allocation will cause at most one
+ * {@linkplain System#arraycopy(Object, int, Object, int, int) arraycopy}
+ * operation of a length of about <var>d</var>, where <var>d</var> is the
+ * distance from the previous change. Let <var>a(x)</var> be the algorithmic
+ * performance of an <code>arraycopy</code> operation of the length
+ * <var>x</var>, then such a change then performs in <i>O(a(x))</i>,
+ * {@linkplain #get(int, int) get(int, <var>length</var>)} performs in
+ * <i>O(a(length))</i>, {@link #get(int)} in <i>O(1)</i>.
+ * <p>
+ * How frequently the array needs re-allocation is controlled by the constructor
+ * parameters.
+ * </p>
+ * <p>
+ * This class is not intended to be subclassed.
+ * </p>
+ * 
+ * @see CopyOnWriteTextStore for a copy-on-write text store wrapper
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class GapTextStore implements ITextStore {
+	/**
+	 * The minimum gap size allocated when re-allocation occurs.
+	 * 
+	 * @since 3.3
+	 */
+	private final int	fMinGapSize;
+	/**
+	 * The maximum gap size allocated when re-allocation occurs.
+	 * 
+	 * @since 3.3
+	 */
+	private final int	fMaxGapSize;
+	/**
+	 * The multiplier to compute the array size from the content length
+	 * (1 <= fSizeMultiplier <= 2).
+	 * 
+	 * @since 3.3
+	 */
+	private final float	fSizeMultiplier;
+
+	/** The store's content */
+	private char[]		fContent	= new char[0];
+	/** Starting index of the gap */
+	private int			fGapStart	= 0;
+	/** End index of the gap */
+	private int			fGapEnd		= 0;
+	/**
+	 * The current high water mark. If a change would cause the gap to grow
+	 * larger than this, the array is re-allocated.
+	 * 
+	 * @since 3.3
+	 */
+	private int			fThreshold	= 0;
+
+	/**
+	 * Creates a new empty text store using the specified low and high
+	 * watermarks.
+	 * 
+	 * @param lowWatermark
+	 *            unused - at the lower bound, the array is only resized when
+	 *            the content does not fit
+	 * @param highWatermark
+	 *            if the gap is ever larger than this, it will automatically be
+	 *            shrunken (>= 0)
+	 * @deprecated use {@link GapTextStore#GapTextStore(int, int, float)}
+	 *             instead
+	 */
+	public GapTextStore(int lowWatermark, int highWatermark) {
+		/*
+		 * Legacy constructor. The API contract states that highWatermark is the
+		 * upper bound for the gap size. Albeit this contract was not previously
+		 * adhered to, it is now: The allocated gap size is fixed at half the
+		 * highWatermark. Since the threshold is always twice the allocated gap
+		 * size, the gap will never grow larger than highWatermark. Previously,
+		 * the gap size was initialized to highWatermark, causing re-allocation
+		 * if the content length shrunk right after allocation. The fixed gap
+		 * size is now only half of the previous value, circumventing that
+		 * problem (there was no API contract specifying the initial gap size).
+		 * The previous implementation did not allow the gap size to become
+		 * smaller than lowWatermark, which doesn't make any sense: that area of
+		 * the gap was simply never ever used.
+		 */
+		this(highWatermark / 2, highWatermark / 2, 0f);
+	}
+
+	/**
+	 * Equivalent to {@linkplain GapTextStore#GapTextStore(int, int, float) new
+	 * GapTextStore(256, 4096, 0.1f)}.
+	 * 
+	 * @since 3.3
+	 */
+	public GapTextStore() {
+		this(256, 4096, 0.1f);
+	}
+
+	/**
+	 * Creates an empty text store that uses re-allocation thresholds relative
+	 * to the content length. Re-allocation is controlled by the
+	 * <em>gap factor</em>, which is the quotient of the gap size and the array
+	 * size. Re-allocation occurs if a change causes the gap factor to go
+	 * outside <code>[0, maxGapFactor]</code>. When re-allocation occurs,
+	 * the array is sized such that the gap factor is
+	 * <code>0.5 * maxGapFactor</code>. The gap size computed in this manner is
+	 * bounded by the <code>minSize</code> and <code>maxSize</code> parameters.
+	 * <p>
+	 * A <code>maxGapFactor</code> of <code>0</code> creates a text store that
+	 * never has a gap at all (if <code>minSize</code> is 0); a
+	 * <code>maxGapFactor</code> of <code>1</code> creates a text store that
+	 * doubles its size with every re-allocation and that never shrinks.
+	 * </p>
+	 * <p>
+	 * The <code>minSize</code> and <code>maxSize</code> parameters are absolute
+	 * bounds to the allocated gap size. Use <code>minSize</code> to avoid
+	 * frequent re-allocation for small documents. Use <code>maxSize</code> to
+	 * avoid a huge gap being allocated for large documents.
+	 * </p>
+	 * 
+	 * @param minSize
+	 *            the minimum gap size to allocate (>= 0; use 0 for no
+	 *            minimum)
+	 * @param maxSize
+	 *            the maximum gap size to allocate (>= minSize; use
+	 *            {@link Integer#MAX_VALUE} for no maximum)
+	 * @param maxGapFactor
+	 *            is the maximum fraction of the array that is occupied by the
+	 *            gap (
+	 *            <code>0 <= maxGapFactor <= 1</code>)
+	 * @since 3.3
+	 */
+	public GapTextStore(int minSize, int maxSize, float maxGapFactor) {
+		fMinGapSize = minSize;
+		fMaxGapSize = maxSize;
+		fSizeMultiplier = 1 / (1 - maxGapFactor / 2);
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.ITextStore#get(int)
+	 */
+	public final char get(int offset) {
+		if (offset < fGapStart)
+			return fContent[offset];
+
+		return fContent[offset + gapSize()];
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.ITextStore#get(int, int)
+	 */
+	public final String get(int offset, int length) {
+		if (fGapStart <= offset)
+			return new String(fContent, offset + gapSize(), length);
+
+		final int end = offset + length;
+
+		if (end <= fGapStart)
+			return new String(fContent, offset, length);
+
+		StringBuffer buf = new StringBuffer(length);
+		buf.append(fContent, offset, fGapStart - offset);
+		buf.append(fContent, fGapEnd, end - fGapStart);
+		return buf.toString();
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.ITextStore#getLength()
+	 */
+	public final int getLength() {
+		return fContent.length - gapSize();
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.ITextStore#set(java.lang.String)
+	 */
+	public final void set(String text) {
+		/*
+		 * Moves the gap to the end of the content. There is no sensible
+		 * prediction of where the next change will occur, but at least the next
+		 * change will not trigger re-allocation. This is especially important
+		 * when using the GapTextStore within a CopyOnWriteTextStore, where the
+		 * GTS is only initialized right before a modification.
+		 */
+		replace(0, getLength(), text);
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.ITextStore#replace(int, int,
+	 * java.lang.String)
+	 */
+	public final void replace(int offset, int length, String text) {
+		if (text == null) {
+			adjustGap(offset, length, 0);
+		} else {
+			int textLength = text.length();
+			adjustGap(offset, length, textLength);
+			if (textLength != 0)
+				text.getChars(0, textLength, fContent, offset);
+		}
+	}
+
+	/**
+	 * Moves the gap to <code>offset + add</code>, moving any content after
+	 * <code>offset + remove</code> behind the gap. The gap size is kept between
+	 * 0 and {@link #fThreshold}, leading to re-allocation if needed. The
+	 * content between <code>offset</code> and <code>offset + add</code> is
+	 * undefined after this operation.
+	 * 
+	 * @param offset
+	 *            the offset at which a change happens
+	 * @param remove
+	 *            the number of character which are removed or overwritten at
+	 *            <code>offset</code>
+	 * @param add
+	 *            the number of character which are inserted or overwriting at
+	 *            <code>offset</code>
+	 */
+	private void adjustGap(int offset, int remove, int add) {
+		final int oldGapSize = gapSize();
+		final int newGapSize = oldGapSize - add + remove;
+		final boolean reuseArray = 0 <= newGapSize && newGapSize <= fThreshold;
+
+		final int newGapStart = offset + add;
+		final int newGapEnd;
+
+		if (reuseArray)
+			newGapEnd = moveGap(offset, remove, oldGapSize, newGapSize, newGapStart);
+		else
+			newGapEnd = reallocate(offset, remove, oldGapSize, newGapSize, newGapStart);
+
+		fGapStart = newGapStart;
+		fGapEnd = newGapEnd;
+	}
+
+	/**
+	 * Moves the gap to <code>newGapStart</code>.
+	 * 
+	 * @param offset
+	 *            the change offset
+	 * @param remove
+	 *            the number of removed / overwritten characters
+	 * @param oldGapSize
+	 *            the old gap size
+	 * @param newGapSize
+	 *            the gap size after the change
+	 * @param newGapStart
+	 *            the offset in the array to move the gap to
+	 * @return the new gap end
+	 * @since 3.3
+	 */
+	private int moveGap(int offset, int remove, int oldGapSize, int newGapSize, int newGapStart) {
+		/*
+		 * No re-allocation necessary. The area between the change offset and
+		 * gap can be copied in at most one operation. Don't copy parts that
+		 * will be overwritten anyway.
+		 */
+		final int newGapEnd = newGapStart + newGapSize;
+		if (offset < fGapStart) {
+			int afterRemove = offset + remove;
+			if (afterRemove < fGapStart) {
+				final int betweenSize = fGapStart - afterRemove;
+				arrayCopy(afterRemove, fContent, newGapEnd, betweenSize);
+			}
+			// otherwise, only the gap gets enlarged
+		} else {
+			final int offsetShifted = offset + oldGapSize;
+			final int betweenSize = offsetShifted - fGapEnd; // in the typing
+																// case,
+																// betweenSize
+																// is 0
+			arrayCopy(fGapEnd, fContent, fGapStart, betweenSize);
+		}
+		return newGapEnd;
+	}
+
+	/**
+	 * Reallocates a new array and copies the data from the previous one.
+	 * 
+	 * @param offset
+	 *            the change offset
+	 * @param remove
+	 *            the number of removed / overwritten characters
+	 * @param oldGapSize
+	 *            the old gap size
+	 * @param newGapSize
+	 *            the gap size after the change if no re-allocation would occur
+	 *            (can be negative)
+	 * @param newGapStart
+	 *            the offset in the array to move the gap to
+	 * @return the new gap end
+	 * @since 3.3
+	 */
+	private int reallocate(int offset, int remove, final int oldGapSize, int newGapSize, final int newGapStart) {
+		// the new content length (without any gap)
+		final int newLength = fContent.length - newGapSize;
+		// the new array size based on the gap factor
+		int newArraySize = (int) (newLength * fSizeMultiplier);
+		newGapSize = newArraySize - newLength;
+
+		// bound the gap size within min/max
+		if (newGapSize < fMinGapSize) {
+			newGapSize = fMinGapSize;
+			newArraySize = newLength + newGapSize;
+		} else if (newGapSize > fMaxGapSize) {
+			newGapSize = fMaxGapSize;
+			newArraySize = newLength + newGapSize;
+		}
+
+		// the upper threshold is always twice the gapsize
+		fThreshold = newGapSize * 2;
+		final char[] newContent = allocate(newArraySize);
+		final int newGapEnd = newGapStart + newGapSize;
+
+		/*
+		 * Re-allocation: The old content can be copied in at most 3 operations
+		 * to the newly allocated array. Either one of change offset and the gap
+		 * may come first. - unchanged area before the change offset / gap -
+		 * area between the change offset and the gap (either one may be first)
+		 * - rest area after the change offset / after the gap
+		 */
+		if (offset < fGapStart) {
+			// change comes before gap
+			arrayCopy(0, newContent, 0, offset);
+			int afterRemove = offset + remove;
+			if (afterRemove < fGapStart) {
+				// removal is completely before the gap
+				final int betweenSize = fGapStart - afterRemove;
+				arrayCopy(afterRemove, newContent, newGapEnd, betweenSize);
+				final int restSize = fContent.length - fGapEnd;
+				arrayCopy(fGapEnd, newContent, newGapEnd + betweenSize, restSize);
+			} else {
+				// removal encompasses the gap
+				afterRemove += oldGapSize;
+				final int restSize = fContent.length - afterRemove;
+				arrayCopy(afterRemove, newContent, newGapEnd, restSize);
+			}
+		} else {
+			// gap comes before change
+			arrayCopy(0, newContent, 0, fGapStart);
+			final int offsetShifted = offset + oldGapSize;
+			final int betweenSize = offsetShifted - fGapEnd;
+			arrayCopy(fGapEnd, newContent, fGapStart, betweenSize);
+			final int afterRemove = offsetShifted + remove;
+			final int restSize = fContent.length - afterRemove;
+			arrayCopy(afterRemove, newContent, newGapEnd, restSize);
+		}
+
+		fContent = newContent;
+		return newGapEnd;
+	}
+
+	/**
+	 * Allocates a new <code>char[size]</code>.
+	 * 
+	 * @param size
+	 *            the length of the new array.
+	 * @return a newly allocated char array
+	 * @since 3.3
+	 */
+	private char[] allocate(int size) {
+		return new char[size];
+	}
+
+	/*
+	 * Executes System.arraycopy if length != 0. A length < 0 cannot happen ->
+	 * don't hide coding errors by checking for negative lengths.
+	 * @since 3.3
+	 */
+	private void arrayCopy(int srcPos, char[] dest, int destPos, int length) {
+		if (length != 0)
+			System.arraycopy(fContent, srcPos, dest, destPos, length);
+	}
+
+	/**
+	 * Returns the gap size.
+	 * 
+	 * @return the gap size
+	 * @since 3.3
+	 */
+	private int gapSize() {
+		return fGapEnd - fGapStart;
+	}
+
+	/**
+	 * Returns a copy of the content of this text store. For internal use only.
+	 * 
+	 * @return a copy of the content of this text store
+	 */
+	protected String getContentAsString() {
+		return new String(fContent);
+	}
+
+	/**
+	 * Returns the start index of the gap managed by this text store. For
+	 * internal use only.
+	 * 
+	 * @return the start index of the gap managed by this text store
+	 */
+	protected int getGapStartIndex() {
+		return fGapStart;
+	}
+
+	/**
+	 * Returns the end index of the gap managed by this text store. For internal
+	 * use only.
+	 * 
+	 * @return the end index of the gap managed by this text store
+	 */
+	protected int getGapEndIndex() {
+		return fGapEnd;
+	}
+}
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/aQute/bnd/properties/IDocument.java b/biz.aQute.bndlib/src/aQute/bnd/properties/IDocument.java
new file mode 100644
index 0000000..267003d
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/properties/IDocument.java
@@ -0,0 +1,21 @@
+package aQute.bnd.properties;
+
+public interface IDocument {
+
+	int getNumberOfLines();
+
+	IRegion getLineInformation(int lineNum) throws BadLocationException;
+
+	String get();
+
+	String get(int offset, int length) throws BadLocationException;
+
+	String getLineDelimiter(int line) throws BadLocationException;
+
+	int getLength();
+
+	void replace(int offset, int length, String data) throws BadLocationException;
+
+	char getChar(int offset) throws BadLocationException;
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/properties/IRegion.java b/biz.aQute.bndlib/src/aQute/bnd/properties/IRegion.java
new file mode 100644
index 0000000..2712d71
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/properties/IRegion.java
@@ -0,0 +1,8 @@
+package aQute.bnd.properties;
+
+public interface IRegion {
+
+	int getLength();
+
+	int getOffset();
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/properties/ITextStore.java b/biz.aQute.bndlib/src/aQute/bnd/properties/ITextStore.java
new file mode 100644
index 0000000..19791de
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/properties/ITextStore.java
@@ -0,0 +1,65 @@
+package aQute.bnd.properties;
+
+/**
+ * Interface for storing and managing text.
+ * <p>
+ * Provides access to the stored text and allows to manipulate it.
+ * </p>
+ * <p>
+ * Clients may implement this interface or use
+ * {@link org.eclipse.jface.text.GapTextStore} or
+ * {@link org.eclipse.jface.text.CopyOnWriteTextStore}.
+ * </p>
+ */
+public interface ITextStore {
+
+	/**
+	 * Returns the character at the specified offset.
+	 * 
+	 * @param offset
+	 *            the offset in this text store
+	 * @return the character at this offset
+	 */
+	char get(int offset);
+
+	/**
+	 * Returns the text of the specified character range.
+	 * 
+	 * @param offset
+	 *            the offset of the range
+	 * @param length
+	 *            the length of the range
+	 * @return the text of the range
+	 */
+	String get(int offset, int length);
+
+	/**
+	 * Returns number of characters stored in this text store.
+	 * 
+	 * @return the number of characters stored in this text store
+	 */
+	int getLength();
+
+	/**
+	 * Replaces the specified character range with the given text.
+	 * <code>replace(getLength(), 0, "some text")</code> is a valid call and
+	 * appends text to the end of the text store.
+	 * 
+	 * @param offset
+	 *            the offset of the range to be replaced
+	 * @param length
+	 *            the number of characters to be replaced
+	 * @param text
+	 *            the substitution text
+	 */
+	void replace(int offset, int length, String text);
+
+	/**
+	 * Replace the content of the text store with the given text. Convenience
+	 * method for <code>replace(0, getLength(), text</code>.
+	 * 
+	 * @param text
+	 *            the new content of the text store
+	 */
+	void set(String text);
+}
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/aQute/bnd/properties/Line.java b/biz.aQute.bndlib/src/aQute/bnd/properties/Line.java
new file mode 100644
index 0000000..6ff1c07
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/properties/Line.java
@@ -0,0 +1,60 @@
+package aQute.bnd.properties;
+
+/**
+ * Describes a line as a particular number of characters beginning at a
+ * particular offset, consisting of a particular number of characters, and being
+ * closed with a particular line delimiter.
+ */
+final class Line implements IRegion {
+
+	/** The offset of the line */
+	public int			offset;
+	/** The length of the line */
+	public int			length;
+	/** The delimiter of this line */
+	public final String	delimiter;
+
+	/**
+	 * Creates a new Line.
+	 * 
+	 * @param offset
+	 *            the offset of the line
+	 * @param end
+	 *            the last including character offset of the line
+	 * @param delimiter
+	 *            the line's delimiter
+	 */
+	public Line(int offset, int end, String delimiter) {
+		this.offset = offset;
+		this.length = (end - offset) + 1;
+		this.delimiter = delimiter;
+	}
+
+	/**
+	 * Creates a new Line.
+	 * 
+	 * @param offset
+	 *            the offset of the line
+	 * @param length
+	 *            the length of the line
+	 */
+	public Line(int offset, int length) {
+		this.offset = offset;
+		this.length = length;
+		this.delimiter = null;
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.IRegion#getOffset()
+	 */
+	public int getOffset() {
+		return offset;
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.IRegion#getLength()
+	 */
+	public int getLength() {
+		return length;
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/properties/LineTracker.java b/biz.aQute.bndlib/src/aQute/bnd/properties/LineTracker.java
new file mode 100644
index 0000000..df65c78
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/properties/LineTracker.java
@@ -0,0 +1,382 @@
+package aQute.bnd.properties;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import aQute.bnd.properties.Document.DelimiterInfo;
+
+public class LineTracker {
+
+	/** The line information */
+	private final List<Line>	fLines	= new ArrayList<Line>();
+	/** The length of the tracked text */
+	private int					fTextLength;
+
+	/**
+	 * Creates a new line tracker.
+	 */
+	protected LineTracker() {}
+
+	/**
+	 * Binary search for the line at a given offset.
+	 * 
+	 * @param offset
+	 *            the offset whose line should be found
+	 * @return the line of the offset
+	 */
+	private int findLine(int offset) {
+
+		if (fLines.size() == 0)
+			return -1;
+
+		int left = 0;
+		int right = fLines.size() - 1;
+		int mid = 0;
+		Line line = null;
+
+		while (left < right) {
+
+			mid = (left + right) / 2;
+
+			line = fLines.get(mid);
+			if (offset < line.offset) {
+				if (left == mid)
+					right = left;
+				else
+					right = mid - 1;
+			} else if (offset > line.offset) {
+				if (right == mid)
+					left = right;
+				else
+					left = mid + 1;
+			} else if (offset == line.offset) {
+				left = right = mid;
+			}
+		}
+
+		line = fLines.get(left);
+		if (line.offset > offset)
+			--left;
+		return left;
+	}
+
+	/**
+	 * Returns the number of lines covered by the specified text range.
+	 * 
+	 * @param startLine
+	 *            the line where the text range starts
+	 * @param offset
+	 *            the start offset of the text range
+	 * @param length
+	 *            the length of the text range
+	 * @return the number of lines covered by this text range
+	 * @exception BadLocationException
+	 *                if range is undefined in this tracker
+	 */
+	private int getNumberOfLines(int startLine, int offset, int length) throws BadLocationException {
+
+		if (length == 0)
+			return 1;
+
+		int target = offset + length;
+
+		Line l = fLines.get(startLine);
+
+		if (l.delimiter == null)
+			return 1;
+
+		if (l.offset + l.length > target)
+			return 1;
+
+		if (l.offset + l.length == target)
+			return 2;
+
+		return getLineNumberOfOffset(target) - startLine + 1;
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.ILineTracker#getLineLength(int)
+	 */
+	public final int getLineLength(int line) throws BadLocationException {
+		int lines = fLines.size();
+
+		if (line < 0 || line > lines)
+			throw new BadLocationException();
+
+		if (lines == 0 || lines == line)
+			return 0;
+
+		Line l = fLines.get(line);
+		return l.length;
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.ILineTracker#getLineNumberOfOffset(int)
+	 */
+	public final int getLineNumberOfOffset(int position) throws BadLocationException {
+		if (position < 0 || position > fTextLength)
+			throw new BadLocationException();
+
+		if (position == fTextLength) {
+
+			int lastLine = fLines.size() - 1;
+			if (lastLine < 0)
+				return 0;
+
+			Line l = fLines.get(lastLine);
+			return (l.delimiter != null ? lastLine + 1 : lastLine);
+		}
+
+		return findLine(position);
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.ILineTracker#getLineInformationOfOffset(int)
+	 */
+	public final IRegion getLineInformationOfOffset(int position) throws BadLocationException {
+		if (position > fTextLength)
+			throw new BadLocationException();
+
+		if (position == fTextLength) {
+			int size = fLines.size();
+			if (size == 0)
+				return new Region(0, 0);
+			Line l = fLines.get(size - 1);
+			return (l.delimiter != null ? new Line(fTextLength, 0) : new Line(fTextLength - l.length, l.length));
+		}
+
+		return getLineInformation(findLine(position));
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.ILineTracker#getLineInformation(int)
+	 */
+	public final IRegion getLineInformation(int line) throws BadLocationException {
+		int lines = fLines.size();
+
+		if (line < 0 || line > lines)
+			throw new BadLocationException();
+
+		if (lines == 0)
+			return new Line(0, 0);
+
+		if (line == lines) {
+			Line l = fLines.get(line - 1);
+			return new Line(l.offset + l.length, 0);
+		}
+
+		Line l = fLines.get(line);
+		return (l.delimiter != null ? new Line(l.offset, l.length - l.delimiter.length()) : l);
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.ILineTracker#getLineOffset(int)
+	 */
+	public final int getLineOffset(int line) throws BadLocationException {
+		int lines = fLines.size();
+
+		if (line < 0 || line > lines)
+			throw new BadLocationException();
+
+		if (lines == 0)
+			return 0;
+
+		if (line == lines) {
+			Line l = fLines.get(line - 1);
+			if (l.delimiter != null)
+				return l.offset + l.length;
+			throw new BadLocationException();
+		}
+
+		Line l = fLines.get(line);
+		return l.offset;
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.ILineTracker#getNumberOfLines()
+	 */
+	public final int getNumberOfLines() {
+		int lines = fLines.size();
+
+		if (lines == 0)
+			return 1;
+
+		Line l = fLines.get(lines - 1);
+		return (l.delimiter != null ? lines + 1 : lines);
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.ILineTracker#getNumberOfLines(int, int)
+	 */
+	public final int getNumberOfLines(int position, int length) throws BadLocationException {
+
+		if (position < 0 || position + length > fTextLength)
+			throw new BadLocationException();
+
+		if (length == 0) // optimization
+			return 1;
+
+		return getNumberOfLines(getLineNumberOfOffset(position), position, length);
+	}
+
+	/*
+	 * @see
+	 * org.eclipse.jface.text.ILineTracker#computeNumberOfLines(java.lang.String
+	 * )
+	 */
+	public final int computeNumberOfLines(String text) {
+		int count = 0;
+		int start = 0;
+		DelimiterInfo delimiterInfo = nextDelimiterInfo(text, start);
+		while (delimiterInfo != null && delimiterInfo.delimiterIndex > -1) {
+			++count;
+			start = delimiterInfo.delimiterIndex + delimiterInfo.delimiterLength;
+			delimiterInfo = nextDelimiterInfo(text, start);
+		}
+		return count;
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.ILineTracker#getLineDelimiter(int)
+	 */
+	public final String getLineDelimiter(int line) throws BadLocationException {
+		int lines = fLines.size();
+
+		if (line < 0 || line > lines)
+			throw new BadLocationException();
+
+		if (lines == 0)
+			return null;
+
+		if (line == lines)
+			return null;
+
+		Line l = fLines.get(line);
+		return l.delimiter;
+	}
+
+	/**
+	 * Returns the information about the first delimiter found in the given text
+	 * starting at the given offset.
+	 * 
+	 * @param text
+	 *            the text to be searched
+	 * @param offset
+	 *            the offset in the given text
+	 * @return the information of the first found delimiter or <code>null</code>
+	 */
+	protected DelimiterInfo nextDelimiterInfo(String text, int offset) {
+
+		char ch;
+		int length = text.length();
+		for (int i = offset; i < length; i++) {
+
+			ch = text.charAt(i);
+			if (ch == '\r') {
+
+				if (i + 1 < length) {
+					if (text.charAt(i + 1) == '\n') {
+						DelimiterInfo fDelimiterInfo = new DelimiterInfo();
+						fDelimiterInfo.delimiter = Document.DELIMITERS[2];
+						fDelimiterInfo.delimiterIndex = i;
+						fDelimiterInfo.delimiterLength = 2;
+						return fDelimiterInfo;
+					}
+				}
+				DelimiterInfo fDelimiterInfo = new DelimiterInfo();
+				fDelimiterInfo.delimiter = Document.DELIMITERS[0];
+				fDelimiterInfo.delimiterIndex = i;
+				fDelimiterInfo.delimiterLength = 1;
+				return fDelimiterInfo;
+
+			} else if (ch == '\n') {
+				DelimiterInfo fDelimiterInfo = new DelimiterInfo();
+				fDelimiterInfo.delimiter = Document.DELIMITERS[1];
+				fDelimiterInfo.delimiterIndex = i;
+				fDelimiterInfo.delimiterLength = 1;
+				return fDelimiterInfo;
+			}
+		}
+
+		return null;
+	}
+
+	/**
+	 * Creates the line structure for the given text. Newly created lines are
+	 * inserted into the line structure starting at the given position. Returns
+	 * the number of newly created lines.
+	 * 
+	 * @param text
+	 *            the text for which to create a line structure
+	 * @param insertPosition
+	 *            the position at which the newly created lines are inserted
+	 *            into the tracker's line structure
+	 * @param offset
+	 *            the offset of all newly created lines
+	 * @return the number of newly created lines
+	 */
+	private int createLines(String text, int insertPosition, int offset) {
+
+		int count = 0;
+		int start = 0;
+		DelimiterInfo delimiterInfo = nextDelimiterInfo(text, 0);
+
+		while (delimiterInfo != null && delimiterInfo.delimiterIndex > -1) {
+
+			int index = delimiterInfo.delimiterIndex + (delimiterInfo.delimiterLength - 1);
+
+			if (insertPosition + count >= fLines.size())
+				fLines.add(new Line(offset + start, offset + index, delimiterInfo.delimiter));
+			else
+				fLines.add(insertPosition + count, new Line(offset + start, offset + index, delimiterInfo.delimiter));
+
+			++count;
+			start = index + 1;
+			delimiterInfo = nextDelimiterInfo(text, start);
+		}
+
+		if (start < text.length()) {
+			if (insertPosition + count < fLines.size()) {
+				// there is a line below the current
+				Line l = fLines.get(insertPosition + count);
+				int delta = text.length() - start;
+				l.offset -= delta;
+				l.length += delta;
+			} else {
+				fLines.add(new Line(offset + start, offset + text.length() - 1, null));
+				++count;
+			}
+		}
+
+		return count;
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.ILineTracker#replace(int, int,
+	 * java.lang.String)
+	 */
+	public final void replace(@SuppressWarnings("unused") int position, @SuppressWarnings("unused") int length, @SuppressWarnings("unused") String text) throws BadLocationException {
+		throw new UnsupportedOperationException();
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.ILineTracker#set(java.lang.String)
+	 */
+	public final void set(String text) {
+		fLines.clear();
+		if (text != null) {
+			fTextLength = text.length();
+			createLines(text, 0, 0);
+		}
+	}
+
+	/**
+	 * Returns the internal data structure, a {@link List} of {@link Line}s.
+	 * Used only by {@link TreeLineTracker#TreeLineTracker(ListLineTracker)}.
+	 * 
+	 * @return the internal list of lines.
+	 */
+	final List<Line> getLines() {
+		return fLines;
+	}
+}
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/aQute/bnd/properties/LineType.java b/biz.aQute.bndlib/src/aQute/bnd/properties/LineType.java
new file mode 100644
index 0000000..58dd96b
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/properties/LineType.java
@@ -0,0 +1,5 @@
+package aQute.bnd.properties;
+
+public enum LineType {
+	blank, comment, entry, eof
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/properties/PropertiesLineReader.java b/biz.aQute.bndlib/src/aQute/bnd/properties/PropertiesLineReader.java
new file mode 100644
index 0000000..720dde0
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/properties/PropertiesLineReader.java
@@ -0,0 +1,125 @@
+package aQute.bnd.properties;
+
+import static aQute.bnd.properties.LineType.*;
+
+public class PropertiesLineReader {
+
+	private final IDocument	document;
+	private final int		lineCount;
+
+	private int				lineNum		= 0;
+
+	private IRegion			lastRegion	= null;
+	private String			lastKey		= null;
+	private String			lastValue	= null;
+
+	public PropertiesLineReader(IDocument document) {
+		this.document = document;
+		this.lineCount = document.getNumberOfLines();
+	}
+
+	public PropertiesLineReader(String data) {
+		this(new Document(data));
+	}
+
+	public LineType next() throws Exception {
+		int index = 0;
+		char[] chars = null;
+
+		StringBuilder keyData = new StringBuilder();
+		StringBuilder valueData = new StringBuilder();
+		StringBuilder currentBuffer = keyData;
+
+		boolean started = false;
+
+		mainLoop: while (true) {
+			if (chars == null)
+				chars = grabLine(false);
+			if (chars == null)
+				return eof;
+
+			if (index >= chars.length)
+				break;
+
+			char c = chars[index];
+			if (c == '\\') {
+				index++;
+				if (index == chars.length) {
+					chars = grabLine(true);
+					index = 0;
+					if (chars == null || chars.length == 0)
+						break; // The last line ended with a backslash
+				}
+				currentBuffer.append(chars[index]);
+				index++;
+				continue mainLoop;
+			}
+
+			if (c == '=' || c == ':')
+				currentBuffer = valueData;
+
+			if (!started && (c == '#' || c == '!'))
+				return comment;
+
+			if (Character.isWhitespace(c)) {
+				if (started) {
+					// whitespace ends the key
+					currentBuffer = valueData;
+				}
+			} else {
+				started = true;
+				currentBuffer.append(c);
+			}
+
+			index++;
+		}
+
+		if (!started)
+			return blank;
+
+		lastKey = keyData.toString();
+		return entry;
+	}
+
+	private char[] grabLine(boolean continued) throws BadLocationException {
+		if (lineNum >= lineCount) {
+			lastRegion = null;
+			return null;
+		}
+
+		IRegion lineInfo = document.getLineInformation(lineNum);
+		char[] chars = document.get(lineInfo.getOffset(), lineInfo.getLength()).toCharArray();
+
+		if (continued) {
+			int length = lastRegion.getLength();
+			length += document.getLineDelimiter(lineNum - 1).length();
+			length += lineInfo.getLength();
+			lastRegion = new Region(lastRegion.getOffset(), length);
+		} else {
+			lastRegion = lineInfo;
+		}
+
+		lineNum++;
+		return chars;
+	}
+
+	public IRegion region() {
+		if (lastRegion == null)
+			throw new IllegalStateException("Last region not available: either before start or after end of document.");
+		return lastRegion;
+	}
+
+	public String key() {
+		if (lastKey == null)
+			throw new IllegalStateException(
+					"Last key not available: either before state or after end of document, or last line type was not 'entry'.");
+		return lastKey;
+	}
+
+	public String value() {
+		if (lastValue == null)
+			throw new IllegalStateException(
+					"Last value not available: either before state or after end of document, or last line type was not 'entry'.");
+		return lastValue;
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/properties/Region.java b/biz.aQute.bndlib/src/aQute/bnd/properties/Region.java
new file mode 100644
index 0000000..d94a06f
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/properties/Region.java
@@ -0,0 +1,22 @@
+package aQute.bnd.properties;
+
+public class Region implements IRegion {
+
+	private final int	offset;
+	private final int	length;
+
+	public Region(int offset, int length) {
+		this.offset = offset;
+		this.length = length;
+	}
+
+	public int getOffset() {
+		return offset;
+
+	}
+
+	public int getLength() {
+		return length;
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/properties/packageinfo b/biz.aQute.bndlib/src/aQute/bnd/properties/packageinfo
new file mode 100644
index 0000000..7a6a5c0
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/properties/packageinfo
@@ -0,0 +1 @@
+version 2.0
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/aQute/bnd/repo/eclipse/EclipseRepo.java b/biz.aQute.bndlib/src/aQute/bnd/repo/eclipse/EclipseRepo.java
deleted file mode 100644
index 3fa967a..0000000
--- a/biz.aQute.bndlib/src/aQute/bnd/repo/eclipse/EclipseRepo.java
+++ /dev/null
@@ -1,199 +0,0 @@
-package aQute.bnd.repo.eclipse;
-
-import java.io.*;
-import java.util.*;
-import java.util.jar.*;
-
-import aQute.bnd.service.*;
-import aQute.lib.osgi.*;
-import aQute.libg.generics.*;
-import aQute.libg.reporter.*;
-import aQute.libg.version.*;
-
-public class EclipseRepo implements Plugin, RepositoryPlugin {
-    File                             root;
-    Reporter                         reporter;
-    String                           name;
-    Map<String, Map<String, String>> index;
-
-    public static String             LOCATION = "location";
-    public static String             NAME     = "name";
-
-    public void setProperties(Map<String, String> map) {
-        String location = (String) map.get(LOCATION);
-        if (location == null)
-            throw new IllegalArgumentException(
-                    "Location muse be set on a EclipseRepo plugin");
-
-        root = new File(location);
-        if (!root.isDirectory())
-            throw new IllegalArgumentException(
-                    "Repository is not a valid directory " + root);
-
-        if (!new File(root, "plugins").isDirectory())
-            throw new IllegalArgumentException(
-                    "Repository is not a valid directory (no plugins directory)"
-                            + root);
-
-        name = (String) map.get(NAME);
-
-        try {
-            index = buildIndex();
-        } catch (Exception e) {
-            throw new RuntimeException(
-                    "Could not build index for eclipse repo: " + root);
-        }
-    }
-
-    Map<String, Map<String, String>> buildIndex() throws Exception {
-        File index = new File(root, "bnd.index").getAbsoluteFile();
-        File[] plugins = new File(root, "plugins").listFiles();
-
-        for (File f : plugins) {
-            f = f.getAbsoluteFile();
-            if (f.isFile()) {
-                if (f.lastModified() > index.lastModified()) {
-
-                    Map<String, Map<String, String>> map = buildIndex(plugins);
-                    write(index, map);
-                    return map;
-                }
-            }
-        }
-
-        String s = read(index);
-        return Processor.parseHeader(s, null);
-    }
-
-    private String read(File index) throws Exception {
-        if (index.isFile()) {
-            BufferedReader fr = new BufferedReader(new FileReader(index));
-            StringBuilder sb = new StringBuilder();
-
-            try {
-                String s = fr.readLine();
-                while (s != null) {
-                    sb.append(s);
-                    s = fr.readLine();
-                }
-            } finally {
-                fr.close();
-            }
-        }
-        return null;
-    }
-
-    private void write(File index, Map<String, Map<String, String>> map)
-            throws Exception {
-        String s = Processor.printClauses(map);
-        index.getParentFile().mkdirs();
-        FileWriter fw = new FileWriter(index);
-        try {
-            fw.write(s);
-        } finally {
-            fw.close();
-        }
-    }
-
-    private Map<String, Map<String, String>> buildIndex(File[] plugins) {
-        Map<String, Map<String, String>> map = Create.map();
-        for (File plugin : plugins) {
-            try {
-                Jar jar = new Jar(plugin);
-                Manifest manifest = jar.getManifest();
-                String bsn = manifest.getMainAttributes().getValue(
-                        Constants.BUNDLE_SYMBOLICNAME);
-                String version = manifest.getMainAttributes().getValue(
-                        Constants.BUNDLE_VERSION);
-
-                if (bsn != null) {
-                    if (version == null)
-                        version = "0";
-
-                    Map<String, String> instance = map.get(bsn);
-                    if (instance == null) {
-                        instance = Create.map();
-                    }
-                    instance.put(version, plugin.getAbsolutePath());
-                }
-            } catch (Exception e) {
-                // Ignore exceptions in the plugins dir.
-            }
-        }
-        return map;
-    }
-
-    public void setReporter(Reporter reporter) {
-        this.reporter = reporter;
-    }
-
-    public boolean canWrite() {
-        return false;
-    }
-
-    public File[] get(String bsn, String range) throws Exception {
-        VersionRange r = new VersionRange(range);
-        Map<String, String> instances = index.get(bsn);
-        if (instances == null)
-            return null;
-
-        List<File> result = Create.list();
-
-        for (String version : instances.keySet()) {
-            Version v = new Version(version);
-            if (r.includes(v)) {
-                File f = new File(instances.get(version));
-                if (f.isFile()) {
-                    result.add(f);
-                }
-            }
-        }
-        return result.toArray(new File[result.size()]);
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public List<String> list(String regex) {
-        Instruction pattern = null;
-        if (regex != null)
-            pattern = Instruction.getPattern(regex);
-
-        List<String> result = new ArrayList<String>();
-        for (String f : index.keySet()) {
-            if (pattern == null || pattern.matches(f))
-                result.add(f);
-        }
-        return result;
-    }
-
-    public File put(Jar jar) throws Exception {
-        return null;
-    }
-
-    public List<Version> versions(String bsn) {
-        Map<String, String> instances = index.get(bsn);
-        if (instances == null)
-            return null;
-
-        List<Version> versions = Create.list();
-        for (String v : instances.keySet())
-            versions.add(new Version(v));
-        return versions;
-    }
-
-
-	public File get(String bsn, String range, Strategy strategy, Map<String,String> properties) throws Exception {
-		File[] files = get(bsn, range);
-		if (files.length >= 0) {
-			switch (strategy) {
-			case LOWEST:
-				return files[0];
-			case HIGHEST:
-				return files[files.length - 1];
-			}
-		}
-		return null;
-	}
-}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/Actionable.java b/biz.aQute.bndlib/src/aQute/bnd/service/Actionable.java
new file mode 100644
index 0000000..4e805a5
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/Actionable.java
@@ -0,0 +1,48 @@
+package aQute.bnd.service;
+
+import java.util.*;
+
+/**
+ * An interface to allow bnd to provide commands on elements. This interface can
+ * provide information about the implementer but it can also provide information
+ * about its elements. These elements are identified by a <i>target</i>. A
+ * target is one or more objects that uniquely identify a child in the
+ * container. The exact protocol for the target is left to the implementers,
+ * this interface is just a conduit between the bnd world (no Eclipse etc) and
+ * the GUI world, using only bnd and java interfaces.
+ */
+public interface Actionable {
+	/**
+	 * Return a map with command names (potentially localized) and a Runnable.
+	 * The caller can execute the caller at will.
+	 * 
+	 * @param target
+	 *            the target object, null if commands for the encompassing
+	 *            entity is sought (e.g. the repo itself).
+	 * @return A Map with the actions or null if no actions are available.
+	 * @throws Exception
+	 */
+	Map<String,Runnable> actions(Object... target) throws Exception;
+
+	/**
+	 * Return a tooltip for the given target or the encompassing entity if null
+	 * is passed.
+	 * 
+	 * @param target
+	 *            the target, any number of parameters to identify
+	 * @return the tooltip or null
+	 * @throws Exception
+	 */
+	String tooltip(Object... target) throws Exception;
+
+	/**
+	 * Provide a title for an element.
+	 * 
+	 * @param target
+	 *            the target, any number of parameters to identify
+	 * @return the text for this element
+	 * @throws Exception
+	 */
+
+	String title(Object... target) throws Exception;
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/AnalyzerPlugin.java b/biz.aQute.bndlib/src/aQute/bnd/service/AnalyzerPlugin.java
index 3efe8ee..9c3e51d 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/service/AnalyzerPlugin.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/AnalyzerPlugin.java
@@ -1,20 +1,20 @@
 package aQute.bnd.service;
 
-import aQute.lib.osgi.*;
+import aQute.bnd.osgi.*;
 
 public interface AnalyzerPlugin {
 
-    /**
-     * This plugin is called after analysis. The plugin is free to modify the
-     * jar and/or change the classpath information (see referred, contained).
-     * This plugin is called after analysis of the JAR but before manifest
-     * generation.
-     * 
-     * @param analyzer
-     * @return true if the classpace has been modified so that the bundle
-     *         classpath must be reanalyzed
-     * @throws Exception
-     */
+	/**
+	 * This plugin is called after analysis. The plugin is free to modify the
+	 * jar and/or change the classpath information (see referred, contained).
+	 * This plugin is called after analysis of the JAR but before manifest
+	 * generation.
+	 * 
+	 * @param analyzer
+	 * @return true if the classpace has been modified so that the bundle
+	 *         classpath must be reanalyzed
+	 * @throws Exception
+	 */
 
-    boolean analyzeJar(Analyzer analyzer) throws Exception;
+	boolean analyzeJar(Analyzer analyzer) throws Exception;
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/BndListener.java b/biz.aQute.bndlib/src/aQute/bnd/service/BndListener.java
index e937110..31db491 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/service/BndListener.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/BndListener.java
@@ -3,21 +3,26 @@ package aQute.bnd.service;
 import java.io.*;
 import java.util.concurrent.atomic.*;
 
-import aQute.libg.reporter.*;
+import aQute.service.reporter.*;
 
 public class BndListener {
-	final AtomicInteger inside = new AtomicInteger();
-	
-    public void changed(File file) {
-    }
-    public void begin() { inside.incrementAndGet();}
-    public void end() { inside.decrementAndGet(); }
-    
-    public boolean isInside() {
-    	return inside.get()!=0;
-    }
-    
-    public void signal(Reporter reporter) {
-    	
-    }
+	final AtomicInteger	inside	= new AtomicInteger();
+
+	public void changed(@SuppressWarnings("unused") File file) {}
+
+	public void begin() {
+		inside.incrementAndGet();
+	}
+
+	public void end() {
+		inside.decrementAndGet();
+	}
+
+	public boolean isInside() {
+		return inside.get() != 0;
+	}
+
+	public void signal(@SuppressWarnings("unused") Reporter reporter) {
+
+	}
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/CommandPlugin.java b/biz.aQute.bndlib/src/aQute/bnd/service/CommandPlugin.java
index 34c72c2..9511637 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/service/CommandPlugin.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/CommandPlugin.java
@@ -3,28 +3,30 @@ package aQute.bnd.service;
 import aQute.bnd.build.*;
 
 /**
- * A plugin that makes it possible to 
+ * A plugin that makes it possible to
+ * 
  * @author aqute
- *
  */
 public interface CommandPlugin {
-    /**
-     * Is run before a command is executed. These plugins are called
-     * in the order of declaration.
-     * 
-     * @param project The project for which the command runs
-     * 
-     * @param command the command name
-     */
-    void before(Project project, String command);
-    
-    /**
-     * Is run after a command is executed. These plugins are
-     * called in the reverse order of declaration.
-     * 
-     * @param project The project for which the command runs
-     *
-     * @param command the command name
-     */
-    void after(Project project, String command, Throwable outcome);
+	/**
+	 * Is run before a command is executed. These plugins are called in the
+	 * order of declaration.
+	 * 
+	 * @param project
+	 *            The project for which the command runs
+	 * @param command
+	 *            the command name
+	 */
+	void before(Project project, String command);
+
+	/**
+	 * Is run after a command is executed. These plugins are called in the
+	 * reverse order of declaration.
+	 * 
+	 * @param project
+	 *            The project for which the command runs
+	 * @param command
+	 *            the command name
+	 */
+	void after(Project project, String command, Throwable outcome);
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/Compiler.java b/biz.aQute.bndlib/src/aQute/bnd/service/Compiler.java
index 626b68c..a57fa5f 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/service/Compiler.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/Compiler.java
@@ -6,6 +6,6 @@ import java.util.*;
 import aQute.bnd.build.*;
 
 public interface Compiler {
-	boolean compile(Project project, Collection<File> sources, Collection<Container> buildpath,
-			File bin) throws Exception;
+	boolean compile(Project project, Collection<File> sources, Collection<Container> buildpath, File bin)
+			throws Exception;
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/DependencyContributor.java b/biz.aQute.bndlib/src/aQute/bnd/service/DependencyContributor.java
index e6a88ff..1fb073b 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/service/DependencyContributor.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/DependencyContributor.java
@@ -5,5 +5,5 @@ import java.util.*;
 import aQute.bnd.build.*;
 
 public interface DependencyContributor {
-    void addDependencies(Project project, Set<String> dependencies);
+	void addDependencies(Project project, Set<String> dependencies);
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/Deploy.java b/biz.aQute.bndlib/src/aQute/bnd/service/Deploy.java
index e1d92e1..fbdac78 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/service/Deploy.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/Deploy.java
@@ -1,12 +1,12 @@
 package aQute.bnd.service;
 
+import java.io.InputStream;
+
 import aQute.bnd.build.*;
-import aQute.lib.osgi.*;
 
 /**
  * Deploy this artifact to maven.
- * 
  */
-public interface Deploy {	
-	boolean deploy(Project project, Jar jar) throws Exception;
+public interface Deploy {
+	boolean deploy(Project project, String jarName, InputStream jarStream) throws Exception;
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/EclipseJUnitTester.java b/biz.aQute.bndlib/src/aQute/bnd/service/EclipseJUnitTester.java
index a2af9b0..f5e4174 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/service/EclipseJUnitTester.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/EclipseJUnitTester.java
@@ -2,5 +2,6 @@ package aQute.bnd.service;
 
 public interface EclipseJUnitTester {
 	void setPort(int port);
-	void setHost( String host);
+
+	void setHost(String host);
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/IndexProvider.java b/biz.aQute.bndlib/src/aQute/bnd/service/IndexProvider.java
new file mode 100644
index 0000000..9805f8b
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/IndexProvider.java
@@ -0,0 +1,12 @@
+package aQute.bnd.service;
+
+import java.net.*;
+import java.util.*;
+
+public interface IndexProvider {
+
+	List<URI> getIndexLocations() throws Exception;
+
+	Set<ResolutionPhase> getSupportedPhases();
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/MakePlugin.java b/biz.aQute.bndlib/src/aQute/bnd/service/MakePlugin.java
index 20a1849..8541436 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/service/MakePlugin.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/MakePlugin.java
@@ -2,20 +2,23 @@ package aQute.bnd.service;
 
 import java.util.*;
 
-import aQute.lib.osgi.*;
+import aQute.bnd.osgi.*;
 
 public interface MakePlugin {
 
-    /**
-     * This plugin is called when Include-Resource detects a reference to a resource
-     * that it can not find in the file system.
-     * 
-     * @param builder   The current builder
-     * @param source    The source string (i.e. the place where bnd looked)
-     * @param arguments Any arguments on the clause in Include-Resource
-     * @return          A resource or null if no resource could be made
-     * @throws Exception
-     */
-    Resource make(Builder builder, String source, Map<String,String> arguments) throws Exception;
+	/**
+	 * This plugin is called when Include-Resource detects a reference to a
+	 * resource that it can not find in the file system.
+	 * 
+	 * @param builder
+	 *            The current builder
+	 * @param source
+	 *            The source string (i.e. the place where bnd looked)
+	 * @param arguments
+	 *            Any arguments on the clause in Include-Resource
+	 * @return A resource or null if no resource could be made
+	 * @throws Exception
+	 */
+	Resource make(Builder builder, String source, Map<String,String> arguments) throws Exception;
 
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/OBRIndexProvider.java b/biz.aQute.bndlib/src/aQute/bnd/service/OBRIndexProvider.java
deleted file mode 100644
index fe12712..0000000
--- a/biz.aQute.bndlib/src/aQute/bnd/service/OBRIndexProvider.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package aQute.bnd.service;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.Collection;
-import java.util.Set;
-
-public interface OBRIndexProvider {
-	Collection<URL> getOBRIndexes() throws IOException;
-	Set<OBRResolutionMode> getSupportedModes();
-}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/OBRResolutionMode.java b/biz.aQute.bndlib/src/aQute/bnd/service/OBRResolutionMode.java
deleted file mode 100644
index f269d45..0000000
--- a/biz.aQute.bndlib/src/aQute/bnd/service/OBRResolutionMode.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package aQute.bnd.service;
-
-public enum OBRResolutionMode {
-	build, runtime
-}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/Plugin.java b/biz.aQute.bndlib/src/aQute/bnd/service/Plugin.java
index 065fac8..15b7898 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/service/Plugin.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/Plugin.java
@@ -2,30 +2,29 @@ package aQute.bnd.service;
 
 import java.util.*;
 
-import aQute.libg.reporter.*;
+import aQute.service.reporter.*;
 
 /**
  * An optional interface for plugins. If a plugin implements this interface then
  * it can receive the reminaing attributes and directives given in its clause as
  * well as the reporter to use.
- * 
  */
 public interface Plugin {
-    /**
-     * Give the plugin the remaining properties.
-     * 
-     * When a plugin is declared, the clause can contain extra properties.
-     * All the properties and directives are given to the plugin to use.
-     * 
-     * @param map attributes and directives for this plugin's clause
-     */
-    void setProperties(Map<String,String> map);
-    
-    /**
-     * Set the current reporter. This is called at init time. This plugin
-     * should report all errors and warnings to this reporter.
-     * 
-     * @param processor
-     */
-    void setReporter(Reporter processor);
+	/**
+	 * Give the plugin the remaining properties. When a plugin is declared, the
+	 * clause can contain extra properties. All the properties and directives
+	 * are given to the plugin to use.
+	 * 
+	 * @param map
+	 *            attributes and directives for this plugin's clause
+	 */
+	void setProperties(Map<String,String> map);
+
+	/**
+	 * Set the current reporter. This is called at init time. This plugin should
+	 * report all errors and warnings to this reporter.
+	 * 
+	 * @param processor
+	 */
+	void setReporter(Reporter processor);
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/Refreshable.java b/biz.aQute.bndlib/src/aQute/bnd/service/Refreshable.java
index e5e62e9..73afa43 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/service/Refreshable.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/Refreshable.java
@@ -3,6 +3,7 @@ package aQute.bnd.service;
 import java.io.*;
 
 public interface Refreshable {
-    boolean refresh();
-    File getRoot();
+	boolean refresh() throws Exception;
+
+	File getRoot();
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/Registry.java b/biz.aQute.bndlib/src/aQute/bnd/service/Registry.java
index 90fca36..a55c927 100755
--- a/biz.aQute.bndlib/src/aQute/bnd/service/Registry.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/Registry.java
@@ -7,5 +7,6 @@ import java.util.*;
  */
 public interface Registry {
 	<T> List<T> getPlugins(Class<T> c);
+
 	<T> T getPlugin(Class<T> c);
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/RegistryPlugin.java b/biz.aQute.bndlib/src/aQute/bnd/service/RegistryPlugin.java
index 7a46849..8a80660 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/service/RegistryPlugin.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/RegistryPlugin.java
@@ -1,6 +1,5 @@
 package aQute.bnd.service;
 
-
 /**
  * A plugin that wants a registry
  */
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/RemoteRepositoryPlugin.java b/biz.aQute.bndlib/src/aQute/bnd/service/RemoteRepositoryPlugin.java
index 82508fb..e87f3b5 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/service/RemoteRepositoryPlugin.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/RemoteRepositoryPlugin.java
@@ -1,20 +1,23 @@
 package aQute.bnd.service;
 
-import java.io.File;
-import java.util.Map;
+import java.io.*;
+import java.util.*;
 
 public interface RemoteRepositoryPlugin extends RepositoryPlugin {
 	/**
-	 * Retrieve a resource handle from the repository. For all implementations of this interface, calling {@code getFile(bsn, range, strategy, props)}
-	 * should always return the same result as {@code getResource(bsn, range, strategy, props).request()}.
-	 * @param bsn
-	 * @param range
-	 * @param strategy
-	 * @param properties
+	 * Retrieve a resource handle from the repository. For all implementations
+	 * of this interface, calling {@code getFile(bsn, range, strategy, props)}
+	 * should always return the same result as {@link RepositoryPlugin#get(String, aQute.bnd.version.Version, Map)}
+	 * 
+	 * @param bsn the bsn of the revision
+	 * @param version the version of the revision
+	 * @param strategy strategy
+	 * @param properties any properties
 	 * @return
 	 * @throws Exception
 	 */
-	ResourceHandle getHandle(String bsn, String range, Strategy strategy, Map<String,String> properties) throws Exception;
-	
+	ResourceHandle getHandle(String bsn, String version, Strategy strategy, Map<String,String> properties)
+			throws Exception;
+
 	File getCacheDirectory();
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/RepositoryListenerPlugin.java b/biz.aQute.bndlib/src/aQute/bnd/service/RepositoryListenerPlugin.java
index 0044da3..abd24f4 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/service/RepositoryListenerPlugin.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/RepositoryListenerPlugin.java
@@ -1,13 +1,14 @@
 package aQute.bnd.service;
 
-import java.io.File;
+import java.io.*;
 
-import aQute.lib.osgi.Jar;
+import aQute.bnd.osgi.*;
 
 public interface RepositoryListenerPlugin {
-	
+
 	/**
 	 * Called when a bundle is added to a repository.
+	 * 
 	 * @param repository
 	 * @param jar
 	 * @param file
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/RepositoryPlugin.java b/biz.aQute.bndlib/src/aQute/bnd/service/RepositoryPlugin.java
index a01c4b1..f213238 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/service/RepositoryPlugin.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/RepositoryPlugin.java
@@ -1,47 +1,168 @@
 package aQute.bnd.service;
 
 import java.io.*;
+import java.net.*;
 import java.util.*;
 
-import aQute.lib.osgi.*;
-import aQute.libg.version.*;
+import aQute.bnd.version.*;
 
+/**
+ * A Repository Plugin abstract a bnd repository. This interface allows bnd to
+ * find programs from their bsn and revisions from their bsn-version
+ * combination. It is also possible to put revisions in a repository if the
+ * repository is not read only.
+ */
 public interface RepositoryPlugin {
-	public enum Strategy {
-		LOWEST, HIGHEST, EXACT
+	/**
+	 * Options used to steer the put operation
+	 */
+	class PutOptions {
+		public static final String	BUNDLE	= "application/vnd.osgi.bundle";
+		public static final String	LIB		= "application/vnd.aQute.lib";
+
+		/**
+		 * The <b>SHA1</b> digest of the artifact to put into the repository.
+		 * When specified the digest of the <b>fetched</b> artifact will be
+		 * calculated and verified against this digest, <b>before</b> putting
+		 * the artifact into the repository. </p> An exception is thrown if the
+		 * specified digest and the calculated digest do not match.
+		 */
+		public byte[]	digest	= null;
+
+		/**
+		 * Specify the mime type of the importing stream. This can be either
+		 * {@link #BUNDLE} or {@link #LIB}. If left open, it is up to the
+		 * repository to guess the content type.
+		 */
+		public String	type;
 	}
 
+	PutOptions	DEFAULTOPTIONS	= new PutOptions();
+
 	/**
-	 * Return a URL to a matching version of the given bundle.
+	 * Results returned by the put operation
+	 */
+	class PutResult {
+		/**
+		 * A (potentially public) uri to the revision as it was put in the
+		 * repository.<br/>
+		 * <br/>
+		 * This can be a URI to the given artifact (when it was put into the
+		 * repository). This does not have to be a File URI!
+		 */
+		public URI		artifact	= null;
+
+		/**
+		 * The <b>SHA1</b> digest of the artifact as it was put into the
+		 * repository.<br/>
+		 * <br/>
+		 * This can be null and it can differ from the input digest if the
+		 * repository rewrote the stream for optimization reason. If the
+		 */
+		public byte[]	digest		= null;
+	}
+
+	/**
+	 * Put an artifact (from the InputStream) into the repository.<br/>
+	 * <br/>
+	 * There is NO guarantee that the artifact on the input stream has not been
+	 * modified after it's been put in the repository since that is dependent on
+	 * the implementation of the repository (see
+	 * {@link RepositoryPlugin.PutOptions#allowArtifactChange}).
 	 * 
-	 * @param bsn
-	 *            Bundle-SymbolicName of the searched bundle
-	 * @param range
-	 *            Version range for this bundle,"latest" if you only want the
-	 *            latest, or null when you want all.
-	 * @return A list of URLs sorted on version, lowest version is at index 0.
-	 *         null is returned when no files with the given bsn ould be found.
+	 * @param stream
+	 *            The input stream with the artifact
+	 * @param options
+	 *            The put options. See {@link RepositoryPlugin.PutOptions}, can
+	 *            be {@code null}, which will then take the default options like
+	 *            new PutOptions().
+	 * @return The result of the put, never null. See
+	 *         {@link RepositoryPlugin.PutResult}
 	 * @throws Exception
-	 *             when anything goes wrong
+	 *             When the repository root directory doesn't exist, when the
+	 *             repository is read-only, when the specified checksum doesn't
+	 *             match the checksum of the fetched artifact (see
+	 *             {@link RepositoryPlugin.PutOptions#digest}), when the
+	 *             implementation wants to modify the artifact but isn't allowed
+	 *             (see {@link RepositoryPlugin.PutOptions#allowArtifactChange}
+	 *             ), or when another error has occurred.
+	 */
+	PutResult put(InputStream stream, PutOptions options) throws Exception;
+
+	/**
+	 * The caller can specify any number of DownloadListener objects that are
+	 * called back when a download is finished (potentially before the get
+	 * method has returned).
 	 */
-	@Deprecated File[] get(String bsn, String range) throws Exception;
+
+	interface DownloadListener {
+		/**
+		 * Called when the file is successfully downloaded from a remote
+		 * repository.
+		 * 
+		 * @param file
+		 *            The file that was downloaded
+		 * @throws Exception
+		 *             , are logged and ignored
+		 */
+		void success(File file) throws Exception;
+
+		/**
+		 * Called when the file could not be downloaded from a remote
+		 * repository.
+		 * 
+		 * @param file
+		 *            The file that was intended to be downloaded.
+		 * @throws Exception
+		 *             , are logged and ignored
+		 */
+		void failure(File file, String reason) throws Exception;
+
+		/**
+		 * Can be called back regularly before success/failure but never after.
+		 * Indicates how far the download has progressed in percents. Since
+		 * downloads can be restarted, it is possible that the percentage
+		 * decreases.
+		 * 
+		 * @param file
+		 *            The file that was intended to be downloaded
+		 * @param percentage
+		 *            Percentage of file downloaded (can go down)
+		 * @return true if the download should continue, fails if it should be
+		 *         canceled (and fail)
+		 * @throws Exception
+		 *             , are logged and ignored
+		 */
+		boolean progress(File file, int percentage) throws Exception;
+	}
 
 	/**
 	 * Return a URL to a matching version of the given bundle.
+	 * <p/>
+	 * If download listeners are specified then the returned file is not
+	 * guaranteed to exist before a download listener is notified of success or
+	 * failure. The callback can happen before the method has returned. If the
+	 * returned file is null then download listeners are not called back.
+	 * <p/>
+	 * The intention of the Download Listeners is to allow a caller to obtain
+	 * references to files that do not yet exist but are to be downloaded. If
+	 * the downloads were done synchronously in the call, then no overlap of
+	 * downloads could take place.
 	 * 
 	 * @param bsn
 	 *            Bundle-SymbolicName of the searched bundle
-	 * @param range
-	 *            Version range for this bundle,"latest" if you only want the
-	 *            latest, or null when you want all.
-	 * @param strategy
-	 *            Get the highest or the lowest
-	 * @return A list of URLs sorted on version, lowest version is at index 0.
-	 *         null is returned when no files with the given bsn ould be found.
+	 * @param version
+	 *            Version requested
+	 * @param listeners
+	 *            Zero or more download listener that will be notified of the
+	 *            outcome.
+	 * @return A file to the revision or null if not found
 	 * @throws Exception
-	 *             when anything goes wrong
+	 *             when anything goes wrong, in this case no listeners will be
+	 *             called back.
 	 */
-	File get(String bsn, String range, Strategy strategy, Map<String,String> properties) throws Exception;
+	File get(String bsn, Version version, Map<String,String> properties, DownloadListener... listeners)
+			throws Exception;
 
 	/**
 	 * Answer if this repository can be used to store files.
@@ -51,24 +172,17 @@ public interface RepositoryPlugin {
 	boolean canWrite();
 
 	/**
-	 * Put a JAR file in the repository.
-	 * 
-	 * @param jar
-	 * @throws Exception
-	 */
-	File put(Jar jar) throws Exception;
-
-	/**
 	 * Return a list of bsns that are present in the repository.
 	 * 
-	 * @param regex
-	 *            if not null, match against the bsn and if matches, return
-	 *            otherwise skip
-	 * @return A list of bsns that match the regex parameter or all if regex is
-	 *         null
+	 * @param pattern
+	 *            A <ahref="https://en.wikipedia.org/wiki/Glob_%28programming%29">glob pattern</a>
+	 *            to be matched against bsns present in the repository, or {@code null}.
+	 * @return A list of bsns that match the pattern parameter or all if pattern
+	 *         is null; repositories that do not support browsing or querying
+	 *         should return an empty list.
 	 * @throws Exception
 	 */
-	List<String> list(String regex) throws Exception;
+	List<String> list(String pattern) throws Exception;
 
 	/**
 	 * Return a list of versions.
@@ -76,11 +190,16 @@ public interface RepositoryPlugin {
 	 * @throws Exception
 	 */
 
-	List<Version> versions(String bsn) throws Exception;
+	SortedSet<Version> versions(String bsn) throws Exception;
 
 	/**
 	 * @return The name of the repository
 	 */
 	String getName();
 
+	/**
+	 * Return a location identifier of this repository
+	 */
+
+	String getLocation();
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/ResolutionPhase.java b/biz.aQute.bndlib/src/aQute/bnd/service/ResolutionPhase.java
new file mode 100644
index 0000000..0fd7ec9
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/ResolutionPhase.java
@@ -0,0 +1,5 @@
+package aQute.bnd.service;
+
+public enum ResolutionPhase {
+	build, runtime
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/ResourceHandle.java b/biz.aQute.bndlib/src/aQute/bnd/service/ResourceHandle.java
index d08ea2c..42abd9b 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/service/ResourceHandle.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/ResourceHandle.java
@@ -1,13 +1,16 @@
 package aQute.bnd.service;
 
-import java.io.File;
-import java.io.IOException;
+import java.io.*;
 
 public interface ResourceHandle {
-	
-	public enum Location { local, remote_cached, remote };
-	
+
+	public enum Location {
+		local, remote_cached, remote
+	}
+
 	String getName();
+
 	Location getLocation();
+
 	File request() throws IOException;
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/Scripter.java b/biz.aQute.bndlib/src/aQute/bnd/service/Scripter.java
index 2e4e1d3..069590c 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/service/Scripter.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/Scripter.java
@@ -5,6 +5,6 @@ import java.util.*;
 
 public interface Scripter {
 
-	void eval(Map<String, Object> x, StringReader stringReader);
+	void eval(Map<String,Object> x, StringReader stringReader);
 
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/SignerPlugin.java b/biz.aQute.bndlib/src/aQute/bnd/service/SignerPlugin.java
index aaef646..54b4e80 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/service/SignerPlugin.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/SignerPlugin.java
@@ -1,15 +1,17 @@
 package aQute.bnd.service;
 
-import aQute.lib.osgi.*;
+import aQute.bnd.osgi.*;
 
 public interface SignerPlugin {
-    /**
-     * Sign the current jar. The alias is the given certificate 
-     * keystore.
-     * 
-     * @param builder   The current builder that contains the jar to sign
-     * @param alias     The keystore certificate alias
-     * @throws Exception When anything goes wrong
-     */
-    void sign(Builder builder, String alias) throws Exception;
+	/**
+	 * Sign the current jar. The alias is the given certificate keystore.
+	 * 
+	 * @param builder
+	 *            The current builder that contains the jar to sign
+	 * @param alias
+	 *            The keystore certificate alias
+	 * @throws Exception
+	 *             When anything goes wrong
+	 */
+	void sign(Builder builder, String alias) throws Exception;
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/Strategy.java b/biz.aQute.bndlib/src/aQute/bnd/service/Strategy.java
new file mode 100644
index 0000000..c24cd37
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/Strategy.java
@@ -0,0 +1,5 @@
+package aQute.bnd.service;
+
+public enum Strategy {
+	LOWEST, EXACT, HIGHEST;
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/action/Action.java b/biz.aQute.bndlib/src/aQute/bnd/service/action/Action.java
index 5167827..c74903d 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/service/action/Action.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/action/Action.java
@@ -3,5 +3,5 @@ package aQute.bnd.service.action;
 import aQute.bnd.build.*;
 
 public interface Action {
-    void execute( Project project, String action) throws Exception;
+	void execute(Project project, String action) throws Exception;
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/action/NamedAction.java b/biz.aQute.bndlib/src/aQute/bnd/service/action/NamedAction.java
index 5a1c697..7b0c29a 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/service/action/NamedAction.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/action/NamedAction.java
@@ -1,6 +1,5 @@
 package aQute.bnd.service.action;
 
-
 public interface NamedAction extends Action {
-    String getName();
+	String getName();
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/diff/Delta.java b/biz.aQute.bndlib/src/aQute/bnd/service/diff/Delta.java
new file mode 100644
index 0000000..5d3aa12
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/diff/Delta.java
@@ -0,0 +1,18 @@
+package aQute.bnd.service.diff;
+
+/**
+ * The Delta provides information about the {@link Diff} object. It tells the
+ * relation between the newer and older compared elements.
+ */
+public enum Delta {
+
+	// ORDER IS IMPORTANT FOR TRANSITIONS TABLE!
+
+	/**
+	 * 
+	 */
+	IGNORED, // for all
+	UNCHANGED, CHANGED, MICRO, MINOR, MAJOR, // content
+	REMOVED, ADDED; // structural
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/diff/Diff.java b/biz.aQute.bndlib/src/aQute/bnd/service/diff/Diff.java
new file mode 100644
index 0000000..bf23eee
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/diff/Diff.java
@@ -0,0 +1,37 @@
+package aQute.bnd.service.diff;
+
+import java.util.*;
+
+public interface Diff {
+	interface Ignore {
+		boolean contains(Diff diff);
+	}
+
+	class Data {
+
+		public Type		type;
+		public Delta	delta;
+		public String	name;
+		public Data[]	children;
+		public String	comment;
+	}
+
+	Data serialize();
+
+	Delta getDelta();
+
+	Delta getDelta(Ignore ignore);
+
+	Type getType();
+
+	String getName();
+
+	Tree getOlder();
+
+	Tree getNewer();
+
+	Collection< ? extends Diff> getChildren();
+
+	Diff get(String name);
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/diff/Differ.java b/biz.aQute.bndlib/src/aQute/bnd/service/diff/Differ.java
new file mode 100644
index 0000000..151051b
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/diff/Differ.java
@@ -0,0 +1,14 @@
+package aQute.bnd.service.diff;
+
+import aQute.bnd.osgi.*;
+
+/**
+ * Compare two Jars and report the differences.
+ */
+public interface Differ {
+	Tree tree(Analyzer source) throws Exception;
+
+	Tree tree(Jar source) throws Exception;
+
+	Tree deserialize(Tree.Data data) throws Exception;
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/diff/Tree.java b/biz.aQute.bndlib/src/aQute/bnd/service/diff/Tree.java
new file mode 100644
index 0000000..0b61f86
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/diff/Tree.java
@@ -0,0 +1,29 @@
+package aQute.bnd.service.diff;
+
+public interface Tree extends Comparable<Tree>{
+
+	public class Data {
+		public String	name;
+		public Type		type		= Type.METHOD;
+		public Delta	add			= Delta.MINOR;
+		public Delta	rem			= Delta.MAJOR;
+		public Data[]	children	= null;
+		public String	comment		= null;
+	}
+
+	Data serialize();
+
+	Tree[] getChildren();
+
+	String getName();
+
+	Type getType();
+
+	Delta ifAdded();
+
+	Delta ifRemoved();
+
+	Diff diff(Tree older);
+
+	Tree get(String name);
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/diff/Type.java b/biz.aQute.bndlib/src/aQute/bnd/service/diff/Type.java
new file mode 100644
index 0000000..91b186c
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/diff/Type.java
@@ -0,0 +1,10 @@
+package aQute.bnd.service.diff;
+
+public enum Type {
+	ACCESS, BUNDLE, API, MANIFEST, PACKAGE, CLASS, INTERFACE, ANNOTATION, ENUM, EXTENDS, IMPLEMENTS, FIELD, METHOD, ANNOTATED, PROPERTY, RESOURCE, SHA, CUSTOM, CLAUSE, HEADER, PARAMETER, CLASS_VERSION, RESOURCES, CONSTANT, RETURN, VERSION, DEPRECATED, REPO, PROGRAM, REVISION;
+
+	public boolean isInherited() {
+		// TODO Auto-generated method stub
+		return false;
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/help/packageinfo b/biz.aQute.bndlib/src/aQute/bnd/service/diff/packageinfo
similarity index 100%
copy from biz.aQute.bndlib/src/aQute/bnd/help/packageinfo
copy to biz.aQute.bndlib/src/aQute/bnd/service/diff/packageinfo
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/packageinfo b/biz.aQute.bndlib/src/aQute/bnd/service/packageinfo
index 5035fd2..63eb236 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/service/packageinfo
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/packageinfo
@@ -1 +1 @@
-version 1.44.0
+version 3.0.0
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/repository/MinimalRepository.java b/biz.aQute.bndlib/src/aQute/bnd/service/repository/MinimalRepository.java
new file mode 100644
index 0000000..dab3b0c
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/repository/MinimalRepository.java
@@ -0,0 +1,24 @@
+package aQute.bnd.service.repository;
+
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import aQute.bnd.version.*;
+import aQute.service.reporter.*;
+
+public interface MinimalRepository {
+	public enum Gestalt {
+		ADD, REMOTE
+	}
+
+	Report add(File f) throws Exception;
+
+	Iterable<String> list(String globbing);
+
+	List<Version> versions(String bsn);
+
+	Future<File> get(String bsn, Version version, Map<String,String> attrs);
+	
+	boolean is(Gestalt gestalt);
+}
diff --git a/aQute.libg/src/aQute/libg/filerepo/packageinfo b/biz.aQute.bndlib/src/aQute/bnd/service/repository/packageinfo
similarity index 100%
rename from aQute.libg/src/aQute/libg/filerepo/packageinfo
rename to biz.aQute.bndlib/src/aQute/bnd/service/repository/packageinfo
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/url/TaggedData.java b/biz.aQute.bndlib/src/aQute/bnd/service/url/TaggedData.java
new file mode 100644
index 0000000..fe81de8
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/url/TaggedData.java
@@ -0,0 +1,36 @@
+package aQute.bnd.service.url;
+
+import java.io.*;
+
+/**
+ * Represents a data stream that has a tag associated with it; the primary
+ * use-case is an HTTP response stream with an ETag header.
+ * 
+ * @author Neil Bartlett
+ */
+public class TaggedData {
+
+	private final String		tag;
+	private final InputStream	inputStream;
+
+	public TaggedData(String tag, InputStream inputStream) {
+		this.tag = tag;
+		this.inputStream = inputStream;
+	}
+
+	/**
+	 * Returns the ETag for the retrieved resource, or {@code null} if the ETag
+	 * was not provided by the server.
+	 */
+	public String getTag() {
+		return tag;
+	}
+
+	/**
+	 * Returns the input stream containing the resource data.
+	 */
+	public InputStream getInputStream() {
+		return inputStream;
+	}
+
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/url/URLConnector.java b/biz.aQute.bndlib/src/aQute/bnd/service/url/URLConnector.java
index 1285e31..5781288 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/service/url/URLConnector.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/url/URLConnector.java
@@ -1,9 +1,46 @@
 package aQute.bnd.service.url;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
+import java.io.*;
+import java.net.*;
 
 public interface URLConnector {
+
+	/**
+	 * Connect to the specified URL.
+	 * 
+	 * @param url
+	 * @return
+	 * @throws IOException
+	 */
 	InputStream connect(URL url) throws IOException;
+
+	/**
+	 * Connect to the specified URL, also returning the ETag if available.
+	 * 
+	 * @param url
+	 *            The remote URL.
+	 * @return An instance of {@link TaggedData}; note that the
+	 *         {@link TaggedData#getTag()} method <strong>may</strong> return
+	 *         {@code null} if the resource has no tag.
+	 * @throws IOException
+	 * @since 1.1
+	 */
+	TaggedData connectTagged(URL url) throws IOException;
+
+	/**
+	 * Connect to the specified URL while providing the last known tag for the
+	 * remote resource; the response will be {@code null} if the remote resource
+	 * is unchanged.
+	 * 
+	 * @param url
+	 *            The remote URL.
+	 * @param tag
+	 *            The last known tag value for the resource.
+	 * @return An instance of {@link TaggedData}, or {@code null} if the
+	 *         resource has not modified (i.e., if it has the same tag value).
+	 * @throws IOException
+	 * @since 1.1
+	 */
+	TaggedData connectTagged(URL url, String tag) throws IOException;
+
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/service/url/packageinfo b/biz.aQute.bndlib/src/aQute/bnd/service/url/packageinfo
new file mode 100644
index 0000000..7ae9673
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/service/url/packageinfo
@@ -0,0 +1 @@
+version 1.1
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/aQute/bnd/settings/Settings.java b/biz.aQute.bndlib/src/aQute/bnd/settings/Settings.java
deleted file mode 100644
index 78ed213..0000000
--- a/biz.aQute.bndlib/src/aQute/bnd/settings/Settings.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package aQute.bnd.settings;
-
-import java.security.*;
-import java.security.interfaces.*;
-import java.util.*;
-import java.util.prefs.*;
-
-import aQute.libg.cryptography.*;
-import aQute.libg.tuple.*;
-
-public class Settings {
-	public final static String	EMAIL			= "email";
-	public final static String	NAME			= "name";
-	public final static String	PASSWORD_SHA1	= "password.sha1";
-	final static String			KEY_PRIVATE		= "key.private";
-	final static String			KEY_PUBLIC		= "key.public";
-	final static String			KEY_SET			= "key.set";
-
-	static Preferences			prefs			= Preferences.userNodeForPackage(Settings.class);
-
-	public String globalGet(String key, String def) {
-		return prefs.get(key, def);
-	}
-
-	public void globalSet(String key, String value) throws BackingStoreException {
-		prefs.put(key, value);
-		prefs.sync();
-	}
-
-	public Collection<String> getKeys() throws BackingStoreException {
-		return Arrays.asList(prefs.keys());
-	}
-
-	public void globalRemove(String key) throws BackingStoreException {
-		prefs.remove(key);
-		prefs.sync();
-	}
-
-	private void generate() throws NoSuchAlgorithmException {
-		Pair<? extends PrivateKey, ? extends RSAPublicKey> pair = RSA.generate();
-		prefs.put(KEY_PRIVATE, Crypto.toString(pair.a));
-		prefs.put(KEY_PUBLIC, Crypto.toString(pair.b));
-		prefs.putBoolean(KEY_SET, true);
-	}
-
-	public PrivateKey getPrivateKey() throws Exception {
-		if (prefs.getBoolean(KEY_SET, false))
-			generate();
-
-		String key = prefs.get(KEY_PRIVATE, null);
-		return Crypto.fromString(key, PrivateKey.class);
-	}
-
-	public PublicKey getPublicKey() throws Exception {
-		if (prefs.getBoolean(KEY_SET, false))
-			generate();
-
-		String key = prefs.get(KEY_PUBLIC, null);
-		return Crypto.fromString(key, PublicKey.class);
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/signing/JartoolSigner.java b/biz.aQute.bndlib/src/aQute/bnd/signing/JartoolSigner.java
index 13e07cb..f878450 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/signing/JartoolSigner.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/signing/JartoolSigner.java
@@ -2,134 +2,141 @@ package aQute.bnd.signing;
 
 import java.io.*;
 import java.util.*;
+import java.util.Map.Entry;
 import java.util.concurrent.*;
 
+import aQute.bnd.osgi.*;
 import aQute.bnd.service.*;
-import aQute.lib.osgi.*;
 import aQute.libg.command.*;
-import aQute.libg.reporter.*;
+import aQute.service.reporter.*;
 
 /**
- * Sign the jar file.
- * 
- * -sign : <alias> [ ';' 'password:=' <password> ] [ ';' 'keystore:=' <keystore> ] [
- * ';' 'sign-password:=' <pw> ] ( ',' ... )*
+ * Sign the jar file. -sign : <alias> [ ';' 'password:=' <password> ] [ ';'
+ * 'keystore:=' <keystore> ] [ ';' 'sign-password:=' <pw> ] ( ',' ... )*
  * 
  * @author aqute
- * 
  */
 public class JartoolSigner implements Plugin, SignerPlugin {
-    String keystore;
-    String storetype;
-    String path = "jarsigner";
-    String storepass;
-    String keypass;
-    String sigFile;
-
-    public void setProperties(Map<String, String> map) {
-        if (map.containsKey("keystore"))
-            this.keystore = map.get("keystore");
-        if (map.containsKey("storetype"))
-            this.storetype = map.get("storetype");
-        if (map.containsKey("storepass"))
-            this.storepass = map.get("storepass");
-        if (map.containsKey("keypass"))
-            this.keypass = map.get("keypass");
-        if (map.containsKey("path"))
-            this.path = map.get("path");
-        if (map.containsKey("sigFile"))
-            this.sigFile = map.get("sigFile");
-
-    }
-
-    public void setReporter(Reporter processor) {
-    }
-
-    public void sign(Builder builder, String alias) throws Exception {    	    	
-    	File f = builder.getFile(keystore);
-    	if ( !f.isFile()) {
-    		builder.error("Invalid keystore %s", f.getAbsolutePath() );
-    		return;
-    	}
-    	
-        Jar jar = builder.getJar();
-        File tmp = File.createTempFile("signdjar", ".jar");
-        tmp.deleteOnExit();
-
-        jar.write(tmp);
-
-        Command command = new Command();
-        command.add(path);
-        if (keystore != null) {
-            command.add("-keystore");
-            command.add(f.getAbsolutePath());
-        }
-
-        if (storetype != null) {
-        	command.add("-storetype");
-        	command.add(storetype);
-        }
-
-        if (keypass != null) {
-        	command.add("-keypass");
-        	command.add(keypass);
-        }
-
-        if (storepass != null) {
-        	command.add("-storepass");
-        	command.add(storepass);
-        }
-
-        if (sigFile != null) {
-        	command.add("-sigFile");
-        	command.add(sigFile);
-        }
-
-        command.add(tmp.getAbsolutePath());
-        command.add(alias);
-        builder.trace("Jarsigner command: %s", command);
-        command.setTimeout(20, TimeUnit.SECONDS);
-        StringBuffer out = new StringBuffer();
-        StringBuffer err = new StringBuffer();
-        int exitValue = command.execute(System.in, out, err);
-        if (exitValue != 0) {
-            builder.error("Signing Jar out: %s\nerr: %s", out, err);
-        } else {
-            builder.trace("Signing Jar out: %s \nerr: %s", out, err);
-        }
-
-        Jar signed = new Jar(tmp);
-        builder.addClose(signed);
-
-        Map<String, Resource> dir = signed.getDirectories().get("META-INF");
-        for (String path : dir.keySet()) {
-            if (path.matches(".*\\.(DSA|RSA|SF|MF)$")) {
-                jar.putResource(path, dir.get(path));
-            }
-        }
-        jar.setDoNotTouchManifest();
-    }
-
-    StringBuffer collect(final InputStream in) throws Exception {
-        final StringBuffer sb = new StringBuffer();
-        
-        Thread tin = new Thread() {
-            public void run() {
-                try {
-                    BufferedReader rdr = new BufferedReader(new InputStreamReader(in, Constants.DEFAULT_CHARSET));
-                    String line = rdr.readLine();
-                    while (line != null) {
-                        sb.append(line);
-                        line = rdr.readLine();
-                    }
-                    rdr.close();
-                    in.close();
-                } catch (Exception e) {
-                    // Ignore any exceptions
-                }
-            }
-        };
-        tin.start();
-        return sb;
-    }
+	String	keystore;
+	String	storetype;
+	String	path	= "jarsigner";
+	String	storepass;
+	String	keypass;
+	String	sigFile;
+	String	digestalg;
+
+	public void setProperties(Map<String,String> map) {
+		if (map.containsKey("keystore"))
+			this.keystore = map.get("keystore");
+		if (map.containsKey("storetype"))
+			this.storetype = map.get("storetype");
+		if (map.containsKey("storepass"))
+			this.storepass = map.get("storepass");
+		if (map.containsKey("keypass"))
+			this.keypass = map.get("keypass");
+		if (map.containsKey("path"))
+			this.path = map.get("path");
+		if (map.containsKey("sigFile"))
+			this.sigFile = map.get("sigFile");
+		if (map.containsKey("digestalg"))
+			this.digestalg = map.get("digestalg");
+	}
+
+	public void setReporter(Reporter processor) {}
+
+	public void sign(Builder builder, String alias) throws Exception {
+		File f = builder.getFile(keystore);
+		if (!f.isFile()) {
+			builder.error("Invalid keystore %s", f.getAbsolutePath());
+			return;
+		}
+
+		Jar jar = builder.getJar();
+		File tmp = File.createTempFile("signdjar", ".jar");
+		tmp.deleteOnExit();
+
+		jar.write(tmp);
+
+		Command command = new Command();
+		command.add(path);
+		if (keystore != null) {
+			command.add("-keystore");
+			command.add(f.getAbsolutePath());
+		}
+
+		if (storetype != null) {
+			command.add("-storetype");
+			command.add(storetype);
+		}
+
+		if (keypass != null) {
+			command.add("-keypass");
+			command.add(keypass);
+		}
+
+		if (storepass != null) {
+			command.add("-storepass");
+			command.add(storepass);
+		}
+
+		if (sigFile != null) {
+			command.add("-sigFile");
+			command.add(sigFile);
+		}
+
+		if (digestalg != null) {
+			command.add("-digestalg");
+			command.add(digestalg);
+		}
+
+		command.add(tmp.getAbsolutePath());
+		command.add(alias);
+		builder.trace("Jarsigner command: %s", command);
+		command.setTimeout(20, TimeUnit.SECONDS);
+		StringBuilder out = new StringBuilder();
+		StringBuilder err = new StringBuilder();
+		int exitValue = command.execute(out, err);
+		if (exitValue != 0) {
+			builder.error("Signing Jar out: %s\nerr: %s", out, err);
+		} else {
+			builder.trace("Signing Jar out: %s \nerr: %s", out, err);
+		}
+
+		Jar signed = new Jar(tmp);
+		builder.addClose(signed);
+
+		Map<String,Resource> dir = signed.getDirectories().get("META-INF");
+		for (Entry<String,Resource> entry : dir.entrySet()) {
+			String path = entry.getKey();
+			if (path.matches(".*\\.(DSA|RSA|SF|MF)$")) {
+				jar.putResource(path, entry.getValue());
+			}
+		}
+		jar.setDoNotTouchManifest();
+	}
+
+	StringBuilder collect(final InputStream in) throws Exception {
+		final StringBuilder sb = new StringBuilder();
+
+		Thread tin = new Thread() {
+			@Override
+			public void run() {
+				try {
+					BufferedReader rdr = new BufferedReader(new InputStreamReader(in, Constants.DEFAULT_CHARSET));
+					String line = rdr.readLine();
+					while (line != null) {
+						sb.append(line);
+						line = rdr.readLine();
+					}
+					rdr.close();
+					in.close();
+				}
+				catch (Exception e) {
+					// Ignore any exceptions
+				}
+			}
+		};
+		tin.start();
+		return sb;
+	}
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/signing/Signer.java b/biz.aQute.bndlib/src/aQute/bnd/signing/Signer.java
index bed91be..1841a58 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/signing/Signer.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/signing/Signer.java
@@ -2,190 +2,187 @@ package aQute.bnd.signing;
 
 import java.io.*;
 import java.security.*;
-import java.security.KeyStore.*;
+import java.security.KeyStore.PrivateKeyEntry;
 import java.util.*;
 import java.util.jar.*;
 import java.util.regex.*;
 
+import aQute.bnd.osgi.*;
 import aQute.lib.base64.*;
-import aQute.lib.osgi.*;
+import aQute.lib.io.*;
 
 /**
- * This class is used with the aQute.lib.osgi package, it signs jars with DSA
- * signature.
- * 
- * -sign: md5, sha1
+ * This class is used with the aQute.bnd.osgi package, it signs jars with DSA
+ * signature. -sign: md5, sha1
  */
 public class Signer extends Processor {
-    static Pattern  METAINFDIR   = Pattern.compile("META-INF/[^/]*");
-    String         digestNames[]    = new String[] { "MD5" };
-    File           keystoreFile  = new File("keystore");
-    String         password;
-    String         alias;
-
-    public void signJar(Jar jar) {
-        if (digestNames == null || digestNames.length == 0)
-            error("Need at least one digest algorithm name, none are specified");
-
-        if (keystoreFile == null || !keystoreFile.getAbsoluteFile().exists()) {
-            error("No such keystore file: " + keystoreFile);
-            return;
-        }
-
-        if (alias == null) {
-            error("Private key alias not set for signing");
-            return;
-        }
-
-        MessageDigest digestAlgorithms[] = new MessageDigest[digestNames.length];
-
-        getAlgorithms(digestNames, digestAlgorithms);
-
-        try {
-            Manifest manifest = jar.getManifest();
-            manifest.getMainAttributes().putValue("Signed-By", "Bnd");
-
-            // Create a new manifest that contains the
-            // Name parts with the specified digests
-
-            ByteArrayOutputStream o = new ByteArrayOutputStream();
-            manifest.write(o);
-            doManifest(jar, digestNames, digestAlgorithms, o);
-            o.flush();
-            byte newManifestBytes[] = o.toByteArray();
-            jar.putResource("META-INF/MANIFEST.MF", new EmbeddedResource(
-                    newManifestBytes, 0));
-
-            // Use the bytes from the new manifest to create
-            // a signature file
-
-            byte[] signatureFileBytes = doSignatureFile(digestNames,
-                    digestAlgorithms, newManifestBytes);
-            jar.putResource("META-INF/BND.SF", new EmbeddedResource(
-                    signatureFileBytes, 0));
-
-            // Now we must create an RSA signature
-            // this requires the private key from the keystore
-
-            KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
-
-            KeyStore.PrivateKeyEntry privateKeyEntry = null;
-
-            try {
-                java.io.FileInputStream keystoreInputStream = new java.io.FileInputStream(
-                        keystoreFile);
-                keystore.load(keystoreInputStream, password == null ? null
-                        : password.toCharArray());
-                keystoreInputStream.close();
-                privateKeyEntry =  (PrivateKeyEntry) keystore.getEntry(
-                        alias, new KeyStore.PasswordProtection(password
-                                .toCharArray()));
-            } catch (Exception e) {
-                error("No able to load the private key from the give keystore("+keystoreFile.getAbsolutePath()+") with alias "+alias+" : "
-                        + e);
-                return;
-            }
-            PrivateKey privateKey = privateKeyEntry.getPrivateKey();
-
-            Signature signature = Signature.getInstance("MD5withRSA");
-            signature.initSign(privateKey);
-
-            signature.update(signatureFileBytes);
-
-            signature.sign();
-
-            // TODO, place the SF in a PCKS#7 structure ...
-            // no standard class for this? The following
-            // is an idea but we will to have do ASN.1 BER
-            // encoding ...
-
-         
-            
-            ByteArrayOutputStream tmpStream = new ByteArrayOutputStream();
-            jar.putResource("META-INF/BND.RSA", new EmbeddedResource(tmpStream
-                    .toByteArray(), 0));
-        } catch (Exception e) {
-            error("During signing: " + e);
-        }
-    }
-
-    private byte[] doSignatureFile(String[] digestNames,
-            MessageDigest[] algorithms, byte[] manbytes) {
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        PrintStream ps = new PrintStream(out);
-        ps.print("Signature-Version: 1.0\r\n");
-
-        for (int a = 0; a < algorithms.length; a++) {
-            if (algorithms[a] != null) {
-                byte[] digest = algorithms[a].digest(manbytes);
-                ps.print(digestNames[a] + "-Digest-Manifest: ");
-                ps.print(new Base64(digest));
-                ps.print("\r\n");
-            }
-        }
-        return out.toByteArray();
-    }
-
-    private void doManifest(Jar jar, String[] digestNames,
-            MessageDigest[] algorithms, OutputStream out) throws Exception {
-
-        for (Map.Entry<String,Resource> entry : jar.getResources().entrySet()) {
-            String name = entry.getKey();
-            if (!METAINFDIR.matcher(name).matches()) {
-                out.write("\r\n".getBytes());
-                out.write("Name: ".getBytes());
-                out.write(name.getBytes());
-                out.write("\r\n".getBytes());
-
-                digest(algorithms, entry.getValue());
-                for (int a = 0; a < algorithms.length; a++) {
-                    if (algorithms[a] != null) {
-                        byte[] digest = algorithms[a].digest();
-                        String header = digestNames[a] + "-Digest: "
-                                + new Base64(digest) + "\r\n";
-                        out.write(header.getBytes());
-                    }
-                }
-            }
-        }
-    }
-
-    private void digest(MessageDigest[] algorithms, Resource r)
-            throws Exception {
-        InputStream in = r.openInputStream();
-        byte[] data = new byte[1024];
-        int size = in.read(data);
-        while (size > 0) {
-            for (int a = 0; a < algorithms.length; a++) {
-                if (algorithms[a] != null) {
-                    algorithms[a].update(data, 0, size);
-                }
-            }
-            size = in.read(data);
-        }
-    }
-
-    private void getAlgorithms(String[] digestNames, MessageDigest[] algorithms) {
-        for (int i = 0; i < algorithms.length; i++) {
-            String name = digestNames[i];
-            try {
-                algorithms[i] = MessageDigest.getInstance(name);
-            } catch (NoSuchAlgorithmException e) {
-                error("Specified digest algorithm " + digestNames[i]
-                        + ", but not such algorithm was found: " + e);
-            }
-        }
-    }
-
-    public void setPassword(String string) {
-        password = string;
-    }
-
-    public void setKeystore(File keystore) {
-        this.keystoreFile = keystore;
-    }
-
-    public void setAlias(String string) {
-        this.alias = string;
-    }
+	static Pattern	METAINFDIR		= Pattern.compile("META-INF/[^/]*");
+	String			digestNames[]	= new String[] {
+										"MD5"
+									};
+	File			keystoreFile	= new File("keystore");
+	String			password;
+	String			alias;
+
+	public void signJar(Jar jar) {
+		if (digestNames == null || digestNames.length == 0)
+			error("Need at least one digest algorithm name, none are specified");
+
+		if (keystoreFile == null || !keystoreFile.getAbsoluteFile().exists()) {
+			error("No such keystore file: " + keystoreFile);
+			return;
+		}
+
+		if (alias == null) {
+			error("Private key alias not set for signing");
+			return;
+		}
+
+		MessageDigest digestAlgorithms[] = new MessageDigest[digestNames.length];
+
+		getAlgorithms(digestNames, digestAlgorithms);
+
+		try {
+			Manifest manifest = jar.getManifest();
+			manifest.getMainAttributes().putValue("Signed-By", "Bnd");
+
+			// Create a new manifest that contains the
+			// Name parts with the specified digests
+
+			ByteArrayOutputStream o = new ByteArrayOutputStream();
+			manifest.write(o);
+			doManifest(jar, digestNames, digestAlgorithms, o);
+			o.flush();
+			byte newManifestBytes[] = o.toByteArray();
+			jar.putResource("META-INF/MANIFEST.MF", new EmbeddedResource(newManifestBytes, 0));
+
+			// Use the bytes from the new manifest to create
+			// a signature file
+
+			byte[] signatureFileBytes = doSignatureFile(digestNames, digestAlgorithms, newManifestBytes);
+			jar.putResource("META-INF/BND.SF", new EmbeddedResource(signatureFileBytes, 0));
+
+			// Now we must create an RSA signature
+			// this requires the private key from the keystore
+
+			KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
+
+			KeyStore.PrivateKeyEntry privateKeyEntry = null;
+
+			java.io.FileInputStream keystoreInputStream = null;
+			try {
+				keystoreInputStream = new java.io.FileInputStream(keystoreFile);
+				char[] pw = password == null ? new char[0] : password.toCharArray();
+
+				keystore.load(keystoreInputStream, pw);
+				keystoreInputStream.close();
+				privateKeyEntry = (PrivateKeyEntry) keystore.getEntry(alias, new KeyStore.PasswordProtection(pw));
+			}
+			catch (Exception e) {
+				error("No able to load the private key from the give keystore(" + keystoreFile.getAbsolutePath()
+						+ ") with alias " + alias + " : " + e);
+				return;
+			}
+			finally {
+				IO.close(keystoreInputStream);
+			}
+			PrivateKey privateKey = privateKeyEntry.getPrivateKey();
+
+			Signature signature = Signature.getInstance("MD5withRSA");
+			signature.initSign(privateKey);
+
+			signature.update(signatureFileBytes);
+
+			signature.sign();
+
+			// TODO, place the SF in a PCKS#7 structure ...
+			// no standard class for this? The following
+			// is an idea but we will to have do ASN.1 BER
+			// encoding ...
+
+			ByteArrayOutputStream tmpStream = new ByteArrayOutputStream();
+			jar.putResource("META-INF/BND.RSA", new EmbeddedResource(tmpStream.toByteArray(), 0));
+		}
+		catch (Exception e) {
+			error("During signing: " + e);
+		}
+	}
+
+	private byte[] doSignatureFile(String[] digestNames, MessageDigest[] algorithms, byte[] manbytes)
+			throws IOException {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		PrintWriter ps = IO.writer(out);
+		ps.print("Signature-Version: 1.0\r\n");
+
+		for (int a = 0; a < algorithms.length; a++) {
+			if (algorithms[a] != null) {
+				byte[] digest = algorithms[a].digest(manbytes);
+				ps.print(digestNames[a] + "-Digest-Manifest: ");
+				ps.print(new Base64(digest));
+				ps.print("\r\n");
+			}
+		}
+		return out.toByteArray();
+	}
+
+	private void doManifest(Jar jar, String[] digestNames, MessageDigest[] algorithms, OutputStream out)
+			throws Exception {
+
+		for (Map.Entry<String,Resource> entry : jar.getResources().entrySet()) {
+			String name = entry.getKey();
+			if (!METAINFDIR.matcher(name).matches()) {
+				out.write("\r\n".getBytes("UTF-8"));
+				out.write("Name: ".getBytes("UTF-8"));
+				out.write(name.getBytes("UTF-8"));
+				out.write("\r\n".getBytes("UTF-8"));
+
+				digest(algorithms, entry.getValue());
+				for (int a = 0; a < algorithms.length; a++) {
+					if (algorithms[a] != null) {
+						byte[] digest = algorithms[a].digest();
+						String header = digestNames[a] + "-Digest: " + new Base64(digest) + "\r\n";
+						out.write(header.getBytes("UTF-8"));
+					}
+				}
+			}
+		}
+	}
+
+	private void digest(MessageDigest[] algorithms, Resource r) throws Exception {
+		InputStream in = r.openInputStream();
+		byte[] data = new byte[1024];
+		int size = in.read(data);
+		while (size > 0) {
+			for (int a = 0; a < algorithms.length; a++) {
+				if (algorithms[a] != null) {
+					algorithms[a].update(data, 0, size);
+				}
+			}
+			size = in.read(data);
+		}
+	}
+
+	private void getAlgorithms(String[] digestNames, MessageDigest[] algorithms) {
+		for (int i = 0; i < algorithms.length; i++) {
+			String name = digestNames[i];
+			try {
+				algorithms[i] = MessageDigest.getInstance(name);
+			}
+			catch (NoSuchAlgorithmException e) {
+				error("Specified digest algorithm " + digestNames[i] + ", but not such algorithm was found: " + e);
+			}
+		}
+	}
+
+	public void setPassword(String string) {
+		password = string;
+	}
+
+	public void setKeystore(File keystore) {
+		this.keystoreFile = keystore;
+	}
+
+	public void setAlias(String string) {
+		this.alias = string;
+	}
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/test/BndTestCase.java b/biz.aQute.bndlib/src/aQute/bnd/test/BndTestCase.java
index c2a145e..2ab2e1d 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/test/BndTestCase.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/test/BndTestCase.java
@@ -3,28 +3,28 @@ package aQute.bnd.test;
 import java.util.*;
 
 import junit.framework.*;
-import aQute.libg.reporter.*;
+import aQute.service.reporter.*;
 
 public abstract class BndTestCase extends TestCase {
 
-	protected void assertOk(Reporter reporter) {
+	protected static void assertOk(Reporter reporter) {
 		try {
 			assertEquals(0, reporter.getErrors().size());
 			assertEquals(0, reporter.getWarnings().size());
-		} catch (AssertionFailedError t) {
+		}
+		catch (AssertionFailedError t) {
 			print("Errors", reporter.getErrors());
 			print("Warnings", reporter.getWarnings());
 			throw t;
 		}
 	}
 
-
-	private void print(String title, List<?> strings) {
-		System.out.println("-------------------------------------------------------------------------");
-		System.out.println(title + " " + strings.size());
-		System.out.println("-------------------------------------------------------------------------");
-		for ( Object s : strings) {
-			System.out.println(s);
+	private static void print(String title, List< ? > strings) {
+		System.err.println("-------------------------------------------------------------------------");
+		System.err.println(title + " " + strings.size());
+		System.err.println("-------------------------------------------------------------------------");
+		for (Object s : strings) {
+			System.err.println(s);
 		}
 	}
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/test/NewlineEscapedStringFormatterTestCase.java b/biz.aQute.bndlib/src/aQute/bnd/test/NewlineEscapedStringFormatterTestCase.java
new file mode 100644
index 0000000..db7a890
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/test/NewlineEscapedStringFormatterTestCase.java
@@ -0,0 +1,16 @@
+package aQute.bnd.test;
+
+import junit.framework.*;
+import aQute.bnd.build.model.conversions.*;
+
+public class NewlineEscapedStringFormatterTestCase extends TestCase {
+	static public void testNewlines() {
+		NewlineEscapedStringFormatter formatter = new NewlineEscapedStringFormatter();
+
+		String i = "1\n2\n3\n";
+		String expected = "1\\n\\\n\t2\\n\\\n\t3\\n\\\n\t";
+		String o = formatter.convert(i);
+
+		assertEquals(expected, o);
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/test/SimpleContext.java b/biz.aQute.bndlib/src/aQute/bnd/test/SimpleContext.java
index 926d740..a66c34d 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/test/SimpleContext.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/test/SimpleContext.java
@@ -5,20 +5,18 @@ import java.util.*;
 import javax.xml.namespace.*;
 
 public class SimpleContext implements NamespaceContext {
-	final String prefix;
-	final String ns;
-	
-	
+	final String	prefix;
+	final String	ns;
+
 	SimpleContext(String prefix, String ns) {
 		this.prefix = prefix;
 		this.ns = ns;
 	}
-	
+
 	public String getNamespaceURI(String prefix) {
-		if ( prefix.equals(prefix))
+		if (prefix.equals(prefix))
 			return ns;
-		else
-			return null;
+		return null;
 	}
 
 	public String getPrefix(String namespaceURI) {
@@ -27,7 +25,7 @@ public class SimpleContext implements NamespaceContext {
 		return prefix;
 	}
 
-	public Iterator getPrefixes(String namespaceURI) {
+	public Iterator<String> getPrefixes(String namespaceURI) {
 		return Arrays.asList(prefix).iterator();
 	}
 
diff --git a/biz.aQute.bndlib/src/aQute/bnd/test/XmlTester.java b/biz.aQute.bndlib/src/aQute/bnd/test/XmlTester.java
index 62a48d2..00466ca 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/test/XmlTester.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/test/XmlTester.java
@@ -20,7 +20,8 @@ public class XmlTester {
 		try {
 			dbf.setNamespaceAware(true);
 			db = dbf.newDocumentBuilder();
-		} catch (ParserConfigurationException e) {
+		}
+		catch (ParserConfigurationException e) {
 			throw new RuntimeException(e);
 		}
 	}
@@ -31,7 +32,7 @@ public class XmlTester {
 	public XmlTester(InputStream in, final String... namespace) throws Exception {
 		xpath.setNamespaceContext(new NamespaceContext() {
 
-			public Iterator getPrefixes(String namespaceURI) {
+			public Iterator<String> getPrefixes(String namespaceURI) {
 				return Arrays.asList("md", "scr").iterator();
 			}
 
@@ -55,12 +56,17 @@ public class XmlTester {
 		document = db.parse(in);
 	}
 
-	public void assertAttribute(String value, String expr)
-			throws XPathExpressionException {
-		System.out.println(expr);
+	public void assertAttribute(String value, String expr) throws XPathExpressionException {
+		System.err.println(expr);
 		String o = (String) xpath.evaluate(expr, document, XPathConstants.STRING);
 		Assert.assertNotNull(o);
 		Assert.assertEquals(value, o);
 	}
+	
+	public void assertNamespace(String namespace) {
+		Element element = document.getDocumentElement();
+		String xmlns = element.getNamespaceURI();
+		Assert.assertEquals(namespace, xmlns);
+	}
 
 }
diff --git a/biz.aQute.bndlib/src/aQute/bnd/version/Version.java b/biz.aQute.bndlib/src/aQute/bnd/version/Version.java
new file mode 100755
index 0000000..5a9d194
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/version/Version.java
@@ -0,0 +1,167 @@
+package aQute.bnd.version;
+
+import java.util.regex.*;
+
+public class Version implements Comparable<Version> {
+	final int					major;
+	final int					minor;
+	final int					micro;
+	final String				qualifier;
+	public final static String	VERSION_STRING	= "(\\d{1,9})(\\.(\\d{1,9})(\\.(\\d{1,9})(\\.([-_\\da-zA-Z]+))?)?)?";
+	public final static Pattern	VERSION			= Pattern.compile(VERSION_STRING);
+	public final static Version	LOWEST			= new Version();
+	public final static Version	HIGHEST			= new Version(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE,
+														"\uFFFF");
+
+	public static final Version	emptyVersion	= LOWEST;
+	public static final Version	ONE				= new Version(1, 0, 0);
+
+	public Version() {
+		this(0);
+	}
+
+	public Version(int major, int minor, int micro, String qualifier) {
+		this.major = major;
+		this.minor = minor;
+		this.micro = micro;
+		this.qualifier = qualifier;
+	}
+
+	public Version(int major, int minor, int micro) {
+		this(major, minor, micro, null);
+	}
+
+	public Version(int major, int minor) {
+		this(major, minor, 0, null);
+	}
+
+	public Version(int major) {
+		this(major, 0, 0, null);
+	}
+
+	public Version(String version) {
+		version = version.trim();
+		Matcher m = VERSION.matcher(version);
+		if (!m.matches())
+			throw new IllegalArgumentException("Invalid syntax for version: " + version);
+
+		major = Integer.parseInt(m.group(1));
+		if (m.group(3) != null)
+			minor = Integer.parseInt(m.group(3));
+		else
+			minor = 0;
+
+		if (m.group(5) != null)
+			micro = Integer.parseInt(m.group(5));
+		else
+			micro = 0;
+
+		qualifier = m.group(7);
+	}
+
+	public int getMajor() {
+		return major;
+	}
+
+	public int getMinor() {
+		return minor;
+	}
+
+	public int getMicro() {
+		return micro;
+	}
+
+	public String getQualifier() {
+		return qualifier;
+	}
+
+	public int compareTo(Version other) {
+		if (other == this)
+			return 0;
+
+		Version o = other;
+		if (major != o.major)
+			return major - o.major;
+
+		if (minor != o.minor)
+			return minor - o.minor;
+
+		if (micro != o.micro)
+			return micro - o.micro;
+
+		int c = 0;
+		if (qualifier != null)
+			c = 1;
+		if (o.qualifier != null)
+			c += 2;
+
+		switch (c) {
+			case 0 :
+				return 0;
+			case 1 :
+				return 1;
+			case 2 :
+				return -1;
+		}
+		return qualifier.compareTo(o.qualifier);
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		sb.append(major);
+		sb.append(".");
+		sb.append(minor);
+		sb.append(".");
+		sb.append(micro);
+		if (qualifier != null) {
+			sb.append(".");
+			sb.append(qualifier);
+		}
+		return sb.toString();
+	}
+
+	@Override
+	public boolean equals(Object ot) {
+		if (!(ot instanceof Version))
+			return false;
+
+		return compareTo((Version) ot) == 0;
+	}
+
+	@Override
+	public int hashCode() {
+		return major * 97 ^ minor * 13 ^ micro + (qualifier == null ? 97 : qualifier.hashCode());
+	}
+
+	public int get(int i) {
+		switch (i) {
+			case 0 :
+				return major;
+			case 1 :
+				return minor;
+			case 2 :
+				return micro;
+			default :
+				throw new IllegalArgumentException("Version can only get 0 (major), 1 (minor), or 2 (micro)");
+		}
+	}
+
+	public static Version parseVersion(String version) {
+		if (version == null) {
+			return LOWEST;
+		}
+
+		version = version.trim();
+		if (version.length() == 0) {
+			return LOWEST;
+		}
+
+		return new Version(version);
+
+	}
+
+	public Version getWithoutQualifier() {
+		return new Version(major, minor, micro);
+	}
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/version/VersionRange.java b/biz.aQute.bndlib/src/aQute/bnd/version/VersionRange.java
new file mode 100755
index 0000000..8c9a8dd
--- /dev/null
+++ b/biz.aQute.bndlib/src/aQute/bnd/version/VersionRange.java
@@ -0,0 +1,94 @@
+package aQute.bnd.version;
+
+import java.util.*;
+import java.util.regex.*;
+
+public class VersionRange {
+	Version			high;
+	Version			low;
+	char			start	= '[';
+	char			end		= ']';
+
+	static Pattern	RANGE	= Pattern.compile("(\\(|\\[)\\s*(" + Version.VERSION_STRING + ")\\s*,\\s*("
+									+ Version.VERSION_STRING + ")\\s*(\\)|\\])");
+
+	public VersionRange(String string) {
+		string = string.trim();
+		Matcher m = RANGE.matcher(string);
+		if (m.matches()) {
+			start = m.group(1).charAt(0);
+			String v1 = m.group(2);
+			String v2 = m.group(10);
+			low = new Version(v1);
+			high = new Version(v2);
+			end = m.group(18).charAt(0);
+			if (low.compareTo(high) > 0)
+				throw new IllegalArgumentException("Low Range is higher than High Range: " + low + "-" + high);
+
+		} else
+			high = low = new Version(string);
+	}
+
+	public boolean isRange() {
+		return high != low;
+	}
+
+	public boolean includeLow() {
+		return start == '[';
+	}
+
+	public boolean includeHigh() {
+		return end == ']';
+	}
+
+	@Override
+	public String toString() {
+		if (high == low)
+			return high.toString();
+
+		StringBuilder sb = new StringBuilder();
+		sb.append(start);
+		sb.append(low);
+		sb.append(',');
+		sb.append(high);
+		sb.append(end);
+		return sb.toString();
+	}
+
+	public Version getLow() {
+		return low;
+	}
+
+	public Version getHigh() {
+		return high;
+	}
+
+	public boolean includes(Version v) {
+		if (!isRange()) {
+			return low.compareTo(v) <= 0;
+		}
+		if (includeLow()) {
+			if (v.compareTo(low) < 0)
+				return false;
+		} else if (v.compareTo(low) <= 0)
+			return false;
+
+		if (includeHigh()) {
+			if (v.compareTo(high) > 0)
+				return false;
+		} else if (v.compareTo(high) >= 0)
+			return false;
+
+		return true;
+	}
+
+	public Iterable<Version> filter(final Iterable<Version> versions) {
+		List<Version> list = new ArrayList<Version>();
+		for (Version v : versions) {
+			if (includes(v))
+				list.add(v);
+		}
+		return list;
+	}
+
+}
\ No newline at end of file
diff --git a/aQute.libg/src/aQute/libg/header/packageinfo b/biz.aQute.bndlib/src/aQute/bnd/version/packageinfo
similarity index 100%
rename from aQute.libg/src/aQute/libg/header/packageinfo
rename to biz.aQute.bndlib/src/aQute/bnd/version/packageinfo
diff --git a/biz.aQute.bndlib/src/aQute/lib/deployer/FileInstallRepo.java b/biz.aQute.bndlib/src/aQute/lib/deployer/FileInstallRepo.java
deleted file mode 100644
index cf05f98..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/deployer/FileInstallRepo.java
+++ /dev/null
@@ -1,149 +0,0 @@
-package aQute.lib.deployer;
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import java.util.jar.*;
-import java.util.regex.*;
-
-import aQute.lib.osgi.*;
-import aQute.libg.reporter.*;
-import aQute.libg.version.*;
-
-public class FileInstallRepo extends FileRepo {
-
-	String group;
-	boolean dirty;
-	Reporter reporter;
-	Pattern              REPO_FILE   = Pattern
-    .compile("([-a-zA-z0-9_\\.]+)-([0-9\\.]+)\\.(jar|lib)");
-	
-    public void setProperties(Map<String, String> map) {
-    	super.setProperties(map);
-    	group = map.get("group");
-    }
-    public void setReporter(Reporter reporter) {
-    	super.setReporter(reporter);
-        this.reporter = reporter;
-    }
-
-    public File put(Jar jar) throws Exception {
-        dirty = true;
-        Manifest manifest = jar.getManifest();
-        if (manifest == null)
-            throw new IllegalArgumentException("No manifest in JAR: " + jar);
-
-        String bsn = manifest.getMainAttributes().getValue(
-                Analyzer.BUNDLE_SYMBOLICNAME);
-        if (bsn == null)
-            throw new IllegalArgumentException("No Bundle SymbolicName set");
-
-        Map<String, Map<String, String>> b = Processor.parseHeader(bsn, null);
-        if (b.size() != 1)
-            throw new IllegalArgumentException("Multiple bsn's specified " + b);
-
-        for (String key : b.keySet()) {
-            bsn = key;
-            if (!Verifier.SYMBOLICNAME.matcher(bsn).matches())
-                throw new IllegalArgumentException(
-                        "Bundle SymbolicName has wrong format: " + bsn);
-        }
-
-        String versionString = manifest.getMainAttributes().getValue(
-                Analyzer.BUNDLE_VERSION);
-        Version version;
-        if (versionString == null)
-            version = new Version();
-        else
-            version = new Version(versionString);
-
-        File dir;
-        if (group == null) {
-        	dir = getRoot();
-        } else {
-        	dir= new File(getRoot(), group);
-        	dir.mkdirs();
-        }
-        String fName = bsn + "-" + version.getMajor() + "."
-                + version.getMinor() + "." + version.getMicro() + ".jar";
-        File file = new File(dir, fName);
-
-        jar.write(file);
-        fireBundleAdded(jar, file);
-
-        file = new File(dir, bsn + "-latest.jar");
-        if (file.isFile() && file.lastModified() < jar.lastModified()) {
-            jar.write(file);
-        }
-        return file;
-    }
-    public boolean refresh() {
-        if ( dirty ) {
-            dirty = false;
-            return true;
-        } else 
-            return false;
-    }
-	@Override
-	public List<String> list(String regex) {
-	       Instruction pattern = null;
-	        if (regex != null)
-	            pattern = Instruction.getPattern(regex);
-
-	        String list[] = getRoot().list();
-	        List<String> result = new ArrayList<String>();
-	        for (String f : list) {
-                Matcher m = REPO_FILE.matcher(f);
-                if (!m.matches()) {
-                	continue;
-                }
-                String s = m.group(1);
-	            if (pattern == null || pattern.matches(s))
-	                result.add(s);
-	        }
-	        return result;
-	}
-	@Override
-	public File[] get(String bsn, String versionRange) throws MalformedURLException {
-	       // If the version is set to project, we assume it is not
-        // for us. A project repo will then get it.
-        if (versionRange != null && versionRange.equals("project"))
-            return null;
-
-        //
-        // The version range we are looking for can
-        // be null (for all) or a version range.
-        //
-        VersionRange range;
-        if (versionRange == null || versionRange.equals("latest")) {
-            range = new VersionRange("0");
-        } else
-            range = new VersionRange(versionRange);
-
-        //
-        // Iterator over all the versions for this BSN.
-        // Create a sorted map over the version as key
-        // and the file as URL as value. Only versions
-        // that match the desired range are included in
-        // this list.
-        //
-        File instances[] = getRoot().listFiles();
-        SortedMap<Version, File> versions = new TreeMap<Version, File>();
-        for (int i = 0; i < instances.length; i++) {
-            Matcher m = REPO_FILE.matcher(instances[i].getName());
-            if (m.matches() && m.group(1).equals(bsn)) {
-                String versionString = m.group(2);
-                Version version;
-                if (versionString.equals("latest"))
-                    version = new Version(Integer.MAX_VALUE);
-                else
-                    version = new Version(versionString);
-
-                if (range.includes(version))
-                    versions.put(version, instances[i]);
-            }
-        }
-        return (File[]) versions.values().toArray(new File[versions.size()]);
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/deployer/FileRepo.java b/biz.aQute.bndlib/src/aQute/lib/deployer/FileRepo.java
index e12d6af..57b6b37 100644
--- a/biz.aQute.bndlib/src/aQute/lib/deployer/FileRepo.java
+++ b/biz.aQute.bndlib/src/aQute/lib/deployer/FileRepo.java
@@ -1,33 +1,211 @@
 package aQute.lib.deployer;
 
 import java.io.*;
+import java.security.*;
 import java.util.*;
-import java.util.jar.*;
 import java.util.regex.*;
 
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Verifier;
 import aQute.bnd.service.*;
+import aQute.bnd.version.*;
+import aQute.lib.collections.*;
+import aQute.lib.hex.*;
 import aQute.lib.io.*;
-import aQute.lib.osgi.*;
+import aQute.libg.command.*;
+import aQute.libg.cryptography.*;
 import aQute.libg.reporter.*;
-import aQute.libg.version.*;
+import aQute.service.reporter.*;
+
+/**
+ * A FileRepo is the primary and example implementation of a repository based on
+ * a file system. It maintains its files in a bsn/bsn-version.jar style from a
+ * given location. It implements all the functions of the
+ * {@link RepositoryPlugin}, {@link Refreshable}, {@link Actionable}, and
+ * {@link Closeable}. The FileRepo can be extended or used as is. When used as
+ * is, it is possible to add shell commands to the life cycle of the FileRepo.
+ * This life cycle is as follows:
+ * <ul>
+ * <li>{@link #CMD_INIT} - Is only executed when the location did not exist</li>
+ * <li>{@link #CMD_OPEN} - Called (after init if necessary) to open it once</li>
+ * <li>{@link #CMD_REFRESH} - Called when refreshed.</li>
+ * <li>{@link #CMD_BEFORE_PUT} - Before the file system is changed</li>
+ * <li>{@link #CMD_AFTER_PUT} - After the file system has changed, and the put
+ * <li>{@link #CMD_BEFORE_GET} - Before the file is gotten</li>
+ * <li>{@link #CMD_AFTER_ACTION} - Before the file is gotten</li>
+ * <li>{@link #CMD_CLOSE} - When the repo is closed and no more actions will
+ * take place</li> was a success</li>
+ * <li>{@link #CMD_ABORT_PUT} - When the put is aborted.</li>
+ * <li>{@link #CMD_CLOSE} - To close the repository.</li>
+ * </ul>
+ * Additionally, it is possible to set the {@link #CMD_SHELL} and the
+ * {@link #CMD_PATH}. Notice that you can use the ${global} macro to read global
+ * (that is, machine local) settings from the ~/.bnd/settings.json file (can be
+ * managed with bnd).
+ */
+public class FileRepo implements Plugin, RepositoryPlugin, Refreshable, RegistryPlugin, Actionable, Closeable {
 
-public class FileRepo implements Plugin, RepositoryPlugin, Refreshable, RegistryPlugin {
-	public static String	LOCATION	= "location";
-	public static String	READONLY	= "readonly";
-	public static String	NAME		= "name";
+	/**
+	 * If set, will trace to stdout. Works only if no reporter is set.
+	 */
+	public final static String	TRACE				= "trace";
 
-	File[]					EMPTY_FILES	= new File[0];
-	protected File			root;
-	Registry				registry;
-	boolean					canWrite	= true;
-	Pattern					REPO_FILE	= Pattern
-												.compile("([-a-zA-z0-9_\\.]+)-([0-9\\.]+|latest)\\.(jar|lib)");
-	Reporter				reporter;
-	boolean					dirty;
-	String					name;
+	/**
+	 * Property name for the location of the repo, must be a valid path name
+	 * using forward slashes (see {@link IO#getFile(String)}.
+	 */
+	public final static String	LOCATION			= "location";
 
-	public FileRepo() {
-	}
+	/**
+	 * Property name for the readonly state of the repository. If no, will
+	 * read/write, otherwise it must be a boolean value read by
+	 * {@link Boolean#parseBoolean(String)}. Read only repositories will not
+	 * accept writes.
+	 */
+	public final static String	READONLY			= "readonly";
+
+	/**
+	 * Set the name of this repository (optional)
+	 */
+	public final static String	NAME				= "name";
+
+	/**
+	 * Path property for commands. A comma separated path for directories to be
+	 * searched for command. May contain $ @} which will be replaced by the
+	 * system path. If this property is not set, the system path is assumed.
+	 */
+	public static final String	CMD_PATH			= "cmd.path";
+
+	/**
+	 * The name ( and path) of the shell to execute the commands. By default
+	 * this is sh and searched in the path.
+	 */
+	public static final String	CMD_SHELL			= "cmd.shell";
+
+	/**
+	 * Property for commands. The command only runs when the location does not
+	 * exist. </p>
+	 * 
+	 * @param rootFile
+	 *            the root of the repo (directory exists)
+	 */
+	public static final String	CMD_INIT			= "cmd.init";
+
+	/**
+	 * Property for commands. Command is run before the repo is first used. </p>
+	 * 
+	 * @param $0
+	 *            rootFile the root of the repo (directory exists)
+	 */
+	public static final String	CMD_OPEN			= "cmd.open";
+
+	/**
+	 * Property for commands. The command runs after a put operation. </p>
+	 * 
+	 * @param $0
+	 *            the root of the repo (directory exists)
+	 * @param $1
+	 *            the file that was put
+	 * @param $2
+	 *            the hex checksum of the file
+	 */
+	public static final String	CMD_AFTER_PUT		= "cmd.after.put";
+
+	/**
+	 * Property for commands. The command runs when the repository is refreshed.
+	 * </p>
+	 * 
+	 * @param $
+	 *            {0} the root of the repo (directory exists)
+	 */
+	public static final String	CMD_REFRESH			= "cmd.refresh";
+
+	/**
+	 * Property for commands. The command runs after the file is put. </p>
+	 * 
+	 * @param $0
+	 *            the root of the repo (directory exists)
+	 * @param $1
+	 *            the path to a temporary file
+	 */
+	public static final String	CMD_BEFORE_PUT		= "cmd.before.put";
+
+	/**
+	 * Property for commands. The command runs when a put is aborted after file
+	 * changes were made. </p>
+	 * 
+	 * @param $0
+	 *            the root of the repo (directory exists)
+	 * @param $1
+	 *            the temporary file that was used (optional)
+	 */
+	public static final String	CMD_ABORT_PUT		= "cmd.abort.put";
+
+	/**
+	 * Property for commands. The command runs after the file is put. </p>
+	 * 
+	 * @param $0
+	 *            the root of the repo (directory exists)
+	 */
+	public static final String	CMD_CLOSE			= "cmd.close";
+
+	/**
+	 * Property for commands. Will be run after an action has been executed.
+	 * </p>
+	 * 
+	 * @param $0
+	 *            the root of the repo (directory exists)
+	 * @param $1
+	 *            the path to the file that the action was executed on
+	 * @param $2
+	 *            the action executed
+	 */
+	public static final String	CMD_AFTER_ACTION	= "cmd.after.action";
+
+	/**
+	 * Called before a before get.
+	 * 
+	 * @param $0
+	 *            the root of the repo (directory exists)
+	 * @param $1
+	 *            the bsn
+	 * @param $2
+	 *            the version
+	 */
+	public static final String	CMD_BEFORE_GET		= "cmd.before.get";
+
+	/**
+	 * Options used when the options are null
+	 */
+	static final PutOptions		DEFAULTOPTIONS		= new PutOptions();
+
+	public static final int	MAX_MAJOR	= 999999999;
+
+	
+	String						shell;
+	String						path;
+	String						init;
+	String						open;
+	String						refresh;
+	String						beforePut;
+	String						afterPut;
+	String						abortPut;
+	String						beforeGet;
+	String						close;
+	String						action;
+
+	File[]						EMPTY_FILES			= new File[0];
+	protected File				root;
+	Registry					registry;
+	boolean						canWrite			= true;
+	Pattern						REPO_FILE			= Pattern.compile("([-a-zA-z0-9_\\.]+)-([0-9\\.]+|latest)\\.(jar|lib)");
+	Reporter					reporter;
+	boolean						dirty;
+	String						name;
+	boolean						inited;
+	boolean						trace;
+
+	public FileRepo() {}
 
 	public FileRepo(String name, File location, boolean canWrite) {
 		this.name = name;
@@ -35,163 +213,203 @@ public class FileRepo implements Plugin, RepositoryPlugin, Refreshable, Registry
 		this.canWrite = canWrite;
 	}
 
-	protected void init() throws Exception {
-		// for extensions
+	/**
+	 * Initialize the repository Subclasses should first call this method and
+	 * then if it returns true, do their own initialization
+	 * 
+	 * @return true if initialized, false if already had been initialized.
+	 * @throws Exception
+	 */
+	protected boolean init() throws Exception {
+		if (inited)
+			return false;
+
+		inited = true;
+
+		if (reporter == null) {
+			ReporterAdapter reporter = trace ? new ReporterAdapter(System.out) : new ReporterAdapter();
+			reporter.setTrace(trace);
+			reporter.setExceptions(trace);
+			this.reporter = reporter;
+		}
+
+		if (!root.isDirectory()) {
+			root.mkdirs();
+			if (!root.isDirectory())
+				throw new IllegalArgumentException("Location cannot be turned into a directory " + root);
+
+			exec(init, root.getAbsolutePath());
+		}
+		open();
+		return true;
 	}
 
-	public void setProperties(Map<String, String> map) {
-		String location = (String) map.get(LOCATION);
+	/**
+	 * @see aQute.bnd.service.Plugin#setProperties(java.util.Map)
+	 */
+	public void setProperties(Map<String,String> map) {
+		String location = map.get(LOCATION);
 		if (location == null)
 			throw new IllegalArgumentException("Location must be set on a FileRepo plugin");
 
-		root = new File(location);
-		if (!root.isDirectory())
-			throw new IllegalArgumentException("Repository is not a valid directory " + root);
-
-		String readonly = (String) map.get(READONLY);
+		root = IO.getFile(IO.home, location);
+		String readonly = map.get(READONLY);
 		if (readonly != null && Boolean.valueOf(readonly).booleanValue())
 			canWrite = false;
 
-		name = (String) map.get(NAME);
+		name = map.get(NAME);
+		path = map.get(CMD_PATH);
+		shell = map.get(CMD_SHELL);
+		init = map.get(CMD_INIT);
+		open = map.get(CMD_OPEN);
+		refresh = map.get(CMD_REFRESH);
+		beforePut = map.get(CMD_BEFORE_PUT);
+		abortPut = map.get(CMD_ABORT_PUT);
+		afterPut = map.get(CMD_AFTER_PUT);
+		beforeGet = map.get(CMD_BEFORE_GET);
+		close = map.get(CMD_CLOSE);
+		action = map.get(CMD_AFTER_ACTION);
+
+		trace = map.get(TRACE) != null && Boolean.parseBoolean(map.get(TRACE));
 	}
 
 	/**
-	 * Get a list of URLs to bundles that are constrained by the bsn and
-	 * versionRange.
+	 * Answer if this repository can write.
 	 */
-	public File[] get(String bsn, String versionRange) throws Exception {
-		init();
+	public boolean canWrite() {
+		return canWrite;
+	}
 
-		// If the version is set to project, we assume it is not
-		// for us. A project repo will then get it.
-		if (versionRange != null && versionRange.equals("project"))
-			return null;
+	/**
+	 * Local helper method that tries to insert a file in the repository. This
+	 * method can be overridden but MUST not change the content of the tmpFile.
+	 * This method should also create a latest version of the artifact for
+	 * reference by tools like ant etc. </p> It is allowed to rename the file,
+	 * the tmp file must be beneath the root directory to prevent rename
+	 * problems.
+	 * 
+	 * @param tmpFile
+	 *            source file
+	 * @param digest
+	 * @return a File that contains the content of the tmpFile
+	 * @throws Exception
+	 */
+	protected File putArtifact(File tmpFile, byte[] digest) throws Exception {
+		assert (tmpFile != null);
 
-		//
-		// Check if the entry exists
-		//
-		File f = new File(root, bsn);
-		if (!f.isDirectory())
-			return null;
+		Jar tmpJar = new Jar(tmpFile);
+		try {
+			dirty = true;
 
-		//
-		// The version range we are looking for can
-		// be null (for all) or a version range.
-		//
-		VersionRange range;
-		if (versionRange == null || versionRange.equals("latest")) {
-			range = new VersionRange("0");
-		} else
-			range = new VersionRange(versionRange);
-
-		//
-		// Iterator over all the versions for this BSN.
-		// Create a sorted map over the version as key
-		// and the file as URL as value. Only versions
-		// that match the desired range are included in
-		// this list.
-		//
-		File instances[] = f.listFiles();
-		SortedMap<Version, File> versions = new TreeMap<Version, File>();
-		for (int i = 0; i < instances.length; i++) {
-			Matcher m = REPO_FILE.matcher(instances[i].getName());
-			if (m.matches() && m.group(1).equals(bsn)) {
-				String versionString = m.group(2);
-				Version version;
-				if (versionString.equals("latest"))
-					version = new Version(Integer.MAX_VALUE);
-				else
-					version = new Version(versionString);
-
-				if (range.includes(version) || versionString.equals(versionRange))
-					versions.put(version, instances[i]);
-			}
-		}
+			String bsn = tmpJar.getBsn();
+			if (bsn == null)
+				throw new IllegalArgumentException("No bsn set in jar: " + tmpFile);
 
-		File[] files = (File[]) versions.values().toArray(EMPTY_FILES);
-		if ("latest".equals(versionRange) && files.length > 0) {
-			return new File[] { files[files.length - 1] };
-		}
-		return files;
-	}
+			String versionString = tmpJar.getVersion();
+			if (versionString == null)
+				versionString = "0";
+			else if (!Verifier.isVersion(versionString))
+				throw new IllegalArgumentException("Incorrect version in : " + tmpFile + " " + versionString);
 
-	public boolean canWrite() {
-		return canWrite;
-	}
+			Version version = new Version(versionString);
 
-	public File put(Jar jar) throws Exception {
-		init();
-		dirty = true;
+			reporter.trace("bsn=%s version=%s", bsn, version);
 
-		Manifest manifest = jar.getManifest();
-		if (manifest == null)
-			throw new IllegalArgumentException("No manifest in JAR: " + jar);
+			File dir = new File(root, bsn);
+			dir.mkdirs();
+			if (!dir.isDirectory())
+				throw new IOException("Could not create directory " + dir);
 
-		String bsn = manifest.getMainAttributes().getValue(Analyzer.BUNDLE_SYMBOLICNAME);
-		if (bsn == null)
-			throw new IllegalArgumentException("No Bundle SymbolicName set");
+			String fName = bsn + "-" + version.getWithoutQualifier() + ".jar";
+			File file = new File(dir, fName);
 
-		Map<String, Map<String, String>> b = Processor.parseHeader(bsn, null);
-		if (b.size() != 1)
-			throw new IllegalArgumentException("Multiple bsn's specified " + b);
+			reporter.trace("updating %s ", file.getAbsolutePath());
 
-		for (String key : b.keySet()) {
-			bsn = key;
-			if (!Verifier.SYMBOLICNAME.matcher(bsn).matches())
-				throw new IllegalArgumentException("Bundle SymbolicName has wrong format: " + bsn);
-		}
+			// An open jar on file will fail rename on windows
+			tmpJar.close();
 
-		String versionString = manifest.getMainAttributes().getValue(Analyzer.BUNDLE_VERSION);
-		Version version;
-		if (versionString == null)
-			version = new Version();
-		else
-			version = new Version(versionString);
+			IO.rename(tmpFile, file);
 
-		File dir = new File(root, bsn);
-		dir.mkdirs();
-		String fName = bsn + "-" + version.getMajor() + "." + version.getMinor() + "."
-				+ version.getMicro() + ".jar";
-		File file = new File(dir, fName);
-
-		reporter.trace("Updating " + file.getAbsolutePath());
-		if (!file.exists() || file.lastModified() < jar.lastModified()) {
-			jar.write(file);
-			reporter.progress("Updated " + file.getAbsolutePath());
-			fireBundleAdded(jar, file);
-		} else {
-			reporter.progress("Did not update " + jar + " because repo has a newer version");
-			reporter.trace("NOT Updating " + fName + " (repo is newer)");
+			fireBundleAdded(file);
+			afterPut(file, bsn, version, Hex.toHexString(digest));
+
+			// TODO like to beforeGet rid of the latest option. This is only
+			// used to have a constant name for the outside users (like ant)
+			// we should be able to handle this differently?
+			File latest = new File(dir, bsn + "-latest.jar");
+			IO.copy(file, latest);
+
+			reporter.trace("updated %s", file.getAbsolutePath());
+
+			return file;
 		}
+		finally {
+			tmpJar.close();
+		}
+	}
 
-		File latest = new File(dir, bsn + "-latest.jar");
-		if (latest.exists() && latest.lastModified() < jar.lastModified()) {
-			jar.write(latest);
-			file = latest;
+	/*
+	 * (non-Javadoc)
+	 * @see aQute.bnd.service.RepositoryPlugin#put(java.io.InputStream,
+	 * aQute.bnd.service.RepositoryPlugin.PutOptions)
+	 */
+	public PutResult put(InputStream stream, PutOptions options) throws Exception {
+		/* determine if the put is allowed */
+		if (!canWrite) {
+			throw new IOException("Repository is read-only");
 		}
 
-		return file;
-	}
+		assert stream != null;
 
-	protected void fireBundleAdded(Jar jar, File file) {
-		if (registry == null)
-			return;
-		List<RepositoryListenerPlugin> listeners = registry
-				.getPlugins(RepositoryListenerPlugin.class);
-		for (RepositoryListenerPlugin listener : listeners) {
+		if (options == null)
+			options = DEFAULTOPTIONS;
+
+		init();
+
+		/*
+		 * copy the artifact from the (new/digest) stream into a temporary file
+		 * in the root directory of the repository
+		 */
+		File tmpFile = IO.createTempFile(root, "put", ".jar");
+		try {
+			DigestInputStream dis = new DigestInputStream(stream, MessageDigest.getInstance("SHA-1"));
 			try {
-				listener.bundleAdded(this, jar, file);
-			} catch (Exception e) {
-				if (reporter != null)
-					reporter.warning("Repository listener threw an unexpected exception: %s", e);
+				IO.copy(dis, tmpFile);
+
+				byte[] digest = dis.getMessageDigest().digest();
+
+				if (options.digest != null && !Arrays.equals(digest, options.digest))
+					throw new IOException("Retrieved artifact digest doesn't match specified digest");
+
+				/*
+				 * put the artifact into the repository (from the temporary
+				 * file)
+				 */
+				beforePut(tmpFile);
+				File file = putArtifact(tmpFile, digest);
+				file.setReadOnly();
+
+				PutResult result = new PutResult();
+				result.digest = digest;
+				result.artifact = file.toURI();
+
+				return result;
 			}
+			finally {
+				dis.close();
+			}
+		}
+		catch (Exception e) {
+			abortPut(tmpFile);
+			throw e;
+		}
+		finally {
+			IO.delete(tmpFile);
 		}
 	}
 
 	public void setLocation(String string) {
-		root = new File(string);
-		if (!root.isDirectory())
-			throw new IllegalArgumentException("Invalid repository directory");
+		root = IO.getFile(string);
 	}
 
 	public void setReporter(Reporter reporter) {
@@ -202,7 +420,7 @@ public class FileRepo implements Plugin, RepositoryPlugin, Refreshable, Registry
 		init();
 		Instruction pattern = null;
 		if (regex != null)
-			pattern = Instruction.getPattern(regex);
+			pattern = new Instruction(regex);
 
 		List<String> result = new ArrayList<String>();
 		if (root == null) {
@@ -227,8 +445,9 @@ public class FileRepo implements Plugin, RepositoryPlugin, Refreshable, Registry
 		return result;
 	}
 
-	public List<Version> versions(String bsn) throws Exception {
+	public SortedSet<Version> versions(String bsn) throws Exception {
 		init();
+		boolean haslatest = false;
 		File dir = new File(root, bsn);
 		if (dir.isDirectory()) {
 			String versions[] = dir.list();
@@ -238,15 +457,19 @@ public class FileRepo implements Plugin, RepositoryPlugin, Refreshable, Registry
 				if (m.matches()) {
 					String version = m.group(2);
 					if (version.equals("latest"))
-						version = Integer.MAX_VALUE+"";
-					list.add(new Version(version));
+						haslatest = true;
+					else
+						list.add(new Version(version));
 				}
 			}
-			return list;
+			if ( list.isEmpty() && haslatest)
+				list.add( new Version(MAX_MAJOR,0,0));
+			return new SortedList<Version>(list);
 		}
-		return null;
+		return SortedList.empty();
 	}
 
+	@Override
 	public String toString() {
 		return String.format("%-40s r/w=%s", root.getAbsolutePath(), canWrite());
 	}
@@ -255,12 +478,14 @@ public class FileRepo implements Plugin, RepositoryPlugin, Refreshable, Registry
 		return root;
 	}
 
-	public boolean refresh() {
+	public boolean refresh() throws Exception {
+		init();
+		exec(refresh, root);
 		if (dirty) {
 			dirty = false;
 			return true;
-		} else
-			return false;
+		}
+		return false;
 	}
 
 	public String getName() {
@@ -270,46 +495,322 @@ public class FileRepo implements Plugin, RepositoryPlugin, Refreshable, Registry
 		return name;
 	}
 
-	public File get(String bsn, String version, Strategy strategy, Map<String, String> properties)
+	/*
+	 * (non-Javadoc)
+	 * @see aQute.bnd.service.RepositoryPlugin#get(java.lang.String,
+	 * aQute.bnd.version.Version, java.util.Map)
+	 */
+	public File get(String bsn, Version version, Map<String,String> properties, DownloadListener... listeners)
 			throws Exception {
-		if (version == null)
-			version = "0.0.0";
+		init();
+		beforeGet(bsn, version);
+		File file = getLocal(bsn, version, properties);
+		if (file.exists()) {
+			for (DownloadListener l : listeners) {
+				try {
+					l.success(file);
+				}
+				catch (Exception e) {
+					reporter.exception(e, "Download listener for %s", file);
+				}
+			}
+			return file;
+		}
+		return null;
+	}
+
+	public void setRegistry(Registry registry) {
+		this.registry = registry;
+	}
 
-		if (strategy == Strategy.EXACT) {
-			VersionRange vr = new VersionRange(version);
-			if (vr.isRange())
+	public String getLocation() {
+		return root.toString();
+	}
+
+	public Map<String,Runnable> actions(Object... target) throws Exception {
+		if (target == null || target.length == 0)
+			return null; // no default actions
+
+		try {
+			String bsn = (String) target[0];
+			Version version = (Version) target[1];
+
+			final File f = get(bsn, version, null);
+			if (f == null)
 				return null;
 
-			if ( vr.getHigh().getMajor() == Integer.MAX_VALUE)
-				version = "latest";
-			
-			File file = IO.getFile(root, bsn + "/" + bsn + "-" + version + ".jar");
-			if (file.isFile())
-				return file;
-			else {
-				file = IO.getFile(root, bsn + "/" + bsn + "-" + version + ".lib");
-				if (file.isFile())
-					return file;
-			}
+			Map<String,Runnable> actions = new HashMap<String,Runnable>();
+			actions.put("Delete " + bsn + "-" + status(bsn, version), new Runnable() {
+				public void run() {
+					IO.delete(f);
+					if (f.getParentFile().list().length == 0)
+						IO.delete(f.getParentFile());
+					afterAction(f, "delete");
+				};
+			});
+			return actions;
+		}
+		catch (Exception e) {
 			return null;
+		}
+	}
+
+	protected void afterAction(File f, String key) {
+		exec(action, root, f, key);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see aQute.bnd.service.Actionable#tooltip(java.lang.Object[])
+	 */
+	@SuppressWarnings("unchecked")
+	public String tooltip(Object... target) throws Exception {
+		if (target == null || target.length == 0)
+			return String.format("%s\n%s", getName(), root);
+
+		try {
+			String bsn = (String) target[0];
+			Version version = (Version) target[1];
+			Map<String,String> map = null;
+			if (target.length > 2)
+				map = (Map<String,String>) target[2];
+
+			File f = getLocal(bsn, version, map);
+			String s = String.format("Path: %s\nSize: %s\nSHA1: %s", f.getAbsolutePath(), readable(f.length(), 0), SHA1
+					.digest(f).asHex());
+			if (f.getName().endsWith(".lib") && f.isFile()) {
+				s += "\n" + IO.collect(f);
+			}
+			return s;
 
 		}
-		File[] files = get(bsn, version);
-		if (files == null || files.length == 0)
+		catch (Exception e) {
 			return null;
+		}
+	}
 
-		if (files.length >= 0) {
-			switch (strategy) {
-			case LOWEST:
-				return files[0];
-			case HIGHEST:
-				return files[files.length - 1];
-			}
+	/*
+	 * (non-Javadoc)
+	 * @see aQute.bnd.service.Actionable#title(java.lang.Object[])
+	 */
+	public String title(Object... target) throws Exception {
+		if (target == null || target.length == 0)
+			return getName();
+
+		if (target.length == 1 && target[0] instanceof String)
+			return (String) target[0];
+
+		if (target.length == 2 && target[0] instanceof String && target[1] instanceof Version) {
+			return status((String) target[0], (Version) target[1]);
 		}
+
 		return null;
 	}
 
-	public void setRegistry(Registry registry) {
-		this.registry = registry;
+	protected File getLocal(String bsn, Version version, Map<String,String> properties) {
+		File dir = new File(root, bsn);
+
+		if ( version.getMajor() == MAX_MAJOR && version.getMinor()== 0 && version.getMicro() == 0 && version.getQualifier() == null) {
+			File fjar = new File(dir, bsn + "-latest.jar");
+			if (fjar.isFile())
+				return fjar.getAbsoluteFile();
+		}
+		
+		File fjar = new File(dir, bsn + "-" + version.getWithoutQualifier() + ".jar");
+		if (fjar.isFile())
+			return fjar.getAbsoluteFile();
+
+		File flib = new File(dir, bsn + "-" + version.getWithoutQualifier() + ".lib");
+		if (flib.isFile())
+			return flib.getAbsoluteFile();
+
+		return fjar.getAbsoluteFile();
+	}
+
+	protected String status(String bsn, Version version) {
+		File file = getLocal(bsn, version, null);
+		StringBuilder sb = new StringBuilder(version.toString());
+		String del = " [";
+
+		if (file.getName().endsWith(".lib")) {
+			sb.append(del).append("L");
+			del = "";
+		}
+		if (!file.getName().endsWith(".jar")) {
+			sb.append(del).append("?");
+			del = "";
+		}
+		if (!file.isFile()) {
+			sb.append(del).append("X");
+			del = "";
+		}
+		if (file.length() == 0) {
+			sb.append(del).append("0");
+			del = "";
+		}
+		if (del.equals(""))
+			sb.append("]");
+		return sb.toString();
+	}
+
+	private static String[]	names	= {
+			"bytes", "Kb", "Mb", "Gb"
+									};
+
+	private Object readable(long length, int n) {
+		if (length < 0)
+			return "<invalid>";
+
+		if (length < 1024 || n >= names.length)
+			return length + names[n];
+
+		return readable(length / 1024, n + 1);
 	}
+
+	public void close() throws IOException {
+		if (inited)
+			exec(close, root.getAbsolutePath());
+	}
+
+	protected void open() {
+		exec(open, root.getAbsolutePath());
+	}
+
+	protected void beforePut(File tmp) {
+		exec(beforePut, root.getAbsolutePath(), tmp.getAbsolutePath());
+	}
+
+	protected void afterPut(File file, String bsn, Version version, String sha) {
+		exec(afterPut, root.getAbsolutePath(), file.getAbsolutePath(), sha);
+	}
+
+	protected void abortPut(File tmpFile) {
+		exec(abortPut, root.getAbsolutePath(), tmpFile.getAbsolutePath());
+	}
+
+	protected void beforeGet(String bsn, Version version) {
+		exec(beforeGet, root.getAbsolutePath(), bsn, version);
+	}
+
+	protected void fireBundleAdded(File file) {
+		if (registry == null)
+			return;
+		List<RepositoryListenerPlugin> listeners = registry.getPlugins(RepositoryListenerPlugin.class);
+		Jar jar = null;
+		for (RepositoryListenerPlugin listener : listeners) {
+			try {
+				if (jar == null)
+					jar = new Jar(file);
+				listener.bundleAdded(this, jar, file);
+			}
+			catch (Exception e) {
+				if (reporter != null)
+					reporter.warning("Repository listener threw an unexpected exception: %s", e);
+			}
+			finally {
+				if (jar != null)
+					jar.close();
+			}
+		}
+	}
+
+	/**
+	 * Execute a command. Used in different stages so that the repository can be
+	 * synced with external tools.
+	 * 
+	 * @param line
+	 * @param target
+	 */
+	void exec(String line, Object... args) {
+		if (line == null) {
+			return;
+		}
+
+		try {
+			if (args != null) {
+				for (int i = 0; i < args.length; i++) {
+					if (i == 0) {
+						// replaceAll backslash magic ensures windows paths
+						// remain intact
+						line = line.replaceAll("\\$\\{@\\}", args[0].toString().replaceAll("\\\\", "\\\\\\\\"));
+					}
+					// replaceAll backslash magic ensures windows paths remain
+					// intact
+					line = line.replaceAll("\\$" + i, args[i].toString().replaceAll("\\\\", "\\\\\\\\"));
+				}
+			}
+			// purge remaining placeholders
+			line = line.replaceAll("\\s*\\$[0-9]\\s*", "");
+
+			int result = 0;
+			StringBuilder stdout = new StringBuilder();
+			StringBuilder stderr = new StringBuilder();
+			if (System.getProperty("os.name").toLowerCase().indexOf("win") >= 0) {
+
+				// FIXME ignoring possible shell setting stdin approach used
+				// below does not work in windows
+				Command cmd = new Command("cmd.exe /C " + line);
+				cmd.setCwd(getRoot());
+				result = cmd.execute(stdout, stderr);
+
+			} else {
+				if (shell == null) {
+					shell = "sh";
+				}
+				Command cmd = new Command(shell);
+				cmd.setCwd(getRoot());
+
+				if (path != null) {
+					cmd.inherit();
+					String oldpath = cmd.var("PATH");
+					path = path.replaceAll("\\s*,\\s*", File.pathSeparator);
+					path = path.replaceAll("\\$\\{@\\}", oldpath);
+					cmd.var("PATH", path);
+				}
+				result = cmd.execute(line, stdout, stderr);
+			}
+			if (result != 0) {
+				reporter.error("Command %s failed with %s %s %s", line, result, stdout, stderr);
+			}
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+			reporter.exception(e, e.getMessage());
+		}
+	}
+
+	/*
+	 * 8 Set the root directory directly
+	 */
+	public void setDir(File repoDir) {
+		this.root = repoDir;
+	}
+
+	/**
+	 * Delete an entry from the repository and cleanup the directory
+	 * 
+	 * @param bsn
+	 * @param version
+	 * @throws Exception
+	 */
+	public void delete(String bsn, Version version) throws Exception {
+		assert bsn != null;
+
+		SortedSet<Version> versions;
+		if (version == null)
+			versions = versions(bsn);
+		else
+			versions = new SortedList<Version>(version);
+
+		for (Version v : versions) {
+			File f = getLocal(bsn, version, null);
+			if (!f.isFile())
+				reporter.error("No artifact found for %s:%s", bsn, version);
+			else
+				IO.delete(f);
+		}
+		if ( versions(bsn).isEmpty())
+			IO.delete( new File(root,bsn));
+	}
+
 }
diff --git a/biz.aQute.bndlib/src/aQute/lib/deployer/http/HttpBasicAuthURLConnector.java b/biz.aQute.bndlib/src/aQute/lib/deployer/http/HttpBasicAuthURLConnector.java
deleted file mode 100644
index 71f7e73..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/deployer/http/HttpBasicAuthURLConnector.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package aQute.lib.deployer.http;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.StringTokenizer;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.regex.Matcher;
-
-import aQute.bnd.service.Plugin;
-import aQute.bnd.service.url.URLConnector;
-import aQute.lib.base64.Base64;
-import aQute.lib.io.IO;
-import aQute.libg.glob.Glob;
-import aQute.libg.reporter.Reporter;
-
-public class HttpBasicAuthURLConnector implements URLConnector, Plugin {
-	
-	private static final String PREFIX_PATTERN = "pattern.";
-	private static final String PREFIX_USER = "uid.";
-	private static final String PREFIX_PASSWORD = "pwd.";
-	
-
-	private static class Mapping {
-		Glob urlPattern;
-		String user;
-		String pass;
-		Mapping(Glob urlPattern, String user, String pass) {
-			this.urlPattern = urlPattern; this.user = user; this.pass = pass;
-		}
-	}
-
-	private final AtomicBoolean inited = new AtomicBoolean(false);
-	private final List<Mapping> mappings = new LinkedList<Mapping>();
-	
-	private Reporter reporter;
-	private String configFileList;
-	
-	public void setReporter(Reporter reporter) {
-		this.reporter = reporter;
-	}
-	
-	public void setProperties(Map<String, String> map) {
-		configFileList = map.get("configs");
-		if (configFileList == null)
-			throw new IllegalArgumentException("'configs' must be specified on HttpBasicAuthURLConnector");
-	}
-	
-	protected void init() {
-		if (inited.compareAndSet(false, true)) {
-			mappings.clear();
-			
-			StringTokenizer tokenizer = new StringTokenizer(configFileList, ",");
-			while (tokenizer.hasMoreTokens()) {
-				String configFileName = tokenizer.nextToken().trim();
-				
-				File file = new File(configFileName);
-				if (file.exists()) {
-					Properties props = new Properties();
-					InputStream stream = null;
-					try {
-						stream = new FileInputStream(file);
-						props.load(stream);
-						
-						for (Object key : props.keySet()) {
-							String name = (String) key;
-							
-							if (name.startsWith(PREFIX_PATTERN)) {
-								String id = name.substring(PREFIX_PATTERN.length());
-								
-								Glob glob = new Glob(props.getProperty(name));
-								String uid = props.getProperty(PREFIX_USER + id);
-								String pwd = props.getProperty(PREFIX_PASSWORD + id);
-								
-								mappings.add(new Mapping(glob, uid, pwd));
-							}
-						}
-					} catch (IOException e) {
-						reporter.error("Failed to load %s", configFileName);
-					} finally {
-						if (stream != null) IO.close(stream);
-					}
-				}
-			}
-		}
-	}
-
-	public InputStream connect(URL url) throws IOException {
-		init();
-		
-		for (Mapping mapping : mappings) {
-			Matcher matcher = mapping.urlPattern.matcher(url.toString());
-			if (matcher.find())
-				return connect(url, mapping.user, mapping.pass);
-		}
-		
-		return url.openStream();
-	}
-
-	private InputStream connect(URL url, String user, String pass) throws IOException {
-		String authString = user + ":" + pass;
-		String encoding = Base64.encodeBase64(authString.getBytes());
-		
-		URLConnection connection = url.openConnection();
-		connection.setRequestProperty("Authorization", "Basic " + encoding);
-		return connection.getInputStream();
-	}
-	
-	
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/AbstractBaseOBR.java b/biz.aQute.bndlib/src/aQute/lib/deployer/obr/AbstractBaseOBR.java
deleted file mode 100644
index 491531d..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/AbstractBaseOBR.java
+++ /dev/null
@@ -1,598 +0,0 @@
-package aQute.lib.deployer.obr;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Properties;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.StringTokenizer;
-import java.util.TreeMap;
-import java.util.regex.Pattern;
-
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-import org.xml.sax.SAXException;
-
-import aQute.bnd.build.ResolverMode;
-import aQute.bnd.service.OBRIndexProvider;
-import aQute.bnd.service.OBRResolutionMode;
-import aQute.bnd.service.Plugin;
-import aQute.bnd.service.Registry;
-import aQute.bnd.service.RegistryPlugin;
-import aQute.bnd.service.RemoteRepositoryPlugin;
-import aQute.bnd.service.ResourceHandle;
-import aQute.bnd.service.ResourceHandle.Location;
-import aQute.bnd.service.url.URLConnector;
-import aQute.lib.deployer.obr.CachingURLResourceHandle.CachingMode;
-import aQute.lib.filter.Filter;
-import aQute.lib.osgi.Jar;
-import aQute.lib.osgi.URLResource;
-import aQute.libg.generics.Create;
-import aQute.libg.reporter.Reporter;
-import aQute.libg.version.Version;
-import aQute.libg.version.VersionRange;
-
-/**
- * Abstract base class for OBR-based repositories.
- * 
- * <p>
- * The repository implementation is read-only by default. To implement a writable
- * repository, subclasses should override {@link #canWrite()} and {@link #put(Jar)}.
- * 
- * @author Neil Bartlett
- *
- */
-public abstract class AbstractBaseOBR implements RegistryPlugin, Plugin, RemoteRepositoryPlugin, OBRIndexProvider {
-	
-	public static final String PROP_NAME = "name";
-	public static final String PROP_RESOLUTION_MODE = "mode";
-	public static final String PROP_RESOLUTION_MODE_ANY = "any";
-	
-	public static final String REPOSITORY_FILE_NAME = "repository.xml";
-	
-	protected Registry registry;
-	protected Reporter reporter;
-	protected String name = this.getClass().getName();
-	protected Set<OBRResolutionMode> supportedModes = EnumSet.allOf(OBRResolutionMode.class);
-
-	private boolean initialised = false;
-	private final Map<String, SortedMap<Version, Resource>> pkgResourceMap = new HashMap<String, SortedMap<Version, Resource>>();
-	private final Map<String, SortedMap<Version, Resource>> bsnMap = new HashMap<String, SortedMap<Version, Resource>>();
-	
-	protected void addResourceToIndex(Resource resource) {
-		addBundleSymbolicNameToIndex(resource);
-		addPackagesToIndex(resource);
-	}
-
-	protected synchronized void reset() {
-		initialised = false;
-	}
-
-	/**
-	 * Initialize the indexes prior to main initialisation of internal
-	 * data structures. This implementation does nothing, but subclasses
-	 * may override if they need to perform such initialisation.
-	 * @throws Exception 
-	 */
-	protected void initialiseIndexes() throws Exception {
-	}
-
-	protected final synchronized void init() throws Exception {
-		if (!initialised) {
-			bsnMap.clear();
-			pkgResourceMap.clear();
-			
-			initialiseIndexes();
-			
-			final URLConnector connector = getConnector();
-			IRepositoryListener listener = new IRepositoryListener() {
-				public boolean processResource(Resource resource) {
-					addResourceToIndex(resource);
-					return true;
-				}
-
-				public boolean processReferral(String fromUrl, Referral referral, int maxDepth, int currentDepth) {
-					try {
-						URL indexLocation = new URL(referral.getUrl());
-						try {
-							CachingURLResourceHandle indexHandle = new CachingURLResourceHandle(indexLocation.toExternalForm(), null, getCacheDirectory(), connector, CachingMode.PreferRemote);
-							indexHandle.setReporter(reporter);
-							return readIndex(indexLocation.toString(), new FileInputStream(indexHandle.request()), this);
-						} catch (Exception e) {
-							reporter.error("Unable to read referral index at URL '%s' from parent index '%s': %s", indexLocation, fromUrl, e);
-						}
-						
-					} catch (MalformedURLException e) {
-						reporter.error("Invalid referral URL '%s' from parent index '%s': %s", referral.getUrl(), fromUrl, e);
-					}
-					return false;
-				}
-			};
-			
-			Collection<URL> indexes = getOBRIndexes();
-			for (URL indexLocation : indexes) {
-				try {
-					CachingURLResourceHandle indexHandle = new CachingURLResourceHandle(indexLocation.toExternalForm(), null, getCacheDirectory(), connector, CachingMode.PreferRemote);
-					indexHandle.setReporter(reporter);
-					File indexFile = indexHandle.request();
-					readIndex(indexLocation.toExternalForm(), new FileInputStream(indexFile), listener);
-				} catch (Exception e) {
-					reporter.error("Unable to read index at URL '%s': %s", indexLocation, e);
-				}
-			}
-			
-			initialised = true;
-		}
-	}
-	
-	private URLConnector getConnector() {
-		URLConnector connector;
-		synchronized (this) {
-			connector = registry.getPlugin(URLConnector.class);
-		}
-		if (connector == null)
-			connector = new DefaultURLConnector();
-		return connector;
-	}
-
-	public synchronized final void setRegistry(Registry registry) {
-		this.registry = registry;
-	}
-
-	public synchronized void setProperties(Map<String, String> map) {
-		if (map.containsKey(PROP_NAME))
-			name = map.get(PROP_NAME);
-		
-		if (map.containsKey(PROP_RESOLUTION_MODE)) {
-			supportedModes = EnumSet.noneOf(OBRResolutionMode.class);
-			StringTokenizer tokenizer = new StringTokenizer(map.get(PROP_RESOLUTION_MODE), ",");
-			while (tokenizer.hasMoreTokens()) {
-				String token = tokenizer.nextToken().trim();
-				if (PROP_RESOLUTION_MODE_ANY.equalsIgnoreCase(token))
-					supportedModes = EnumSet.allOf(OBRResolutionMode.class);
-				else {
-					try {
-						supportedModes.add(OBRResolutionMode.valueOf(token));
-					} catch (Exception e) {
-						if (reporter != null) reporter.error("Unknown OBR resolution mode: " + token);
-					}
-				}
-			}
-		}
-	}
-	
-	public File[] get(String bsn, String range) throws Exception {
-		ResourceHandle[] handles = getHandles(bsn, range);
-		
-		return requestAll(handles);
-	}
-	
-	protected static File[] requestAll(ResourceHandle[] handles) throws IOException {
-		File[] result = (handles == null) ? new File[0] : new File[handles.length];
-		for (int i = 0; i < result.length; i++) {
-			result[i] = handles[i].request();
-		}
-		return result;
-	}
-
-	protected ResourceHandle[] getHandles(String bsn, String rangeStr) throws Exception {
-		init();
-		
-		// If the range is set to "project", we cannot resolve it.
-		if ("project".equals(rangeStr))
-			return null;
-		
-		
-		SortedMap<Version, Resource> versionMap = bsnMap.get(bsn);
-		if (versionMap == null || versionMap.isEmpty())
-			return null;
-		List<Resource> resources = narrowVersionsByVersionRange(versionMap, rangeStr);
-		List<ResourceHandle> handles = mapResourcesToHandles(resources);
-		
-		return (ResourceHandle[]) handles.toArray(new ResourceHandle[handles.size()]);
-	}
-	
-	public synchronized void setReporter(Reporter reporter) {
-		this.reporter = reporter;
-	}
-	
-	public File get(String bsn, String range, Strategy strategy, Map<String, String> properties) throws Exception {
-		ResourceHandle handle = getHandle(bsn, range, strategy, properties);
-		return handle != null ? handle.request() : null;
-	}
-	
-	public ResourceHandle getHandle(String bsn, String range, Strategy strategy, Map<String, String> properties) throws Exception {
-		ResourceHandle result;
-		if (bsn != null)
-			result = resolveBundle(bsn, range, strategy);
-		else {
-			String pkgName = properties.get(CapabilityType.PACKAGE.getTypeName());
-			
-			String modeName = properties.get(CapabilityType.MODE.getTypeName());
-			ResolverMode mode = (modeName != null) ? ResolverMode.valueOf(modeName) : null;
-			
-			if (pkgName != null)
-				result = resolvePackage(pkgName, range, strategy, mode, properties);
-			else
-				throw new IllegalArgumentException("Cannot resolve bundle: neither bsn nor package specified.");
-		}
-		return result;
-	}
-
-	public boolean canWrite() {
-		return false;
-	}
-
-	public File put(Jar jar) throws Exception {
-		throw new UnsupportedOperationException("Read-only repository.");
-	}
-
-	public List<String> list(String regex) throws Exception {
-		init();
-		Pattern pattern = regex != null ? Pattern.compile(regex) : null;
-		List<String> result = new LinkedList<String>();
-		
-		for (String bsn : bsnMap.keySet()) {
-			if (pattern == null || pattern.matcher(bsn).matches())
-				result.add(bsn);
-		}
-		
-		return result;
-	}
-
-	public List<Version> versions(String bsn) throws Exception {
-		init();
-		SortedMap<Version, Resource> versionMap = bsnMap.get(bsn);
-		List<Version> list;
-		if (versionMap != null) {
-			list = new ArrayList<Version>(versionMap.size());
-			list.addAll(versionMap.keySet());
-		} else {
-			list = Collections.emptyList();
-		}
-		return list;
-	}
-
-	public synchronized String getName() {
-		return name;
-	}
-
-	void addBundleSymbolicNameToIndex(Resource resource) {
-		String bsn = resource.getSymbolicName();
-		Version version;
-		String versionStr = resource.getVersion();
-		try {
-			version = new Version(versionStr);
-		} catch (Exception e) {
-			version = new Version("0.0.0");
-		}
-		SortedMap<Version, Resource> versionMap = bsnMap.get(bsn);
-		if (versionMap == null) {
-			versionMap = new TreeMap<Version, Resource>();
-			bsnMap.put(bsn, versionMap);
-		}
-		versionMap.put(version, resource);
-	}
-
-	void addPackagesToIndex(Resource resource) {
-		for (Capability capability : resource.getCapabilities()) {
-			if (CapabilityType.PACKAGE.getTypeName().equals(capability.getName())) {
-				String pkgName = null;
-				String versionStr = null;
-				
-				for (Property prop : capability.getProperties()) {
-					if (Property.PACKAGE.equals(prop.getName()))
-						pkgName = prop.getValue();
-					else if (Property.VERSION.equals(prop.getName()))
-						versionStr = prop.getValue();
-				}
-				
-				Version version;
-				try {
-					version = new Version(versionStr);
-				} catch (Exception e) {
-					version = new Version("0.0.0");
-				}
-				
-				if (pkgName != null) {
-					SortedMap<Version, Resource> versionMap = pkgResourceMap.get(pkgName);
-					if (versionMap == null) {
-						versionMap = new TreeMap<Version, Resource>();
-						pkgResourceMap.put(pkgName, versionMap);
-					}
-					versionMap.put(version, resource);
-				}
-			}
-		}
-	}
-
-	/**
-	 * @return Whether to continue parsing other indexes
-	 * @throws IOException 
-	 */
-	boolean readIndex(String baseUrl, InputStream stream, IRepositoryListener listener) throws ParserConfigurationException, SAXException, IOException {
-		SAXParserFactory parserFactory = SAXParserFactory.newInstance();
-		SAXParser parser = parserFactory.newSAXParser();
-		try {
-			parser.parse(stream, new OBRSAXHandler(baseUrl, listener));
-			return true;
-		} catch (StopParseException e) {
-			return false;
-		} finally {
-			stream.close();
-		}
-	}
-
-	List<Resource> narrowVersionsByFilter(String pkgName, SortedMap<Version, Resource> versionMap, Filter filter) {
-		List<Resource> result = new ArrayList<Resource>(versionMap.size());
-		
-		Dictionary<String, String> dict = new Hashtable<String, String>();
-		dict.put("package", pkgName);
-		
-		for (Version version : versionMap.keySet()) {
-			dict.put("version", version.toString());
-			if (filter.match(dict))
-				result.add(versionMap.get(version));
-		}
-		
-		return result;
-	}
-
-	List<Resource> narrowVersionsByVersionRange(SortedMap<Version, Resource> versionMap, String rangeStr) {
-		List<Resource> result;
-		if ("latest".equals(rangeStr)) {
-			Version highest = versionMap.lastKey();
-			result = Create.list(new Resource[] { versionMap.get(highest) });
-		} else {
-			VersionRange range = rangeStr != null ? new VersionRange(rangeStr) : null;
-			
-			// optimisation: skip versions definitely less than the range
-			if (range != null && range.getLow() != null)
-				versionMap = versionMap.tailMap(range.getLow());
-			
-			result = new ArrayList<Resource>(versionMap.size());
-			for (Version version : versionMap.keySet()) {
-				if (range == null || range.includes(version))
-					result.add(versionMap.get(version));
-				
-				// optimisation: skip versions definitely higher than the range
-				if (range != null && range.isRange() && version.compareTo(range.getHigh()) >= 0)
-					break;
-			}
-		}
-		return result;
-	}
-	
-	void filterResourcesByResolverMode(Collection<Resource> resources, ResolverMode mode) {
-		assert mode != null;
-		
-		Properties modeCapability = new Properties();
-		modeCapability.setProperty(CapabilityType.MODE.getTypeName(), mode.name());
-		
-		for (Iterator<Resource> iter = resources.iterator(); iter.hasNext(); ) {
-			Resource resource = iter.next();
-			
-			Require modeRequire = resource.findRequire(CapabilityType.MODE.getTypeName());
-			if (modeRequire == null)
-				continue;
-			else if (modeRequire.getFilter() == null)
-				iter.remove();
-			else {
-				try {
-					Filter filter = new Filter(modeRequire.getFilter());
-					if (!filter.match(modeCapability))
-						iter.remove();
-				} catch (IllegalArgumentException e) {
-					synchronized (this) {
-						if (reporter != null)
-							reporter.error("Error parsing mode filter requirement on resource %s: %s", resource.getUrl(), modeRequire.getFilter());
-					}
-					iter.remove();
-				}
-			}
-		}
-	}
-	
-	List<ResourceHandle> mapResourcesToHandles(Collection<Resource> resources) throws Exception {
-		List<ResourceHandle> result = new ArrayList<ResourceHandle>(resources.size());
-		
-		for (Resource resource : resources) {
-			ResourceHandle handle = mapResourceToHandle(resource);
-			if (handle != null)
-				result.add(handle);
-		}
-		
-		return result;
-	}
-	
-	ResourceHandle mapResourceToHandle(Resource resource) throws Exception {
-		ResourceHandle result = null;
-		
-		CachingURLResourceHandle handle ;
-		try {
-			handle = new CachingURLResourceHandle(resource.getUrl(), resource.getBaseUrl(), getCacheDirectory(), getConnector(), CachingMode.PreferCache);
-		} catch (FileNotFoundException e) {
-			throw new FileNotFoundException("Broken link in repository index: " + e.getMessage());
-		}
-		if (handle.getLocation() == Location.local || getCacheDirectory() != null)
-			result = handle;
-		
-		return result;
-	}
-
-	ResourceHandle resolveBundle(String bsn, String rangeStr, Strategy strategy) throws Exception {
-		if (rangeStr == null) rangeStr = "0.0.0";
-		
-		if (strategy == Strategy.EXACT) {
-			return findExactMatch(bsn, rangeStr, bsnMap);
-		}
-		
-		ResourceHandle[] handles = getHandles(bsn, rangeStr);
-		ResourceHandle selected;
-		if (handles == null || handles.length == 0)
-			selected = null;
-		else {
-			switch(strategy) {
-			case LOWEST:
-				selected = handles[0];
-				break;
-			default:
-				selected = handles[handles.length - 1];
-			}
-		}
-		return selected;
-	}
-
-	ResourceHandle resolvePackage(String pkgName, String rangeStr, Strategy strategy, ResolverMode mode, Map<String, String> props) throws Exception {
-		init();
-		if (rangeStr == null) rangeStr = "0.0.0";
-		
-		SortedMap<Version, Resource> versionMap = pkgResourceMap.get(pkgName);
-		if (versionMap == null)
-			return null;
-		
-		// Was a filter expression supplied?
-		Filter filter = null;
-		String filterStr = props.get("filter");
-		if (filterStr != null) {
-			filter = new Filter(filterStr);
-		}
-		
-		// Narrow the resources by version range string or filter.
-		List<Resource> resources;
-		if (filter != null)
-			resources = narrowVersionsByFilter(pkgName, versionMap, filter);
-		else
-			resources = narrowVersionsByVersionRange(versionMap, rangeStr);
-		
-		// Remove resources that are invalid for the current resolution mode
-		if (mode != null)
-			filterResourcesByResolverMode(resources, mode);
-		
-		// Select the most suitable one
-		Resource selected;
-		if (resources == null || resources.isEmpty())
-			selected = null;
-		else {
-			switch (strategy) {
-			case LOWEST:
-				selected = resources.get(0);
-				break;
-			default:
-				selected = resources.get(resources.size() - 1);
-			}
-			expandPackageUses(pkgName, selected, props);
-		}
-		return selected != null ? mapResourceToHandle(selected) : null;
-	}
-
-	void expandPackageUses(String pkgName, Resource resource, Map<String, String> props) {
-		List<String> internalUses = new LinkedList<String>();
-		Map<String, Require> externalUses = new HashMap<String, Require>();
-		
-		internalUses.add(pkgName);
-		
-		Capability capability = resource.findPackageCapability(pkgName);
-		Property usesProp = capability.findProperty(Property.USES);
-		if (usesProp != null) {
-			StringTokenizer tokenizer = new StringTokenizer(usesProp.getValue(), ",");
-			while (tokenizer.hasMoreTokens()) {
-				String usesPkgName = tokenizer.nextToken();
-				Capability usesPkgCap = resource.findPackageCapability(usesPkgName);
-				if (usesPkgCap != null)
-					internalUses.add(usesPkgName);
-				else {
-					Require require = resource.findPackageRequire(usesPkgName);
-					if (require != null)
-						externalUses.put(usesPkgName, require);
-				}
-			}
-		}
-		props.put("packages", listToString(internalUses));
-		props.put("import-uses", formatPackageRequires(externalUses));
-	}
-	
-	String listToString(List<?> list) {
-		StringBuilder builder = new StringBuilder();
-		
-		int count = 0;
-		for (Object item : list) {
-			if (count++ > 0) builder.append(',');
-			builder.append(item);
-		}
-		
-		return builder.toString();
-	}
-
-	String formatPackageRequires(Map<String, Require> externalUses) {
-		StringBuilder builder = new StringBuilder();
-		
-		int count = 0;
-		for (Entry<String, Require> entry : externalUses.entrySet()) {
-			String pkgName = entry.getKey();
-			String filter = entry.getValue().getFilter();
-
-			if (count++ > 0)
-				builder.append(',');
-			builder.append(pkgName);
-			builder.append(";filter='");
-			builder.append(filter);
-			builder.append('\'');
-		}
-		
-		return builder.toString();
-	}
-
-	ResourceHandle findExactMatch(String identity, String version, Map<String, SortedMap<Version, Resource>> resourceMap) throws Exception {
-		Resource resource;
-		VersionRange range = new VersionRange(version);
-		if (range.isRange())
-			return null;
-		
-		SortedMap<Version, Resource> versions = resourceMap.get(identity);
-		resource = versions.get(range.getLow());
-		
-		return mapResourceToHandle(resource);
-	}
-	
-	/**
-	 * Utility function for parsing lists of URLs.
-	 * 
-	 * @param locationsStr
-	 *            Comma-separated list of URLs
-	 * @throws MalformedURLException
-	 */
-	protected static List<URL> parseLocations(String locationsStr) throws MalformedURLException {
-		StringTokenizer tok = new StringTokenizer(locationsStr, ",");
-		List<URL> urls = new ArrayList<URL>(tok.countTokens());
-		while (tok.hasMoreTokens()) {
-			String urlStr = tok.nextToken().trim();
-			urls.add(new URL(urlStr));
-		}
-		return urls;
-	}
-
-	public Set<OBRResolutionMode> getSupportedModes() {
-		return supportedModes;
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/CachingURLResourceHandle.java b/biz.aQute.bndlib/src/aQute/lib/deployer/obr/CachingURLResourceHandle.java
deleted file mode 100644
index 902a031..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/CachingURLResourceHandle.java
+++ /dev/null
@@ -1,243 +0,0 @@
-package aQute.lib.deployer.obr;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.URL;
-import java.net.URLEncoder;
-
-import aQute.bnd.service.ResourceHandle;
-import aQute.bnd.service.url.URLConnector;
-import aQute.lib.io.IO;
-import aQute.libg.reporter.Reporter;
-
-/**
- * <p>
- * This resource handler downloads remote resources on demand, and caches them
- * as local files. Resources that are already local (i.e. <code>file:...</code>
- * URLs) are returned directly.
- * </p>
- * 
- * <p>
- * Two alternative caching modes are available. When the mode is
- * {@link CachingMode#PreferCache}, the cached file will always be returned if
- * it exists; therefore to refresh from the remote resource it will be necessary
- * to delete the cache. When the mode is {@link CachingMode#PreferRemote}, the
- * first call to {@link #request()} will always attempt to download the remote
- * resource, and only uses the pre-downloaded cache if the remote could not be
- * downloaded (e.g. because the network is offline).
- * </p>
- * 
- * @author njbartlett
- * 
- */
-public class CachingURLResourceHandle implements ResourceHandle {
-	
-	public static enum CachingMode {
-		/**
-		 * Always use the cached file, if it exists.
-		 */
-		PreferCache,
-
-		/**
-		 * Download the remote resource if possible, falling back to the cached
-		 * file if remote fails. Subsequently the cached resource will be used.
-		 */
-		PreferRemote;
-	}
-	
-	static final String FILE_SCHEME = "file:";
-	static final String HTTP_SCHEME = "http:";
-	static final String UTF_8 = "UTF-8";
-	
-	final File cacheDir;
-	final URLConnector connector;
-	
-	// The resolved, absolute URL of the resource
-	final URL url;
-	
-	// The local file, if the resource IS a file, otherwise null.
-	final File localFile;
-	
-	// The cached file copy of the resource, if it is remote and has been downloaded.
-	final File cachedFile;
-	
-	final CachingMode mode;
-	boolean downloaded = false; // only used with mode=PreferRemote
-	
-	Reporter reporter;
-	
-	public CachingURLResourceHandle(String url, String baseUrl, final File cacheDir, CachingMode mode) throws IOException {
-		this(url, baseUrl, cacheDir, new DefaultURLConnector(), mode);
-	}
-	
-	public CachingURLResourceHandle(String url, String baseUrl, final File cacheDir, URLConnector connector, CachingMode mode) throws IOException {
-		this.cacheDir = cacheDir;
-		this.connector = connector;
-		this.mode = mode;
-		
-		if (url.startsWith(FILE_SCHEME)) {
-			// File URL may be relative or absolute
-			File file = new File(url.substring(FILE_SCHEME.length()));
-			if (file.isAbsolute()) {
-				this.localFile = file;
-			} else {
-				if (baseUrl == null || !baseUrl.startsWith(FILE_SCHEME))
-					throw new IllegalArgumentException("Relative file URLs cannot be resolved if the base URL is a non-file URL.");
-				this.localFile = resolveFile(baseUrl.substring(FILE_SCHEME.length()), file.toString());
-			}
-			this.url = localFile.toURI().toURL();
-			if (!localFile.isFile() && !localFile.isDirectory())
-				throw new FileNotFoundException("File URL " + this.url + " points at a non-existing file.");
-			this.cachedFile = null;
-		} else if (url.startsWith(HTTP_SCHEME)) {
-			// HTTP URLs must be absolute
-			this.url = new URL(url);
-			this.localFile = null;
-			this.cachedFile = mapRemoteURL(this.url);
-		} else if (baseUrl == null) {
-			// Some other scheme and no base => must be absolute
-			this.url = new URL(url);
-			this.localFile = null;
-			this.cachedFile = mapRemoteURL(this.url);
-		} else {
-			// A path with no scheme means resolve relative to the base URL
-			if (baseUrl.startsWith(FILE_SCHEME)) {
-				this.localFile = resolveFile(baseUrl.substring(FILE_SCHEME.length()), url);
-				this.url = localFile.toURI().toURL();
-				this.cachedFile = null;
-			} else {
-				URL base = new URL(baseUrl);
-				this.url = new URL(base, url);
-				this.localFile = null;
-				this.cachedFile = mapRemoteURL(this.url);
-			}
-		}
-	}
-	
-	public void setReporter(Reporter reporter) {
-		this.reporter = reporter;
-	}
-	
-	File resolveFile(String baseFileName, String fileName) {
-		File resolved;
-		
-		File baseFile = new File(baseFileName);
-		if (baseFile.isDirectory())
-			resolved = new File(baseFile, fileName);
-		else if (baseFile.isFile())
-			resolved = new File(baseFile.getParentFile(), fileName);
-		else
-			throw new IllegalArgumentException("Cannot resolve relative to non-existant base file path: " + baseFileName);
-		
-		return resolved;
-	}
-
-	private File mapRemoteURL(URL url) throws UnsupportedEncodingException {
-		
-		String localDirName;
-		String localFileName;
-		
-		String fullUrl = url.toExternalForm();
-		int lastSlashIndex = fullUrl.lastIndexOf('/');
-		
-		File localDir;
-		if (lastSlashIndex > -1) {
-			localDirName = URLEncoder.encode(fullUrl.substring(0, lastSlashIndex), UTF_8);
-			localDir = new File(cacheDir, localDirName);
-			if (localDir.exists() && !localDir.isDirectory()) {
-				localDir = cacheDir;
-				localFileName = URLEncoder.encode(fullUrl, UTF_8);
-			} else {
-				localFileName = URLEncoder.encode(fullUrl.substring(lastSlashIndex + 1), UTF_8);
-			}
-		} else {
-			localDir = cacheDir;
-			localFileName = URLEncoder.encode(fullUrl, UTF_8);
-		}
-		localDir.mkdirs();
-		
-		return new File(localDir, localFileName);
-	}
-
-	public String getName() {
-		return url.toString();
-	}
-
-	public Location getLocation() {
-		Location result;
-		
-		if (localFile != null)
-			result = Location.local;
-		else if (cachedFile.exists())
-			result = Location.remote_cached;
-		else
-			result = Location.remote;
-		
-		return result;
-	}
-
-	public File request() throws IOException {
-		if (localFile != null)
-			return localFile;
-		if (cachedFile == null)
-			throw new IllegalStateException("Invalid URLResourceHandle: both local file and cache file location are uninitialised.");
-		
-		switch (mode) {
-		case PreferCache:
-			if (!cachedFile.exists()) {
-				cacheDir.mkdirs();
-				downloadToFile(url, cachedFile);
-			}
-			return cachedFile;
-		case PreferRemote:
-			File tempFile = File.createTempFile("download", ".tmp");
-			try {
-				downloadToFile(url, tempFile);
-				
-				// remote download succeeded... copy tmp to cache
-				cacheDir.mkdirs();
-				IO.copy(tempFile, cachedFile);
-				return cachedFile;
-			} catch (IOException e) {
-				// Remote download failed... use the cache if available
-				if (cachedFile.exists()) {
-					if (reporter != null) reporter.warning("Download of remote resource %s failed, using local cache %s.", url, cachedFile); 
-					return cachedFile;
-				} else {
-					throw new IOException(String.format("Download of remote resource %s failed and cached file %s not available!", url, cachedFile));
-				}
-			}
-		default:
-			throw new IllegalArgumentException("Invalid caching mode");
-		}
-	}
-	
-	void downloadToFile(URL url, File file) throws IOException {
-		InputStream in = null;
-		OutputStream out = null;
-		try {
-			in = connector.connect(url);
-			out = new FileOutputStream(file);
-			
-			byte[] buf = new byte[1024];
-			for(;;) {
-				int bytes = in.read(buf, 0, 1024);
-				if (bytes < 0) break;
-				out.write(buf, 0, bytes);
-			}
-		} finally {
-			try { if (in != null) in.close(); } catch (IOException e) {};
-			try { if (out != null) in.close(); } catch (IOException e) {};
-		}
-	}
-	
-	public URL getResolvedUrl() {
-		return url;
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/Capability.java b/biz.aQute.bndlib/src/aQute/lib/deployer/obr/Capability.java
deleted file mode 100644
index 983afed..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/Capability.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package aQute.lib.deployer.obr;
-
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-
-public class Capability {
-	
-	private final String name;
-	private final List<Property> properties;
-
-	private Capability(String name, List<Property> properties) {
-		this.name = name;
-		this.properties = properties;
-	}
-	
-	public static class Builder {
-		private String name;
-		private final List<Property> properties = new LinkedList<Property>();
-		
-		public Builder setName(String name) {
-			this.name = name;
-			return this;
-		}
-		
-		public Builder addProperty(Property property) {
-			this.properties.add(property);
-			return this;
-		}
-		
-		public Capability build() {
-			if (name == null) throw new IllegalStateException("'name' field is not initialised.");
-			return new Capability(name, Collections.unmodifiableList(properties));
-		}
-	}
-
-	public String getName() {
-		return name;
-	}
-
-	public List<Property> getProperties() {
-		return properties;
-	}
-	
-	public Property findProperty(String propertyName) {
-		assert propertyName != null;
-		for (Property prop : properties) {
-			if (propertyName.equals(prop.getName()))
-				return prop;
-		}
-		return null;
-	}
-
-	@Override
-	public String toString() {
-		StringBuilder builder = new StringBuilder();
-		builder.append("Capability [name=").append(name).append(", properties=").append(properties).append("]");
-		return builder.toString();
-	}
-
-	@Override
-	public int hashCode() {
-		final int prime = 31;
-		int result = 1;
-		result = prime * result + ((name == null) ? 0 : name.hashCode());
-		result = prime * result
-				+ ((properties == null) ? 0 : properties.hashCode());
-		return result;
-	}
-
-	@Override
-	public boolean equals(Object obj) {
-		if (this == obj)
-			return true;
-		if (obj == null)
-			return false;
-		if (getClass() != obj.getClass())
-			return false;
-		Capability other = (Capability) obj;
-		if (name == null) {
-			if (other.name != null)
-				return false;
-		} else if (!name.equals(other.name))
-			return false;
-		if (properties == null) {
-			if (other.properties != null)
-				return false;
-		} else if (!properties.equals(other.properties))
-			return false;
-		return true;
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/CapabilityType.java b/biz.aQute.bndlib/src/aQute/lib/deployer/obr/CapabilityType.java
deleted file mode 100644
index d3f8ae3..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/CapabilityType.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package aQute.lib.deployer.obr;
-
-public enum CapabilityType {
-	
-	PACKAGE("package"),
-	EE("ee"),
-	BUNDLE("bundle"),
-	MODE("mode"),
-	OTHER(null);
-	
-	private String typeName;
-
-	CapabilityType(String name) {
-		this.typeName = name;
-	}
-	
-	public String getTypeName() {
-		return typeName;
-	}
-	
-	/**
-	 * @throws IllegalArgumentException
-	 */
-	public static CapabilityType getForTypeName(String typeName) {
-		for (CapabilityType type : CapabilityType.values()) {
-			if (type.typeName != null && type.typeName.equals(typeName))
-				return type;
-		}
-		throw new IllegalArgumentException("Unknown capability type: " + typeName);
-	}
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/DefaultURLConnector.java b/biz.aQute.bndlib/src/aQute/lib/deployer/obr/DefaultURLConnector.java
deleted file mode 100644
index 77ac2f0..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/DefaultURLConnector.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package aQute.lib.deployer.obr;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-
-import aQute.bnd.service.url.URLConnector;
-
-public class DefaultURLConnector implements URLConnector {
-
-	public InputStream connect(URL url) throws IOException {
-		if (url == null)
-			throw new IOException("Can't connect to null URL");
-		return url.openStream();
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/IRepositoryListener.java b/biz.aQute.bndlib/src/aQute/lib/deployer/obr/IRepositoryListener.java
deleted file mode 100644
index 664db13..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/IRepositoryListener.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package aQute.lib.deployer.obr;
-
-public interface IRepositoryListener {
-	/**
-	 * Process an OBR resource descriptor from the index document, and possibly
-	 * request early termination of the parser.
-	 * 
-	 * @param resource
-	 *            The resource descriptor to be processed.
-	 * @return Whether to continue parsing the document; returning {@code false}
-	 *         will result in the parser being stopped with a
-	 *         {@link StopParseException}.
-	 */
-	boolean processResource(Resource resource);
-	
-	/**
-	 * Process an OBR referral
-	 * @param parentUrl The url of the Repository that referred to this Referral
-	 * @param referral The referral to be processed
-	 * @param maxDepth The depth of referrals this repository acknowledges.
-	 * @param currentDepth The current depth
-	 * @return Whether to continue parsing the document; returning {@code false}
-	 *         will result in the parser being stopped with a
-	 *         {@link StopParseException}.
-	 */
-	boolean processReferral(String parentUrl, Referral referral, int maxDepth, int currentDepth);
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/LocalOBR.java b/biz.aQute.bndlib/src/aQute/lib/deployer/obr/LocalOBR.java
deleted file mode 100644
index 98d8ee8..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/LocalOBR.java
+++ /dev/null
@@ -1,195 +0,0 @@
-package aQute.lib.deployer.obr;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.xml.transform.stream.StreamResult;
-
-import org.osgi.service.bindex.BundleIndexer;
-import org.xml.sax.InputSource;
-import org.xml.sax.XMLReader;
-
-import aQute.bnd.service.Refreshable;
-import aQute.lib.deployer.FileRepo;
-import aQute.lib.io.IO;
-import aQute.lib.osgi.Jar;
-import aQute.libg.reporter.Reporter;
-import aQute.libg.sax.SAXUtil;
-import aQute.libg.sax.filters.MergeContentFilter;
-import aQute.libg.version.Version;
-
-public class LocalOBR extends OBR implements Refreshable {
-	
-	public static final String PROP_LOCAL_DIR = "local";
-	public static final String PROP_READONLY = "readonly";
-
-	private final FileRepo storageRepo = new FileRepo();
-	
-	private File storageDir;
-	private File localIndex;
-	
-	private List<URL> indexUrls;
-	
-	@Override
-	public void setReporter(Reporter reporter) {
-		super.setReporter(reporter);
-		storageRepo.setReporter(reporter);
-	}
-
-	@Override
-	public void setProperties(Map<String, String> map) {
-		super.setProperties(map);
-		
-		// Load essential properties
-		String localDirPath = map.get(PROP_LOCAL_DIR);
-		if (localDirPath == null)
-			throw new IllegalArgumentException(String.format("Attribute '%s' must be set on LocalOBR plugin.", PROP_LOCAL_DIR));
-		storageDir = new File(localDirPath);
-		if (!storageDir.isDirectory())
-			throw new IllegalArgumentException(String.format("Local path '%s' does not exist or is not a directory.", localDirPath));
-		
-		// Configure the storage repository
-		Map<String, String> storageRepoConfig = new HashMap<String, String>(2);
-		storageRepoConfig.put(FileRepo.LOCATION, localDirPath);
-		storageRepoConfig.put(FileRepo.READONLY, map.get(PROP_READONLY));
-		storageRepo.setProperties(storageRepoConfig);
-		
-		// Set the local index and cache directory locations
-		localIndex = new File(storageDir, REPOSITORY_FILE_NAME);
-		if (localIndex.exists() && !localIndex.isFile())
-			throw new IllegalArgumentException(String.format("Cannot build local repository index: '%s' already exists but is not a plain file.", localIndex.getAbsolutePath()));
-		cacheDir = new File(storageDir, ".obrcache");
-		if (cacheDir.exists() && !cacheDir.isDirectory())
-			throw new IllegalArgumentException(String.format("Cannot create repository cache: '%s' already exists but is not directory.", cacheDir.getAbsolutePath()));
-	}
-	
-	@Override
-	protected void initialiseIndexes() throws Exception {
-		if (!localIndex.exists()) {
-			regenerateIndex();
-		}
-		try {
-			Collection<URL> remotes = super.getOBRIndexes();
-			indexUrls = new ArrayList<URL>(remotes.size() + 1);
-			indexUrls.add(localIndex.toURI().toURL());
-			indexUrls.addAll(remotes);
-		} catch (IOException e) {
-			throw new IllegalArgumentException("Error initialising local index URL", e);
-		}
-	}
-	
-	private void regenerateIndex() throws Exception {
-		BundleIndexer indexer = registry.getPlugin(BundleIndexer.class);
-		if (indexer == null)
-			throw new IllegalStateException("Cannot index repository: no Bundle Indexer service or plugin found.");
-		
-		Set<File> allFiles = new HashSet<File>();
-		gatherFiles(allFiles);
-		
-		FileOutputStream out = null;
-		try {
-			out = new FileOutputStream(localIndex);
-			if (!allFiles.isEmpty()) {
-				Map<String, String> config = new HashMap<String, String>();
-				config.put(BundleIndexer.REPOSITORY_NAME, this.getName());
-				config.put(BundleIndexer.ROOT_URL, localIndex.getCanonicalFile().toURI().toURL().toString());
-				indexer.index(allFiles, out, config);
-			} else {
-				ByteArrayInputStream emptyRepo = new ByteArrayInputStream("<?xml version='1.0' encoding='UTF-8'?>\n<repository lastmodified='0'/>".getBytes());
-				IO.copy(emptyRepo, out);
-			}
-		} finally {
-			out.close();
-		}
-	}
-
-	private void gatherFiles(Set<File> allFiles) throws Exception {
-		List<String> bsns = storageRepo.list(null);
-		if (bsns != null) for (String bsn : bsns) {
-			List<Version> versions = storageRepo.versions(bsn);
-			if (versions != null) for (Version version : versions) {
-				File file = storageRepo.get(bsn, version.toString(), Strategy.HIGHEST, null);
-				if (file != null)
-					allFiles.add(file.getCanonicalFile());
-			}
-		}
-	}
-
-	@Override
-	public List<URL> getOBRIndexes() {
-		return indexUrls;
-	}
-	
-	@Override
-	public boolean canWrite() {
-		return storageRepo.canWrite();
-	}
-	
-	@Override
-	public synchronized File put(Jar jar) throws Exception {
-		File newFile = storageRepo.put(jar);
-		
-		// Index the new file
-		BundleIndexer indexer = registry.getPlugin(BundleIndexer.class);
-		if (indexer == null)
-			throw new IllegalStateException("Cannot index repository: no Bundle Indexer service or plugin found.");
-		ByteArrayOutputStream newIndexBuffer = new ByteArrayOutputStream();
-
-		Map<String, String> config = new HashMap<String, String>();
-		config.put(BundleIndexer.REPOSITORY_NAME, this.getName());
-		config.put(BundleIndexer.ROOT_URL, localIndex.getCanonicalFile().toURI().toURL().toString());
-		indexer.index(Collections.singleton(newFile.getCanonicalFile()), newIndexBuffer, null);
-		
-		// Merge into main index
-		File tempIndex = File.createTempFile("repository", ".xml");
-		FileOutputStream tempIndexOutput = new FileOutputStream(tempIndex);
-		MergeContentFilter merger = new MergeContentFilter();
-		XMLReader reader = SAXUtil.buildPipeline(new StreamResult(tempIndexOutput), new UniqueResourceFilter(), merger);
-		
-		try {
-			// Parse the newly generated index
-			reader.parse(new InputSource(new ByteArrayInputStream(newIndexBuffer.toByteArray())));
-			
-			// Parse the existing index (which may be empty/missing)
-			try {
-				reader.parse(new InputSource(new FileInputStream(localIndex)));
-			} catch (Exception e) {
-				reporter.warning("Existing local index is invalid or missing, overwriting (%s).", localIndex.getAbsolutePath());
-			}
-			
-			merger.closeRootAndDocument();
-		} finally {
-			tempIndexOutput.flush();
-			tempIndexOutput.close();
-		}
-		IO.copy(tempIndex, localIndex);
-		
-		// Re-read the index
-		reset();
-		init();
-		
-		return newFile;
-	}
-
-	public boolean refresh() {
-		reset();
-		return true;
-	}
-
-	public File getRoot() {
-		return storageDir;
-	}
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/OBR.java b/biz.aQute.bndlib/src/aQute/lib/deployer/obr/OBR.java
deleted file mode 100644
index 875ec45..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/OBR.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package aQute.lib.deployer.obr;
-
-import java.io.File;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-import aQute.lib.deployer.FileRepo;
-
-/**
- * A simple read-only OBR-based repository that uses a list of index locations
- * and a basic local cache.
- * 
- * <p>
- * <h2>Properties</h2>
- * <ul>
- * <li><b>locations:</b> comma-separated list of index URLs. <b>NB:</b> surround with single quotes!</li>
- * <li><b>name:</b> repository name; defaults to the index URLs.
- * <li><b>cache:</b> local cache directory. May be omitted, in which case the repository will only be
- * able to serve resources with {@code file:} URLs.</li>
- * <li><b>location:</b> (deprecated) alias for "locations".
- * </ul>
- * 
- * <p>
- * <h2>Example</h2>
- * 
- * <pre>
- * -plugin: aQute.lib.deployer.obr.OBR;locations='http://www.example.com/repository.xml';cache=${workspace}/.cache
- * </pre>
- * 
- * @author Neil Bartlett
- *
- */
-public class OBR extends AbstractBaseOBR {
-	
-	public static final String PROP_LOCATIONS = "locations";
-	@Deprecated
-	public static final String PROP_LOCATION = "location";
-	public static final String PROP_CACHE = "cache";
-
-	protected List<URL> locations;
-	protected File cacheDir;
-
-	public void setProperties(Map<String, String> map) {
-		super.setProperties(map);
-		
-		String locationsStr = map.get(PROP_LOCATIONS);
-		// backwards compatibility
-		if (locationsStr == null) locationsStr = map.get(PROP_LOCATION);
-		
-		try {
-			if (locationsStr != null)
-				locations = parseLocations(locationsStr);
-			else
-				locations = Collections.emptyList();
-		} catch (MalformedURLException e) {
-			throw new IllegalArgumentException(String.format("Invalid location, unable to parse as URL list: %s", locationsStr), e);
-		}
-		
-		String cacheDirStr = map.get(PROP_CACHE);
-		if (cacheDirStr != null)
-			cacheDir = new File(cacheDirStr);
-	}
-	
-	private FileRepo lookupCachedFileRepo() {
-		if (registry != null) {
-			List<FileRepo> repos = registry.getPlugins(FileRepo.class);
-			for (FileRepo repo : repos) {
-				if ("cache".equals(repo.getName()))
-					return repo;
-			}
-		}
-		return null;
-	}
-
-	public List<URL> getOBRIndexes() {
-		return locations;
-	}
-
-	public synchronized File getCacheDirectory() {
-		if (cacheDir == null) {
-			FileRepo cacheRepo = lookupCachedFileRepo();
-			if (cacheRepo != null) {
-				File temp = new File(cacheRepo.getRoot(), ".obr");
-				temp.mkdirs();
-				if (temp.exists())
-					cacheDir = temp;
-			}
-		}
-		return cacheDir;
-	}
-	
-	public void setCacheDirectory(File cacheDir) {
-		this.cacheDir = cacheDir;
-	}
-	
-	@Override
-	public String getName() {
-		if (name != null && name != this.getClass().getName())
-			return name;
-		
-		StringBuilder builder = new StringBuilder();
-		
-		int count = 0;
-		for (URL location : locations) {
-			if (count++ > 0 ) builder.append(',');
-			builder.append(location);
-		}
-		return builder.toString();
-	}
-
-	public void setLocations(URL[] urls) {
-		this.locations = Arrays.asList(urls);
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/OBRSAXHandler.java b/biz.aQute.bndlib/src/aQute/lib/deployer/obr/OBRSAXHandler.java
deleted file mode 100644
index bf4676e..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/OBRSAXHandler.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package aQute.lib.deployer.obr;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
-public class OBRSAXHandler extends DefaultHandler {
-	
-	private static final String TAG_RESOURCE = "resource";
-	private static final String ATTR_RESOURCE_ID = "id";
-	private static final String ATTR_RESOURCE_PRESENTATION_NAME = "presentationname";
-	private static final String ATTR_RESOURCE_SYMBOLIC_NAME = "symbolicname";
-	private static final String ATTR_RESOURCE_URI = "uri";
-	private static final String ATTR_RESOURCE_VERSION = "version";
-	
-	private static final String TAG_REFERRAL = "referral";
-	private static final String ATTR_REFERRAL_URL = "url";
-	private static final String ATTR_REFERRAL_DEPTH = "depth";
-	
-	private static final String TAG_CAPABILITY = "capability";
-	private static final String ATTR_CAPABILITY_NAME = "name";
-	
-	private static final String TAG_REQUIRE = "require";
-	private static final String ATTR_REQUIRE_NAME = "name";
-	private static final String ATTR_REQUIRE_FILTER = "filter";
-	private static final String ATTR_REQUIRE_OPTIONAL = "optional";
-	
-	private static final String TAG_PROPERTY = "p";
-	private static final String ATTR_PROPERTY_NAME = "n";
-	private static final String ATTR_PROPERTY_TYPE = "t";
-	private static final String ATTR_PROPERTY_VALUE = "v";
-
-	private final String baseUrl;
-	private final IRepositoryListener resourceListener;
-	
-	private Resource.Builder resourceBuilder = null;
-	private Capability.Builder capabilityBuilder = null;
-	private Require require = null;
-	private Referral referral = null;
-	private int currentDepth;
-	private int maxDepth;
-
-	public OBRSAXHandler(String baseUrl, IRepositoryListener listener) {
-		this.baseUrl = baseUrl;
-		this.resourceListener = listener;
-		this.currentDepth = 0;
-	}
-	
-	public OBRSAXHandler(String baseUrl, IRepositoryListener listener, int maxDepth, int currentDepth) {
-		this.baseUrl = baseUrl;
-		this.resourceListener = listener;
-		this.currentDepth = currentDepth;
-	}
-
-	@Override
-	public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
-		if (TAG_REFERRAL.equals(qName)) {
-			referral = new Referral(atts.getValue(ATTR_REFERRAL_URL), parseInt(atts.getValue(ATTR_REFERRAL_DEPTH)));
-		} else if (TAG_RESOURCE.equals(qName)) {
-			resourceBuilder = new Resource.Builder()
-				.setId(atts.getValue(ATTR_RESOURCE_ID))
-				.setPresentationName(atts.getValue(ATTR_RESOURCE_PRESENTATION_NAME))
-				.setSymbolicName(atts.getValue(ATTR_RESOURCE_SYMBOLIC_NAME))
-				.setUrl(atts.getValue(ATTR_RESOURCE_URI))
-				.setVersion(atts.getValue(ATTR_RESOURCE_VERSION))
-				.setBaseUrl(baseUrl);
-		} else if (TAG_CAPABILITY.equals(qName)) {
-			capabilityBuilder = new Capability.Builder()
-				.setName(atts.getValue(ATTR_CAPABILITY_NAME));
-		} else if (TAG_REQUIRE.equals(qName)) {
-			require = new Require(atts.getValue(ATTR_REQUIRE_NAME), atts.getValue(ATTR_REQUIRE_FILTER), "true".equalsIgnoreCase(atts.getValue(ATTR_REQUIRE_OPTIONAL)));
-		} else if (TAG_PROPERTY.equals(qName)) {
-			Property p = new Property(atts.getValue(ATTR_PROPERTY_NAME), atts.getValue(ATTR_PROPERTY_TYPE), atts.getValue(ATTR_PROPERTY_VALUE));
-			if (capabilityBuilder != null)
-				capabilityBuilder.addProperty(p);
-		}
-	}
-
-	@Override
-	public void endElement(String uri, String localName, String qName) throws SAXException {
-		if (TAG_CAPABILITY.equals(qName)) {
-			resourceBuilder.addCapability(capabilityBuilder);
-			capabilityBuilder = null;
-		} else if (TAG_RESOURCE.equals(qName)) {
-			if (!resourceListener.processResource(resourceBuilder.build()))
-				throw new StopParseException();
-			resourceBuilder = null;
-		} else if (TAG_REQUIRE.equals(qName)) {
-			resourceBuilder.addRequire(require);
-			require = null;
-		} else if (TAG_REFERRAL.equals(qName)) {
-			if (maxDepth == 0) {
-				maxDepth = referral.getDepth();
-			}
-			resourceListener.processReferral(baseUrl, referral, maxDepth, currentDepth + 1);
-			referral = null;
-		}
-	}
-
-	private static int parseInt(String value) {
-		if (value == null || "".equals(value))
-			return 0;
-		return Integer.parseInt(value);
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/Property.java b/biz.aQute.bndlib/src/aQute/lib/deployer/obr/Property.java
deleted file mode 100644
index 1eaaa8a..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/Property.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package aQute.lib.deployer.obr;
-
-/**
- * @immutable
- * @author Neil Bartlett
- */
-public class Property {
-	
-	static final String PACKAGE = "package";
-	static final String USES = "uses";
-	static final String VERSION = "version";
-
-	private final String name;
-	private final String type;
-	private final String value;
-
-	public Property(String name, String type, String value) {
-		this.name = name;
-		this.type = type;
-		this.value = value;
-	}
-
-	public String getName() {
-		return name;
-	}
-
-	public String getType() {
-		return type;
-	}
-
-	public String getValue() {
-		return value;
-	}
-
-	@Override
-	public String toString() {
-		StringBuilder builder = new StringBuilder();
-		builder.append("Property [name=").append(name).append(", type=").append(type).append(", value=").append(value).append("]");
-		return builder.toString();
-	}
-
-	@Override
-	public int hashCode() {
-		final int prime = 31;
-		int result = 1;
-		result = prime * result + ((name == null) ? 0 : name.hashCode());
-		result = prime * result + ((type == null) ? 0 : type.hashCode());
-		result = prime * result + ((value == null) ? 0 : value.hashCode());
-		return result;
-	}
-
-	@Override
-	public boolean equals(Object obj) {
-		if (this == obj)
-			return true;
-		if (obj == null)
-			return false;
-		if (getClass() != obj.getClass())
-			return false;
-		Property other = (Property) obj;
-		if (name == null) {
-			if (other.name != null)
-				return false;
-		} else if (!name.equals(other.name))
-			return false;
-		if (type == null) {
-			if (other.type != null)
-				return false;
-		} else if (!type.equals(other.type))
-			return false;
-		if (value == null) {
-			if (other.value != null)
-				return false;
-		} else if (!value.equals(other.value))
-			return false;
-		return true;
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/Referral.java b/biz.aQute.bndlib/src/aQute/lib/deployer/obr/Referral.java
deleted file mode 100644
index a6f28da..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/Referral.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package aQute.lib.deployer.obr;
-
-public class Referral {
-
-	private final String url;
-	private final int depth;
-
-	public Referral(String url, int depth) {
-		this.url = url;
-		this.depth = depth;
-	}
-
-	public String getUrl() {
-		return url;
-	}
-
-	public int getDepth() {
-		return depth;
-	}
-
-	@Override
-	public String toString() {
-		StringBuilder builder = new StringBuilder();
-		builder.append("Referral [");
-		if (url != null)
-			builder.append("url=").append(url).append(", ");
-		builder.append("depth=").append(depth).append(", ");
-		return builder.toString();
-	}
-
-	@Override
-	public int hashCode() {
-		final int prime = 31;
-		int result = 1;
-		result = prime * result + ((url == null) ? 0 : url.hashCode());
-		result = prime * result + depth;
-		return result;
-	}
-
-	@Override
-	public boolean equals(Object obj) {
-		if (this == obj)
-			return true;
-		if (obj == null)
-			return false;
-		if (getClass() != obj.getClass())
-			return false;
-		Referral other = (Referral) obj;
-		if (url == null) {
-			if (other.url != null)
-				return false;
-		} else if (!url.equals(other.url))
-			return false;
-		if (depth != other.depth)
-			return false;
-		return true;
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/Require.java b/biz.aQute.bndlib/src/aQute/lib/deployer/obr/Require.java
deleted file mode 100644
index d8d0fbb..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/Require.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package aQute.lib.deployer.obr;
-
-public class Require {
-
-	private final String name;
-	private final String filter;
-	private final boolean optional;
-
-	public Require(String name, String filter, boolean optional) {
-		this.name = name;
-		this.filter = filter;
-		this.optional = optional;
-	}
-
-	public String getName() {
-		return name;
-	}
-
-	public String getFilter() {
-		return filter;
-	}
-
-	public boolean isOptional() {
-		return optional;
-	}
-
-	@Override
-	public String toString() {
-		StringBuilder builder = new StringBuilder();
-		builder.append("Require [");
-		if (name != null)
-			builder.append("name=").append(name).append(", ");
-		if (filter != null)
-			builder.append("filter=").append(filter).append(", ");
-		builder.append("optional=").append(optional).append("]");
-		return builder.toString();
-	}
-
-	@Override
-	public int hashCode() {
-		final int prime = 31;
-		int result = 1;
-		result = prime * result + ((filter == null) ? 0 : filter.hashCode());
-		result = prime * result + ((name == null) ? 0 : name.hashCode());
-		result = prime * result + (optional ? 1231 : 1237);
-		return result;
-	}
-
-	@Override
-	public boolean equals(Object obj) {
-		if (this == obj)
-			return true;
-		if (obj == null)
-			return false;
-		if (getClass() != obj.getClass())
-			return false;
-		Require other = (Require) obj;
-		if (filter == null) {
-			if (other.filter != null)
-				return false;
-		} else if (!filter.equals(other.filter))
-			return false;
-		if (name == null) {
-			if (other.name != null)
-				return false;
-		} else if (!name.equals(other.name))
-			return false;
-		if (optional != other.optional)
-			return false;
-		return true;
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/Resource.java b/biz.aQute.bndlib/src/aQute/lib/deployer/obr/Resource.java
deleted file mode 100644
index a355326..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/Resource.java
+++ /dev/null
@@ -1,240 +0,0 @@
-package aQute.lib.deployer.obr;
-
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * @immutable
- * @author Neil Bartlett
- */
-public class Resource {
-	
-	private final String id;
-	private final String presentationName;
-	private final String symbolicName;
-	private final String baseUrl;
-	private final String url;
-	private final String version;
-	private final List<Capability> capabilities;
-	private final List<Require> requires;
-
-	private Resource(String id, String presentationName, String symbolicName, String baseUrl, String url, String version, List<Capability> capabilities, List<Require> requires) {
-		this.id = id;
-		this.presentationName = presentationName;
-		this.symbolicName = symbolicName;
-		this.baseUrl = baseUrl;
-		this.url = url;
-		this.version = version;
-		
-		this.capabilities = capabilities;
-		this.requires = requires;
-	}
-	
-	public static class Builder {
-		private String id;
-		private String presentationName;
-		private String symbolicName;
-		private String baseUrl;
-		private String url;
-		private String version;
-		private final List<Capability> capabilities = new LinkedList<Capability>();
-		private final List<Require> requires = new LinkedList<Require>();
-		
-		public Builder setId(String id) {
-			this.id = id;
-			return this;
-		}
-		public Builder setPresentationName(String presentationName) {
-			this.presentationName = presentationName;
-			return this;
-		}
-		public Builder setSymbolicName(String symbolicName) {
-			this.symbolicName = symbolicName;
-			return this;
-		}
-		public Builder setBaseUrl(String baseUrl) {
-			this.baseUrl = baseUrl;
-			return this;
-		}
-		public Builder setUrl(String url) {
-			this.url = url;
-			return this;
-		}
-		public Builder setVersion(String version) {
-			this.version = version;
-			return this;
-		}
-		public Builder addCapability(Capability capability) {
-			this.capabilities.add(capability);
-			return this;
-		}
-		public Builder addCapability(Capability.Builder capabilityBuilder) {
-			this.capabilities.add(capabilityBuilder.build());
-			return this;
-		}
-		public Builder addRequire(Require require) {
-			this.requires.add(require);
-			return this;
-		}
-		
-		public Resource build() {
-			if (id == null) throw new IllegalStateException("'id' field is not initialised");
-			if (symbolicName == null) throw new IllegalStateException("'symbolicName' field is not initialised");
-			if (url == null) throw new IllegalStateException("'url' field is not initialised");
-			
-			return new Resource(id, presentationName, symbolicName, baseUrl, url, version, Collections.unmodifiableList(capabilities), Collections.unmodifiableList(requires));
-		}
-	}
-
-	public String getId() {
-		return id;
-	}
-
-	public String getPresentationName() {
-		return presentationName;
-	}
-
-	public String getSymbolicName() {
-		return symbolicName;
-	}
-	
-	public String getBaseUrl() {
-		return baseUrl;
-	}
-
-	public String getUrl() {
-		return url;
-	}
-
-	public String getVersion() {
-		return version;
-	}
-
-	public List<Capability> getCapabilities() {
-		return capabilities;
-	}
-	
-	public Capability findPackageCapability(String pkgName) {
-		for (Capability capability : capabilities) {
-			if (CapabilityType.PACKAGE.getTypeName().equals(capability.getName())) {
-				List<Property> props = capability.getProperties();
-				for (Property prop : props) {
-					if (Property.PACKAGE.equals(prop.getName())) {
-						if (pkgName.equals(prop.getValue()))
-							return capability;
-						else
-							break;
-					}
-				}
-			}
-		}
-		return null;
-	}
-
-
-	
-	public List<Require> getRequires() {
-		return requires;
-	}
-	
-	public Require findRequire(String name) {
-		for (Require require : requires) {
-			if (name.equals(require.getName()))
-				return require;
-		}
-		return null;
-	}
-	
-	public Require findPackageRequire(String usesPkgName) {
-		String matchString = String.format("(package=%s)", usesPkgName);
-		
-		for (Require require : requires) {
-			if (CapabilityType.PACKAGE.getTypeName().equals(require.getName())) {
-				String filter = require.getFilter();
-				if (filter.indexOf(matchString) > -1)
-					return require;
-			}
-		}
-		return null;
-	}
-
-	@Override
-	public String toString() {
-		StringBuilder builder = new StringBuilder();
-		builder.append("Resource [id=").append(id)
-				.append(", presentationName=").append(presentationName)
-				.append(", symbolicName=").append(symbolicName)
-				.append(", baseUrl=").append(baseUrl)
-				.append(", url=").append(url).append(", version=")
-				.append(version).append(", capabilities=").append(capabilities)
-				.append("]");
-		return builder.toString();
-	}
-
-	@Override
-	public int hashCode() {
-		final int prime = 31;
-		int result = 1;
-		result = prime * result + ((baseUrl == null) ? 0 : baseUrl.hashCode());
-		result = prime * result
-				+ ((capabilities == null) ? 0 : capabilities.hashCode());
-		result = prime * result + ((id == null) ? 0 : id.hashCode());
-		result = prime
-				* result
-				+ ((presentationName == null) ? 0 : presentationName.hashCode());
-		result = prime * result
-				+ ((symbolicName == null) ? 0 : symbolicName.hashCode());
-		result = prime * result + ((url == null) ? 0 : url.hashCode());
-		result = prime * result + ((version == null) ? 0 : version.hashCode());
-		return result;
-	}
-
-	@Override
-	public boolean equals(Object obj) {
-		if (this == obj)
-			return true;
-		if (obj == null)
-			return false;
-		if (getClass() != obj.getClass())
-			return false;
-		Resource other = (Resource) obj;
-		if (baseUrl == null) {
-			if (other.baseUrl != null)
-				return false;
-		} else if (!baseUrl.equals(other.baseUrl))
-			return false;
-		if (capabilities == null) {
-			if (other.capabilities != null)
-				return false;
-		} else if (!capabilities.equals(other.capabilities))
-			return false;
-		if (id == null) {
-			if (other.id != null)
-				return false;
-		} else if (!id.equals(other.id))
-			return false;
-		if (presentationName == null) {
-			if (other.presentationName != null)
-				return false;
-		} else if (!presentationName.equals(other.presentationName))
-			return false;
-		if (symbolicName == null) {
-			if (other.symbolicName != null)
-				return false;
-		} else if (!symbolicName.equals(other.symbolicName))
-			return false;
-		if (url == null) {
-			if (other.url != null)
-				return false;
-		} else if (!url.equals(other.url))
-			return false;
-		if (version == null) {
-			if (other.version != null)
-				return false;
-		} else if (!version.equals(other.version))
-			return false;
-		return true;
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/StopParseException.java b/biz.aQute.bndlib/src/aQute/lib/deployer/obr/StopParseException.java
deleted file mode 100644
index 2ca3005..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/StopParseException.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package aQute.lib.deployer.obr;
-
-import org.xml.sax.SAXException;
-
-public class StopParseException extends SAXException {
-	private static final long serialVersionUID = 1L;
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/UniqueResourceFilter.java b/biz.aQute.bndlib/src/aQute/lib/deployer/obr/UniqueResourceFilter.java
deleted file mode 100644
index 0ad2cfb..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/deployer/obr/UniqueResourceFilter.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package aQute.lib.deployer.obr;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.xml.sax.Attributes;
-
-import aQute.libg.sax.filters.ElementSelectionFilter;
-
-public class UniqueResourceFilter extends ElementSelectionFilter {
-	
-	final Set<String> uris = new HashSet<String>();
-	final Map<String, List<String>> filteredResources = new HashMap<String, List<String>>();
-
-	@Override
-	protected boolean select(int depth, String uri, String localName, String qName, Attributes attribs) {
-		if ("resource".equals(qName)) {
-			String resourceUri = attribs.getValue("uri");
-			if (uris.contains(resourceUri)) {
-				addFilteredBundle(attribs.getValue("symbolicname"), attribs.getValue("version"));
-				return false;
-			}
-			uris.add(resourceUri);
-		}
-		return true;
-	}
-
-	private void addFilteredBundle(String bsn, String version) {
-		List<String> versions = filteredResources.get(bsn);
-		if (versions == null) {
-			versions = new LinkedList<String>();
-			filteredResources.put(bsn, versions);
-		}
-		versions.add(version);
-	}
-	
-	public Collection<String> getFilteredBSNs() {
-		return filteredResources.keySet();
-	}
-	
-	public Collection<String> getFilteredVersions(String bsn) {
-		List<String> list = filteredResources.get(bsn);
-		if (list == null)
-			list = Collections.emptyList();
-		return list;
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/jardiff/Diff.java b/biz.aQute.bndlib/src/aQute/lib/jardiff/Diff.java
deleted file mode 100644
index b5daec8..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/jardiff/Diff.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package aQute.lib.jardiff;
-
-import java.io.*;
-import java.util.*;
-import java.util.jar.*;
-
-import aQute.lib.osgi.*;
-
-public class Diff {
-
-    /**
-     * Compare two JAR files with each other.
-     * 
-     * @param a
-     * @param b
-     * @param strict
-     * @return
-     * @throws IOException
-     */
-    public Map<String, Object> diff(Jar a, Jar b, boolean strict)
-            throws Exception {
-        Map<String, Object> different = new TreeMap<String, Object>();
-        compareManifest(different, a.getManifest(), b.getManifest(), strict);
-        diff(different, a.getResources().keySet(), b.getResources().keySet());
-
-        Set<String> shared = new HashSet<String>(a.getResources().keySet());
-        shared.retainAll(b.getResources().keySet());
-
-        for (String path : a.getResources().keySet()) {
-            Resource ra = a.getResource(path);
-            Resource rb = a.getResource(path);
-            if (rb != null) {
-                if (ra.getClass() != rb.getClass()) {
-                    different.put(path, "Different types: "
-                            + a.getClass().getName() + " : "
-                            + b.getClass().getName());
-                } else {
-                    if (path.endsWith(".jar")) {
-                        Jar aa = new Jar(path, ra.openInputStream());
-                        Jar bb = new Jar(path, rb.openInputStream());
-                        try {
-                            Map<String, Object> result = diff(aa, bb, strict);
-                            if (!result.isEmpty())
-                                different.put(path, result);
-                        } finally {
-                            aa.close();
-                            bb.close();
-                        }
-                    } else {
-                        String cmp = diff(ra.openInputStream(), rb
-                                .openInputStream());
-                        if (cmp != null)
-                            different.put(path, cmp);
-                    }
-                }
-            }
-        }
-        return different;
-    }
-
-    String diff(InputStream a, InputStream b) throws IOException {
-        int n = 0;
-        int binary = 0;
-        StringBuffer sb = new StringBuffer();
-        while (true) {
-            int ac = a.read();
-            int bc = b.read();
-            if (ac < 0) {
-                if (bc < 0)
-                    return null;
-
-                return "a is smaller";
-            } else if (bc < 0) {
-                return "b is smaller";
-            }
-
-            if (ac != bc) {
-                String s = "Difference at pos: " + n;
-                if (binary == 0 && sb.length() > 5) {
-                    s = s + "Context: " + sb.substring(sb.length() - 5);
-                }
-            }
-
-            if (ac >= ' ' && ac <= '~')
-                sb.append((char) ac);
-            else
-                binary++;
-
-            n++;
-        }
-    }
-
-    void diff(Map<String, Object> different, Set<?> a, Set<?> b) {
-        Set<Object> onlyInA = new HashSet<Object>(a);
-        onlyInA.removeAll(b);
-        Set<Object> onlyInB = new HashSet<Object>(b);
-        onlyInB.removeAll(a);
-
-        for (Object element : onlyInA) {
-            different.put(element.toString(), "a");
-        }
-        for (Object element : onlyInB) {
-            different.put(element.toString(), "b");
-        }
-    }
-
-    public void compareManifest(Map<String, Object> different, Manifest a,
-            Manifest b, boolean strict) {
-        if (a == null || b == null) {
-            different.put("Manifest null", (a == null ? "a=null" : "a exists")
-                    + " " + (b == null ? "b=null" : "b exists"));
-            return;
-        }
-
-        Attributes attrs = a.getMainAttributes();
-        Attributes bttrs = b.getMainAttributes();
-        diff(different, attrs.keySet(), bttrs.keySet());
-        for (Object element : attrs.keySet()) {
-            Attributes.Name name = (Attributes.Name) element;
-            String av = attrs.getValue(name);
-            String bv = bttrs.getValue(name);
-            if (bv != null) {
-                if (!av.equals(bv))
-                    different.put(name.toString(), "M:" + name + ":" + av
-                            + "!=" + bv);
-            }
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    public void print(PrintStream pout, Map<String, Object> map, int indent) {
-        for (Map.Entry<String, Object> entry : map.entrySet()) {
-            for (int j = 0; j < indent; j++) {
-                pout.print(" ");
-            }
-            String key = entry.getKey();
-            pout.print(key);
-            for (int j = 0; j < 70 - indent - key.length(); j++) {
-                pout.print(" ");
-            }
-            if (entry.getValue() instanceof Map) {
-                pout.println();
-                print(pout, (Map<String, Object>) entry.getValue(), indent + 1);
-            } else
-                pout.println(entry.getValue());
-        }
-    }
-
-    public void close() {
-
-    }
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/About.java b/biz.aQute.bndlib/src/aQute/lib/osgi/About.java
deleted file mode 100755
index 204e511..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/About.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package aQute.lib.osgi;
-
-/**
- * This package contains a number of classes that assists by analyzing JARs and
- * constructing bundles.
- * 
- * The Analyzer class can be used to analyze an existing bundle and can create a
- * manifest specification from proposed (wildcard) Export-Package,
- * Bundle-Includes, and Import-Package headers.
- * 
- * The Builder class can use the headers to construct a JAR from the classpath.
- * 
- * The Verifier class can take an existing JAR and verify that all headers are
- * correctly set. It will verify the syntax of the headers, match it against the
- * proper contents, and verify imports and exports.
- * 
- * A number of utility classes are available.
- * 
- * Jar, provides an abstraction of a Jar file. It has constructors for creating
- * a Jar from a stream, a directory, or a jar file. A Jar, keeps a collection
- * Resource's. There are Resource implementations for File, from ZipFile, or from
- * a stream (which copies the data). The Jar tries to minimize the work during
- * build up so that it is cheap to use. The Resource's can be used to iterate 
- * over the names and later read the resources when needed.
- * 
- * Clazz, provides a parser for the class files. This will be used to define the
- * imports and exports.
- * 
- * A key component in this library is the Map. Headers are translated to Maps of Maps. OSGi
- * header syntax is like:
- * <pre>
- * 	  header = clause ( ',' clause ) *
- *    clause = file ( ';' file ) * ( parameter ) *
- *    param  = attr '=' value | directive ':=' value
- * </pre>
- * These headers are translated to a Map that contains all headers (the order is
- * maintained). Each additional file in a header definition will have its own
- * entry (only native code does not work this way). The clause is represented
- * as another map. The ':' of directives is considered part of the name. This
- * allows attributes and directives to be maintained in the clause map. 
- * 
- * @version $Revision: 1.2 $
- */
-public class About {
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/AbstractResource.java b/biz.aQute.bndlib/src/aQute/lib/osgi/AbstractResource.java
deleted file mode 100644
index 532b33e..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/AbstractResource.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package aQute.lib.osgi;
-
-import java.io.*;
-
-public abstract class AbstractResource implements Resource {
-    String extra;
-    byte[] calculated;
-    long   lastModified;
-
-    protected AbstractResource(long modified) {
-        lastModified = modified;
-    }
-
-    public String getExtra() {
-        return extra;
-    }
-
-    public long lastModified() {
-        return lastModified;
-    }
-
-    public InputStream openInputStream() throws IOException {
-        return new ByteArrayInputStream(getLocalBytes());
-    }
-
-    private byte[] getLocalBytes() throws IOException {
-        try {
-            if (calculated != null)
-                return calculated;
-
-            return calculated = getBytes();
-        } catch (IOException e) {
-            throw e;
-        } catch (Exception e) {
-            IOException ee = new IOException("Opening resource");
-            ee.initCause(e);
-            throw ee;
-        }
-    }
-
-    public void setExtra(String extra) {
-        this.extra = extra;
-    }
-
-    public void write(OutputStream out) throws IOException {
-        out.write(getLocalBytes());
-    }
-
-    abstract protected byte[] getBytes() throws Exception;
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/Analyzer.java b/biz.aQute.bndlib/src/aQute/lib/osgi/Analyzer.java
deleted file mode 100755
index 957269a..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/Analyzer.java
+++ /dev/null
@@ -1,2301 +0,0 @@
-package aQute.lib.osgi;
-
-/**
- * This class can calculate the required headers for a (potential) JAR file. It
- * analyzes a directory or JAR for the packages that are contained and that are
- * referred to by the bytecodes. The user can the use regular expressions to
- * define the attributes and directives. The matching is not fully regex for
- * convenience. A * and ? get a . prefixed and dots are escaped.
- * 
- * <pre>
- *                                                             			*;auto=true				any		
- *                                                             			org.acme.*;auto=true    org.acme.xyz
- *                                                             			org.[abc]*;auto=true    org.acme.xyz
- * </pre>
- * 
- * Additional, the package instruction can start with a '=' or a '!'. The '!'
- * indicates negation. Any matching package is removed. The '=' is literal, the
- * expression will be copied verbatim and no matching will take place.
- * 
- * Any headers in the given properties are used in the output properties.
- */
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import java.util.Map.Entry;
-import java.util.jar.*;
-import java.util.jar.Attributes.Name;
-import java.util.regex.*;
-
-import aQute.bnd.annotation.*;
-import aQute.bnd.service.*;
-import aQute.lib.base64.*;
-import aQute.lib.collections.*;
-import aQute.lib.filter.*;
-import aQute.lib.hex.*;
-import aQute.lib.io.*;
-import aQute.lib.osgi.Clazz.QUERY;
-import aQute.libg.cryptography.*;
-import aQute.libg.generics.*;
-import aQute.libg.header.*;
-import aQute.libg.tarjan.*;
-import aQute.libg.version.Version;
-
-public class Analyzer extends Processor {
-
-	static String							version;
-	static Pattern							versionPattern			= Pattern
-																			.compile("(\\d+\\.\\d+)\\.\\d+.*");
-	final Map<String, Map<String, String>>	contained				= newHashMap();							// package
-	final Map<String, Map<String, String>>	referred				= newHashMap();							// refers
-	// package
-	final Map<String, Set<String>>			uses					= newHashMap();							// package
-	Map<String, Clazz>						classspace;
-	Map<String, Clazz>						importedClassesCache	= newMap();
-	Map<String, Map<String, String>>		exports;
-	Map<String, Map<String, String>>		imports;
-	Map<String, Map<String, String>>		bundleClasspath;													// Bundle
-	final Map<String, Map<String, String>>	ignored					= newHashMap();							// Ignored
-	// packages
-	Jar										dot;
-	Map<String, Map<String, String>>		classpathExports;
-
-	String									activator;
-
-	final List<Jar>							classpath				= newList();
-
-	static Properties						bndInfo;
-
-	boolean									analyzed;
-	String									bsn;
-	String									versionPolicyUses;
-	String									versionPolicyImplemented;
-	boolean									diagnostics				= false;
-	SortedSet<Clazz.JAVA>					formats					= new TreeSet<Clazz.JAVA>();
-	private boolean							inited;
-
-	public Analyzer(Processor parent) {
-		super(parent);
-	}
-
-	public Analyzer() {
-	}
-
-	/**
-	 * Specifically for Maven
-	 * 
-	 * @param properties
-	 *            the properties
-	 */
-
-	public static Properties getManifest(File dirOrJar) throws Exception {
-		Analyzer analyzer = new Analyzer();
-		try {
-			analyzer.setJar(dirOrJar);
-			Properties properties = new Properties();
-			properties.put(IMPORT_PACKAGE, "*");
-			properties.put(EXPORT_PACKAGE, "*");
-			analyzer.setProperties(properties);
-			Manifest m = analyzer.calcManifest();
-			Properties result = new Properties();
-			for (Iterator<Object> i = m.getMainAttributes().keySet().iterator(); i.hasNext();) {
-				Attributes.Name name = (Attributes.Name) i.next();
-				result.put(name.toString(), m.getMainAttributes().getValue(name));
-			}
-			return result;
-		} finally {
-			analyzer.close();
-		}
-	}
-
-	/**
-	 * Calculates the data structures for generating a manifest.
-	 * 
-	 * @throws IOException
-	 */
-	public void analyze() throws Exception {
-		if (!analyzed) {
-			analyzed = true;
-			activator = getProperty(BUNDLE_ACTIVATOR);
-			bundleClasspath = parseHeader(getProperty(BUNDLE_CLASSPATH));
-
-			analyzeClasspath();
-
-			classspace = analyzeBundleClasspath(dot, bundleClasspath, contained, referred, uses);
-
-			for (AnalyzerPlugin plugin : getPlugins(AnalyzerPlugin.class)) {
-				if (plugin instanceof AnalyzerPlugin) {
-					AnalyzerPlugin analyzer = (AnalyzerPlugin) plugin;
-					try {
-						boolean reanalyze = analyzer.analyzeJar(this);
-						if (reanalyze)
-							classspace = analyzeBundleClasspath(dot, bundleClasspath, contained,
-									referred, uses);
-					} catch (Exception e) {
-						error("Plugin Analyzer " + analyzer + " throws exception " + e);
-						e.printStackTrace();
-					}
-				}
-			}
-
-			if (activator != null) {
-				// Add the package of the activator to the set
-				// of referred classes. This must be done before we remove
-				// contained set.
-				int n = activator.lastIndexOf('.');
-				if (n > 0) {
-					referred.put(activator.substring(0, n), new LinkedHashMap<String, String>());
-				}
-			}
-
-			referred.keySet().removeAll(contained.keySet());
-			if (referred.containsKey(".")) {
-				error("The default package '.' is not permitted by the Import-Package syntax. \n"
-						+ " This can be caused by compile errors in Eclipse because Eclipse creates \n"
-						+ "valid class files regardless of compile errors.\n"
-						+ "The following package(s) import from the default package "
-						+ getUsedBy("."));
-			}
-
-			Map<String, Map<String, String>> exportInstructions = parseHeader(getProperty(EXPORT_PACKAGE));
-			Map<String, Map<String, String>> additionalExportInstructions = parseHeader(getProperty(EXPORT_CONTENTS));
-			exportInstructions.putAll(additionalExportInstructions);
-			Map<String, Map<String, String>> importInstructions = parseHeader(getImportPackages());
-			Map<String, Map<String, String>> dynamicImports = parseHeader(getProperty(DYNAMICIMPORT_PACKAGE));
-
-			if (dynamicImports != null) {
-				// Remove any dynamic imports from the referred set.
-				referred.keySet().removeAll(dynamicImports.keySet());
-			}
-
-			Map<String, Map<String, String>> superfluous = newHashMap();
-			// Tricky!
-			for (Iterator<String> i = exportInstructions.keySet().iterator(); i.hasNext();) {
-				String instr = i.next();
-				if (!instr.startsWith("!"))
-					superfluous.put(instr, exportInstructions.get(instr));
-			}
-
-			exports = merge("export-package", exportInstructions, contained, superfluous.keySet(),
-					null);
-
-			// disallow export of default package
-			exports.remove(".");
-
-			for (Iterator<Map.Entry<String, Map<String, String>>> i = superfluous.entrySet()
-					.iterator(); i.hasNext();) {
-				// It is possible to mention metadata directories in the export
-				// explicitly, they are then exported and removed from the
-				// warnings. Note that normally metadata directories are not
-				// exported.
-				Map.Entry<String, Map<String, String>> entry = i.next();
-				String pack = entry.getKey();
-				if (isDuplicate(pack))
-					i.remove();
-				else if (isMetaData(pack)) {
-					exports.put(pack, entry.getValue());
-					i.remove();
-				}
-			}
-
-			if (!superfluous.isEmpty()) {
-				warning("Superfluous export-package instructions: " + superfluous.keySet());
-			}
-
-			// Add all exports that do not have an -noimport: directive
-			// to the imports.
-			Map<String, Map<String, String>> referredAndExported = newMap(referred);
-			referredAndExported.putAll(doExportsToImports(exports));
-
-			// match the imports to the referred and exported packages,
-			// merge the info for matching packages
-			Set<String> extra = new TreeSet<String>(importInstructions.keySet());
-			imports = merge("import-package", importInstructions, referredAndExported, extra,
-					ignored);
-
-			// Instructions that have not been used could be superfluous
-			// or if they do not contain wildcards, should be added
-			// as extra imports, the user knows best.
-			for (Iterator<String> i = extra.iterator(); i.hasNext();) {
-				String p = i.next();
-				if (p.startsWith("!") || p.indexOf('*') >= 0 || p.indexOf('?') >= 0
-						|| p.indexOf('[') >= 0) {
-					if (!isResourceOnly() && !(p.equals("*")))
-						warning("Did not find matching referal for " + p);
-				} else {
-					Map<String, String> map = importInstructions.get(p);
-					imports.put(p, map);
-				}
-			}
-
-			// See what information we can find to augment the
-			// exports. I.e. look on the classpath
-			augmentExports();
-
-			// See what information we can find to augment the
-			// imports. I.e. look on the classpath
-			augmentImports();
-
-			// Add the uses clause to the exports
-			doUses(exports, uses, imports);
-		}
-	}
-
-	/**
-	 * Copy the input collection into an output set but skip names that have
-	 * been marked as duplicates or are optional.
-	 * 
-	 * @param superfluous
-	 * @return
-	 */
-	Set<Instruction> removeMarkedDuplicates(Collection<Instruction> superfluous) {
-		Set<Instruction> result = new HashSet<Instruction>();
-		for (Iterator<Instruction> i = superfluous.iterator(); i.hasNext();) {
-			Instruction instr = (Instruction) i.next();
-			if (!isDuplicate(instr.getPattern()) && !instr.isOptional())
-				result.add(instr);
-		}
-		return result;
-	}
-
-	/**
-	 * Analyzer has an empty default but the builder has a * as default.
-	 * 
-	 * @return
-	 */
-	protected String getImportPackages() {
-		return getProperty(IMPORT_PACKAGE);
-	}
-
-	/**
-	 * 
-	 * @return
-	 */
-	boolean isResourceOnly() {
-		return isTrue(getProperty(RESOURCEONLY));
-	}
-
-	/**
-	 * Answer the list of packages that use the given package.
-	 */
-	Set<String> getUsedBy(String pack) {
-		Set<String> set = newSet();
-		for (Iterator<Map.Entry<String, Set<String>>> i = uses.entrySet().iterator(); i.hasNext();) {
-			Map.Entry<String, Set<String>> entry = i.next();
-			Set<String> used = entry.getValue();
-			if (used.contains(pack))
-				set.add(entry.getKey());
-		}
-		return set;
-	}
-
-	/**
-	 * One of the main workhorses of this class. This will analyze the current
-	 * setp and calculate a new manifest according to this setup. This method
-	 * will also set the manifest on the main jar dot
-	 * 
-	 * @return
-	 * @throws IOException
-	 */
-	public Manifest calcManifest() throws Exception {
-		analyze();
-		Manifest manifest = new Manifest();
-		Attributes main = manifest.getMainAttributes();
-
-		main.put(Attributes.Name.MANIFEST_VERSION, "1.0");
-		main.putValue(BUNDLE_MANIFESTVERSION, "2");
-
-		boolean noExtraHeaders = "true".equalsIgnoreCase(getProperty(NOEXTRAHEADERS));
-
-		if (!noExtraHeaders) {
-			main.putValue(CREATED_BY,
-					System.getProperty("java.version") + " (" + System.getProperty("java.vendor")
-							+ ")");
-			main.putValue(TOOL, "Bnd-" + getBndVersion());
-			main.putValue(BND_LASTMODIFIED, "" + System.currentTimeMillis());
-		}
-
-		String exportHeader = printClauses(exports, true);
-
-		if (exportHeader.length() > 0)
-			main.putValue(EXPORT_PACKAGE, exportHeader);
-		else
-			main.remove(EXPORT_PACKAGE);
-
-		Map<String, Map<String, String>> temp = removeKeys(imports, "java.");
-		if (!temp.isEmpty()) {
-			main.putValue(IMPORT_PACKAGE, printClauses(temp));
-		} else {
-			main.remove(IMPORT_PACKAGE);
-		}
-
-		temp = newMap(contained);
-		temp.keySet().removeAll(exports.keySet());
-
-		if (!temp.isEmpty())
-			main.putValue(PRIVATE_PACKAGE, printClauses(temp));
-		else
-			main.remove(PRIVATE_PACKAGE);
-
-		if (!ignored.isEmpty()) {
-			main.putValue(IGNORE_PACKAGE, printClauses(ignored));
-		} else {
-			main.remove(IGNORE_PACKAGE);
-		}
-
-		if (bundleClasspath != null && !bundleClasspath.isEmpty())
-			main.putValue(BUNDLE_CLASSPATH, printClauses(bundleClasspath));
-		else
-			main.remove(BUNDLE_CLASSPATH);
-
-		doNamesection(dot, manifest);
-
-		for (Enumeration<?> h = getProperties().propertyNames(); h.hasMoreElements();) {
-			String header = (String) h.nextElement();
-			if (header.trim().length() == 0) {
-				warning("Empty property set with value: " + getProperties().getProperty(header));
-				continue;
-			}
-
-			if (isMissingPlugin(header.trim())) {
-				error("Missing plugin for command %s", header);
-			}
-			if (!Character.isUpperCase(header.charAt(0))) {
-				if (header.charAt(0) == '@')
-					doNameSection(manifest, header);
-				continue;
-			}
-
-			if (header.equals(BUNDLE_CLASSPATH) || header.equals(EXPORT_PACKAGE)
-					|| header.equals(IMPORT_PACKAGE))
-				continue;
-
-			if (header.equalsIgnoreCase("Name")) {
-				error("Your bnd file contains a header called 'Name'. This interferes with the manifest name section.");
-				continue;
-			}
-
-			if (Verifier.HEADER_PATTERN.matcher(header).matches()) {
-				String value = getProperty(header);
-				if (value != null && main.getValue(header) == null) {
-					if (value.trim().length() == 0)
-						main.remove(header);
-					else if (value.trim().equals(EMPTY_HEADER))
-						main.putValue(header, "");
-					else
-						main.putValue(header, value);
-				}
-			} else {
-				// TODO should we report?
-			}
-		}
-
-		//
-		// Calculate the bundle symbolic name if it is
-		// not set.
-		// 1. set
-		// 2. name of properties file (must be != bnd.bnd)
-		// 3. name of directory, which is usualy project name
-		//
-		String bsn = getBsn();
-		if (main.getValue(BUNDLE_SYMBOLICNAME) == null) {
-			main.putValue(BUNDLE_SYMBOLICNAME, bsn);
-		}
-
-		//
-		// Use the same name for the bundle name as BSN when
-		// the bundle name is not set
-		//
-		if (main.getValue(BUNDLE_NAME) == null) {
-			main.putValue(BUNDLE_NAME, bsn);
-		}
-
-		if (main.getValue(BUNDLE_VERSION) == null)
-			main.putValue(BUNDLE_VERSION, "0");
-
-		// Copy old values into new manifest, when they
-		// exist in the old one, but not in the new one
-		merge(manifest, dot.getManifest());
-
-		// Remove all the headers mentioned in -removeheaders
-		Map<String, Map<String, String>> removes = parseHeader(getProperty(REMOVEHEADERS));
-		Set<Instruction> matchers = Instruction.replaceWithInstruction(removes).keySet();
-
-		Collection<Object> toBeRemoved = Instruction.select(matchers, main.keySet());
-		Iterator<Object> i = main.keySet().iterator();
-		while (i.hasNext())
-			if (toBeRemoved.contains(i.next()))
-				i.remove();
-
-		dot.setManifest(manifest);
-		return manifest;
-	}
-
-	/**
-	 * Parse the namesection as instructions and then match them against the
-	 * current set of resources
-	 * 
-	 * For example:
-	 * 
-	 * <pre>
-	 * 	-namesection: *;baz=true, abc/def/bar/X.class=3
-	 * </pre>
-	 * 
-	 * The raw value of {@link Constants#NAMESECTION} is used but the values of
-	 * the attributes are replaced where @ is set to the resource name. This
-	 * allows macro to operate on the resource
-	 * 
-	 */
-
-	private void doNamesection(Jar dot, Manifest manifest) {
-
-		Map<String, Map<String, String>> namesection = parseHeader(getProperties().getProperty(
-				NAMESECTION));
-		Set<Entry<Instruction, Map<String, String>>> instructions = Instruction
-				.replaceWithInstruction(namesection).entrySet();
-		Set<Map.Entry<String, Resource>> resources = new HashSet<Map.Entry<String, Resource>>(dot
-				.getResources().entrySet());
-
-		//
-		// For each instruction, iterator over the resources and filter
-		// them. If a resource matches, it must be removed even if the
-		// instruction is negative. If positive, add a name section
-		// to the manifest for the given resource name. Then add all
-		// attributes from the instruction to that name section.
-		//
-		for (Map.Entry<Instruction, Map<String, String>> instr : instructions) {
-			boolean matched = false;
-
-			// For each instruction
-
-			for (Iterator<Map.Entry<String, Resource>> it = resources.iterator(); it.hasNext();) {
-
-				// For each resource
-
-				Map.Entry<String, Resource> next = it.next();
-				if (instr.getKey().matches(next.getKey())) {
-
-					// Instruction matches the resource
-
-					matched = true;
-					if (!instr.getKey().isNegated()) {
-
-						// Positive match, add the attributes
-
-						Attributes attrs = manifest.getAttributes(next.getKey());
-						if (attrs == null) {
-							attrs = new Attributes();
-							manifest.getEntries().put(next.getKey(), attrs);
-						}
-
-						//
-						// Add all the properties from the instruction to the
-						// name section
-						//
-
-						for (Map.Entry<String, String> property : instr.getValue().entrySet()) {
-							setProperty("@", next.getKey());
-							try {
-								String processed = getReplacer().process(property.getValue());
-								attrs.putValue(property.getKey(), processed);
-							} finally {
-								unsetProperty("@");
-							}
-						}
-					}
-					it.remove();
-				}
-			}
-
-			if (!matched)
-				warning("The instruction %s in %s did not match any resources", instr.getKey(),
-						NAMESECTION);
-		}
-
-	}
-
-	/**
-	 * This method is called when the header starts with a @, signifying a name
-	 * section header. The name part is defined by replacing all the @ signs to
-	 * a /, removing the first and the last, and using the last part as header
-	 * name:
-	 * 
-	 * <pre>
-	 * @org at osgi@service at event@Implementation-Title
-	 * </pre>
-	 * 
-	 * This will be the header Implementation-Title in the
-	 * org/osgi/service/event named section.
-	 * 
-	 * @param manifest
-	 * @param header
-	 */
-	private void doNameSection(Manifest manifest, String header) {
-		String path = header.replace('@', '/');
-		int n = path.lastIndexOf('/');
-		// Must succeed because we start with @
-		String name = path.substring(n + 1);
-		// Skip first /
-		path = path.substring(1, n);
-		if (name.length() != 0 && path.length() != 0) {
-			Attributes attrs = manifest.getAttributes(path);
-			if (attrs == null) {
-				attrs = new Attributes();
-				manifest.getEntries().put(path, attrs);
-			}
-			attrs.putValue(name, getProperty(header));
-		} else {
-			warning("Invalid header (starts with @ but does not seem to be for the Name section): %s",
-					header);
-		}
-	}
-
-	/**
-	 * Clear the key part of a header. I.e. remove everything from the first ';'
-	 * 
-	 * @param value
-	 * @return
-	 */
-	public String getBsn() {
-		String value = getProperty(BUNDLE_SYMBOLICNAME);
-		if (value == null) {
-			if (getPropertiesFile() != null)
-				value = getPropertiesFile().getName();
-
-			String projectName = getBase().getName();
-			if (value == null || value.equals("bnd.bnd")) {
-				value = projectName;
-			} else if (value.endsWith(".bnd")) {
-				value = value.substring(0, value.length() - 4);
-				if (!value.startsWith(getBase().getName()))
-					value = projectName + "." + value;
-			}
-		}
-
-		if (value == null)
-			return "untitled";
-
-		int n = value.indexOf(';');
-		if (n > 0)
-			value = value.substring(0, n);
-		return value.trim();
-	}
-
-	public String _bsn(String args[]) {
-		return getBsn();
-	}
-
-	/**
-	 * Calculate an export header solely based on the contents of a JAR file
-	 * 
-	 * @param bundle
-	 *            The jar file to analyze
-	 * @return
-	 */
-	public String calculateExportsFromContents(Jar bundle) {
-		String ddel = "";
-		StringBuffer sb = new StringBuffer();
-		Map<String, Map<String, Resource>> map = bundle.getDirectories();
-		for (Iterator<String> i = map.keySet().iterator(); i.hasNext();) {
-			String directory = (String) i.next();
-			if (directory.equals("META-INF") || directory.startsWith("META-INF/"))
-				continue;
-			if (directory.equals("OSGI-OPT") || directory.startsWith("OSGI-OPT/"))
-				continue;
-			if (directory.equals("/"))
-				continue;
-
-			if (directory.endsWith("/"))
-				directory = directory.substring(0, directory.length() - 1);
-
-			directory = directory.replace('/', '.');
-			sb.append(ddel);
-			sb.append(directory);
-			ddel = ",";
-		}
-		return sb.toString();
-	}
-
-	public Map<String, Map<String, String>> getBundleClasspath() {
-		return bundleClasspath;
-	}
-
-	public Map<String, Map<String, String>> getContained() {
-		return contained;
-	}
-
-	public Map<String, Map<String, String>> getExports() {
-		return exports;
-	}
-
-	public Map<String, Map<String, String>> getImports() {
-		return imports;
-	}
-
-	public Jar getJar() {
-		return dot;
-	}
-
-	public Map<String, Map<String, String>> getReferred() {
-		return referred;
-	}
-
-	/**
-	 * Return the set of unreachable code depending on exports and the bundle
-	 * activator.
-	 * 
-	 * @return
-	 */
-	public Set<String> getUnreachable() {
-		Set<String> unreachable = new HashSet<String>(uses.keySet()); // all
-		for (Iterator<String> r = exports.keySet().iterator(); r.hasNext();) {
-			String packageName = r.next();
-			removeTransitive(packageName, unreachable);
-		}
-		if (activator != null) {
-			String pack = activator.substring(0, activator.lastIndexOf('.'));
-			removeTransitive(pack, unreachable);
-		}
-		return unreachable;
-	}
-
-	public Map<String, Set<String>> getUses() {
-		return uses;
-	}
-
-	/**
-	 * Get the version for this bnd
-	 * 
-	 * @return version or unknown.
-	 */
-	public String getBndVersion() {
-		return getBndInfo("version", "1.42.1");
-	}
-
-	public long getBndLastModified() {
-		String time = getBndInfo("modified", "0");
-		try {
-			return Long.parseLong(time);
-		} catch (Exception e) {
-		}
-		return 0;
-	}
-
-	public String getBndInfo(String key, String defaultValue) {
-		if (bndInfo == null) {
-			bndInfo = new Properties();
-			try {
-				InputStream in = Analyzer.class.getResourceAsStream("bnd.info");
-				if (in != null) {
-					bndInfo.load(in);
-					in.close();
-				}
-			} catch (IOException ioe) {
-				warning("Could not read bnd.info in " + Analyzer.class.getPackage() + ioe);
-			}
-		}
-		return bndInfo.getProperty(key, defaultValue);
-	}
-
-	/**
-	 * Merge the existing manifest with the instructions.
-	 * 
-	 * @param manifest
-	 *            The manifest to merge with
-	 * @throws IOException
-	 */
-	public void mergeManifest(Manifest manifest) throws IOException {
-		if (manifest != null) {
-			Attributes attributes = manifest.getMainAttributes();
-			for (Iterator<Object> i = attributes.keySet().iterator(); i.hasNext();) {
-				Name name = (Name) i.next();
-				String key = name.toString();
-				// Dont want instructions
-				if (key.startsWith("-"))
-					continue;
-
-				if (getProperty(key) == null)
-					setProperty(key, (String) attributes.get(name));
-			}
-		}
-	}
-
-	public void setBase(File file) {
-		super.setBase(file);
-		getProperties().put("project.dir", getBase().getAbsolutePath());
-	}
-
-	/**
-	 * Set the classpath for this analyzer by file.
-	 * 
-	 * @param classpath
-	 * @throws IOException
-	 */
-	public void setClasspath(File[] classpath) throws IOException {
-		List<Jar> list = new ArrayList<Jar>();
-		for (int i = 0; i < classpath.length; i++) {
-			if (classpath[i].exists()) {
-				Jar current = new Jar(classpath[i]);
-				list.add(current);
-			} else {
-				error("Missing file on classpath: %s", classpath[i]);
-			}
-		}
-		for (Iterator<Jar> i = list.iterator(); i.hasNext();) {
-			addClasspath(i.next());
-		}
-	}
-
-	public void setClasspath(Jar[] classpath) {
-		for (int i = 0; i < classpath.length; i++) {
-			addClasspath(classpath[i]);
-		}
-	}
-
-	public void setClasspath(String[] classpath) {
-		for (int i = 0; i < classpath.length; i++) {
-			Jar jar = getJarFromName(classpath[i], " setting classpath");
-			if (jar != null)
-				addClasspath(jar);
-		}
-	}
-
-	/**
-	 * Set the JAR file we are going to work in. This will read the JAR in
-	 * memory.
-	 * 
-	 * @param jar
-	 * @return
-	 * @throws IOException
-	 */
-	public Jar setJar(File jar) throws IOException {
-		Jar jarx = new Jar(jar);
-		addClose(jarx);
-		return setJar(jarx);
-	}
-
-	/**
-	 * Set the JAR directly we are going to work on.
-	 * 
-	 * @param jar
-	 * @return
-	 */
-	public Jar setJar(Jar jar) {
-		this.dot = jar;
-		return jar;
-	}
-
-	protected void begin() {
-		if (inited == false) {
-			inited = true;
-			super.begin();
-
-			updateModified(getBndLastModified(), "bnd last modified");
-			verifyManifestHeadersCase(getProperties());
-
-		}
-	}
-
-	/**
-	 * Check if the given class or interface name is contained in the jar.
-	 * 
-	 * @param interfaceName
-	 * @return
-	 */
-
-	public boolean checkClass(String interfaceName) {
-		String path = Clazz.fqnToPath(interfaceName);
-		if (classspace.containsKey(path))
-			return true;
-
-		if (interfaceName.startsWith("java."))
-			return true;
-
-		if (imports != null && !imports.isEmpty()) {
-			String pack = interfaceName;
-			int n = pack.lastIndexOf('.');
-			if (n > 0)
-				pack = pack.substring(0, n);
-			else
-				pack = ".";
-
-			if (imports.containsKey(pack))
-				return true;
-		}
-		int n = interfaceName.lastIndexOf('.');
-		if (n > 0 && n + 1 < interfaceName.length()
-				&& Character.isUpperCase(interfaceName.charAt(n + 1))) {
-			return checkClass(interfaceName.substring(0, n) + '$' + interfaceName.substring(n + 1));
-		}
-		return false;
-	}
-
-	/**
-	 * Try to get a Jar from a file name/path or a url, or in last resort from
-	 * the classpath name part of their files.
-	 * 
-	 * @param name
-	 *            URL or filename relative to the base
-	 * @param from
-	 *            Message identifying the caller for errors
-	 * @return null or a Jar with the contents for the name
-	 */
-	Jar getJarFromName(String name, String from) {
-		File file = new File(name);
-		if (!file.isAbsolute())
-			file = new File(getBase(), name);
-
-		if (file.exists())
-			try {
-				Jar jar = new Jar(file);
-				addClose(jar);
-				return jar;
-			} catch (Exception e) {
-				error("Exception in parsing jar file for " + from + ": " + name + " " + e);
-			}
-		// It is not a file ...
-		try {
-			// Lets try a URL
-			URL url = new URL(name);
-			Jar jar = new Jar(fileName(url.getPath()));
-			addClose(jar);
-			URLConnection connection = url.openConnection();
-			InputStream in = connection.getInputStream();
-			long lastModified = connection.getLastModified();
-			if (lastModified == 0)
-				// We assume the worst :-(
-				lastModified = System.currentTimeMillis();
-			EmbeddedResource.build(jar, in, lastModified);
-			in.close();
-			return jar;
-		} catch (IOException ee) {
-			// Check if we have files on the classpath
-			// that have the right name, allows us to specify those
-			// names instead of the full path.
-			for (Iterator<Jar> cp = getClasspath().iterator(); cp.hasNext();) {
-				Jar entry = cp.next();
-				if (entry.source != null && entry.source.getName().equals(name)) {
-					return entry;
-				}
-			}
-			// error("Can not find jar file for " + from + ": " + name);
-		}
-		return null;
-	}
-
-	private String fileName(String path) {
-		int n = path.lastIndexOf('/');
-		if (n > 0)
-			return path.substring(n + 1);
-		return path;
-	}
-
-	/**
-	 * 
-	 * @param manifests
-	 * @throws Exception
-	 */
-	void merge(Manifest result, Manifest old) throws IOException {
-		if (old != null) {
-			for (Iterator<Map.Entry<Object, Object>> e = old.getMainAttributes().entrySet()
-					.iterator(); e.hasNext();) {
-				Map.Entry<Object, Object> entry = e.next();
-				Attributes.Name name = (Attributes.Name) entry.getKey();
-				String value = (String) entry.getValue();
-				if (name.toString().equalsIgnoreCase("Created-By"))
-					name = new Attributes.Name("Originally-Created-By");
-				if (!result.getMainAttributes().containsKey(name))
-					result.getMainAttributes().put(name, value);
-			}
-
-			// do not overwrite existing entries
-			Map<String, Attributes> oldEntries = old.getEntries();
-			Map<String, Attributes> newEntries = result.getEntries();
-			for (Iterator<Map.Entry<String, Attributes>> e = oldEntries.entrySet().iterator(); e
-					.hasNext();) {
-				Map.Entry<String, Attributes> entry = e.next();
-				if (!newEntries.containsKey(entry.getKey())) {
-					newEntries.put(entry.getKey(), entry.getValue());
-				}
-			}
-		}
-	}
-
-	String stem(String name) {
-		int n = name.lastIndexOf('.');
-		if (n > 0)
-			return name.substring(0, n);
-		else
-			return name;
-	}
-
-	/**
-	 * Bnd is case sensitive for the instructions so we better check people are
-	 * not using an invalid case. We do allow this to set headers that should
-	 * not be processed by us but should be used by the framework.
-	 * 
-	 * @param properties
-	 *            Properties to verify.
-	 */
-
-	void verifyManifestHeadersCase(Properties properties) {
-		for (Iterator<Object> i = properties.keySet().iterator(); i.hasNext();) {
-			String header = (String) i.next();
-			for (int j = 0; j < headers.length; j++) {
-				if (!headers[j].equals(header) && headers[j].equalsIgnoreCase(header)) {
-					warning("Using a standard OSGi header with the wrong case (bnd is case sensitive!), using: "
-							+ header + " and expecting: " + headers[j]);
-					break;
-				}
-			}
-		}
-	}
-
-	/**
-	 * We will add all exports to the imports unless there is a -noimport
-	 * directive specified on an export. This directive is skipped for the
-	 * manifest.
-	 * 
-	 * We also remove any version parameter so that augmentImports can do the
-	 * version policy.
-	 * 
-	 * The following method is really tricky and evolved over time. Coming from
-	 * the original background of OSGi, it was a weird idea for me to have a
-	 * public package that should not be substitutable. I was so much convinced
-	 * that this was the right rule that I rücksichtlos imported them all. Alas,
-	 * the real world was more subtle than that. It turns out that it is not a
-	 * good idea to always import. First, there must be a need to import, i.e.
-	 * there must be a contained package that refers to the exported package for
-	 * it to make use importing that package. Second, if an exported package
-	 * refers to an internal package than it should not be imported.
-	 * 
-	 * Additionally, it is necessary to treat the exports in groups. If an
-	 * exported package refers to another exported packages than it must be in
-	 * the same group. A framework can only substitute exports for imports for
-	 * the whole of such a group. WHY????? Not clear anymore ...
-	 * 
-	 */
-	/**
-	 * I could no longer argue why the groups are needed :-( See what happens
-	 * ... The getGroups calculated the groups and then removed the imports from
-	 * there. Now we only remove imports that have internal references. Using
-	 * internal code for an exported package means that a bundle cannot import
-	 * that package from elsewhere because its assumptions might be violated if
-	 * it receives a substitution. //
-	 */
-	Map<String, Map<String, String>> doExportsToImports(Map<String, Map<String, String>> exports) {
-
-		// private packages = contained - exported.
-		Set<String> privatePackages = new HashSet<String>(contained.keySet());
-		privatePackages.removeAll(exports.keySet());
-
-		// private references = ∀ p : private packages | uses(p)
-		Set<String> privateReferences = newSet();
-		for (String p : privatePackages) {
-			Set<String> uses = this.uses.get(p);
-			if (uses != null)
-				privateReferences.addAll(uses);
-		}
-
-		// Assume we are going to export all exported packages
-		Set<String> toBeImported = new HashSet<String>(exports.keySet());
-
-		// Remove packages that are not referenced privately
-		toBeImported.retainAll(privateReferences);
-
-		// Not necessary to import anything that is already
-		// imported in the Import-Package statement.
-		if (imports != null)
-			toBeImported.removeAll(imports.keySet());
-
-		// Remove exported packages that are referring to
-		// private packages.
-		// Each exported package has a uses clause. We just use
-		// the used packages for each exported package to find out
-		// if it refers to an internal package.
-		//
-
-		for (Iterator<String> i = toBeImported.iterator(); i.hasNext();) {
-			Set<String> usedByExportedPackage = this.uses.get(i.next());
-			for (String privatePackage : privatePackages) {
-				if (usedByExportedPackage.contains(privatePackage)) {
-					i.remove();
-					break;
-				}
-			}
-		}
-
-		// Clean up attributes and generate result map
-		Map<String, Map<String, String>> result = newMap();
-		for (Iterator<String> i = toBeImported.iterator(); i.hasNext();) {
-			String ep = i.next();
-			Map<String, String> parameters = exports.get(ep);
-
-			String noimport = parameters.get(NO_IMPORT_DIRECTIVE);
-			if (noimport != null && noimport.equalsIgnoreCase("true"))
-				continue;
-
-			// // we can't substitute when there is no version
-			// String version = parameters.get(VERSION_ATTRIBUTE);
-			// if (version == null) {
-			// if (isPedantic())
-			// warning(
-			// "Cannot automatically import exported package %s because it has no version defined",
-			// ep);
-			// continue;
-			// }
-
-			parameters = newMap(parameters);
-			parameters.remove(VERSION_ATTRIBUTE);
-			result.put(ep, parameters);
-		}
-		return result;
-	}
-
-	private <T> boolean intersects(Collection<T> aa, Collection<T> bb) {
-		if (aa.equals(bb))
-			return true;
-
-		if (aa.size() > bb.size())
-			return intersects(bb, aa);
-
-		for (T t : aa)
-			if (bb.contains(t))
-				return true;
-		return false;
-	}
-
-	public boolean referred(String packageName) {
-		// return true;
-		for (Map.Entry<String, Set<String>> contained : uses.entrySet()) {
-			if (!contained.getKey().equals(packageName)) {
-				if (contained.getValue().contains(packageName))
-					return true;
-			}
-		}
-		return false;
-	}
-
-	/**
-	 * Create the imports/exports by parsing
-	 * 
-	 * @throws IOException
-	 */
-	void analyzeClasspath() throws Exception {
-		classpathExports = newHashMap();
-		for (Iterator<Jar> c = getClasspath().iterator(); c.hasNext();) {
-			Jar current = c.next();
-			checkManifest(current);
-			for (Iterator<String> j = current.getDirectories().keySet().iterator(); j.hasNext();) {
-				String dir = j.next();
-				Resource resource = current.getResource(dir + "/packageinfo");
-				if (resource != null) {
-					InputStream in = resource.openInputStream();
-					try {
-						String version = parsePackageInfo(in);
-						setPackageInfo(dir, VERSION_ATTRIBUTE, version);
-					} finally {
-						in.close();
-					}
-				}
-			}
-		}
-	}
-
-	/**
-	 * 
-	 * @param jar
-	 */
-	void checkManifest(Jar jar) {
-		try {
-			Manifest m = jar.getManifest();
-			if (m != null) {
-				String exportHeader = m.getMainAttributes().getValue(EXPORT_PACKAGE);
-				if (exportHeader != null) {
-					Map<String, Map<String, String>> exported = parseHeader(exportHeader);
-					if (exported != null) {
-						for (Map.Entry<String, Map<String, String>> entry : exported.entrySet()) {
-							if (!classpathExports.containsKey(entry.getKey())) {
-								classpathExports.put(entry.getKey(), entry.getValue());
-							}
-						}
-					}
-				}
-			}
-		} catch (Exception e) {
-			warning("Erroneous Manifest for " + jar + " " + e);
-		}
-	}
-
-	/**
-	 * Find some more information about imports in manifest and other places.
-	 */
-	void augmentImports() {
-
-		for (String packageName : imports.keySet()) {
-			setProperty(CURRENT_PACKAGE, packageName);
-			try {
-				Map<String, String> importAttributes = imports.get(packageName);
-				Map<String, String> exporterAttributes = classpathExports.get(packageName);
-				if (exporterAttributes == null)
-					exporterAttributes = exports.get(packageName);
-
-				if (exporterAttributes != null) {
-					augmentVersion(importAttributes, exporterAttributes);
-					augmentMandatory(importAttributes, exporterAttributes);
-					if (exporterAttributes.containsKey(IMPORT_DIRECTIVE))
-						importAttributes.put(IMPORT_DIRECTIVE,
-								exporterAttributes.get(IMPORT_DIRECTIVE));
-				}
-
-				fixupAttributes(importAttributes);
-				removeAttributes(importAttributes);
-
-			} finally {
-				unsetProperty(CURRENT_PACKAGE);
-			}
-		}
-	}
-
-	/**
-	 * Provide any macro substitutions and versions for exported packages.
-	 */
-
-	void augmentExports() {
-		for (String packageName : exports.keySet()) {
-			setProperty(CURRENT_PACKAGE, packageName);
-			try {
-				Map<String, String> attributes = exports.get(packageName);
-				Map<String, String> exporterAttributes = classpathExports.get(packageName);
-				if (exporterAttributes == null)
-					continue;
-
-				for (Map.Entry<String, String> entry : exporterAttributes.entrySet()) {
-					String key = entry.getKey();
-					if (key.equalsIgnoreCase(SPECIFICATION_VERSION))
-						key = VERSION_ATTRIBUTE;
-					if (!key.endsWith(":") && !attributes.containsKey(key)) {
-						attributes.put(key, entry.getValue());
-					}
-				}
-
-				fixupAttributes(attributes);
-				removeAttributes(attributes);
-
-			} finally {
-				unsetProperty(CURRENT_PACKAGE);
-			}
-		}
-	}
-
-	/**
-	 * Fixup Attributes
-	 * 
-	 * Execute any macros on an export and
-	 */
-
-	void fixupAttributes(Map<String, String> attributes) {
-		// Convert any attribute values that have macros.
-		for (String key : attributes.keySet()) {
-			String value = attributes.get(key);
-			if (value.indexOf('$') >= 0) {
-				value = getReplacer().process(value);
-				attributes.put(key, value);
-			}
-		}
-
-	}
-
-	/*
-	 * Remove the attributes mentioned in the REMOVE_ATTRIBUTE_DIRECTIVE.
-	 */
-
-	void removeAttributes(Map<String, String> attributes) {
-		// You can add a remove-attribute: directive with a regular
-		// expression for attributes that need to be removed. We also
-		// remove all attributes that have a value of !. This allows
-		// you to use macros with ${if} to remove values.
-		String remove = attributes.remove(REMOVE_ATTRIBUTE_DIRECTIVE);
-		Instruction removeInstr = null;
-
-		if (remove != null)
-			removeInstr = Instruction.getPattern(remove);
-
-		for (Iterator<Map.Entry<String, String>> i = attributes.entrySet().iterator(); i.hasNext();) {
-			Map.Entry<String, String> entry = i.next();
-			if (entry.getValue().equals("!"))
-				i.remove();
-			else if (removeInstr != null && removeInstr.matches((String) entry.getKey()))
-				i.remove();
-			else {
-				// Not removed ...
-			}
-		}
-	}
-
-	/**
-	 * If we use an import with mandatory attributes we better all use them
-	 * 
-	 * @param currentAttributes
-	 * @param exporter
-	 */
-	private void augmentMandatory(Map<String, String> currentAttributes,
-			Map<String, String> exporter) {
-		String mandatory = (String) exporter.get("mandatory:");
-		if (mandatory != null) {
-			String[] attrs = mandatory.split("\\s*,\\s*");
-			for (int i = 0; i < attrs.length; i++) {
-				if (!currentAttributes.containsKey(attrs[i]))
-					currentAttributes.put(attrs[i], exporter.get(attrs[i]));
-			}
-		}
-	}
-
-	/**
-	 * Check if we can augment the version from the exporter.
-	 * 
-	 * We allow the version in the import to specify a @ which is replaced with
-	 * the exporter's version.
-	 * 
-	 * @param currentAttributes
-	 * @param exporter
-	 */
-	private void augmentVersion(Map<String, String> currentAttributes, Map<String, String> exporter) {
-
-		String exportVersion = (String) exporter.get(VERSION_ATTRIBUTE);
-		if (exportVersion == null)
-			return;
-
-		exportVersion = cleanupVersion(exportVersion);
-		String importRange = currentAttributes.get(VERSION_ATTRIBUTE);
-		boolean impl = isTrue(currentAttributes.get(PROVIDE_DIRECTIVE));
-		try {
-			setProperty("@", exportVersion);
-
-			if (importRange != null) {
-				importRange = cleanupVersion(importRange);
-				importRange = getReplacer().process(importRange);
-			} else
-				importRange = getVersionPolicy(impl);
-
-		} finally {
-			unsetProperty("@");
-		}
-		// See if we can borrow the version
-		// we must replace the ${@} with the version we
-		// found this can be useful if you want a range to start
-		// with the found version.
-		currentAttributes.put(VERSION_ATTRIBUTE, importRange);
-	}
-
-	/**
-	 * Calculate a version from a version policy.
-	 * 
-	 * @param version
-	 *            The actual exported version
-	 * @param impl
-	 *            true for implementations and false for clients
-	 */
-
-	String calculateVersionRange(String version, boolean impl) {
-		setProperty("@", version);
-		try {
-			return getVersionPolicy(impl);
-		} finally {
-			unsetProperty("@");
-		}
-	}
-
-	/**
-	 * Add the uses clauses. This method iterates over the exports and cal
-	 * 
-	 * @param exports
-	 * @param uses
-	 * @throws MojoExecutionException
-	 */
-	void doUses(Map<String, Map<String, String>> exports, Map<String, Set<String>> uses,
-			Map<String, Map<String, String>> imports) {
-		if ("true".equalsIgnoreCase(getProperty(NOUSES)))
-			return;
-
-		for (Iterator<String> i = exports.keySet().iterator(); i.hasNext();) {
-			String packageName = i.next();
-			setProperty(CURRENT_PACKAGE, packageName);
-			try {
-				doUses(packageName, exports, uses, imports);
-			} finally {
-				unsetProperty(CURRENT_PACKAGE);
-			}
-
-		}
-	}
-
-	/**
-	 * @param packageName
-	 * @param exports
-	 * @param uses
-	 * @param imports
-	 */
-	protected void doUses(String packageName, Map<String, Map<String, String>> exports,
-			Map<String, Set<String>> uses, Map<String, Map<String, String>> imports) {
-		Map<String, String> clause = exports.get(packageName);
-
-		// Check if someone already set the uses: directive
-		String override = clause.get(USES_DIRECTIVE);
-		if (override == null)
-			override = USES_USES;
-
-		// Get the used packages
-		Set<String> usedPackages = uses.get(packageName);
-
-		if (usedPackages != null) {
-
-			// Only do a uses on exported or imported packages
-			// and uses should also not contain our own package
-			// name
-			Set<String> sharedPackages = new HashSet<String>();
-			sharedPackages.addAll(imports.keySet());
-			sharedPackages.addAll(exports.keySet());
-			usedPackages.retainAll(sharedPackages);
-			usedPackages.remove(packageName);
-
-			StringBuffer sb = new StringBuffer();
-			String del = "";
-			for (Iterator<String> u = usedPackages.iterator(); u.hasNext();) {
-				String usedPackage = u.next();
-				if (!usedPackage.startsWith("java.")) {
-					sb.append(del);
-					sb.append(usedPackage);
-					del = ",";
-				}
-			}
-			if (override.indexOf('$') >= 0) {
-				setProperty(CURRENT_USES, sb.toString());
-				override = getReplacer().process(override);
-				unsetProperty(CURRENT_USES);
-			} else
-				// This is for backward compatibility 0.0.287
-				// can be deprecated over time
-				override = override.replaceAll(USES_USES, sb.toString()).trim();
-
-			if (override.endsWith(","))
-				override = override.substring(0, override.length() - 1);
-			if (override.startsWith(","))
-				override = override.substring(1);
-			if (override.length() > 0) {
-				clause.put(USES_DIRECTIVE, override);
-			}
-		}
-	}
-
-	/**
-	 * Transitively remove all elemens from unreachable through the uses link.
-	 * 
-	 * @param name
-	 * @param unreachable
-	 */
-	void removeTransitive(String name, Set<String> unreachable) {
-		if (!unreachable.contains(name))
-			return;
-
-		unreachable.remove(name);
-
-		Set<String> ref = uses.get(name);
-		if (ref != null) {
-			for (Iterator<String> r = ref.iterator(); r.hasNext();) {
-				String element = (String) r.next();
-				removeTransitive(element, unreachable);
-			}
-		}
-	}
-
-	/**
-	 * Helper method to set the package info
-	 * 
-	 * @param dir
-	 * @param key
-	 * @param value
-	 */
-	void setPackageInfo(String dir, String key, String value) {
-		if (value != null) {
-			String pack = dir.replace('/', '.');
-			Map<String, String> map = classpathExports.get(pack);
-			if (map == null) {
-				map = new HashMap<String, String>();
-				classpathExports.put(pack, map);
-			}
-			if (!map.containsKey(VERSION_ATTRIBUTE))
-				map.put(key, value);
-			else if (!map.get(VERSION_ATTRIBUTE).equals(value)) {
-				// System.out.println("duplicate version info for " + dir + " "
-				// + value + " and " + map.get(VERSION_ATTRIBUTE));
-			}
-		}
-	}
-
-	public void close() {
-		if (diagnostics) {
-			PrintStream out = System.out;
-			out.printf("Current directory            : %s\n", new File("").getAbsolutePath());
-			out.println("Classpath used");
-			for (Jar jar : getClasspath()) {
-				out.printf("File                                : %s\n", jar.getSource());
-				out.printf("File abs path                       : %s\n", jar.getSource()
-						.getAbsolutePath());
-				out.printf("Name                                : %s\n", jar.getName());
-				Map<String, Map<String, Resource>> dirs = jar.getDirectories();
-				for (Map.Entry<String, Map<String, Resource>> entry : dirs.entrySet()) {
-					Map<String, Resource> dir = entry.getValue();
-					String name = entry.getKey().replace('/', '.');
-					if (dir != null) {
-						out.printf("                                      %-30s %d\n", name,
-								dir.size());
-					} else {
-						out.printf("                                      %-30s <<empty>>\n", name);
-					}
-				}
-			}
-		}
-
-		super.close();
-		if (dot != null)
-			dot.close();
-
-		if (classpath != null)
-			for (Iterator<Jar> j = classpath.iterator(); j.hasNext();) {
-				Jar jar = j.next();
-				jar.close();
-			}
-	}
-
-	/**
-	 * Findpath looks through the contents of the JAR and finds paths that end
-	 * with the given regular expression
-	 * 
-	 * ${findpath (; reg-expr (; replacement)? )? }
-	 * 
-	 * @param args
-	 * @return
-	 */
-	public String _findpath(String args[]) {
-		return findPath("findpath", args, true);
-	}
-
-	public String _findname(String args[]) {
-		return findPath("findname", args, false);
-	}
-
-	String findPath(String name, String[] args, boolean fullPathName) {
-		if (args.length > 3) {
-			warning("Invalid nr of arguments to " + name + " " + Arrays.asList(args)
-					+ ", syntax: ${" + name + " (; reg-expr (; replacement)? )? }");
-			return null;
-		}
-
-		String regexp = ".*";
-		String replace = null;
-
-		switch (args.length) {
-		case 3:
-			replace = args[2];
-		case 2:
-			regexp = args[1];
-		}
-		StringBuffer sb = new StringBuffer();
-		String del = "";
-
-		Pattern expr = Pattern.compile(regexp);
-		for (Iterator<String> e = dot.getResources().keySet().iterator(); e.hasNext();) {
-			String path = e.next();
-			if (!fullPathName) {
-				int n = path.lastIndexOf('/');
-				if (n >= 0) {
-					path = path.substring(n + 1);
-				}
-			}
-
-			Matcher m = expr.matcher(path);
-			if (m.matches()) {
-				if (replace != null)
-					path = m.replaceAll(replace);
-
-				sb.append(del);
-				sb.append(path);
-				del = ", ";
-			}
-		}
-		return sb.toString();
-	}
-
-	public void putAll(Map<String, String> additional, boolean force) {
-		for (Iterator<Map.Entry<String, String>> i = additional.entrySet().iterator(); i.hasNext();) {
-			Map.Entry<String, String> entry = i.next();
-			if (force || getProperties().get(entry.getKey()) == null)
-				setProperty((String) entry.getKey(), (String) entry.getValue());
-		}
-	}
-
-	boolean	firstUse	= true;
-
-	public List<Jar> getClasspath() {
-		if (firstUse) {
-			firstUse = false;
-			String cp = getProperty(CLASSPATH);
-			if (cp != null)
-				for (String s : split(cp)) {
-					Jar jar = getJarFromName(s, "getting classpath");
-					if (jar != null)
-						addClasspath(jar);
-					else
-						warning("Cannot find entry on -classpath: %s", s);
-				}
-		}
-		return classpath;
-	}
-
-	public void addClasspath(Jar jar) {
-		if (isPedantic() && jar.getResources().isEmpty())
-			warning("There is an empty jar or directory on the classpath: " + jar.getName());
-
-		classpath.add(jar);
-	}
-
-	public void addClasspath(File cp) throws IOException {
-		if (!cp.exists())
-			warning("File on classpath that does not exist: " + cp);
-		Jar jar = new Jar(cp);
-		addClose(jar);
-		classpath.add(jar);
-	}
-
-	public void clear() {
-		classpath.clear();
-	}
-
-	public Jar getTarget() {
-		return dot;
-	}
-
-	protected Map<String, Clazz> analyzeBundleClasspath(Jar dot,
-			Map<String, Map<String, String>> bundleClasspath,
-			Map<String, Map<String, String>> contained, Map<String, Map<String, String>> referred,
-			Map<String, Set<String>> uses) throws Exception {
-		Map<String, Clazz> classSpace = new HashMap<String, Clazz>();
-		Set<String> hide = Create.set();
-		boolean containsDirectory = false;
-
-		for (String path : bundleClasspath.keySet()) {
-			if (dot.getDirectories().containsKey(path)) {
-				containsDirectory = true;
-				break;
-			}
-		}
-
-		if (bundleClasspath.isEmpty()) {
-			analyzeJar(dot, "", classSpace, contained, referred, uses, hide, true);
-		} else {
-			for (String path : bundleClasspath.keySet()) {
-				Map<String, String> info = bundleClasspath.get(path);
-
-				if (path.equals(".")) {
-					analyzeJar(dot, "", classSpace, contained, referred, uses, hide,
-							!containsDirectory);
-					continue;
-				}
-				//
-				// There are 3 cases:
-				// - embedded JAR file
-				// - directory
-				// - error
-				//
-
-				Resource resource = dot.getResource(path);
-				if (resource != null) {
-					try {
-						Jar jar = new Jar(path);
-						addClose(jar);
-						EmbeddedResource.build(jar, resource);
-						analyzeJar(jar, "", classSpace, contained, referred, uses, hide, true);
-					} catch (Exception e) {
-						warning("Invalid bundle classpath entry: " + path + " " + e);
-					}
-				} else {
-					if (dot.getDirectories().containsKey(path)) {
-						// if directories are used, we should not have dot as we
-						// would have the classes in these directories on the
-						// class
-						// path twice.
-						if (bundleClasspath.containsKey("."))
-							warning("Bundle-ClassPath uses a directory '%s' as well as '.', this implies the directory is seen \n"
-									+ "twice by the class loader. bnd assumes that the classes are only "
-									+ "loaded from '%s'. It is better to unroll the directory to create a flat bundle.",
-									path, path);
-						analyzeJar(dot, Processor.appendPath(path) + "/", classSpace, contained,
-								referred, uses, hide, true);
-					} else {
-						if (!"optional".equals(info.get(RESOLUTION_DIRECTIVE)))
-							warning("No sub JAR or directory " + path);
-					}
-				}
-			}
-
-			for (Clazz c : classSpace.values()) {
-				formats.add(c.getFormat());
-			}
-		}
-		return classSpace;
-	}
-
-	/**
-	 * We traverse through all the classes that we can find and calculate the
-	 * contained and referred set and uses. This method ignores the Bundle
-	 * classpath.
-	 * 
-	 * @param jar
-	 * @param contained
-	 * @param referred
-	 * @param uses
-	 * @throws IOException
-	 */
-	private void analyzeJar(Jar jar, String prefix, Map<String, Clazz> classSpace,
-			Map<String, Map<String, String>> contained, Map<String, Map<String, String>> referred,
-			Map<String, Set<String>> uses, Set<String> hide, boolean reportWrongPath)
-			throws Exception {
-
-		next: for (String path : jar.getResources().keySet()) {
-			if (path.startsWith(prefix) /* && !hide.contains(path) */) {
-				hide.add(path);
-				String relativePath = path.substring(prefix.length());
-
-				// // TODO this check (and the whole hide) is likely redundant
-				// // it only protects against repeated checks for non-class
-				// // bundle resources, but should not affect results otherwise.
-				// if (!hide.add(relativePath)) {
-				// continue;
-				// }
-
-				// Check if we'd already had this one.
-				// Notice that we're flattening the space because
-				// this is what class loaders do.
-				if (classSpace.containsKey(relativePath))
-					continue;
-
-				String pack = getPackage(relativePath);
-
-				if (pack != null && !contained.containsKey(pack)) {
-					// For each package we encounter for the first
-					// time
-					if (!isMetaData(relativePath)) {
-
-						Map<String, String> info = newMap();
-						contained.put(pack, info);
-
-						Resource pinfo = jar.getResource(prefix + pack.replace('.', '/')
-								+ "/packageinfo");
-						if (pinfo != null) {
-							InputStream in = pinfo.openInputStream();
-							String version;
-							try {
-								version = parsePackageInfo(in);
-							} finally {
-								in.close();
-							}
-							if (version != null)
-								info.put(VERSION_ATTRIBUTE, version);
-						}
-					}
-				}
-
-				// Check class resources, we need to analyze them
-				if (path.endsWith(".class")) {
-					Resource resource = jar.getResource(path);
-					Clazz clazz;
-
-					try {
-						InputStream in = resource.openInputStream();
-						clazz = new Clazz(relativePath, resource);
-						try {
-							// Check if we have a package-info
-							if (relativePath.endsWith("/package-info.class")) {
-								// package-info can contain an Export annotation
-								Map<String, String> info = contained.get(pack);
-								parsePackageInfoClass(clazz, info);
-							} else {
-								// Otherwise we just parse it simply
-								clazz.parseClassFile();
-							}
-						} finally {
-							in.close();
-						}
-					} catch (Throwable e) {
-						error("Invalid class file: " + relativePath, e);
-						e.printStackTrace();
-						continue next;
-					}
-
-					String calculatedPath = clazz.getClassName() + ".class";
-					if (!calculatedPath.equals(relativePath)) {
-						if (!isNoBundle() && reportWrongPath) {
-							error("Class in different directory than declared. Path from class name is "
-									+ calculatedPath
-									+ " but the path in the jar is "
-									+ relativePath + " from '" + jar + "'");
-						}
-					}
-
-					classSpace.put(relativePath, clazz);
-
-					// Look at the referred packages
-					// and copy them to our baseline
-					for (String p : clazz.getReferred()) {
-						Map<String, String> attrs = referred.get(p);
-						if (attrs == null) {
-							attrs = newMap();
-							referred.put(p, attrs);
-						}
-					}
-
-					// Add all the used packages
-					// to this package
-					Set<String> t = uses.get(pack);
-					if (t == null)
-						uses.put(pack, t = new LinkedHashSet<String>());
-					t.addAll(clazz.getReferred());
-					t.remove(pack);
-				}
-			}
-		}
-	}
-
-	static Pattern	OBJECT_REFERENCE	= Pattern.compile("L([^/]+/)*([^;]+);");
-
-	private void parsePackageInfoClass(final Clazz clazz, final Map<String, String> info)
-			throws Exception {
-		clazz.parseClassFileWithCollector(new ClassDataCollector() {
-			@Override public void annotation(Annotation a) {
-				if (a.name.equals(Clazz.toDescriptor(aQute.bnd.annotation.Version.class))) {
-
-					// Check version
-					String version = a.get("value");
-					if (!info.containsKey(Constants.VERSION_ATTRIBUTE)) {
-						if (version != null) {
-							version = getReplacer().process(version);
-							if (Verifier.VERSION.matcher(version).matches())
-								info.put(VERSION_ATTRIBUTE, version);
-							else
-								error("Export annotatio in %s has invalid version info: %s", clazz,
-										version);
-						}
-					} else {
-						// Verify this matches with packageinfo
-						String presentVersion = info.get(VERSION_ATTRIBUTE);
-						try {
-							Version av = new Version(presentVersion);
-							Version bv = new Version(version);
-							if (!av.equals(bv)) {
-								error("Version from annotation for %s differs with packageinfo or Manifest",
-										Clazz.getPackage(clazz.className));
-							}
-						} catch (Exception e) {
-							// Ignore
-						}
-					}
-				} else if (a.name.equals(Clazz.toDescriptor(Export.class))) {
-
-					// Check mandatory attributes
-					Map<String, String> attrs = doAttrbutes((Object[]) a.get(Export.MANDATORY),
-							clazz, getReplacer());
-					if (!attrs.isEmpty()) {
-						info.putAll(attrs);
-						info.put(MANDATORY_DIRECTIVE, Processor.join(attrs.keySet()));
-					}
-
-					// Check optional attributes
-					attrs = doAttrbutes((Object[]) a.get(Export.OPTIONAL), clazz, getReplacer());
-					if (!attrs.isEmpty()) {
-						info.putAll(attrs);
-					}
-
-					// Check Included classes
-					Object[] included = a.get(Export.INCLUDE);
-					if (included != null && included.length > 0) {
-						StringBuilder sb = new StringBuilder();
-						String del = "";
-						for (Object i : included) {
-							Matcher m = OBJECT_REFERENCE.matcher((String) i);
-							if (m.matches()) {
-								sb.append(del);
-								sb.append(m.group(2));
-								del = ",";
-							}
-						}
-						info.put(INCLUDE_DIRECTIVE, sb.toString());
-					}
-
-					// Check Excluded classes
-					Object[] excluded = a.get(Export.EXCLUDE);
-					if (excluded != null && excluded.length > 0) {
-						StringBuilder sb = new StringBuilder();
-						String del = "";
-						for (Object i : excluded) {
-							Matcher m = OBJECT_REFERENCE.matcher((String) i);
-							if (m.matches()) {
-								sb.append(del);
-								sb.append(m.group(2));
-								del = ",";
-							}
-						}
-						info.put(EXCLUDE_DIRECTIVE, sb.toString());
-					}
-
-					// Check Uses
-					Object[] uses = a.get(Export.USES);
-					if (uses != null && uses.length > 0) {
-						String old = info.get(USES_DIRECTIVE);
-						if (old == null)
-							old = "";
-						StringBuilder sb = new StringBuilder(old);
-						String del = sb.length() == 0 ? "" : ",";
-
-						for (Object use : uses) {
-							sb.append(del);
-							sb.append(use);
-							del = ",";
-						}
-						info.put(USES_DIRECTIVE, sb.toString());
-					}
-				}
-			}
-
-		});
-	}
-
-	/**
-	 * Clean up version parameters. Other builders use more fuzzy definitions of
-	 * the version syntax. This method cleans up such a version to match an OSGi
-	 * version.
-	 * 
-	 * @param VERSION_STRING
-	 * @return
-	 */
-	static Pattern	fuzzyVersion		= Pattern
-												.compile(
-														"(\\d+)(\\.(\\d+)(\\.(\\d+))?)?([^a-zA-Z0-9](.*))?",
-														Pattern.DOTALL);
-	static Pattern	fuzzyVersionRange	= Pattern
-												.compile(
-														"(\\(|\\[)\\s*([-\\da-zA-Z.]+)\\s*,\\s*([-\\da-zA-Z.]+)\\s*(\\]|\\))",
-														Pattern.DOTALL);
-	static Pattern	fuzzyModifier		= Pattern.compile("(\\d+[.-])*(.*)", Pattern.DOTALL);
-
-	static Pattern	nummeric			= Pattern.compile("\\d*");
-
-	static public String cleanupVersion(String version) {
-		Matcher m = Verifier.VERSIONRANGE.matcher(version);
-
-		if (m.matches()) {
-			return version;
-		}
-
-		m = fuzzyVersionRange.matcher(version);
-		if (m.matches()) {
-			String prefix = m.group(1);
-			String first = m.group(2);
-			String last = m.group(3);
-			String suffix = m.group(4);
-			return prefix + cleanupVersion(first) + "," + cleanupVersion(last) + suffix;
-		} else {
-			m = fuzzyVersion.matcher(version);
-			if (m.matches()) {
-				StringBuffer result = new StringBuffer();
-				String major = removeLeadingZeroes(m.group(1));
-				String minor = removeLeadingZeroes(m.group(3));
-				String micro = removeLeadingZeroes(m.group(5));
-				String qualifier = m.group(7);
-
-				if (major != null) {
-					result.append(major);
-					if (minor != null) {
-						result.append(".");
-						result.append(minor);
-						if (micro != null) {
-							result.append(".");
-							result.append(micro);
-							if (qualifier != null) {
-								result.append(".");
-								cleanupModifier(result, qualifier);
-							}
-						} else if (qualifier != null) {
-							result.append(".0.");
-							cleanupModifier(result, qualifier);
-						}
-					} else if (qualifier != null) {
-						result.append(".0.0.");
-						cleanupModifier(result, qualifier);
-					}
-					return result.toString();
-				}
-			}
-		}
-		return version;
-	}
-
-	private static String removeLeadingZeroes(String group) {
-		int n = 0;
-		while (group != null && n < group.length() - 1 && group.charAt(n) == '0')
-			n++;
-		if (n == 0)
-			return group;
-
-		return group.substring(n);
-	}
-
-	static void cleanupModifier(StringBuffer result, String modifier) {
-		Matcher m = fuzzyModifier.matcher(modifier);
-		if (m.matches())
-			modifier = m.group(2);
-
-		for (int i = 0; i < modifier.length(); i++) {
-			char c = modifier.charAt(i);
-			if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
-					|| c == '_' || c == '-')
-				result.append(c);
-		}
-	}
-
-	/**
-	 * Decide if the package is a metadata package.
-	 * 
-	 * @param pack
-	 * @return
-	 */
-	boolean isMetaData(String pack) {
-		for (int i = 0; i < METAPACKAGES.length; i++) {
-			if (pack.startsWith(METAPACKAGES[i]))
-				return true;
-		}
-		return false;
-	}
-
-	public String getPackage(String clazz) {
-		int n = clazz.lastIndexOf('/');
-		if (n < 0)
-			return ".";
-		return clazz.substring(0, n).replace('/', '.');
-	}
-
-	//
-	// We accept more than correct OSGi versions because in a later
-	// phase we actually cleanup maven versions. But it is a bit yucky
-	//
-	static String parsePackageInfo(InputStream jar) throws IOException {
-		try {
-			Properties p = new Properties();
-			p.load(jar);
-			jar.close();
-			if (p.containsKey("version")) {
-				return p.getProperty("version");
-			}
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
-		return null;
-	}
-
-	final static String	DEFAULT_PROVIDER_POLICY	= "${range;[==,=+)}";
-	final static String	DEFAULT_CONSUMER_POLICY	= "${range;[==,+)}";
-
-	@SuppressWarnings("deprecation") public String getVersionPolicy(boolean implemented) {
-		if (implemented) {
-			String s = getProperty(PROVIDER_POLICY);
-			if (s != null)
-				return s;
-
-			s = getProperty(VERSIONPOLICY_IMPL);
-			if (s != null)
-				return s;
-
-			return getProperty(VERSIONPOLICY, DEFAULT_PROVIDER_POLICY);
-		} else {
-			String s = getProperty(CONSUMER_POLICY);
-			if (s != null)
-				return s;
-
-			s = getProperty(VERSIONPOLICY_USES);
-			if (s != null)
-				return s;
-
-			return getProperty(VERSIONPOLICY, DEFAULT_CONSUMER_POLICY);
-		}
-		// String vp = implemented ? getProperty(VERSIONPOLICY_IMPL) :
-		// getProperty(VERSIONPOLICY_USES);
-		//
-		// if (vp != null)
-		// return vp;
-		//
-		// if (implemented)
-		// return getProperty(VERSIONPOLICY_IMPL, "{$range;[==,=+}");
-		// else
-		// return getProperty(VERSIONPOLICY, "${range;[==,+)}");
-	}
-
-	/**
-	 * The extends macro traverses all classes and returns a list of class names
-	 * that extend a base class.
-	 */
-
-	static String	_classesHelp	= "${classes;'implementing'|'extending'|'importing'|'named'|'version'|'any';<pattern>}, Return a list of class fully qualified class names that extend/implement/import any of the contained classes matching the pattern\n";
-
-	public String _classes(String... args) throws Exception {
-		// Macro.verifyCommand(args, _classesHelp, new
-		// Pattern[]{null,Pattern.compile("(implementing|implements|extending|extends|importing|imports|any)"),
-		// null}, 3,3);
-
-		Collection<Clazz> matched = getClasses(args);
-		if (matched.isEmpty())
-			return "";
-
-		return join(matched);
-	}
-
-	public Collection<Clazz> getClasses(String... args) throws Exception {
-
-		Set<Clazz> matched = new HashSet<Clazz>(classspace.values());
-		for (int i = 1; i < args.length; i++) {
-			if (args.length < i + 1)
-				throw new IllegalArgumentException(
-						"${classes} macro must have odd number of arguments. " + _classesHelp);
-
-			String typeName = args[i];
-			if (typeName.equalsIgnoreCase("extending"))
-				typeName = "extends";
-			else if (typeName.equalsIgnoreCase("importing"))
-				typeName = "imports";
-			else if (typeName.equalsIgnoreCase("implementing"))
-				typeName = "implements";
-
-			Clazz.QUERY type = Clazz.QUERY.valueOf(typeName.toUpperCase());
-
-			if (type == null)
-				throw new IllegalArgumentException("${classes} has invalid type: " + typeName
-						+ ". " + _classesHelp);
-
-			Instruction instr = null;
-			if (Clazz.HAS_ARGUMENT.contains(type)) {
-				StringBuilder sb = new StringBuilder();
-				String s = args[++i];
-				if (type == QUERY.ANNOTATION) {
-					// Annotations use the descriptor format ...
-					// But at least they're always an object
-					sb.append("L");
-					for (int ci = 0; ci < s.length(); ci++) {
-						char c = s.charAt(ci);
-						if (c == '.')
-							sb.append("/");
-						else
-							sb.append(c);
-					}
-					sb.append(';');
-				} else {
-					// The argument is declared as a dotted name but the classes
-					// use a slashed named. So convert the name before we make
-					// it a instruction. We also have to take into account
-					// that some classes are nested and use $ for separator
-					for (int ci = 0; ci < s.length(); ci++) {
-						char c = s.charAt(ci);
-						if (c == '.')
-							sb.append("(/|\\$)");
-						else
-							sb.append(c);
-					}
-				}
-				instr = Instruction.getPattern(sb.toString());
-			}
-			for (Iterator<Clazz> c = matched.iterator(); c.hasNext();) {
-				Clazz clazz = c.next();
-				if (!clazz.is(type, instr, this)) {
-					c.remove();
-				}
-			}
-		}
-		return matched;
-	}
-
-	/**
-	 * Get the exporter of a package ...
-	 */
-
-	public String _exporters(String args[]) throws Exception {
-		Macro.verifyCommand(
-				args,
-				"${exporters;<packagename>}, returns the list of jars that export the given package",
-				null, 2, 2);
-		StringBuilder sb = new StringBuilder();
-		String del = "";
-		String pack = args[1].replace('.', '/');
-		for (Jar jar : classpath) {
-			if (jar.getDirectories().containsKey(pack)) {
-				sb.append(del);
-				sb.append(jar.getName());
-			}
-		}
-		return sb.toString();
-	}
-
-	public Map<String, Clazz> getClassspace() {
-		return classspace;
-	}
-
-	/**
-	 * Locate a resource on the class path.
-	 * 
-	 * @param path
-	 *            Path of the reosurce
-	 * @return A resource or <code>null</code>
-	 */
-	public Resource findResource(String path) {
-		for (Jar entry : getClasspath()) {
-			Resource r = entry.getResource(path);
-			if (r != null)
-				return r;
-		}
-		return null;
-	}
-
-	/**
-	 * Find a clazz on the class path. This class has been parsed.
-	 * 
-	 * @param path
-	 * @return
-	 */
-	public Clazz findClass(String path) throws Exception {
-		Clazz c = classspace.get(path);
-		if (c != null)
-			return c;
-
-		c = importedClassesCache.get(path);
-		if (c != null)
-			return c;
-
-		Resource r = findResource(path);
-		if (r != null) {
-			c = new Clazz(path, r);
-			c.parseClassFile();
-			importedClassesCache.put(path, c);
-		}
-		return c;
-	}
-
-	/**
-	 * Answer the bundle version.
-	 * 
-	 * @return
-	 */
-	public String getVersion() {
-		String version = getProperty(BUNDLE_VERSION);
-		if (version == null)
-			version = "0.0.0";
-		return version;
-	}
-
-	public boolean isNoBundle() {
-		return isTrue(getProperty(RESOURCEONLY)) || isTrue(getProperty(NOMANIFEST));
-	}
-
-	public void referTo(String impl) {
-		String pack = Clazz.getPackage(impl);
-		if (!referred.containsKey(pack))
-			referred.put(pack, new LinkedHashMap<String, String>());
-	}
-
-	/**
-	 * Calculate the groups inside the bundle. A group consists of packages that
-	 * have a reference to each other.
-	 */
-
-	public MultiMap<Set<String>, String> getGroups() {
-		MultiMap<String, String> map = new MultiMap<String, String>();
-		Set<String> keys = uses.keySet();
-
-		for (Map.Entry<String, Set<String>> entry : uses.entrySet()) {
-			Set<String> newSet = new HashSet<String>(entry.getValue());
-			newSet.retainAll(keys);
-			map.put(entry.getKey(), newSet);
-		}
-
-		// Calculate strongly connected packages
-		Set<Set<String>> scc = Tarjan.tarjan(map);
-
-		MultiMap<Set<String>, String> grouped = new MultiMap<Set<String>, String>();
-		for (Set<String> group : scc) {
-			for (String p : group) {
-				grouped.addAll(group, uses.get(p));
-			}
-		}
-		return grouped;
-	}
-
-	/**
-	 * Ensure that we are running on the correct bnd.
-	 */
-	void doRequireBnd() {
-		Map<String, String> require = OSGiHeader.parseProperties(getProperty(REQUIRE_BND));
-		if (require == null || require.isEmpty())
-			return;
-
-		Hashtable<String, String> map = new Hashtable<String, String>();
-		map.put(Constants.VERSION_FILTER, getBndVersion());
-
-		for (String filter : require.keySet()) {
-			try {
-				Filter f = new Filter(filter);
-				if (f.match(map))
-					continue;
-				error("%s fails %s", REQUIRE_BND, require.get(filter));
-			} catch (Exception t) {
-				error("%s with value %s throws exception", t, REQUIRE_BND, require);
-			}
-		}
-	}
-
-	/**
-	 * md5 macro
-	 */
-
-	static String	_md5Help	= "${md5;path}";
-
-	public String _md5(String args[]) throws Exception {
-		Macro.verifyCommand(args, _md5Help,
-				new Pattern[] { null, null, Pattern.compile("base64|hex") }, 2, 3);
-
-		Digester<MD5> digester = MD5.getDigester();
-		Resource r = dot.getResource(args[1]);
-		if (r == null)
-			throw new FileNotFoundException("From " + digester + ", not found " + args[1]);
-
-		IO.copy(r.openInputStream(), digester);
-		boolean hex = args.length > 2 && args[2].equals("hex");
-		if (hex)
-			return Hex.toHexString(digester.digest().digest());
-		else
-			return Base64.encodeBase64(digester.digest().digest());
-	}
-
-	/**
-	 * SHA1 macro
-	 */
-
-	static String	_sha1Help	= "${sha1;path}";
-
-	public String _sha1(String args[]) throws Exception {
-		Macro.verifyCommand(args, _sha1Help,
-				new Pattern[] { null, null, Pattern.compile("base64|hex") }, 2, 3);
-		Digester<SHA1> digester = SHA1.getDigester();
-		Resource r = dot.getResource(args[1]);
-		if (r == null)
-			throw new FileNotFoundException("From sha1, not found " + args[1]);
-
-		IO.copy(r.openInputStream(), digester);
-		return Base64.encodeBase64(digester.digest().digest());
-	}
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/Annotation.java b/biz.aQute.bndlib/src/aQute/lib/osgi/Annotation.java
deleted file mode 100644
index e2b7ed2..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/Annotation.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package aQute.lib.osgi;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import aQute.bnd.annotation.metatype.*;
-
-public class Annotation {
-	String				name;
-	Map<String, Object>	elements;
-	ElementType			member;
-	RetentionPolicy		policy;
-
-	public Annotation(String name, Map<String, Object> elements, ElementType member,
-			RetentionPolicy policy) {
-		this.name = name;
-		if ( elements == null)
-			this.elements = Collections.emptyMap();
-		else
-			this.elements = elements;
-		this.member = member;
-		this.policy = policy;
-	}
-
-	public String getName() {
-		return name;
-	}
-
-	public ElementType getElementType() {
-		return member;
-	}
-	
-	public RetentionPolicy getRetentionPolicy() {
-		return policy;
-	}
-	
-	public String toString() {
-		return name + ":" + member + ":" + policy + ":" + elements;
-	}
-
-	@SuppressWarnings("unchecked") public <T> T get(String string) {
-		if (elements == null)
-			return null;
-
-		return (T) elements.get(string);
-	}
-
-	public <T> void put(String string, Object v) {
-		if (elements == null)
-			return;
-
-		elements.put(string, v);
-	}
-
-	public Set<String> keySet() {
-		if (elements == null)
-			return Collections.emptySet();
-		
-		return elements.keySet();
-	}
-	@SuppressWarnings("unchecked") public <T extends java.lang.annotation.Annotation> T getAnnotation() throws Exception {
-		String cname = Clazz.objectDescriptorToFQN(name);
-		Class<T> c = (Class<T>) getClass().getClassLoader().loadClass(cname);
-		return getAnnotation(c);
-	}
-	public <T extends java.lang.annotation.Annotation> T getAnnotation(Class<T> c)
-			throws Exception {
-		String cname = Clazz.objectDescriptorToFQN(name);
-		if ( ! c.getName().equals(cname))
-			return null;
-		return Configurable.createConfigurable(c, elements );
-	}
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/Builder.java b/biz.aQute.bndlib/src/aQute/lib/osgi/Builder.java
deleted file mode 100755
index cf4d389..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/Builder.java
+++ /dev/null
@@ -1,1220 +0,0 @@
-package aQute.lib.osgi;
-
-import java.io.*;
-import java.util.*;
-import java.util.jar.*;
-import java.util.regex.*;
-import java.util.zip.*;
-
-import aQute.bnd.component.*;
-import aQute.bnd.make.*;
-import aQute.bnd.make.component.*;
-import aQute.bnd.make.metatype.*;
-import aQute.bnd.maven.*;
-import aQute.bnd.service.*;
-
-/**
- * Include-Resource: ( [name '=' ] file )+
- * 
- * Private-Package: package-decl ( ',' package-decl )*
- * 
- * Export-Package: package-decl ( ',' package-decl )*
- * 
- * Import-Package: package-decl ( ',' package-decl )*
- * 
- * @version $Revision: 1.27 $
- */
-public class Builder extends Analyzer {
-	Pattern						xdoNotCopy			= null;
-	private static final int	SPLIT_MERGE_LAST	= 1;
-	private static final int	SPLIT_MERGE_FIRST	= 2;
-	private static final int	SPLIT_ERROR			= 3;
-	private static final int	SPLIT_FIRST			= 4;
-	private static final int	SPLIT_DEFAULT		= 0;
-
-	List<File>					sourcePath			= new ArrayList<File>();
-
-	Make						make				= new Make(this);
-
-	public Builder(Processor parent) {
-		super(parent);
-	}
-
-	public Builder() {
-	}
-
-	public Jar build() throws Exception {
-		init();
-		if (isTrue(getProperty(NOBUNDLES)))
-			return null;
-
-		if (getProperty(CONDUIT) != null)
-			error("Specified " + CONDUIT
-					+ " but calls build() instead of builds() (might be a programmer error");
-
-		dot = new Jar("dot");
-		addClose(dot);
-		try {
-			long modified = Long.parseLong(getProperty("base.modified"));
-			dot.updateModified(modified, "Base modified");
-		} catch (Exception e) {
-		}
-
-		doExpand(dot);
-		doIncludeResources(dot);
-		doConditional(dot);
-		dot = doWab(dot);
-
-		// NEW!
-		// Check if we override the calculation of the
-		// manifest. We still need to calculated it because
-		// we need to have analyzed the classpath.
-
-		Manifest manifest = calcManifest();
-
-		String mf = getProperty(MANIFEST);
-		if (mf != null) {
-			File mff = getFile(mf);
-			if (mff.isFile()) {
-				try {
-					InputStream in = new FileInputStream(mff);
-					manifest = new Manifest(in);
-					in.close();
-				} catch (Exception e) {
-					error(MANIFEST + " while reading manifest file", e);
-				}
-			} else {
-				error(MANIFEST + ", no such file " + mf);
-			}
-		}
-
-		if (getProperty(NOMANIFEST) == null)
-			dot.setManifest(manifest);
-		else
-			dot.setDoNotTouchManifest();
-
-		// This must happen after we analyzed so
-		// we know what it is on the classpath
-		addSources(dot);
-
-		if (getProperty(POM) != null)
-			dot.putResource("pom.xml", new PomResource(dot.getManifest()));
-
-		if (!isNoBundle())
-			doVerify(dot);
-
-		if (dot.getResources().isEmpty())
-			error("The JAR is empty: " + dot.getName());
-
-		dot.updateModified(lastModified(), "Last Modified Processor");
-		dot.setName(getBsn());
-
-		sign(dot);
-
-		doSaveManifest(dot);
-		return dot;
-	}
-
-	/**
-	 * Allow any local initialization by subclasses before we build.
-	 */
-	public void init() throws Exception {
-		begin();
-		doRequireBnd();
-	}
-
-	/**
-	 * Turn this normal bundle in a web and add any resources.
-	 * 
-	 * @throws Exception
-	 */
-	private Jar doWab(Jar dot) throws Exception {
-		String wab = getProperty(WAB);
-		String wablib = getProperty(WABLIB);
-		if (wab == null && wablib == null)
-			return dot;
-
-		setProperty(BUNDLE_CLASSPATH, append("WEB-INF/classes", getProperty(BUNDLE_CLASSPATH)));
-
-		Jar next = new Jar(dot.getName());
-		addClose(next);
-
-		for (Map.Entry<String, Resource> entry : dot.getResources().entrySet()) {
-			String path = entry.getKey();
-			if (path.indexOf('/') > 0 && !Character.isUpperCase(path.charAt(0))) {
-				trace("wab: moving: %s", path);
-				next.putResource("WEB-INF/classes/" + path, entry.getValue());
-			} else {
-				trace("wab: not moving: %s", path);
-				next.putResource(path, entry.getValue());
-			}
-		}
-
-		Map<String, Map<String, String>> clauses = parseHeader(getProperty(WABLIB));
-		for (String key : clauses.keySet()) {
-			File f = getFile(key);
-			addWabLib(next, f);
-		}
-		doIncludeResource(next, wab);
-		return next;
-	}
-
-	/**
-	 * Add a wab lib to the jar.
-	 * 
-	 * @param f
-	 */
-	private void addWabLib(Jar dot, File f) throws Exception {
-		if (f.exists()) {
-			Jar jar = new Jar(f);
-			jar.setDoNotTouchManifest();
-			addClose(jar);
-			String path = "WEB-INF/lib/" + f.getName();
-			dot.putResource(path, new JarResource(jar));
-			setProperty(BUNDLE_CLASSPATH, append(getProperty(BUNDLE_CLASSPATH), path));
-
-			Manifest m = jar.getManifest();
-			String cp = m.getMainAttributes().getValue("Class-Path");
-			if (cp != null) {
-				Collection<String> parts = split(cp, ",");
-				for (String part : parts) {
-					File sub = getFile(f.getParentFile(), part);
-					if (!sub.exists() || !sub.getParentFile().equals(f.getParentFile())) {
-						warning("Invalid Class-Path entry %s in %s, must exist and must reside in same directory",
-								sub, f);
-					} else {
-						addWabLib(dot, sub);
-					}
-				}
-			}
-		} else {
-			error("WAB lib does not exist %s", f);
-		}
-	}
-
-	/**
-	 * Get the manifest and write it out separately if -savemanifest is set
-	 * 
-	 * @param dot
-	 */
-	private void doSaveManifest(Jar dot) throws Exception {
-		String output = getProperty(SAVEMANIFEST);
-		if (output == null)
-			return;
-
-		File f = getFile(output);
-		if (f.isDirectory()) {
-			f = new File(f, "MANIFEST.MF");
-		}
-		f.delete();
-		f.getParentFile().mkdirs();
-		OutputStream out = new FileOutputStream(f);
-		try {
-			Jar.writeManifest(dot.getManifest(), out);
-		} finally {
-			out.close();
-		}
-		changedFile(f);
-	}
-
-	protected void changedFile(File f) {
-	}
-
-	/**
-	 * Sign the jar file.
-	 * 
-	 * -sign : <alias> [ ';' 'password:=' <password> ] [ ';' 'keystore:='
-	 * <keystore> ] [ ';' 'sign-password:=' <pw> ] ( ',' ... )*
-	 * 
-	 * @return
-	 */
-
-	void sign(Jar jar) throws Exception {
-		String signing = getProperty("-sign");
-		if (signing == null)
-			return;
-
-		trace("Signing %s, with %s", getBsn(), signing);
-		List<SignerPlugin> signers = getPlugins(SignerPlugin.class);
-
-		Map<String, Map<String, String>> infos = parseHeader(signing);
-		for (Map.Entry<String, Map<String, String>> entry : infos.entrySet()) {
-			for (SignerPlugin signer : signers) {
-				signer.sign(this, entry.getKey());
-			}
-		}
-	}
-
-	public boolean hasSources() {
-		return isTrue(getProperty(SOURCES));
-	}
-
-	protected String getImportPackages() {
-		String ip = super.getImportPackages();
-		if (ip != null)
-			return ip;
-
-		return "*";
-	}
-
-	private void doConditional(Jar dot) throws Exception {
-		Map<String, Map<String, String>> conditionals = getHeader(CONDITIONAL_PACKAGE);
-		if (conditionals.isEmpty())
-			return;
-
-		while (true) {
-			analyze();
-			Map<String, Map<String, String>> imports = getImports();
-
-			// Match the packages specified in conditionals
-			// against the imports. Any match must become a
-			// Private-Package
-			Map<String, Map<String, String>> filtered = merge(CONDITIONAL_PACKAGE, conditionals,
-					imports, new HashSet<String>(), null);
-
-			// Imports can also specify a private import. These
-			// packages must also be copied to the bundle
-			for (Map.Entry<String, Map<String, String>> entry : getImports().entrySet()) {
-				String type = entry.getValue().get(IMPORT_DIRECTIVE);
-				if (type != null && type.equals(PRIVATE_DIRECTIVE))
-					filtered.put(entry.getKey(), entry.getValue());
-			}
-
-			// remove existing packages to prevent merge errors
-			filtered.keySet().removeAll(dot.getPackages());
-			if (filtered.size() == 0)
-				break;
-
-			int size = dot.getResources().size();
-			doExpand(dot, CONDITIONAL_PACKAGE + " Private imports",
-					Instruction.replaceWithInstruction(filtered), false);
-
-			// Were there any expansions?
-			if (size == dot.getResources().size())
-				break;
-
-			analyzed = false;
-		}
-	}
-
-	/**
-	 * Intercept the call to analyze and cleanup versions after we have analyzed
-	 * the setup. We do not want to cleanup if we are going to verify.
-	 */
-
-	public void analyze() throws Exception {
-		super.analyze();
-		cleanupVersion(imports, null);
-		cleanupVersion(exports, getVersion());
-		String version = getProperty(BUNDLE_VERSION);
-		if (version != null) {
-			version = cleanupVersion(version);
-			if (version.endsWith(".SNAPSHOT")) {
-				version = version.replaceAll("SNAPSHOT$", getProperty(SNAPSHOT, "SNAPSHOT"));
-			}
-			setProperty(BUNDLE_VERSION, version);
-		}
-	}
-
-	public void cleanupVersion(Map<String, Map<String, String>> mapOfMap, String defaultVersion) {
-		for (Iterator<Map.Entry<String, Map<String, String>>> e = mapOfMap.entrySet().iterator(); e
-				.hasNext();) {
-			Map.Entry<String, Map<String, String>> entry = e.next();
-			Map<String, String> attributes = entry.getValue();
-			String v = attributes.get(Constants.VERSION_ATTRIBUTE);
-			if (v == null && defaultVersion != null) {
-				if (!isTrue(getProperty(Constants.NODEFAULTVERSION))) {
-					v = defaultVersion;
-					if (isPedantic())
-						warning("Used bundle version %s for exported package %s", v, entry.getKey());
-				} else {
-					if (isPedantic())
-						warning("No export version for exported package %s", entry.getKey());
-				}
-			}
-			if (v != null)
-				attributes.put(Constants.VERSION_ATTRIBUTE, cleanupVersion(v));
-		}
-	}
-
-	/**
-     * 
-     */
-	private void addSources(Jar dot) {
-		if (!hasSources())
-			return;
-
-		Set<String> packages = new HashSet<String>();
-
-		try {
-			ByteArrayOutputStream out = new ByteArrayOutputStream();
-			getProperties().store(out, "Generated by BND, at " + new Date());
-			dot.putResource("OSGI-OPT/bnd.bnd", new EmbeddedResource(out.toByteArray(), 0));
-			out.close();
-		} catch (Exception e) {
-			error("Can not embed bnd file in JAR: " + e);
-		}
-
-		for (Iterator<String> cpe = classspace.keySet().iterator(); cpe.hasNext();) {
-			String path = cpe.next();
-			path = path.substring(0, path.length() - ".class".length()) + ".java";
-			String pack = getPackage(path).replace('.', '/');
-			if (pack.length() > 1)
-				pack = pack + "/";
-			boolean found = false;
-			String[] fixed = { "packageinfo", "package.html", "module-info.java",
-					"package-info.java" };
-			for (Iterator<File> i = getSourcePath().iterator(); i.hasNext();) {
-				File root = i.next();
-				File f = getFile(root, path);
-				if (f.exists()) {
-					found = true;
-					if (!packages.contains(pack)) {
-						packages.add(pack);
-						File bdir = getFile(root, pack);
-						for (int j = 0; j < fixed.length; j++) {
-							File ff = getFile(bdir, fixed[j]);
-							if (ff.isFile()) {
-								String name = "OSGI-OPT/src/" + pack + fixed[j];
-								dot.putResource(name,
-										new FileResource(ff));
-							}
-						}
-					}
-					if ( path.trim().length() == 0)
-						System.out.println("Duh?");
-					dot.putResource("OSGI-OPT/src/" + path, new FileResource(f));
-				}
-			}
-			if (!found) {
-				for (Jar jar : classpath) {
-					Resource resource = jar.getResource(path);
-					if (resource != null) {
-						dot.putResource("OSGI-OPT/src/"+path, resource);
-					} else {
-						resource = jar.getResource("OSGI-OPT/src/" + path);
-						if (resource != null) {
-							dot.putResource("OSGI-OPT/src/"+path, resource);
-						}
-					}
-				}
-			}
-			if (getSourcePath().isEmpty())
-				warning("Including sources but " + SOURCEPATH
-						+ " does not contain any source directories ");
-			// TODO copy from the jars where they came from
-		}
-	}
-
-	boolean	firstUse	= true;
-
-	public Collection<File> getSourcePath() {
-		if (firstUse) {
-			firstUse = false;
-			String sp = getProperty(SOURCEPATH);
-			if (sp != null) {
-				Map<String, Map<String, String>> map = parseHeader(sp);
-				for (Iterator<String> i = map.keySet().iterator(); i.hasNext();) {
-					String file = i.next();
-					if (!isDuplicate(file)) {
-						File f = getFile(file);
-						if (!f.isDirectory()) {
-							error("Adding a sourcepath that is not a directory: " + f);
-						} else {
-							sourcePath.add(f);
-						}
-					}
-				}
-			}
-		}
-		return sourcePath;
-	}
-
-	private void doVerify(Jar dot) throws Exception {
-		Verifier verifier = new Verifier(dot, getProperties());
-		verifier.setPedantic(isPedantic());
-
-		// Give the verifier the benefit of our analysis
-		// prevents parsing the files twice
-		verifier.setClassSpace(classspace, contained, referred, uses);
-		verifier.verify();
-		getInfo(verifier);
-	}
-
-	private void doExpand(Jar jar) throws IOException {
-		if (getClasspath().size() == 0
-				&& (getProperty(EXPORT_PACKAGE) != null || getProperty(EXPORT_PACKAGE) != null || getProperty(PRIVATE_PACKAGE) != null))
-			warning("Classpath is empty. Private-Package and Export-Package can only expand from the classpath when there is one");
-
-		Map<Instruction, Map<String, String>> privateMap = Instruction
-				.replaceWithInstruction(getHeader(PRIVATE_PACKAGE));
-		Map<Instruction, Map<String, String>> exportMap = Instruction
-				.replaceWithInstruction(getHeader(EXPORT_PACKAGE));
-
-		if (isTrue(getProperty(Constants.UNDERTEST))) {
-			privateMap.putAll(Instruction.replaceWithInstruction(parseHeader(getProperty(
-					Constants.TESTPACKAGES, "test;presence:=optional"))));
-		}
-		if (!privateMap.isEmpty())
-			doExpand(jar, "Private-Package, or -testpackages", privateMap, true);
-
-		if (!exportMap.isEmpty()) {
-			Jar exports = new Jar("exports");
-			doExpand(exports, EXPORT_PACKAGE, exportMap, true);
-			jar.addAll(exports);
-			exports.close();
-		}
-
-		if (!isNoBundle()) {
-			if (privateMap.isEmpty() && exportMap.isEmpty() && !isResourceOnly()
-					&& getProperty(EXPORT_CONTENTS) == null) {
-				warning("None of Export-Package, Provide-Package, Private-Package, -testpackages, or -exportcontents is set, therefore no packages will be included");
-			}
-		}
-	}
-
-	/**
-	 * 
-	 * @param jar
-	 * @param name
-	 * @param instructions
-	 */
-	private void doExpand(Jar jar, String name, Map<Instruction, Map<String, String>> instructions,
-			boolean mandatory) {
-		Set<Instruction> superfluous = removeMarkedDuplicates(instructions.keySet());
-
-		for (Iterator<Jar> c = getClasspath().iterator(); c.hasNext();) {
-			Jar now = c.next();
-			doExpand(jar, instructions, now, superfluous);
-		}
-
-		if (mandatory && superfluous.size() > 0) {
-			StringBuilder sb = new StringBuilder();
-			String del = "Instructions in " + name + " that are never used: ";
-			for (Iterator<Instruction> i = superfluous.iterator(); i.hasNext();) {
-				Instruction p = i.next();
-				sb.append(del);
-				sb.append(p.toString());
-				del = "\n                ";
-			}
-			sb.append("\nClasspath: ");
-			sb.append(Processor.join(getClasspath()));
-			sb.append("\n");
-
-			warning("%s",sb.toString());
-			if (isPedantic())
-				diagnostics = true;
-		}
-	}
-
-	/**
-	 * Iterate over each directory in the class path entry and check if that
-	 * directory is a desired package.
-	 * 
-	 * @param included
-	 * @param classpathEntry
-	 */
-	private void doExpand(Jar jar, Map<Instruction, Map<String, String>> included,
-			Jar classpathEntry, Set<Instruction> superfluous) {
-
-		loop: for (Map.Entry<String, Map<String, Resource>> directory : classpathEntry
-				.getDirectories().entrySet()) {
-			String path = directory.getKey();
-
-			if (doNotCopy(getName(path)))
-				continue;
-
-			if (directory.getValue() == null)
-				continue;
-
-			String pack = path.replace('/', '.');
-			Instruction instr = matches(included, pack, superfluous, classpathEntry.getName());
-			if (instr != null) {
-				// System.out.println("Pattern match: " + pack + " " +
-				// instr.getPattern() + " " + instr.isNegated());
-				if (!instr.isNegated()) {
-					Map<String, Resource> contents = directory.getValue();
-
-					// What to do with split packages? Well if this
-					// directory already exists, we will check the strategy
-					// and react accordingly.
-					boolean overwriteResource = true;
-					if (jar.hasDirectory(path)) {
-						Map<String, String> directives = included.get(instr);
-
-						switch (getSplitStrategy((String) directives.get(SPLIT_PACKAGE_DIRECTIVE))) {
-						case SPLIT_MERGE_LAST:
-							overwriteResource = true;
-							break;
-
-						case SPLIT_MERGE_FIRST:
-							overwriteResource = false;
-							break;
-
-						case SPLIT_ERROR:
-							error(diagnostic(pack, getClasspath(), classpathEntry.source));
-							continue loop;
-
-						case SPLIT_FIRST:
-							continue loop;
-
-						default:
-							warning("%s", diagnostic(pack, getClasspath(), classpathEntry.source));
-							overwriteResource = false;
-							break;
-						}
-					}
-
-					jar.addDirectory(contents, overwriteResource);
-
-					String key = path + "/bnd.info";
-					Resource r = jar.getResource(key);
-					if (r != null)
-						jar.putResource(key, new PreprocessResource(this, r));
-
-					if (hasSources()) {
-						String srcPath = "OSGI-OPT/src/" + path;
-						Map<String, Resource> srcContents = classpathEntry.getDirectories().get(
-								srcPath);
-						if (srcContents != null) {
-							jar.addDirectory(srcContents, overwriteResource);
-						}
-					}
-				}
-			}
-		}
-	}
-
-	/**
-	 * Analyze the classpath for a split package
-	 * 
-	 * @param pack
-	 * @param classpath
-	 * @param source
-	 * @return
-	 */
-	private String diagnostic(String pack, List<Jar> classpath, File source) {
-		// Default is like merge-first, but with a warning
-		// Find the culprits
-		pack = pack.replace('.', '/');
-		List<Jar> culprits = new ArrayList<Jar>();
-		for (Iterator<Jar> i = classpath.iterator(); i.hasNext();) {
-			Jar culprit = (Jar) i.next();
-			if (culprit.getDirectories().containsKey(pack)) {
-				culprits.add(culprit);
-			}
-		}
-		return "Split package "
-				+ pack
-				+ "\nUse directive -split-package:=(merge-first|merge-last|error|first) on Export/Private Package instruction to get rid of this warning\n"
-				+ "Package found in   " + culprits + "\n" + "Reference from     " + source + "\n"
-				+ "Classpath          " + classpath;
-	}
-
-	private int getSplitStrategy(String type) {
-		if (type == null)
-			return SPLIT_DEFAULT;
-
-		if (type.equals("merge-last"))
-			return SPLIT_MERGE_LAST;
-
-		if (type.equals("merge-first"))
-			return SPLIT_MERGE_FIRST;
-
-		if (type.equals("error"))
-			return SPLIT_ERROR;
-
-		if (type.equals("first"))
-			return SPLIT_FIRST;
-
-		error("Invalid strategy for split-package: " + type);
-		return SPLIT_DEFAULT;
-	}
-
-	/**
-	 * Matches the instructions against a package.
-	 * 
-	 * @param instructions
-	 *            The list of instructions
-	 * @param pack
-	 *            The name of the package
-	 * @param superfluousPatterns
-	 *            The total list of patterns, matched patterns are removed
-	 * @param source
-	 *            The name of the source container, can be filtered upon with
-	 *            the from: directive.
-	 * @return
-	 */
-	private Instruction matches(Map<Instruction, Map<String, String>> instructions, String pack,
-			Set<Instruction> superfluousPatterns, String source) {
-		for (Map.Entry<Instruction, Map<String, String>> entry : instructions.entrySet()) {
-			Instruction pattern = entry.getKey();
-
-			// It is possible to filter on the source of the
-			// package with the from: directive. This is an
-			// instruction that must match the name of the
-			// source class path entry.
-
-			String from = entry.getValue().get(FROM_DIRECTIVE);
-			if (from != null) {
-				Instruction f = Instruction.getPattern(from);
-				if (!f.matches(source) || f.isNegated())
-					return null;
-			}
-
-			// Now do the normal
-			// matching
-			if (pattern.matches(pack)) {
-				if (superfluousPatterns != null)
-					superfluousPatterns.remove(pattern);
-				return pattern;
-			}
-		}
-		return null;
-	}
-
-	private Map<String, Map<String, String>> getHeader(String string) {
-		if (string == null)
-			return Collections.emptyMap();
-		return parseHeader(getProperty(string));
-	}
-
-	/**
-	 * Parse the Bundle-Includes header. Files in the bundles Include header are
-	 * included in the jar. The source can be a directory or a file.
-	 * 
-	 * @throws IOException
-	 * @throws FileNotFoundException
-	 */
-	private void doIncludeResources(Jar jar) throws Exception {
-		String includes = getProperty("Bundle-Includes");
-		if (includes == null) {
-			includes = getProperty(INCLUDERESOURCE);
-			if (includes == null || includes.length() == 0)
-				includes = getProperty("Include-Resource");
-		} else
-			warning("Please use -includeresource instead of Bundle-Includes");
-
-		doIncludeResource(jar, includes);
-
-	}
-
-	private void doIncludeResource(Jar jar, String includes) throws Exception {
-		Map<String, Map<String, String>> clauses = parseHeader(includes);
-		doIncludeResource(jar, clauses);
-	}
-
-	private void doIncludeResource(Jar jar, Map<String, Map<String, String>> clauses)
-			throws ZipException, IOException, Exception {
-		for (Map.Entry<String, Map<String, String>> entry : clauses.entrySet()) {
-			doIncludeResource(jar, entry.getKey(), entry.getValue());
-		}
-	}
-
-	private void doIncludeResource(Jar jar, String name, Map<String, String> extra)
-			throws ZipException, IOException, Exception {
-		boolean preprocess = false;
-		if (name.startsWith("{") && name.endsWith("}")) {
-			preprocess = true;
-			name = name.substring(1, name.length() - 1).trim();
-		}
-
-		String parts[] = name.split("\\s*=\\s*");
-		String source = parts[0];
-		String destination = parts[0];
-		if (parts.length == 2)
-			source = parts[1];
-
-		if (source.startsWith("@")) {
-			extractFromJar(jar, source.substring(1), parts.length == 1 ? "" : destination);
-		} else if (extra.containsKey("literal")) {
-			String literal = (String) extra.get("literal");
-			Resource r = new EmbeddedResource(literal.getBytes("UTF-8"), 0);
-			String x = (String) extra.get("extra");
-			if (x != null)
-				r.setExtra(x);
-			jar.putResource(name, r);
-		} else {
-			File sourceFile;
-			String destinationPath;
-
-			sourceFile = getFile(source);
-			if (parts.length == 1) {
-				// Directories should be copied to the root
-				// but files to their file name ...
-				if (sourceFile.isDirectory())
-					destinationPath = "";
-				else
-					destinationPath = sourceFile.getName();
-			} else {
-				destinationPath = parts[0];
-			}
-			// Handle directories
-			if (sourceFile.isDirectory()) {
-				destinationPath = doResourceDirectory(jar, extra, preprocess, sourceFile,
-						destinationPath);
-				return;
-			}
-
-			// destinationPath = checkDestinationPath(destinationPath);
-
-			if (!sourceFile.exists()) {
-				noSuchFile(jar, name, extra, source, destinationPath);
-			} else
-				copy(jar, destinationPath, sourceFile, preprocess, extra);
-		}
-	}
-
-	private String doResourceDirectory(Jar jar, Map<String, String> extra, boolean preprocess,
-			File sourceFile, String destinationPath) throws Exception {
-		String filter = extra.get("filter:");
-		boolean flatten = isTrue(extra.get("flatten:"));
-		boolean recursive = true;
-		String directive = extra.get("recursive:");
-		if (directive != null) {
-			recursive = isTrue(directive);
-		}
-
-		InstructionFilter iFilter = null;
-		if (filter != null) {
-			iFilter = new InstructionFilter(Instruction.getPattern(filter), recursive,
-					getDoNotCopy());
-		} else {
-			iFilter = new InstructionFilter(null, recursive, getDoNotCopy());
-		}
-
-		Map<String, File> files = newMap();
-		resolveFiles(sourceFile, iFilter, recursive, destinationPath, files, flatten);
-
-		for (Map.Entry<String, File> entry : files.entrySet()) {
-			copy(jar, entry.getKey(), entry.getValue(), preprocess, extra);
-		}
-		return destinationPath;
-	}
-
-	private void resolveFiles(File dir, FileFilter filter, boolean recursive, String path,
-			Map<String, File> files, boolean flatten) {
-
-		if (doNotCopy(dir.getName())) {
-			return;
-		}
-
-		File[] fs = dir.listFiles(filter);
-		for (File file : fs) {
-			if (file.isDirectory()) {
-				if (recursive) {
-					String nextPath;
-					if (flatten)
-						nextPath = path;
-					else
-						nextPath = appendPath(path, file.getName());
-
-					resolveFiles(file, filter, recursive, nextPath, files, flatten);
-				}
-				// Directories are ignored otherwise
-			} else {
-				String p = appendPath(path, file.getName());
-				if (files.containsKey(p))
-					warning("Include-Resource overwrites entry %s from file %s", p, file);
-				files.put(p, file);
-			}
-		}
-	}
-
-	private void noSuchFile(Jar jar, String clause, Map<String, String> extra, String source,
-			String destinationPath) throws Exception {
-		Jar src = getJarFromName(source, "Include-Resource " + source);
-		if (src != null) {
-			JarResource jarResource = new JarResource(src);
-			jar.putResource(destinationPath, jarResource);
-		} else {
-			Resource lastChance = make.process(source);
-			if (lastChance != null) {
-				String x = extra.get("extra");
-				if (x != null)
-					lastChance.setExtra(x);
-				jar.putResource(destinationPath, lastChance);
-			} else
-				error("Input file does not exist: " + source);
-		}
-	}
-
-	/**
-	 * Extra resources from a Jar and add them to the given jar. The clause is
-	 * the
-	 * 
-	 * @param jar
-	 * @param clauses
-	 * @param i
-	 * @throws ZipException
-	 * @throws IOException
-	 */
-	private void extractFromJar(Jar jar, String source, String destination) throws ZipException,
-			IOException {
-		// Inline all resources and classes from another jar
-		// optionally appended with a modified regular expression
-		// like @zip.jar!/META-INF/MANIFEST.MF
-		int n = source.lastIndexOf("!/");
-		Instruction instr = null;
-		if (n > 0) {
-			instr = Instruction.getPattern(source.substring(n + 2));
-			source = source.substring(0, n);
-		}
-
-		// Pattern filter = null;
-		// if (n > 0) {
-		// String fstring = source.substring(n + 2);
-		// source = source.substring(0, n);
-		// filter = wildcard(fstring);
-		// }
-		Jar sub = getJarFromName(source, "extract from jar");
-		if (sub == null)
-			error("Can not find JAR file " + source);
-		else {
-			jar.addAll(sub, instr, destination);
-		}
-	}
-
-	private void copy(Jar jar, String path, File from, boolean preprocess, Map<String, String> extra)
-			throws Exception {
-		if (doNotCopy(from.getName()))
-			return;
-
-		if (from.isDirectory()) {
-
-			File files[] = from.listFiles();
-			for (int i = 0; i < files.length; i++) {
-				copy(jar, appendPath(path, files[i].getName()), files[i], preprocess, extra);
-			}
-		} else {
-			if (from.exists()) {
-				Resource resource = new FileResource(from);
-				if (preprocess) {
-					resource = new PreprocessResource(this, resource);
-				}
-				String x = extra.get("extra");
-				if (x != null)
-					resource.setExtra(x);
-				if (path.endsWith("/"))
-					path = path + from.getName();
-				jar.putResource(path, resource);
-
-				if (isTrue(extra.get(LIB_DIRECTIVE))) {
-					setProperty(BUNDLE_CLASSPATH, append(getProperty(BUNDLE_CLASSPATH), path));
-				}
-			} else {
-				error("Input file does not exist: " + from);
-			}
-		}
-	}
-
-	private String getName(String where) {
-		int n = where.lastIndexOf('/');
-		if (n < 0)
-			return where;
-
-		return where.substring(n + 1);
-	}
-
-	public void setSourcepath(File[] files) {
-		for (int i = 0; i < files.length; i++)
-			addSourcepath(files[i]);
-	}
-
-	public void addSourcepath(File cp) {
-		if (!cp.exists())
-			warning("File on sourcepath that does not exist: " + cp);
-
-		sourcePath.add(cp);
-	}
-
-	public void close() {
-		super.close();
-	}
-
-	/**
-	 * Build Multiple jars. If the -sub command is set, we filter the file with
-	 * the given patterns.
-	 * 
-	 * @return
-	 * @throws Exception
-	 */
-	public Jar[] builds() throws Exception {
-		begin();
-
-		// Are we acting as a conduit for another JAR?
-		String conduit = getProperty(CONDUIT);
-		if (conduit != null) {
-			Map<String, Map<String, String>> map = parseHeader(conduit);
-			Jar[] result = new Jar[map.size()];
-			int n = 0;
-			for (String file : map.keySet()) {
-				Jar c = new Jar(getFile(file));
-				addClose(c);
-				String name = map.get(file).get("name");
-				if (name != null)
-					c.setName(name);
-
-				result[n++] = c;
-			}
-			return result;
-		}
-
-		List<Jar> result = new ArrayList<Jar>();
-		List<Builder> builders;
-
-		builders = getSubBuilders();
-
-		for (Builder builder : builders) {
-			try {
-				Jar jar = builder.build();
-				jar.setName(builder.getBsn());
-				result.add(jar);
-			} catch (Exception e) {
-				e.printStackTrace();
-				error("Sub Building " + builder.getBsn(), e);
-			}
-			if (builder != this)
-				getInfo(builder, builder.getBsn() + ": ");
-		}
-		return result.toArray(new Jar[result.size()]);
-	}
-
-	/**
-	 * Answer a list of builders that represent this file or a list of files
-	 * specified in -sub. This list can be empty. These builders represents to
-	 * be created artifacts and are each scoped to such an artifacts. The
-	 * builders can be used to build the bundles or they can be used to find out
-	 * information about the to be generated bundles.
-	 * 
-	 * @return List of 0..n builders representing artifacts.
-	 * @throws Exception
-	 */
-	public List<Builder> getSubBuilders() throws Exception {
-		String sub = (String) getProperty(SUB);
-		if (sub == null || sub.trim().length() == 0 || EMPTY_HEADER.equals(sub))
-			return Arrays.asList(this);
-
-		List<Builder> builders = new ArrayList<Builder>();
-		if (isTrue(getProperty(NOBUNDLES)))
-			return builders;
-
-		Map<String, Map<String, String>> subsMap = parseHeader(sub);
-		for (Iterator<String> i = subsMap.keySet().iterator(); i.hasNext();) {
-			File file = getFile(i.next());
-			if (file.isFile()) {
-				builders.add(getSubBuilder(file));
-				i.remove();
-			}
-		}
-
-		Set<Instruction> subs = Instruction.replaceWithInstruction(subsMap).keySet();
-
-		List<File> members = new ArrayList<File>(Arrays.asList(getBase().listFiles()));
-
-		nextFile: while (members.size() > 0) {
-
-			File file = members.remove(0);
-
-			// Check if the file is one of our parents
-			Processor p = this;
-			while (p != null) {
-				if (file.equals(p.getPropertiesFile()))
-					continue nextFile;
-				p = p.getParent();
-			}
-
-			for (Iterator<Instruction> i = subs.iterator(); i.hasNext();) {
-
-				Instruction instruction = i.next();
-				if (instruction.matches(file.getName())) {
-
-					if (!instruction.isNegated()) {
-						builders.add(getSubBuilder(file));
-					}
-
-					// Because we matched (even though we could be negated)
-					// we skip any remaining searches
-					continue nextFile;
-				}
-			}
-		}
-		return builders;
-	}
-
-	public Builder getSubBuilder(File file) throws Exception {
-		Builder builder = getSubBuilder();
-		if (builder != null) {
-			builder.setProperties(file);
-			addClose(builder);
-		}
-		return builder;
-	}
-
-	public Builder getSubBuilder() throws Exception {
-		Builder builder = new Builder(this);
-		builder.setBase(getBase());
-
-		for (Jar file : getClasspath()) {
-			builder.addClasspath(file);
-		}
-
-		return builder;
-	}
-
-	/**
-	 * A macro to convert a maven version to an OSGi version
-	 */
-
-	public String _maven_version(String args[]) {
-		if (args.length > 2)
-			error("${maven_version} macro receives too many arguments " + Arrays.toString(args));
-		else if (args.length < 2)
-			error("${maven_version} macro has no arguments, use ${maven_version;1.2.3-SNAPSHOT}");
-		else {
-			return cleanupVersion(args[1]);
-		}
-		return null;
-	}
-
-	public String _permissions(String args[]) throws IOException {
-		StringBuilder sb = new StringBuilder();
-
-		for (String arg : args) {
-			if ("packages".equals(arg) || "all".equals(arg)) {
-				for (String imp : getImports().keySet()) {
-					if (!imp.startsWith("java.")) {
-						sb.append("(org.osgi.framework.PackagePermission \"");
-						sb.append(imp);
-						sb.append("\" \"import\")\r\n");
-					}
-				}
-				for (String exp : getExports().keySet()) {
-					sb.append("(org.osgi.framework.PackagePermission \"");
-					sb.append(exp);
-					sb.append("\" \"export\")\r\n");
-				}
-			} else if ("admin".equals(arg) || "all".equals(arg)) {
-				sb.append("(org.osgi.framework.AdminPermission)");
-			} else if ("permissions".equals(arg))
-				;
-			else
-				error("Invalid option in ${permissions}: %s", arg);
-		}
-		return sb.toString();
-	}
-
-	/**
-     * 
-     */
-	public void removeBundleSpecificHeaders() {
-		Set<String> set = new HashSet<String>(Arrays.asList(BUNDLE_SPECIFIC_HEADERS));
-		setForceLocal(set);
-	}
-
-	/**
-	 * Check if the given resource is in scope of this bundle. That is, it
-	 * checks if the Include-Resource includes this resource or if it is a class
-	 * file it is on the class path and the Export-Pacakge or Private-Package
-	 * include this resource.
-	 * 
-	 * For now, include resources are skipped.
-	 * 
-	 * @param f
-	 * @return
-	 */
-	public boolean isInScope(Collection<File> resources) throws Exception {
-		Map<String, Map<String, String>> clauses = parseHeader(getProperty(Constants.EXPORT_PACKAGE));
-		clauses.putAll(parseHeader(getProperty(Constants.PRIVATE_PACKAGE)));
-		if (isTrue(getProperty(Constants.UNDERTEST))) {
-			clauses.putAll(parseHeader(getProperty(Constants.TESTPACKAGES,
-					"test;presence:=optional")));
-		}
-		Map<Instruction, Map<String, String>> instructions = Instruction
-				.replaceWithInstruction(clauses);
-
-		for (File r : resources) {
-			String cpEntry = getClasspathEntrySuffix(r);
-			if (cpEntry != null) {
-				String pack = Clazz.getPackage(cpEntry);
-				Instruction i = matches(instructions, pack, null, r.getName());
-				if (i != null)
-					return !i.isNegated();
-			}
-		}
-		return false;
-	}
-
-	/**
-	 * Answer the string of the resource that it has in the container.
-	 * 
-	 * @param resource
-	 *            The resource to look for
-	 * @return
-	 * @throws Exception
-	 */
-	public String getClasspathEntrySuffix(File resource) throws Exception {
-		for (Jar jar : getClasspath()) {
-			File source = jar.getSource();
-			if (source != null) {
-				source = source.getCanonicalFile();
-				String sourcePath = source.getAbsolutePath();
-				String resourcePath = resource.getAbsolutePath();
-
-				if (resourcePath.startsWith(sourcePath)) {
-					// Make sure that the path name is translated correctly
-					// i.e. on Windows the \ must be translated to /
-					String filePath = resourcePath.substring(sourcePath.length() + 1);
-
-					return filePath.replace(File.separatorChar, '/');
-				}
-			}
-		}
-		return null;
-	}
-
-	/**
-	 * doNotCopy
-	 * 
-	 * The doNotCopy variable maintains a patter for files that should not be
-	 * copied. There is a default {@link #DEFAULT_DO_NOT_COPY} but this ca be
-	 * overridden with the {@link Constants#DONOTCOPY} property.
-	 */
-
-	public boolean doNotCopy(String v) {
-		return getDoNotCopy().matcher(v).matches();
-	}
-
-	public Pattern getDoNotCopy() {
-		if (xdoNotCopy == null) {
-			String string = null;
-			try {
-				string = getProperty(DONOTCOPY, DEFAULT_DO_NOT_COPY);
-				xdoNotCopy = Pattern.compile(string);
-			} catch (Exception e) {
-				error("Invalid value for %s, value is %s", DONOTCOPY, string);
-				xdoNotCopy = Pattern.compile(DEFAULT_DO_NOT_COPY);
-			}
-		}
-		return xdoNotCopy;
-	}
-
-	/**
-	 */
-
-	static MakeBnd			makeBnd				= new MakeBnd();
-	static MakeCopy			makeCopy			= new MakeCopy();
-	static ServiceComponent	serviceComponent	= new ServiceComponent();
-	static DSAnnotations	dsAnnotations		= new DSAnnotations();
-	static MetatypePlugin	metatypePlugin		= new MetatypePlugin();
-
-	@Override protected void setTypeSpecificPlugins(Set<Object> list) {
-		list.add(makeBnd);
-		list.add(makeCopy);
-		list.add(serviceComponent);
-		list.add(dsAnnotations);
-		list.add(metatypePlugin);
-		super.setTypeSpecificPlugins(list);
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/ClassDataCollector.java b/biz.aQute.bndlib/src/aQute/lib/osgi/ClassDataCollector.java
deleted file mode 100644
index 12e9a37..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/ClassDataCollector.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package aQute.lib.osgi;
-
-public class ClassDataCollector {
-    public void classBegin(int access, String name) {
-    }
-
-    public boolean classStart(int access, String name) {
-        classBegin(access,name);
-        return true;
-    }
-
-    public void extendsClass(String name) {
-    }
-
-    public void implementsInterfaces(String name[]) {
-    }
-
-    public void addReference(String token) {
-    }
-
-    public void annotation(Annotation annotation) {
-    }
-
-    public void parameter(int p) {
-    }
-
-    public void method(Clazz.MethodDef defined) {
-        if (defined.isConstructor())
-            constructor(defined.access, defined.descriptor);
-        else
-            method(defined.access, defined.name, defined.descriptor);
-    }
-
-    public void field(Clazz.FieldDef defined) {
-        field(defined.access, defined.name, defined.descriptor);
-    }
-
-    public void reference(Clazz.MethodDef referenced) {
-    }
-
-    public void reference(Clazz.FieldDef referenced) {
-    }
-
-    public void classEnd() {
-    }
-
-    @Deprecated // Will really be removed!
-    public void field(int access, String name, String descriptor) {
-    }
-
-    @Deprecated // Will really be removed!
-    public void constructor(int access, String descriptor) {
-    }
-
-    @Deprecated // Will really be removed!
-    public void method(int access, String name, String descriptor) {
-    }
-
-    /**
-     * The EnclosingMethod attribute
-     * 
-     * @param cName The name of the enclosing class, never null. Name is with slashes.
-     * @param mName The name of the enclosing method in the class with cName or null
-     * @param mDescriptor The descriptor of this type
-     */
-	public void enclosingMethod(String cName, String mName, String mDescriptor) {
-		
-	}
-
-	/**
-	 * The InnerClass attribute
-	 * 
-	 * @param innerClass The name of the inner class (with slashes). Can be null.
-	 * @param outerClass The name of the outer class (with slashes) Can be null.
-	 * @param innerName The name inside the outer class, can be null.
-	 * @param modifiers The access flags 
-	 */
-	public void innerClass(String innerClass, String outerClass, String innerName,
-			int innerClassAccessFlags) {		
-	}
-
-	public void signature(String signature) {
-	}
-
-	public void constant(Object object) {
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/Clazz.java b/biz.aQute.bndlib/src/aQute/lib/osgi/Clazz.java
deleted file mode 100755
index cb5e1f0..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/Clazz.java
+++ /dev/null
@@ -1,1613 +0,0 @@
-package aQute.lib.osgi;
-
-import java.io.*;
-import java.lang.annotation.*;
-import java.nio.*;
-import java.util.*;
-import java.util.regex.*;
-
-import aQute.bnd.annotation.*;
-import aQute.libg.generics.*;
-
-public class Clazz {
-
-	public class ClassConstant {
-		int	cname;
-
-		public ClassConstant(int class_index) {
-			this.cname = class_index;
-		}
-
-		public String getName() {
-			return (String) pool[cname];
-		}
-	}
-
-	public static enum JAVA {
-		UNKNOWN(Integer.MAX_VALUE), OpenJDK7(51), J2S6(50), J2SE5(49), JDK1_4(48), JDK1_3(47), JDK1_2(
-				46), JDK1_1(45);
-
-		final int	major;
-
-		JAVA(int major) {
-			this.major = major;
-		}
-
-		static JAVA format(int n) {
-			for (JAVA e : JAVA.values())
-				if (e.major == n)
-					return e;
-			return UNKNOWN;
-		}
-
-		public int getMajor() {
-			return major;
-		}
-
-		public boolean hasAnnotations() {
-			return major >= J2SE5.major;
-		}
-
-		public boolean hasGenerics() {
-			return major >= J2SE5.major;
-		}
-
-		public boolean hasEnums() {
-			return major >= J2SE5.major;
-		}
-	};
-
-	public static enum QUERY {
-		IMPLEMENTS, EXTENDS, IMPORTS, NAMED, ANY, VERSION, CONCRETE, ABSTRACT, PUBLIC, ANNOTATION, RUNTIMEANNOTATIONS, CLASSANNOTATIONS
-	};
-
-	public static EnumSet<QUERY>	HAS_ARGUMENT	= EnumSet.of(QUERY.IMPLEMENTS, QUERY.EXTENDS,
-															QUERY.IMPORTS, QUERY.NAMED,
-															QUERY.VERSION, QUERY.ANNOTATION);
-
-	/**
-	 * <pre>
-	 * ACC_PUBLIC 0x0001 Declared public; may be accessed from outside its
-	 * package. 
-	 * ACC_FINAL 0x0010 Declared final; no subclasses allowed.
-	 * ACC_SUPER 0x0020 Treat superclass methods specially when invoked by the
-	 * invokespecial instruction. 
-	 * ACC_INTERFACE 0x0200 Is an interface, not a
-	 * class. 
-	 * ACC_ABSTRACT 0x0400 Declared abstract; may not be instantiated.
-	 * </pre>
-	 * 
-	 * @param mod
-	 */
-	final static int				ACC_PUBLIC		= 0x0001;									// Declared
-	// public;
-	// may
-	// be
-	// accessed
-	// from outside its package.
-	final static int				ACC_FINAL		= 0x0010;									// Declared
-	// final;
-	// no
-	// subclasses
-	// allowed.
-	final static int				ACC_SUPER		= 0x0020;									// Treat
-	// superclass
-	// methods
-	// specially when invoked by the
-	// invokespecial instruction.
-	final static int				ACC_INTERFACE	= 0x0200;									// Is
-	// an
-	// interface,
-	// not
-	// a
-	// classs
-	final static int				ACC_ABSTRACT	= 0x0400;									// Declared
-
-	// abstract;
-	// may
-	// not
-	// be
-
-	// instantiated.
-
-	final static int				ACC_ENUM		= 0x04000;
-
-	static protected class Assoc {
-		Assoc(byte tag, int a, int b) {
-			this.tag = tag;
-			this.a = a;
-			this.b = b;
-		}
-
-		byte	tag;
-		int		a;
-		int		b;
-	}
-
-	static public class FieldDef implements Comparable<FieldDef> {
-		public FieldDef(int access, String clazz, String name, String descriptor) {
-			this.access = access;
-			this.clazz = clazz.replace('/', '.');
-			this.name = name;
-			this.descriptor = descriptor;
-		}
-
-		final public int	access;
-		final public String	clazz;
-		final public String	name;
-		final public String	descriptor;
-		public String		signature;
-		public Object		constant;
-
-		public boolean equals(Object other) {
-			if (!(other instanceof MethodDef))
-				return false;
-
-			FieldDef m = (FieldDef) other;
-			return clazz.equals(m.clazz) && name.equals(m.name) && descriptor.equals(m.descriptor);
-		}
-
-		public int hashCode() {
-			return clazz.hashCode() ^ name.hashCode() ^ descriptor.hashCode();
-		}
-
-		public int compareTo(FieldDef o) {
-			int result = clazz.compareTo(o.clazz);
-			if (result == 0) {
-				result = name.compareTo(o.name);
-				if (result == 0) {
-					result = descriptor.compareTo(o.descriptor);
-				}
-			}
-			return result;
-		}
-
-		public String getPretty() {
-			return name;
-		}
-
-		public String toString() {
-			return getPretty();
-		}
-
-		public boolean isEnum() {
-			return (access & ACC_ENUM) != 0;
-		}
-	}
-
-	static public class MethodDef extends FieldDef {
-		Pattern	METHOD_DESCRIPTOR	= Pattern.compile("\\((.*)\\)(.+)");
-
-		public MethodDef(int access, String clazz, String method, String descriptor) {
-			super(access, clazz, method, descriptor);
-		}
-
-		public boolean isConstructor() {
-			return name.equals("<init>") || name.equals("<clinit>");
-		}
-
-		public String getReturnType() {
-			String use = descriptor;
-			if (signature != null)
-				use = signature;
-
-			Matcher m = METHOD_DESCRIPTOR.matcher(use);
-			if (!m.matches())
-				throw new IllegalArgumentException("Not a valid method descriptor: " + descriptor);
-
-			String returnType = m.group(2);
-			return objectDescriptorToFQN(returnType);
-		}
-
-		public String getPretty() {
-
-			StringBuilder sb = new StringBuilder();
-			sb.append(descriptor.charAt(0));
-			int index = 1;
-			String del = "";
-			while (index < descriptor.length() && descriptor.charAt(index) != ')') {
-				sb.append(del);
-				index = printParameter(sb, descriptor, index);
-				del = ",";
-			}
-			sb.append(descriptor.charAt(index++));
-			StringBuilder sb2 = new StringBuilder();
-			if (isConstructor()) {
-				sb2.append(getShortName(clazz));
-				index++; // skip the V
-			} else {
-				printParameter(sb2, descriptor, index);
-				sb2.append(" ");
-				sb2.append(getShortName(clazz));
-				sb2.append(".");
-				sb2.append(name);
-			}
-			sb2.append(sb);
-			return sb2.toString();
-		}
-
-		private int printParameter(StringBuilder sb, CharSequence descriptor, int index) {
-			char c = descriptor.charAt(index++);
-			switch (c) {
-			case 'B':
-				sb.append("byte");
-				break;
-			case 'C':
-				sb.append("char");
-				break;
-			case 'D':
-				sb.append("double");
-				break;
-			case 'F':
-				sb.append("float");
-				break;
-			case 'I':
-				sb.append("int");
-				break;
-			case 'J':
-				sb.append("long");
-				break;
-			case 'S':
-				sb.append("short");
-				break;
-			case 'Z':
-				sb.append("boolean");
-				break;
-			case 'V':
-				sb.append("void");
-				break;
-			case 'L':
-				index = reference(sb, descriptor, index);
-				break;
-
-			case '[':
-				index = array(sb, descriptor, index);
-				break;
-			}
-			return index;
-		}
-
-		private int reference(StringBuilder sb, CharSequence descriptor, int index) {
-			int n = sb.length();
-			int lastSlash = n;
-			while (index < descriptor.length() && descriptor.charAt(index) != ';') {
-				char c = descriptor.charAt(index++);
-				if (c == '/') {
-					c = '.';
-					lastSlash = sb.length() + 1;
-				}
-				sb.append(c);
-			}
-			if (lastSlash != n) {
-				sb.delete(n, lastSlash);
-			}
-			return ++index;
-		}
-
-		private int array(StringBuilder sb, CharSequence descriptor, int index) {
-			int n = 1;
-			while (index < descriptor.length() && descriptor.charAt(index) == '[') {
-				index++;
-			}
-			index = printParameter(sb, descriptor, index);
-			while (n-- > 0) {
-				sb.append("[]");
-			}
-			return index;
-		}
-	}
-
-	final static byte	SkipTable[]	= { 0, // 0 non existent
-			-1, // 1 CONSTANT_utf8 UTF 8, handled in
-			// method
-			-1, // 2
-			4, // 3 CONSTANT_Integer
-			4, // 4 CONSTANT_Float
-			8, // 5 CONSTANT_Long (index +=2!)
-			8, // 6 CONSTANT_Double (index +=2!)
-			-1, // 7 CONSTANT_Class
-			2, // 8 CONSTANT_String
-			4, // 9 CONSTANT_FieldRef
-			4, // 10 CONSTANT_MethodRef
-			4, // 11 CONSTANT_InterfaceMethodRef
-			4, // 12 CONSTANT_NameAndType
-									};
-
-	boolean				isAbstract;
-	boolean				isPublic;
-	boolean				isEnum;
-	boolean				hasRuntimeAnnotations;
-	boolean				hasClassAnnotations;
-
-	String				className;
-	Object				pool[];
-	int					intPool[];
-	Set<String>			imports		= Create.set();
-	String				path;
-	int					minor		= 0;
-	int					major		= 0;
-	int					access		= 0;
-	String				sourceFile;
-	Set<String>			xref;
-	Set<Integer>		classes;
-	Set<Integer>		descriptors;
-	Set<String>			annotations;
-	int					forName		= 0;
-	int					class$		= 0;
-	String[]			interfaces;
-	String				zuper;
-	ClassDataCollector	cd			= null;
-	Resource			resource;
-	FieldDef			last		= null;
-
-	public Clazz(String path, Resource resource) {
-		this.path = path;
-		this.resource = resource;
-	}
-
-	public Set<String> parseClassFile() throws Exception {
-		return parseClassFileWithCollector(null);
-	}
-
-	public Set<String> parseClassFile(InputStream in) throws IOException {
-		return parseClassFile(in, null);
-	}
-
-	public Set<String> parseClassFileWithCollector(ClassDataCollector cd) throws Exception {
-		InputStream in = resource.openInputStream();
-		try {
-			return parseClassFile(in, cd);
-		} finally {
-			in.close();
-		}
-	}
-
-	public Set<String> parseClassFile(InputStream in, ClassDataCollector cd) throws IOException {
-		DataInputStream din = new DataInputStream(in);
-		try {
-			this.cd = cd;
-			return parseClassFile(din);
-		} finally {
-			cd = null;
-			din.close();
-		}
-	}
-
-	Set<String> parseClassFile(DataInputStream in) throws IOException {
-
-		xref = new HashSet<String>();
-		classes = new HashSet<Integer>();
-		descriptors = new HashSet<Integer>();
-
-		boolean crawl = cd != null; // Crawl the byte code if we have a
-		// collector
-		int magic = in.readInt();
-		if (magic != 0xCAFEBABE)
-			throw new IOException("Not a valid class file (no CAFEBABE header)");
-
-		minor = in.readUnsignedShort(); // minor version
-		major = in.readUnsignedShort(); // major version
-		int count = in.readUnsignedShort();
-		pool = new Object[count];
-		intPool = new int[count];
-
-		process: for (int poolIndex = 1; poolIndex < count; poolIndex++) {
-			byte tag = in.readByte();
-			switch (tag) {
-			case 0:
-				break process;
-			case 1:
-				constantUtf8(in, poolIndex);
-				break;
-
-			case 3:
-				constantInteger(in, poolIndex);
-				break;
-
-			case 4:
-				constantFloat(in, poolIndex);
-				break;
-
-			// For some insane optimization reason are
-			// the long and the double two entries in the
-			// constant pool. See 4.4.5
-			case 5:
-				constantLong(in, poolIndex);
-				poolIndex++;
-				break;
-
-			case 6:
-				constantDouble(in, poolIndex);
-				poolIndex++;
-				break;
-
-			case 7:
-				constantClass(in, poolIndex);
-				break;
-
-			case 8:
-				constantString(in, poolIndex);
-				break;
-
-			case 10: // Method ref
-			case 11: // Interface Method ref
-				methodRef(in, poolIndex);
-				break;
-
-			// Name and Type
-			case 12:
-				nameAndType(in, poolIndex, tag);
-				break;
-
-			// We get the skip count for each record type
-			// from the SkipTable. This will also automatically
-			// abort when
-			default:
-				if (tag == 2)
-					throw new IOException("Invalid tag " + tag);
-				in.skipBytes(SkipTable[tag]);
-				break;
-			}
-		}
-
-		pool(pool, intPool);
-		/*
-		 * Parse after the constant pool, code thanks to Hans Christian
-		 * Falkenberg
-		 */
-
-		int access_flags = in.readUnsignedShort(); // access
-		isAbstract = (access_flags & ACC_ABSTRACT) != 0;
-		isPublic = (access_flags & ACC_PUBLIC) != 0;
-		isEnum = (access_flags & ACC_ENUM) != 0;
-
-		int this_class = in.readUnsignedShort();
-		className = (String) pool[intPool[this_class]];
-
-		try {
-
-			if (cd != null) {
-				if (!cd.classStart(access_flags, className))
-					return null;
-			}
-
-			int super_class = in.readUnsignedShort();
-			zuper = (String) pool[intPool[super_class]];
-			if (zuper != null) {
-				String pack = getPackage(zuper);
-				packageReference(pack);
-				if (cd != null)
-					cd.extendsClass(zuper);
-			}
-
-			int interfacesCount = in.readUnsignedShort();
-			if (interfacesCount > 0) {
-				interfaces = new String[interfacesCount];
-				for (int i = 0; i < interfacesCount; i++)
-					interfaces[i] = (String) pool[intPool[in.readUnsignedShort()]];
-				if (cd != null)
-					cd.implementsInterfaces(interfaces);
-			}
-
-			int fieldsCount = in.readUnsignedShort();
-			for (int i = 0; i < fieldsCount; i++) {
-				access_flags = in.readUnsignedShort(); // skip access flags
-				int name_index = in.readUnsignedShort();
-				int descriptor_index = in.readUnsignedShort();
-
-				// Java prior to 1.5 used a weird
-				// static variable to hold the com.X.class
-				// result construct. If it did not find it
-				// it would create a variable class$com$X
-				// that would be used to hold the class
-				// object gotten with Class.forName ...
-				// Stupidly, they did not actively use the
-				// class name for the field type, so bnd
-				// would not see a reference. We detect
-				// this case and add an artificial descriptor
-				String name = pool[name_index].toString(); // name_index
-				if (name.startsWith("class$")) {
-					crawl = true;
-				}
-				if (cd != null)
-					cd.field(last = new FieldDef(access_flags, className, name,
-							pool[descriptor_index].toString()));
-				descriptors.add(new Integer(descriptor_index));
-				doAttributes(in, ElementType.FIELD, false);
-			}
-
-			//
-			// Check if we have to crawl the code to find
-			// the ldc(_w) <string constant> invokestatic Class.forName
-			// if so, calculate the method ref index so we
-			// can do this efficiently
-			//
-			if (crawl) {
-				forName = findMethodReference("java/lang/Class", "forName",
-						"(Ljava/lang/String;)Ljava/lang/Class;");
-				class$ = findMethodReference(className, "class$",
-						"(Ljava/lang/String;)Ljava/lang/Class;");
-			} else if (major == 48) {
-				forName = findMethodReference("java/lang/Class", "forName",
-						"(Ljava/lang/String;)Ljava/lang/Class;");
-				if (forName > 0) {
-					crawl = true;
-					class$ = findMethodReference(className, "class$",
-							"(Ljava/lang/String;)Ljava/lang/Class;");
-				}
-			}
-
-			//
-			// Handle the methods
-			//
-			int methodCount = in.readUnsignedShort();
-			for (int i = 0; i < methodCount; i++) {
-				access_flags = in.readUnsignedShort();
-				int name_index = in.readUnsignedShort();
-				int descriptor_index = in.readUnsignedShort();
-				descriptors.add(new Integer(descriptor_index));
-				String name = pool[name_index].toString();
-				String descriptor = pool[descriptor_index].toString();
-				if (cd != null) {
-					MethodDef mdef = new MethodDef(access_flags, className, name, descriptor);
-					last = mdef;
-					cd.method(mdef);
-				}
-
-				if ("<init>".equals(name)) {
-					doAttributes(in, ElementType.CONSTRUCTOR, crawl);
-				} else {
-					doAttributes(in, ElementType.METHOD, crawl);
-				}
-			}
-
-			doAttributes(in, ElementType.TYPE, false);
-
-			//
-			// Now iterate over all classes we found and
-			// parse those as well. We skip duplicates
-			//
-
-			for (int n : classes) {
-				String clazz = (String) pool[n];
-				if (clazz.endsWith(";") || clazz.startsWith("["))
-					parseReference(clazz, 0);
-				else {
-
-					String pack = getPackage(clazz);
-					packageReference(pack);
-				}
-			}
-
-			//
-			// Parse all the descriptors we found
-			//
-
-			for (Iterator<Integer> e = descriptors.iterator(); e.hasNext();) {
-				Integer index = e.next();
-				String prototype = (String) pool[index.intValue()];
-				if (prototype != null)
-					parseDescriptor(prototype);
-				else
-					System.err.println("Unrecognized descriptor: " + index);
-			}
-			Set<String> xref = this.xref;
-			reset();
-			return xref;
-		} finally {
-			if (cd != null)
-				cd.classEnd();
-		}
-	}
-
-	private void constantFloat(DataInputStream in, int poolIndex) throws IOException {
-		if (cd != null)
-			pool[poolIndex] = in.readFloat(); // ALU
-		else
-			in.skipBytes(4);
-	}
-
-	private void constantInteger(DataInputStream in, int poolIndex) throws IOException {
-		intPool[poolIndex] = in.readInt();
-		if (cd != null)
-			pool[poolIndex] = intPool[poolIndex];
-	}
-
-	protected void pool(Object[] pool, int[] intPool) {
-	}
-
-	/**
-	 * @param in
-	 * @param poolIndex
-	 * @param tag
-	 * @throws IOException
-	 */
-	protected void nameAndType(DataInputStream in, int poolIndex, byte tag) throws IOException {
-		int name_index = in.readUnsignedShort();
-		int descriptor_index = in.readUnsignedShort();
-		descriptors.add(new Integer(descriptor_index));
-		pool[poolIndex] = new Assoc(tag, name_index, descriptor_index);
-	}
-
-	/**
-	 * @param in
-	 * @param poolIndex
-	 * @param tag
-	 * @throws IOException
-	 */
-	private void methodRef(DataInputStream in, int poolIndex) throws IOException {
-		int class_index = in.readUnsignedShort();
-		int name_and_type_index = in.readUnsignedShort();
-		pool[poolIndex] = new Assoc((byte) 10, class_index, name_and_type_index);
-	}
-
-	/**
-	 * @param in
-	 * @param poolIndex
-	 * @throws IOException
-	 */
-	private void constantString(DataInputStream in, int poolIndex) throws IOException {
-		int string_index = in.readUnsignedShort();
-		intPool[poolIndex] = string_index;
-	}
-
-	/**
-	 * @param in
-	 * @param poolIndex
-	 * @throws IOException
-	 */
-	protected void constantClass(DataInputStream in, int poolIndex) throws IOException {
-		int class_index = in.readUnsignedShort();
-		classes.add(new Integer(class_index));
-		intPool[poolIndex] = class_index;
-		ClassConstant c = new ClassConstant(class_index);
-		pool[poolIndex] = c;
-	}
-
-	/**
-	 * @param in
-	 * @throws IOException
-	 */
-	protected void constantDouble(DataInputStream in, int poolIndex) throws IOException {
-		if (cd != null)
-			pool[poolIndex] = in.readDouble();
-		else
-			in.skipBytes(8);
-	}
-
-	/**
-	 * @param in
-	 * @throws IOException
-	 */
-	protected void constantLong(DataInputStream in, int poolIndex) throws IOException {
-		if (cd != null) {
-			pool[poolIndex] = in.readLong();
-		} else
-			in.skipBytes(8);
-	}
-
-	/**
-	 * @param in
-	 * @param poolIndex
-	 * @throws IOException
-	 */
-	protected void constantUtf8(DataInputStream in, int poolIndex) throws IOException {
-		// CONSTANT_Utf8
-
-		String name = in.readUTF();
-		xref.add(name);
-		pool[poolIndex] = name;
-	}
-
-	/**
-	 * Find a method reference in the pool that points to the given class,
-	 * methodname and descriptor.
-	 * 
-	 * @param clazz
-	 * @param methodname
-	 * @param descriptor
-	 * @return index in constant pool
-	 */
-	private int findMethodReference(String clazz, String methodname, String descriptor) {
-		for (int i = 1; i < pool.length; i++) {
-			if (pool[i] instanceof Assoc) {
-				Assoc methodref = (Assoc) pool[i];
-				if (methodref.tag == 10) {
-					// Method ref
-					int class_index = methodref.a;
-					int class_name_index = intPool[class_index];
-					if (clazz.equals(pool[class_name_index])) {
-						int name_and_type_index = methodref.b;
-						Assoc name_and_type = (Assoc) pool[name_and_type_index];
-						if (name_and_type.tag == 12) {
-							// Name and Type
-							int name_index = name_and_type.a;
-							int type_index = name_and_type.b;
-							if (methodname.equals(pool[name_index])) {
-								if (descriptor.equals(pool[type_index])) {
-									return i;
-								}
-							}
-						}
-					}
-				}
-			}
-		}
-		return -1;
-	}
-
-	/**
-	 * Called for each attribute in the class, field, or method.
-	 * 
-	 * @param in
-	 *            The stream
-	 * @throws IOException
-	 */
-	private void doAttributes(DataInputStream in, ElementType member, boolean crawl)
-			throws IOException {
-		int attributesCount = in.readUnsignedShort();
-		for (int j = 0; j < attributesCount; j++) {
-			// skip name CONSTANT_Utf8 pointer
-			doAttribute(in, member, crawl);
-		}
-	}
-
-	/**
-	 * Process a single attribute, if not recognized, skip it.
-	 * 
-	 * @param in
-	 *            the data stream
-	 * @throws IOException
-	 */
-	private void doAttribute(DataInputStream in, ElementType member, boolean crawl)
-			throws IOException {
-		int attribute_name_index = in.readUnsignedShort();
-		String attributeName = (String) pool[attribute_name_index];
-		long attribute_length = in.readInt();
-		attribute_length &= 0xFFFFFFFF;
-		if ("RuntimeVisibleAnnotations".equals(attributeName))
-			doAnnotations(in, member, RetentionPolicy.RUNTIME);
-		else if ("RuntimeVisibleParameterAnnotations".equals(attributeName))
-			doParameterAnnotations(in, member, RetentionPolicy.RUNTIME);
-		else if ("RuntimeInvisibleAnnotations".equals(attributeName))
-			doAnnotations(in, member, RetentionPolicy.CLASS);
-		else if ("RuntimeInvisibleParameterAnnotations".equals(attributeName))
-			doParameterAnnotations(in, member, RetentionPolicy.CLASS);
-		else if ("InnerClasses".equals(attributeName))
-			doInnerClasses(in);
-		else if ("EnclosingMethod".equals(attributeName))
-			doEnclosingMethod(in);
-		else if ("SourceFile".equals(attributeName))
-			doSourceFile(in);
-		else if ("Code".equals(attributeName) && crawl)
-			doCode(in);
-		else if ("Signature".equals(attributeName))
-			doSignature(in, member);
-		else if ("ConstantValue".equals(attributeName))
-			doConstantValue(in);
-		else {
-			if (attribute_length > 0x7FFFFFFF) {
-				throw new IllegalArgumentException("Attribute > 2Gb");
-			}
-			in.skipBytes((int) attribute_length);
-		}
-	}
-
-	/**
-	 * <pre>
-	 * EnclosingMethod_attribute { 
-	 * 	u2 attribute_name_index; 
-	 * 	u4 attribute_length; 
-	 * 	u2 class_index
-	 * 	u2 method_index;
-	 * }
-	 * </pre>
-	 * 
-	 * 
-	 * @param in
-	 * @throws IOException
-	 */
-	private void doEnclosingMethod(DataInputStream in) throws IOException {
-		int cIndex = in.readShort();
-		int mIndex = in.readShort();
-
-		if (cd != null) {
-			int nameIndex = intPool[cIndex];
-			String cName = (String) pool[nameIndex];
-
-			String mName = null;
-			String mDescriptor = null;
-
-			if (mIndex != 0) {
-				Assoc nameAndType = (Assoc) pool[mIndex];
-				mName = (String) pool[nameAndType.a];
-				mDescriptor = (String) pool[nameAndType.b];
-			}
-			cd.enclosingMethod(cName, mName, mDescriptor);
-		}
-	}
-
-	/**
-	 * <pre>
-	 * InnerClasses_attribute {
-	 * 	u2 attribute_name_index; 
-	 * 	u4 attribute_length; 
-	 * 	u2 number_of_classes; {	
-	 * 		u2 inner_class_info_index;
-	 * 		u2 outer_class_info_index; 
-	 * 		u2 inner_name_index; 
-	 * 		u2 inner_class_access_flags;
-	 * 	} classes[number_of_classes];
-	 * }
-	 * </pre>
-	 * 
-	 * @param in
-	 * @throws IOException
-	 */
-	private void doInnerClasses(DataInputStream in) throws IOException {
-		int number_of_classes = in.readShort();
-		for (int i = 0; i < number_of_classes; i++) {
-			int inner_class_info_index = in.readShort();
-			int outer_class_info_index = in.readShort();
-			int inner_name_index = in.readShort();
-			int inner_class_access_flags = in.readShort() & 0xFFFF;
-
-			if (cd != null) {
-				String innerClass = null;
-				String outerClass = null;
-				String innerName = null;
-
-				if (inner_class_info_index != 0) {
-					int nameIndex = intPool[inner_class_info_index];
-					innerClass = (String) pool[nameIndex];
-				}
-
-				if (outer_class_info_index != 0) {
-					int nameIndex = intPool[outer_class_info_index];
-					outerClass = (String) pool[nameIndex];
-				}
-
-				if (inner_name_index != 0)
-					innerName = (String) pool[inner_name_index];
-
-				cd.innerClass(innerClass, outerClass, innerName, inner_class_access_flags);
-			}
-		}
-	}
-
-	/**
-	 * Handle a signature
-	 * 
-	 * <pre>
-	 * Signature_attribute { 
-	 *     u2 attribute_name_index; 
-	 *     u4 attribute_length; 
-	 *     u2 signature_index; 
-	 *     }
-	 * </pre>
-	 * 
-	 * @param member
-	 */
-
-	void doSignature(DataInputStream in, ElementType member) throws IOException {
-		int signature_index = in.readUnsignedShort();
-		String signature = (String) pool[signature_index];
-
-		// System.out.println("Signature " + signature );
-
-		// The type signature is kind of weird,
-		// lets skip it for now. Seems to be some kind of
-		// type variable name index but it does not seem to
-		// conform to the language specification.
-		if (member != ElementType.TYPE)
-			parseDescriptor(signature);
-
-		if (last != null)
-			last.signature = signature;
-
-		if (cd != null)
-			cd.signature(signature);
-	}
-
-	/**
-	 * Handle a constant value call the data collector with it
-	 */
-	void doConstantValue(DataInputStream in) throws IOException {
-		int constantValue_index = in.readUnsignedShort();
-		if (cd == null)
-			return;
-
-		Object object = pool[constantValue_index];
-		if (object == null)
-			object = pool[intPool[constantValue_index]];
-
-		last.constant = object;
-		cd.constant(object);
-	}
-
-	/**
-	 * <pre>
-	 * Code_attribute {
-	 * 		u2 attribute_name_index;
-	 * 		u4 attribute_length;
-	 * 		u2 max_stack;
-	 * 		u2 max_locals;
-	 * 		u4 code_length;
-	 * 		u1 code[code_length];
-	 * 		u2 exception_table_length;
-	 * 		{    	u2 start_pc;
-	 * 		      	u2 end_pc;
-	 * 		      	u2  handler_pc;
-	 * 		      	u2  catch_type;
-	 * 		}	exception_table[exception_table_length];
-	 * 		u2 attributes_count;
-	 * 		attribute_info attributes[attributes_count];
-	 * 	}
-	 * </pre>
-	 * 
-	 * @param in
-	 * @param pool
-	 * @throws IOException
-	 */
-	private void doCode(DataInputStream in) throws IOException {
-		/* int max_stack = */in.readUnsignedShort();
-		/* int max_locals = */in.readUnsignedShort();
-		int code_length = in.readInt();
-		byte code[] = new byte[code_length];
-		in.readFully(code);
-		crawl(code);
-		int exception_table_length = in.readUnsignedShort();
-		in.skipBytes(exception_table_length * 8);
-		doAttributes(in, ElementType.METHOD, false);
-	}
-
-	/**
-	 * We must find Class.forName references ...
-	 * 
-	 * @param code
-	 */
-	protected void crawl(byte[] code) {
-		ByteBuffer bb = ByteBuffer.wrap(code);
-		bb.order(ByteOrder.BIG_ENDIAN);
-		int lastReference = -1;
-
-		while (bb.remaining() > 0) {
-			int instruction = 0xFF & bb.get();
-			switch (instruction) {
-			case OpCodes.ldc:
-				lastReference = 0xFF & bb.get();
-				break;
-
-			case OpCodes.ldc_w:
-				lastReference = 0xFFFF & bb.getShort();
-				break;
-
-			case OpCodes.invokespecial: {
-				int mref = 0xFFFF & bb.getShort();
-				if (cd != null)
-					cd.reference(getMethodDef(0, mref));
-				break;
-			}
-
-			case OpCodes.invokevirtual: {
-				int mref = 0xFFFF & bb.getShort();
-				if (cd != null)
-					cd.reference(getMethodDef(0, mref));
-				break;
-			}
-
-			case OpCodes.invokeinterface: {
-				int mref = 0xFFFF & bb.getShort();
-				if (cd != null)
-					cd.reference(getMethodDef(0, mref));
-				break;
-			}
-
-			case OpCodes.invokestatic: {
-				int methodref = 0xFFFF & bb.getShort();
-				if (cd != null)
-					cd.reference(getMethodDef(0, methodref));
-
-				if ((methodref == forName || methodref == class$) && lastReference != -1
-						&& pool[intPool[lastReference]] instanceof String) {
-					String clazz = (String) pool[intPool[lastReference]];
-					if (clazz.startsWith("[") || clazz.endsWith(";"))
-						parseReference(clazz, 0);
-					else {
-						int n = clazz.lastIndexOf('.');
-						if (n > 0)
-							packageReference(clazz.substring(0, n));
-					}
-				}
-				break;
-			}
-
-			case OpCodes.tableswitch:
-				// Skip to place divisible by 4
-				while ((bb.position() & 0x3) != 0)
-					bb.get();
-				/* int deflt = */
-				bb.getInt();
-				int low = bb.getInt();
-				int high = bb.getInt();
-				try {
-					bb.position(bb.position() + (high - low + 1) * 4);
-				} catch (Exception e) {
-					// TODO Auto-generated catch block
-					e.printStackTrace();
-				}
-				lastReference = -1;
-				break;
-
-			case OpCodes.lookupswitch:
-				// Skip to place divisible by 4
-				while ((bb.position() & 0x3) != 0)
-					bb.get();
-				/* deflt = */
-				bb.getInt();
-				int npairs = bb.getInt();
-				bb.position(bb.position() + npairs * 8);
-				lastReference = -1;
-				break;
-
-			default:
-				lastReference = -1;
-				bb.position(bb.position() + OpCodes.OFFSETS[instruction]);
-			}
-		}
-	}
-
-	private void doSourceFile(DataInputStream in) throws IOException {
-		int sourcefile_index = in.readUnsignedShort();
-		this.sourceFile = pool[sourcefile_index].toString();
-	}
-
-	private void doParameterAnnotations(DataInputStream in, ElementType member,
-			RetentionPolicy policy) throws IOException {
-		int num_parameters = in.readUnsignedByte();
-		for (int p = 0; p < num_parameters; p++) {
-			if (cd != null)
-				cd.parameter(p);
-			doAnnotations(in, member, policy);
-		}
-	}
-
-	private void doAnnotations(DataInputStream in, ElementType member, RetentionPolicy policy)
-			throws IOException {
-		int num_annotations = in.readUnsignedShort(); // # of annotations
-		for (int a = 0; a < num_annotations; a++) {
-			if (cd == null)
-				doAnnotation(in, member, policy, false);
-			else {
-				Annotation annotion = doAnnotation(in, member, policy, true);
-				cd.annotation(annotion);
-			}
-		}
-	}
-
-	private Annotation doAnnotation(DataInputStream in, ElementType member, RetentionPolicy policy,
-			boolean collect) throws IOException {
-		int type_index = in.readUnsignedShort();
-		if (annotations == null)
-			annotations = new HashSet<String>();
-
-		annotations.add(pool[type_index].toString());
-
-		if (policy == RetentionPolicy.RUNTIME) {
-			descriptors.add(new Integer(type_index));
-			hasRuntimeAnnotations = true;
-		} else {
-			hasClassAnnotations = true;
-		}
-		String name = (String) pool[type_index];
-		int num_element_value_pairs = in.readUnsignedShort();
-		Map<String, Object> elements = null;
-		for (int v = 0; v < num_element_value_pairs; v++) {
-			int element_name_index = in.readUnsignedShort();
-			String element = (String) pool[element_name_index];
-			Object value = doElementValue(in, member, policy, collect);
-			if (collect) {
-				if (elements == null)
-					elements = new LinkedHashMap<String, Object>();
-				elements.put(element, value);
-			}
-		}
-		if (collect)
-			return new Annotation(name, elements, member, policy);
-		else
-			return null;
-	}
-
-	private Object doElementValue(DataInputStream in, ElementType member, RetentionPolicy policy,
-			boolean collect) throws IOException {
-		char tag = (char) in.readUnsignedByte();
-		switch (tag) {
-		case 'B': // Byte
-		case 'C': // Character
-		case 'I': // Integer
-		case 'S': // Short
-			int const_value_index = in.readUnsignedShort();
-			return intPool[const_value_index];
-
-		case 'D': // Double
-		case 'F': // Float
-		case 's': // String
-		case 'J': // Long
-			const_value_index = in.readUnsignedShort();
-			return pool[const_value_index];
-
-		case 'Z': // Boolean
-			const_value_index = in.readUnsignedShort();
-			return pool[const_value_index] == null || pool[const_value_index].equals(0) ? false : true;
-
-		case 'e': // enum constant
-			int type_name_index = in.readUnsignedShort();
-			if (policy == RetentionPolicy.RUNTIME)
-				descriptors.add(new Integer(type_name_index));
-			int const_name_index = in.readUnsignedShort();
-			return pool[const_name_index];
-
-		case 'c': // Class
-			int class_info_index = in.readUnsignedShort();
-			if (policy == RetentionPolicy.RUNTIME)
-				descriptors.add(new Integer(class_info_index));
-			return pool[class_info_index];
-
-		case '@': // Annotation type
-			return doAnnotation(in, member, policy, collect);
-
-		case '[': // Array
-			int num_values = in.readUnsignedShort();
-			Object[] result = new Object[num_values];
-			for (int i = 0; i < num_values; i++) {
-				result[i] = doElementValue(in, member, policy, collect);
-			}
-			return result;
-
-		default:
-			throw new IllegalArgumentException("Invalid value for Annotation ElementValue tag "
-					+ tag);
-		}
-	}
-
-	/**
-	 * Add a new package reference.
-	 * 
-	 * @param pack
-	 *            A '.' delimited package name
-	 */
-	void packageReference(String pack) {
-		imports.add(pack);
-	}
-
-	/**
-	 * This method parses a descriptor and adds the package of the descriptor to
-	 * the referenced packages.
-	 * 
-	 * The syntax of the descriptor is:
-	 * 
-	 * <pre>
-	 *   descriptor ::= ( '(' reference * ')' )? reference
-	 *   reference  ::= 'L' classname ( '<' references '>' )? ';' | 'B' | 'Z' | ... | '+' | '-' | '['
-	 * </pre>
-	 * 
-	 * This methods uses heavy recursion to parse the descriptor and a roving
-	 * pointer to limit the creation of string objects.
-	 * 
-	 * @param descriptor
-	 *            The to be parsed descriptor
-	 * @param rover
-	 *            The pointer to start at
-	 */
-	public void parseDescriptor(String descriptor) {
-		// Some descriptors are weird, they start with a generic
-		// declaration that contains ':', not sure what they mean ...
-		if (descriptor.charAt(0) == '<')
-			return;
-
-		int rover = 0;
-		if (descriptor.charAt(rover) == '(') {
-			rover = parseReferences(descriptor, rover + 1, ')');
-			rover++;
-		}
-		parseReferences(descriptor, rover, (char) 0);
-	}
-
-	/**
-	 * Parse a sequence of references. A sequence ends with a given character or
-	 * when the string ends.
-	 * 
-	 * @param descriptor
-	 *            The whole descriptor.
-	 * @param rover
-	 *            The index in the descriptor
-	 * @param delimiter
-	 *            The end character or 0
-	 * @return the last index processed, one character after the delimeter
-	 */
-	int parseReferences(String descriptor, int rover, char delimiter) {
-		while (rover < descriptor.length() && descriptor.charAt(rover) != delimiter) {
-			rover = parseReference(descriptor, rover);
-		}
-		return rover;
-	}
-
-	/**
-	 * Parse a single reference. This can be a single character or an object
-	 * reference when it starts with 'L'.
-	 * 
-	 * @param descriptor
-	 *            The descriptor
-	 * @param rover
-	 *            The place to start
-	 * @return The return index after the reference
-	 */
-	int parseReference(String descriptor, int rover) {
-
-		char c = descriptor.charAt(rover);
-		while (c == '[')
-			c = descriptor.charAt(++rover);
-
-		if (c == '<') {
-			rover = parseReferences(descriptor, rover + 1, '>');
-		} else if (c == 'T') {
-			// Type variable name
-			rover++;
-			while (descriptor.charAt(rover) != ';')
-				rover++;
-		} else if (c == 'L') {
-			StringBuilder sb = new StringBuilder();
-			rover++;
-			int lastSlash = -1;
-			while ((c = descriptor.charAt(rover)) != ';') {
-				if (c == '<') {
-					rover = parseReferences(descriptor, rover + 1, '>');
-				} else if (c == '/') {
-					lastSlash = sb.length();
-					sb.append('.');
-				} else
-					sb.append(c);
-				rover++;
-			}
-			if (cd != null)
-				cd.addReference(sb.toString());
-
-			if (lastSlash > 0)
-				packageReference(sb.substring(0, lastSlash));
-		} else {
-			if ("+-*BCDFIJSZV".indexOf(c) < 0)
-				;// System.out.println("Should not skip: " + c);
-		}
-
-		// this skips a lot of characters
-		// [, *, +, -, B, etc.
-
-		return rover + 1;
-	}
-
-	public static String getPackage(String clazz) {
-		int n = clazz.lastIndexOf('/');
-		if (n < 0) {
-			n = clazz.lastIndexOf('.');
-			if (n < 0)
-				return ".";
-		}
-		return clazz.substring(0, n).replace('/', '.');
-	}
-
-	public Set<String> getReferred() {
-		return imports;
-	}
-
-	String getClassName() {
-		if (className == null)
-			return "NOCLASSNAME";
-		return className;
-	}
-
-	public String getPath() {
-		return path;
-	}
-
-	public String getSourceFile() {
-		return sourceFile;
-	}
-
-	/**
-	 * .class construct for different compilers
-	 * 
-	 * sun 1.1 Detect static variable class$com$acme$MyClass 1.2 " 1.3 " 1.4 "
-	 * 1.5 ldc_w (class) 1.6 "
-	 * 
-	 * eclipse 1.1 class$0, ldc (string), invokestatic Class.forName 1.2 " 1.3 "
-	 * 1.5 ldc (class) 1.6 "
-	 * 
-	 * 1.5 and later is not an issue, sun pre 1.5 is easy to detect the static
-	 * variable that decodes the class name. For eclipse, the class$0 gives away
-	 * we have a reference encoded in a string.
-	 * compilerversions/compilerversions.jar contains test versions of all
-	 * versions/compilers.
-	 */
-
-	public void reset() {
-		pool = null;
-		intPool = null;
-		xref = null;
-		classes = null;
-		descriptors = null;
-	}
-
-	public boolean is(QUERY query, Instruction instr, Analyzer analyzer) throws Exception {
-		switch (query) {
-		case ANY:
-			return true;
-
-		case NAMED:
-			if (instr.matches(getClassName()))
-				return !instr.isNegated();
-			return false;
-
-		case VERSION:
-			String v = major + "/" + minor;
-			if (instr.matches(v))
-				return !instr.isNegated();
-			return false;
-
-		case IMPLEMENTS:
-			for (int i = 0; interfaces != null && i < interfaces.length; i++) {
-				if (instr.matches(interfaces[i]))
-					return !instr.isNegated();
-			}
-			break;
-
-		case EXTENDS:
-			if (zuper == null)
-				return false;
-
-			if (instr.matches(zuper))
-				return !instr.isNegated();
-			break;
-
-		case PUBLIC:
-			return !isPublic;
-
-		case CONCRETE:
-			return !isAbstract;
-
-		case ANNOTATION:
-			if (annotations == null)
-				return false;
-
-			if (annotations.contains(instr.getPattern()))
-				return true;
-
-			for (String annotation : annotations) {
-				if (instr.matches(annotation))
-					return !instr.isNegated();
-			}
-
-			return false;
-
-		case RUNTIMEANNOTATIONS:
-			return hasClassAnnotations;
-		case CLASSANNOTATIONS:
-			return hasClassAnnotations;
-
-		case ABSTRACT:
-			return isAbstract;
-
-		case IMPORTS:
-			for (String imp : imports) {
-				if (instr.matches(imp.replace('.', '/')))
-					return !instr.isNegated();
-			}
-		}
-
-		if (zuper == null)
-			return false;
-
-		Clazz clazz = analyzer.findClass(zuper + ".class");
-		if (clazz == null)
-			return false;
-
-		return clazz.is(query, instr, analyzer);
-	}
-
-	public String toString() {
-		return getFQN();
-	}
-
-	public String getFQN() {
-		String s = getClassName().replace('/', '.');
-		return s;
-	}
-
-	/**
-	 * Return a list of packages implemented by this class.
-	 * 
-	 * @param implemented
-	 * @param classspace
-	 * @param clazz
-	 * @throws Exception
-	 */
-	@SuppressWarnings("deprecation") final static String	USEPOLICY		= toDescriptor(UsePolicy.class);
-	final static String										PROVIDERPOLICY	= toDescriptor(ProviderType.class);
-
-	public static void getImplementedPackages(Set<String> implemented, Analyzer analyzer,
-			Clazz clazz) throws Exception {
-		if (clazz.interfaces != null) {
-			for (String interf : clazz.interfaces) {
-				interf = interf + ".class";
-				Clazz c = analyzer.getClassspace().get(interf);
-
-				// If not found, actually parse the imported
-				// class file to check for implementation policy.
-				if (c == null)
-					c = analyzer.findClass(interf);
-
-				if (c != null) {
-					boolean consumer = false;
-					Set<String> annotations = c.annotations;
-					if (annotations != null)
-						// Override if we marked the interface as a consumer
-						// interface
-						consumer = annotations.contains(USEPOLICY)
-								|| annotations.contains(PROVIDERPOLICY);
-
-					if (!consumer)
-						implemented.add(getPackage(interf));
-					getImplementedPackages(implemented, analyzer, c);
-				} else
-					implemented.add(getPackage(interf));
-
-			}
-		}
-		if (clazz.zuper != null) {
-			Clazz c = analyzer.getClassspace().get(clazz.zuper);
-			if (c != null) {
-				getImplementedPackages(implemented, analyzer, c);
-			}
-		}
-
-	}
-
-	// String RNAME = "LaQute/bnd/annotation/UsePolicy;";
-
-	public static String toDescriptor(Class<?> clazz) {
-		StringBuilder sb = new StringBuilder();
-		sb.append('L');
-		sb.append(clazz.getName().replace('.', '/'));
-		sb.append(';');
-		return sb.toString();
-	}
-
-	MethodDef getMethodDef(int access, int methodRefPoolIndex) {
-		Object o = pool[methodRefPoolIndex];
-		if (o != null && o instanceof Assoc) {
-			Assoc assoc = (Assoc) o;
-			if (assoc.tag == 10) {
-				int string_index = intPool[assoc.a];
-				String className = (String) pool[string_index];
-				int name_and_type_index = assoc.b;
-				Assoc name_and_type = (Assoc) pool[name_and_type_index];
-				if (name_and_type.tag == 12) {
-					// Name and Type
-					int name_index = name_and_type.a;
-					int type_index = name_and_type.b;
-					String method = (String) pool[name_index];
-					String descriptor = (String) pool[type_index];
-					return new MethodDef(access, className, method, descriptor);
-				} else
-					throw new IllegalArgumentException(
-							"Invalid class file (or parsing is wrong), assoc is not type + name (12)");
-			} else
-				throw new IllegalArgumentException(
-						"Invalid class file (or parsing is wrong), Assoc is not method ref! (10)");
-		} else
-			throw new IllegalArgumentException(
-					"Invalid class file (or parsing is wrong), Not an assoc at a method ref");
-	}
-
-	public static String getShortName(String cname) {
-		int n = cname.lastIndexOf('.');
-		if (n < 0)
-			return cname;
-		return cname.substring(n + 1, cname.length());
-	}
-
-	public static String fqnToPath(String dotted) {
-		return dotted.replace('.', '/') + ".class";
-	}
-
-	public static String fqnToBinary(String dotted) {
-		return "L" + dotted.replace('.', '/') + ";";
-	}
-
-	public static String pathToFqn(String path) {
-		return path.replace('/', '.').substring(0, path.length() - 6);
-	}
-
-	public boolean isPublic() {
-		return isPublic;
-	}
-
-	public boolean isEnum() {
-		return isEnum;
-	}
-
-	public JAVA getFormat() {
-		return JAVA.format(major);
-
-	}
-
-	public static String objectDescriptorToFQN(String string) {
-		if (string.startsWith("L") && string.endsWith(";"))
-			return string.substring(1, string.length() - 1).replace('/', '.');
-
-		switch (string.charAt(0)) {
-		case 'V':
-			return "void";
-		case 'B':
-			return "byte";
-		case 'C':
-			return "char";
-		case 'I':
-			return "int";
-		case 'S':
-			return "short";
-		case 'D':
-			return "double";
-		case 'F':
-			return "float";
-		case 'J':
-			return "long";
-		case 'Z':
-			return "boolean";
-		case '[': // Array
-			return objectDescriptorToFQN(string.substring(1)) + "[]";
-		}
-		throw new IllegalArgumentException("Invalid type character in descriptor " + string);
-	}
-
-	public static String internalToFqn(String string) {
-		return string.replace('/', '.');
-	}
-
-	public static String unCamel(String id) {
-		StringBuilder out = new StringBuilder();
-		for (int i = 0; i < id.length(); i++) {
-			char c = id.charAt(i);
-			if (c == '_' || c == '$' || c == '.') {
-				if (out.length() > 0 && !Character.isWhitespace(out.charAt(out.length() - 1)))
-					out.append(' ');
-				continue;
-			}
-
-			int n = i;
-			while (n < id.length() && Character.isUpperCase(id.charAt(n))) {
-				n++;
-			}
-			if (n == i)
-				out.append(id.charAt(i));
-			else {
-				boolean tolower = (n - i) == 1;
-				if (i > 0 && !Character.isWhitespace(out.charAt(out.length() - 1)))
-					out.append(' ');
-
-				for (; i < n;) {
-					if (tolower)
-						out.append(Character.toLowerCase(id.charAt(i)));
-					else
-						out.append(id.charAt(i));
-					i++;
-				}
-				i--;
-			}
-		}
-		if (id.startsWith("."))
-			out.append(" *");
-		out.replace(0, 1, Character.toUpperCase(out.charAt(0)) + "");
-		return out.toString();
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/Constants.java b/biz.aQute.bndlib/src/aQute/lib/osgi/Constants.java
deleted file mode 100644
index 8410a3e..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/Constants.java
+++ /dev/null
@@ -1,295 +0,0 @@
-package aQute.lib.osgi;
-
-import java.nio.charset.*;
-import java.util.*;
-import java.util.regex.*;
-
-public interface Constants {
-	/*
-	 * Defined in OSGi
-	 */
-	/**
-	 * @syntax Bundle-ActivationPolicy ::= policy ( ’;’ directive )* policy ::=
-	 *         ’lazy’
-	 */
-	String					BND_ADDXMLTOTEST							= "Bnd-AddXMLToTest";
-	String					BUNDLE_ACTIVATIONPOLICY						= "Bundle-ActivationPolicy";
-	String					BUNDLE_ACTIVATOR							= "Bundle-Activator";
-	String					BUNDLE_BLUEPRINT							= "Bundle-Copyright";
-	String					BUNDLE_CATEGORY								= "Bundle-Category";
-	String					BUNDLE_CLASSPATH							= "Bundle-ClassPath";
-	String					BUNDLE_CONTACTADDRESS						= "Bundle-ContactAddress";
-	String					BUNDLE_COPYRIGHT							= "Bundle-Copyright";
-	String					BUNDLE_DESCRIPTION							= "Bundle-Description";
-	String					BUNDLE_DOCURL								= "Bundle-DocURL";
-	String					BUNDLE_ICON									= "Bundle-Icon";
-	String					BUNDLE_LICENSE								= "Bundle-License";
-	String					BUNDLE_LOCALIZATION							= "Bundle-Localization";
-	String					BUNDLE_MANIFESTVERSION						= "Bundle-ManifestVersion";
-	String					BUNDLE_NAME									= "Bundle-Name";
-	String					BUNDLE_NATIVECODE							= "Bundle-NativeCode";
-	String					BUNDLE_REQUIREDEXECUTIONENVIRONMENT			= "Bundle-RequiredExecutionEnvironment";
-	String					BUNDLE_SYMBOLICNAME							= "Bundle-SymbolicName";
-	String					BUNDLE_UPDATELOCATION						= "Bundle-UpdateLocation";
-	String					BUNDLE_VENDOR								= "Bundle-Vendor";
-	String					BUNDLE_VERSION								= "Bundle-Version";
-	String					DYNAMICIMPORT_PACKAGE						= "DynamicImport-Package";
-	String					EXPORT_PACKAGE								= "Export-Package";
-	String					EXPORT_SERVICE								= "Export-Service";
-	String					FRAGMENT_HOST								= "Fragment-Host";
-	String					IMPORT_PACKAGE								= "Import-Package";
-	String					IMPORT_SERVICE								= "Import-Service";
-	String					REQUIRE_BUNDLE								= "Require-Bundle";
-	String					SERVICE_COMPONENT							= "Service-Component";
-
-	String					PRIVATE_PACKAGE								= "Private-Package";
-	String					IGNORE_PACKAGE								= "Ignore-Package";
-	String					INCLUDE_RESOURCE							= "Include-Resource";
-	String					CONDITIONAL_PACKAGE							= "Conditional-Package";
-	String					BND_LASTMODIFIED							= "Bnd-LastModified";
-	String					CREATED_BY									= "Created-By";
-	String					TOOL										= "Tool";
-	String					TESTCASES									= "Test-Cases";
-	String					SIGNATURE_TEST								= "-signaturetest";
-
-	String					headers[]									= { BUNDLE_ACTIVATOR,
-			BUNDLE_CONTACTADDRESS, BUNDLE_COPYRIGHT, BUNDLE_DESCRIPTION, BUNDLE_DOCURL,
-			BUNDLE_LOCALIZATION, BUNDLE_NATIVECODE, BUNDLE_VENDOR, BUNDLE_VERSION, BUNDLE_LICENSE,
-			BUNDLE_CLASSPATH, SERVICE_COMPONENT, EXPORT_PACKAGE, IMPORT_PACKAGE,
-			BUNDLE_LOCALIZATION, BUNDLE_MANIFESTVERSION, BUNDLE_NAME, BUNDLE_NATIVECODE,
-			BUNDLE_REQUIREDEXECUTIONENVIRONMENT, BUNDLE_SYMBOLICNAME, BUNDLE_VERSION,
-			FRAGMENT_HOST, PRIVATE_PACKAGE, IGNORE_PACKAGE, INCLUDE_RESOURCE, REQUIRE_BUNDLE,
-			IMPORT_SERVICE, EXPORT_SERVICE, CONDITIONAL_PACKAGE, BND_LASTMODIFIED, TESTCASES,
-			SIGNATURE_TEST												};
-
-	String					BUILDPATH									= "-buildpath";
-	String					BUILDPACKAGES								= "-buildpackages";
-	String					BUMPPOLICY									= "-bumppolicy";
-	String					CONDUIT										= "-conduit";
-	String					COMPILER_SOURCE								= "-source";
-	String					COMPILER_TARGET								= "-target";
-	String					DEPENDSON									= "-dependson";
-	String					DEPLOY										= "-deploy";
-	String					DEPLOYREPO									= "-deployrepo";
-	String					DONOTCOPY									= "-donotcopy";
-	String					DEBUG										= "-debug";
-	String					EXPORT_CONTENTS								= "-exportcontents";
-	String					FAIL_OK										= "-failok";
-	String					INCLUDE										= "-include";
-	String					INCLUDERESOURCE								= "-includeresource";
-	String					MAKE										= "-make";
-	String					METATYPE									= "-metatype";
-	String					MANIFEST									= "-manifest";
-	String					SAVEMANIFEST								= "-savemanifest";
-	String					NAMESECTION									= "-namesection";
-	String					NODEFAULTVERSION							= "-nodefaultversion";
-	String					NOEXTRAHEADERS								= "-noextraheaders";
-	String					NOMANIFEST									= "-nomanifest";
-	String					NOUSES										= "-nouses";
-	@Deprecated String		NOPE										= "-nope";
-	String					NOBUNDLES									= "-nobundles";
-	String					PEDANTIC									= "-pedantic";
-	String					PLUGIN										= "-plugin";
-	String					POM											= "-pom";
-	String					RELEASEREPO									= "-releaserepo";
-	String					REMOVEHEADERS								= "-removeheaders";
-	String					RESOURCEONLY								= "-resourceonly";
-	String					SOURCES										= "-sources";
-	String					SOURCEPATH									= "-sourcepath";
-	String					SUB											= "-sub";
-	String					RUNPROPERTIES								= "-runproperties";
-	String					RUNSYSTEMPACKAGES							= "-runsystempackages";
-	String					RUNBUNDLES									= "-runbundles";
-	String					RUNPATH										= "-runpath";
-	String					RUNSTORAGE									= "-runstorage";
-	String					RUNBUILDS									= "-runbuilds";
-	String					RUNPATH_MAIN_DIRECTIVE						= "main:";
-	String					RUNPATH_LAUNCHER_DIRECTIVE					= "launcher:";
-	String					RUNVM										= "-runvm";
-	String					RUNTRACE									= "-runtrace";
-	String					RUNFRAMEWORK								= "-runframework";
-	String					RUNTIMEOUT									= "-runtimeout";
-	String					SNAPSHOT									= "-snapshot";
-	String					RUNFRAMEWORK_SERVICES						= "services";
-	String					RUNFRAMEWORK_NONE							= "none";
-	String					REPORTNEWER									= "-reportnewer";
-	String					SIGN										= "-sign";
-	String					TESTPACKAGES								= "-testpackages";
-	String					TESTREPORT									= "-testreport";
-	String					TESTPATH									= "-testpath";
-	String					TESTCONTINUOUS								= "-testcontinuous";
-	String					UNDERTEST									= "-undertest";
-	String					VERBOSE										= "-verbose";
-	@Deprecated String		VERSIONPOLICY_IMPL							= "-versionpolicy-impl";
-	@Deprecated String		VERSIONPOLICY_USES							= "-versionpolicy-uses";
-	String					PROVIDER_POLICY								= "-provider-policy";
-	String					CONSUMER_POLICY								= "-consumer-policy";
-	@Deprecated String		VERSIONPOLICY								= "-versionpolicy";
-	String					WAB											= "-wab";
-	String					WABLIB										= "-wablib";
-	String					REQUIRE_BND									= "-require-bnd";
-
-	// Deprecated
-	String					CLASSPATH									= "-classpath";
-
-	String					options[]									= { BUILDPATH, BUMPPOLICY,
-			CONDUIT, CLASSPATH, CONSUMER_POLICY, DEPENDSON, DONOTCOPY, EXPORT_CONTENTS, FAIL_OK,
-			INCLUDE, INCLUDERESOURCE, MAKE, MANIFEST, NOEXTRAHEADERS, NOUSES, NOBUNDLES, PEDANTIC,
-			PLUGIN, POM, PROVIDER_POLICY, REMOVEHEADERS, RESOURCEONLY, SOURCES, SOURCEPATH,
-			SOURCES, SOURCEPATH, SUB, RUNBUNDLES, RUNPATH, RUNSYSTEMPACKAGES, RUNPROPERTIES,
-			REPORTNEWER, UNDERTEST, TESTPATH, TESTPACKAGES, TESTREPORT, VERBOSE, NOMANIFEST,
-			DEPLOYREPO, RELEASEREPO, SAVEMANIFEST, RUNVM, WAB, WABLIB, RUNFRAMEWORK, RUNTRACE,
-			TESTCONTINUOUS, SNAPSHOT									};
-
-	// Ignore bundle specific headers. These bundles do not make
-	// a lot of sense to inherit
-	String[]				BUNDLE_SPECIFIC_HEADERS						= new String[] {
-			INCLUDE_RESOURCE, BUNDLE_ACTIVATOR, BUNDLE_CLASSPATH, BUNDLE_NAME, BUNDLE_NATIVECODE,
-			BUNDLE_SYMBOLICNAME, IMPORT_PACKAGE, EXPORT_PACKAGE, DYNAMICIMPORT_PACKAGE,
-			FRAGMENT_HOST, REQUIRE_BUNDLE, PRIVATE_PACKAGE, EXPORT_CONTENTS, TESTCASES, NOMANIFEST,
-			SIGNATURE_TEST, WAB, WABLIB								};
-
-	char					DUPLICATE_MARKER							= '~';
-	String					SPECIFICATION_VERSION						= "specification-version";
-	String					SPLIT_PACKAGE_DIRECTIVE						= "-split-package:";
-	String					IMPORT_DIRECTIVE							= "-import:";
-	String					NO_IMPORT_DIRECTIVE							= "-noimport:";
-	String					REMOVE_ATTRIBUTE_DIRECTIVE					= "-remove-attribute:";
-	String					LIB_DIRECTIVE								= "lib:";
-	String					NOANNOTATIONS								= "-noannotations";
-	String					COMMAND_DIRECTIVE							= "command:";
-	String					USES_DIRECTIVE								= "uses:";
-	String					MANDATORY_DIRECTIVE							= "mandatory:";
-	String					INCLUDE_DIRECTIVE							= "include:";
-	String					PROVIDE_DIRECTIVE							= "provide:";
-	String					EXCLUDE_DIRECTIVE							= "exclude:";
-	String					PRESENCE_DIRECTIVE							= "presence:";
-	String					PRIVATE_DIRECTIVE							= "private:";
-	String					SINGLETON_DIRECTIVE							= "singleton:";
-	String					EXTENSION_DIRECTIVE							= "extension:";
-	String					VISIBILITY_DIRECTIVE						= "visibility:";
-	String					FRAGMENT_ATTACHMENT_DIRECTIVE				= "fragment-attachment:";
-	String					RESOLUTION_DIRECTIVE						= "resolution:";
-	String					PATH_DIRECTIVE								= "path:";
-	String					SIZE_ATTRIBUTE								= "size";
-	String					LINK_ATTRIBUTE								= "link";
-	String					NAME_ATTRIBUTE								= "name";
-	String					DESCRIPTION_ATTRIBUTE						= "description";
-	String					OSNAME_ATTRIBUTE							= "osname";
-	String					OSVERSION_ATTRIBUTE							= "osversion";
-	String					PROCESSOR_ATTRIBUTE							= "processor";
-	String					LANGUAGE_ATTRIBUTE							= "language";
-	String					SELECTION_FILTER_ATTRIBUTE					= "selection-filter";
-	String					BLUEPRINT_WAIT_FOR_DEPENDENCIES_ATTRIBUTE	= "blueprint.wait-for-dependencies";
-	String					BLUEPRINT_TIMEOUT_ATTRIBUTE					= "blueprint.timeout";
-	String					VERSION_ATTRIBUTE							= "version";
-	String					BUNDLE_SYMBOLIC_NAME_ATTRIBUTE				= "bundle-symbolic-name";
-	String					BUNDLE_VERSION_ATTRIBUTE					= "bundle-version";
-	String					FROM_DIRECTIVE								= "from:";
-
-	String					KEYSTORE_LOCATION_DIRECTIVE					= "keystore:";
-	String					KEYSTORE_PROVIDER_DIRECTIVE					= "provider:";
-	String					KEYSTORE_PASSWORD_DIRECTIVE					= "password:";
-	String					SIGN_PASSWORD_DIRECTIVE						= "sign-password:";
-
-	String					NONE										= "none";
-
-	String					directives[]								= {
-			SPLIT_PACKAGE_DIRECTIVE, NO_IMPORT_DIRECTIVE, IMPORT_DIRECTIVE, RESOLUTION_DIRECTIVE,
-			INCLUDE_DIRECTIVE, USES_DIRECTIVE, EXCLUDE_DIRECTIVE, KEYSTORE_LOCATION_DIRECTIVE,
-			KEYSTORE_PROVIDER_DIRECTIVE, KEYSTORE_PASSWORD_DIRECTIVE, SIGN_PASSWORD_DIRECTIVE,
-			COMMAND_DIRECTIVE, NOANNOTATIONS, LIB_DIRECTIVE, RUNPATH_LAUNCHER_DIRECTIVE,
-			FROM_DIRECTIVE, PRIVATE_DIRECTIVE
-
-																		// TODO
-																		};
-
-	String					USES_USES									= "<<USES>>";
-	String					CURRENT_USES								= "@uses";
-	String					IMPORT_REFERENCE							= "reference";
-	String					IMPORT_PRIVATE								= "private";
-	String[]				importDirectives							= { IMPORT_REFERENCE,
-			IMPORT_PRIVATE												};
-
-	static final Pattern	VALID_PROPERTY_TYPES						= Pattern
-																				.compile("(String|Long|Double|Float|Integer|Byte|Character|Boolean|Short)");
-
-	String					DEFAULT_BND_EXTENSION						= ".bnd";
-	String					DEFAULT_JAR_EXTENSION						= ".jar";
-	String					DEFAULT_BAR_EXTENSION						= ".bar";
-	String					DEFAULT_BNDRUN_EXTENSION					= ".bndrun";
-	String[]				METAPACKAGES								= { "META-INF", "OSGI-INF",
-			"OSGI-OPT"													};
-
-	String					CURRENT_VERSION								= "@";
-	String					CURRENT_PACKAGE								= "@package";
-
-	String					BUILDFILES									= "buildfiles";
-
-	String					EMPTY_HEADER								= "<<EMPTY>>";
-
-	String					EMBEDDED_REPO								= "/embedded-repo.jar";
-	String					LAUNCHER_PLUGIN								= "Launcher-Plugin";
-	String					TESTER_PLUGIN								= "Tester-Plugin";
-
-	String					DEFAULT_LAUNCHER_BSN						= "biz.aQute.launcher";
-	String					DEFAULT_TESTER_BSN							= "biz.aQute.junit";
-
-	String					DEFAULT_DO_NOT_COPY							= "CVS|\\.svn|\\.git|\\.DS_Store";
-
-	Charset					DEFAULT_CHARSET								= Charset.forName("UTF8");
-	String					VERSION_FILTER								= "version";
-
-
-	/**
-	 * Component constants
-	 */
-	public final static String			NAMESPACE_STEM					= "http://www.osgi.org/xmlns/scr";
-	public final static String			JIDENTIFIER						= "<<identifier>>";
-	public final static String			COMPONENT_NAME					= "name:";
-	public final static String			COMPONENT_FACTORY				= "factory:";
-	public final static String			COMPONENT_SERVICEFACTORY		= "servicefactory:";
-	public final static String			COMPONENT_IMMEDIATE				= "immediate:";
-	public final static String			COMPONENT_ENABLED				= "enabled:";
-	public final static String			COMPONENT_DYNAMIC				= "dynamic:";
-	public final static String			COMPONENT_MULTIPLE				= "multiple:";
-	public final static String			COMPONENT_PROVIDE				= "provide:";
-	public final static String			COMPONENT_OPTIONAL				= "optional:";
-	public final static String			COMPONENT_PROPERTIES			= "properties:";
-	public final static String			COMPONENT_IMPLEMENTATION		= "implementation:";
-	public final static String			COMPONENT_DESIGNATE				= "designate:";
-	public final static String			COMPONENT_DESIGNATEFACTORY		= "designateFactory:";
-	public final static String			COMPONENT_DESCRIPTORS			= ".descriptors:";
-
-	// v1.1.0
-	public final static String			COMPONENT_VERSION				= "version:";
-	public final static String			COMPONENT_CONFIGURATION_POLICY	= "configuration-policy:";
-	public final static String			COMPONENT_MODIFIED				= "modified:";
-	public final static String			COMPONENT_ACTIVATE				= "activate:";
-	public final static String			COMPONENT_DEACTIVATE			= "deactivate:";
-
-	final static Map<String, String>	EMPTY							= Collections.emptyMap();
-
-	public final static String[]		componentDirectives				= new String[] {
-			COMPONENT_FACTORY, COMPONENT_IMMEDIATE, COMPONENT_ENABLED, COMPONENT_DYNAMIC,
-			COMPONENT_MULTIPLE, COMPONENT_PROVIDE, COMPONENT_OPTIONAL, COMPONENT_PROPERTIES,
-			COMPONENT_IMPLEMENTATION, COMPONENT_SERVICEFACTORY, COMPONENT_VERSION,
-			COMPONENT_CONFIGURATION_POLICY, COMPONENT_MODIFIED, COMPONENT_ACTIVATE,
-			COMPONENT_DEACTIVATE, COMPONENT_NAME, COMPONENT_DESCRIPTORS, COMPONENT_DESIGNATE,
-			COMPONENT_DESIGNATEFACTORY									};
-
-	public final static Set<String>		SET_COMPONENT_DIRECTIVES		= new HashSet<String>(
-																				Arrays.asList(componentDirectives));
-
-	public final static Set<String>		SET_COMPONENT_DIRECTIVES_1_1	= //
-																		new HashSet<String>(
-																				Arrays.asList(
-																						COMPONENT_VERSION,
-																						COMPONENT_CONFIGURATION_POLICY,
-																						COMPONENT_MODIFIED,
-																						COMPONENT_ACTIVATE,
-																						COMPONENT_DEACTIVATE));
-
-
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/EmbeddedResource.java b/biz.aQute.bndlib/src/aQute/lib/osgi/EmbeddedResource.java
deleted file mode 100755
index cb302da..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/EmbeddedResource.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package aQute.lib.osgi;
-
-import java.io.*;
-import java.util.zip.*;
-
-public class EmbeddedResource implements Resource {
-	byte	data[];
-	long 	lastModified;
-	String	extra;
-
-	public EmbeddedResource(byte data[], long lastModified) {
-		this.data = data;
-		this.lastModified = lastModified;
-	}
-
-	public InputStream openInputStream() throws FileNotFoundException {
-		return new ByteArrayInputStream(data);
-	}
-
-	public void write(OutputStream out) throws IOException {
-		out.write(data);
-	}
-
-	public String toString() {
-		return ":" + data.length + ":";
-	}
-
-	public static void build(Jar jar, InputStream in, long lastModified) throws IOException {
-		ZipInputStream jin = new ZipInputStream(in);
-		ZipEntry entry = jin.getNextEntry();
-		while (entry != null) {
-			if (!entry.isDirectory()) {
-				byte data[] = collect(jin);
-				jar.putResource(entry.getName(), new EmbeddedResource(data, lastModified), true);
-			}
-			entry = jin.getNextEntry();
-		}
-		jin.close();
-	}
-
-	/**
-	 * Convenience method to turn an inputstream into a byte array. The method
-	 * uses a recursive algorithm to minimize memory usage.
-	 * 
-	 * @param in stream with data
-	 * @param offset where we are in the stream
-	 * @returns byte array filled with data
-	 */
-    static byte[] collect(InputStream in) throws IOException {
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        copy(in,out);
-        return out.toByteArray();
-    }
-
-    static void copy(InputStream in, OutputStream out) throws IOException {
-        int available = in.available();
-        if ( available <= 10000)
-            available = 64000;
-        byte [] buffer = new byte[available];
-        int size;
-        while ( (size=in.read(buffer))>0)
-            out.write(buffer,0,size);
-    }
-
-	public long lastModified() {
-		return lastModified;
-	}
-
-	public static void build(Jar sub, Resource resource) throws Exception {
-			InputStream in = resource.openInputStream();
-			build(sub,in, resource.lastModified());
-			in.close();
-	}
-
-	public String getExtra() {
-		return extra;
-	}
-
-	public void setExtra(String extra) {
-		this.extra = extra;
-	}
-
-	public long size() {
-	    return data.length;
-	}
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/FileResource.java b/biz.aQute.bndlib/src/aQute/lib/osgi/FileResource.java
deleted file mode 100755
index f99ead4..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/FileResource.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package aQute.lib.osgi;
-
-import java.io.*;
-import java.util.regex.Pattern;
-
-public class FileResource implements Resource {
-	File	file;
-	String	extra;
-	
-	public FileResource(File file) {
-		this.file = file;
-	}
-
-	public InputStream openInputStream() throws FileNotFoundException {
-		return new FileInputStream(file);
-	}
-
-	public static void build(Jar jar, File directory, Pattern doNotCopy) {
-		traverse(
-				jar,
-				directory.getAbsolutePath().length(),
-				directory,
-				doNotCopy);
-	}
-
-	public String toString() {
-		return ":" + file.getName() + ":";
-	}
-
-	public void write(OutputStream out) throws Exception {
-		copy(this, out);
-	}
-
-	static synchronized void copy(Resource resource, OutputStream out)
-			throws Exception {
-		InputStream in = resource.openInputStream();
-		try {
-			byte buffer[] = new byte[20000];
-			int size = in.read(buffer);
-			while (size > 0) {
-				out.write(buffer, 0, size);
-				size = in.read(buffer);
-			}
-		}
-		finally {
-			in.close();
-		}
-	}
-
-	static void traverse(Jar jar, int rootlength, File directory,
-			Pattern doNotCopy) {
-		if (doNotCopy != null && doNotCopy.matcher(directory.getName()).matches())
-			return;
-		jar.updateModified(directory.lastModified(), "Dir change");
-		
-		File files[] = directory.listFiles();
-		for (int i = 0; i < files.length; i++) {
-			if (files[i].isDirectory())
-				traverse(jar, rootlength, files[i], doNotCopy);
-			else {
-				String path = files[i].getAbsolutePath().substring(
-						rootlength + 1);
-				if (File.separatorChar != '/')
-					path = path.replace(File.separatorChar, '/');
-				jar.putResource(path, new FileResource(files[i]), true);
-			}
-		}
-	}
-
-	public long lastModified() {
-		return file.lastModified();
-	}
-
-	public String getExtra() {
-		return extra;
-	}
-
-	public void setExtra(String extra) {
-		this.extra = extra;
-	}
-	
-	public long size() {
-	    return (int) file.length();
-	}
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/Instruction.java b/biz.aQute.bndlib/src/aQute/lib/osgi/Instruction.java
deleted file mode 100755
index f466f57..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/Instruction.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package aQute.lib.osgi;
-
-import java.util.*;
-import java.util.regex.*;
-
-import aQute.libg.generics.*;
-
-public class Instruction {
-    Pattern pattern;
-    String  instruction;
-    boolean negated;
-    boolean optional;
-
-    public Instruction(String instruction, boolean negated) {
-        this.instruction = instruction;
-        this.negated = negated;
-    }
-
-    public boolean matches(String value) {
-        return getMatcher(value).matches();
-    }
-
-    public boolean isNegated() {
-        return negated;
-    }
-
-    public String getPattern() {
-        return instruction;
-    }
-
-    /**
-     * Convert a string based pattern to a regular expression based pattern.
-     * This is called an instruction, this object makes it easier to handle the
-     * different cases
-     * 
-     * @param string
-     * @return
-     */
-    public static Instruction getPattern(String string) {
-        boolean negated = false;
-        if (string.startsWith("!")) {
-            negated = true;
-            string = string.substring(1);
-        }
-        StringBuffer sb = new StringBuffer();
-        for (int c = 0; c < string.length(); c++) {
-            switch (string.charAt(c)) {
-            case '.':
-                sb.append("\\.");
-                break;
-            case '*':
-                sb.append(".*");
-                break;
-            case '?':
-                sb.append(".?");
-                break;
-            default:
-                sb.append(string.charAt(c));
-                break;
-            }
-        }
-        string = sb.toString();
-        if (string.endsWith("\\..*")) {
-            sb.append("|");
-            sb.append(string.substring(0, string.length() - 4));
-        }
-        return new Instruction(sb.toString(), negated);
-    }
-
-    public String toString() {
-        return getPattern();
-    }
-
-    public Matcher getMatcher(String value) {
-        if (pattern == null) {
-            pattern = Pattern.compile(instruction);
-        }
-        return pattern.matcher(value);
-    }
-
-    public int hashCode() {
-        return instruction.hashCode();
-    }
-
-    public boolean equals(Object other) {
-        return other != null && (other instanceof Instruction)
-                && instruction.equals(((Instruction) other).instruction);
-    }
-
-    public void setOptional() {
-        optional = true;
-    }
-
-    public boolean isOptional() {
-        return optional;
-    }
-
-    public static Map<Instruction, Map<String, String>> replaceWithInstruction(
-            Map<String, Map<String, String>> header) {
-        Map<Instruction, Map<String, String>> map = Processor.newMap();
-        for (Iterator<Map.Entry<String, Map<String, String>>> e = header
-                .entrySet().iterator(); e.hasNext();) {
-            Map.Entry<String, Map<String, String>> entry = e.next();
-            String pattern = entry.getKey();
-            Instruction instr = getPattern(pattern);
-            String presence = entry.getValue()
-                    .get(Constants.PRESENCE_DIRECTIVE);
-            if ("optional".equals(presence))
-                instr.setOptional();
-            map.put(instr, entry.getValue());
-        }
-        return map;
-    }
-
-    public static <T> Collection<T> select(Collection<Instruction> matchers,
-            Collection<T> targets) {
-        Collection<T> result = Create.list();
-        outer: for (T t : targets) {
-            String s = t.toString();
-            for (Instruction i : matchers) {
-                if (i.matches(s)) {
-                    if (!i.isNegated())
-                        result.add(t);
-                    continue outer;
-                }
-            }
-        }
-        return result;
-    }
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/InstructionFilter.java b/biz.aQute.bndlib/src/aQute/lib/osgi/InstructionFilter.java
deleted file mode 100644
index 83f85ee..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/InstructionFilter.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package aQute.lib.osgi;
-
-import java.io.*;
-import java.util.regex.*;
-
-public class InstructionFilter implements FileFilter {
-
-	private Instruction instruction;
-	private boolean recursive;
-	private Pattern doNotCopy;
-	
-	public InstructionFilter (Instruction instruction, boolean recursive, Pattern doNotCopy) {
-		this.instruction = instruction;
-		this.recursive = recursive;
-		this.doNotCopy = doNotCopy;
-	}
-	public InstructionFilter (Instruction instruction, boolean recursive) {
-		this(instruction, recursive, Pattern.compile(Constants.DEFAULT_DO_NOT_COPY));
-	}
-	public boolean isRecursive() {
-		return recursive;
-	}
-	public boolean accept(File pathname) {
-		if (doNotCopy != null && doNotCopy.matcher(pathname.getName()).matches()) {
-			return false;
-		}
-
-		if (pathname.isDirectory() && isRecursive()) {
-			return true;
-		}
-		
-		if (instruction == null) {
-			return true;
-		}
-		return !instruction.isNegated() == instruction.matches(pathname.getName());
-	}
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/Jar.java b/biz.aQute.bndlib/src/aQute/lib/osgi/Jar.java
deleted file mode 100755
index c8b2359..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/Jar.java
+++ /dev/null
@@ -1,690 +0,0 @@
-package aQute.lib.osgi;
-
-import static aQute.lib.io.IO.*;
-
-import java.io.*;
-import java.security.*;
-import java.util.*;
-import java.util.jar.*;
-import java.util.regex.*;
-import java.util.zip.*;
-
-import aQute.lib.base64.*;
-import aQute.libg.reporter.*;
-
-public class Jar implements Closeable {
-	public static final Object[]		EMPTY_ARRAY	= new Jar[0];
-	Map<String, Resource>				resources	= new TreeMap<String, Resource>();
-	Map<String, Map<String, Resource>>	directories	= new TreeMap<String, Map<String, Resource>>();
-	Manifest							manifest;
-	boolean								manifestFirst;
-	String								name;
-	File								source;
-	ZipFile								zipFile;
-	long								lastModified;
-	String								lastModifiedReason;
-	Reporter							reporter;
-	boolean								doNotTouchManifest;
-	boolean								nomanifest;
-
-	public Jar(String name) {
-		this.name = name;
-	}
-
-	public Jar(String name, File dirOrFile, Pattern doNotCopy) throws ZipException, IOException {
-		this(name);
-		source = dirOrFile;
-		if (dirOrFile.isDirectory())
-			FileResource.build(this, dirOrFile, doNotCopy);
-		else if (dirOrFile.isFile()) {
-			zipFile = ZipResource.build(this, dirOrFile);
-		} else {
-			throw new IllegalArgumentException("A Jar can only accept a valid file or directory: "
-					+ dirOrFile);
-		}
-	}
-
-	public Jar(String name, InputStream in, long lastModified) throws IOException {
-		this(name);
-		EmbeddedResource.build(this, in, lastModified);
-	}
-
-	public Jar(String name, String path) throws IOException {
-		this(name);
-		File f = new File(path);
-		InputStream in = new FileInputStream(f);
-		EmbeddedResource.build(this, in, f.lastModified());
-		in.close();
-	}
-
-	public Jar(File f) throws IOException {
-		this(getName(f), f, null);
-	}
-
-	/**
-	 * Make the JAR file name the project name if we get a src or bin directory.
-	 * 
-	 * @param f
-	 * @return
-	 */
-	private static String getName(File f) {
-		f = f.getAbsoluteFile();
-		String name = f.getName();
-		if (name.equals("bin") || name.equals("src"))
-			return f.getParentFile().getName();
-		else {
-			if (name.endsWith(".jar"))
-				name = name.substring(0, name.length() - 4);
-			return name;
-		}
-	}
-
-	public Jar(String string, InputStream resourceAsStream) throws IOException {
-		this(string, resourceAsStream, 0);
-	}
-
-	public Jar(String string, File file) throws ZipException, IOException {
-		this(string, file, Pattern.compile(Constants.DEFAULT_DO_NOT_COPY));
-	}
-
-	public void setName(String name) {
-		this.name = name;
-	}
-
-	public String toString() {
-		return "Jar:" + name;
-	}
-
-	public boolean putResource(String path, Resource resource) {
-		return putResource(path, resource, true);
-	}
-
-	public boolean putResource(String path, Resource resource, boolean overwrite) {
-		updateModified(resource.lastModified(), path);
-		while (path.startsWith("/"))
-			path = path.substring(1);
-
-		if (path.equals("META-INF/MANIFEST.MF")) {
-			manifest = null;
-			if (resources.isEmpty())
-				manifestFirst = true;
-		}
-		String dir = getDirectory(path);
-		Map<String, Resource> s = directories.get(dir);
-		if (s == null) {
-			s = new TreeMap<String, Resource>();
-			directories.put(dir, s);
-			int n = dir.lastIndexOf('/');
-			while (n > 0) {
-				String dd = dir.substring(0, n);
-				if (directories.containsKey(dd))
-					break;
-				directories.put(dd, null);
-				n = dd.lastIndexOf('/');
-			}
-		}
-		boolean duplicate = s.containsKey(path);
-		if (!duplicate || overwrite) {
-			resources.put(path, resource);
-			s.put(path, resource);
-		}
-		return duplicate;
-	}
-
-	public Resource getResource(String path) {
-		return resources.get(path);
-	}
-
-	private String getDirectory(String path) {
-		int n = path.lastIndexOf('/');
-		if (n < 0)
-			return "";
-
-		return path.substring(0, n);
-	}
-
-	public Map<String, Map<String, Resource>> getDirectories() {
-		return directories;
-	}
-
-	public Map<String, Resource> getResources() {
-		return resources;
-	}
-
-	public boolean addDirectory(Map<String, Resource> directory, boolean overwrite) {
-		boolean duplicates = false;
-		if (directory == null)
-			return false;
-
-		for (Map.Entry<String, Resource> entry : directory.entrySet()) {
-			String key = entry.getKey();
-			if (!key.endsWith(".java")) {
-				duplicates |= putResource(key, (Resource) entry.getValue(), overwrite);
-			}
-		}
-		return duplicates;
-	}
-
-	public Manifest getManifest() throws Exception {
-		if (manifest == null) {
-			Resource manifestResource = getResource("META-INF/MANIFEST.MF");
-			if (manifestResource != null) {
-				InputStream in = manifestResource.openInputStream();
-				manifest = new Manifest(in);
-				in.close();
-			}
-		}
-		return manifest;
-	}
-
-	public boolean exists(String path) {
-		return resources.containsKey(path);
-	}
-
-	public void setManifest(Manifest manifest) {
-		manifestFirst = true;
-		this.manifest = manifest;
-	}
-
-	public void write(File file) throws Exception {
-		try {
-			OutputStream out = new FileOutputStream(file);
-			write(out);
-			out.close();
-			return;
-
-		} catch (Exception t) {
-			file.delete();
-			throw t;
-		}
-	}
-
-	public void write(String file) throws Exception {
-		write(new File(file));
-	}
-
-	public void write(OutputStream out) throws Exception {
-		ZipOutputStream jout = nomanifest || doNotTouchManifest ? new ZipOutputStream(out)
-				: new JarOutputStream(out);
-		Set<String> done = new HashSet<String>();
-
-		Set<String> directories = new HashSet<String>();
-		if (doNotTouchManifest) {
-			Resource r = getResource("META-INF/MANIFEST.MF");
-			if (r != null) {
-				writeResource(jout, directories, "META-INF/MANIFEST.MF", r);
-				done.add("META-INF/MANIFEST.MF");
-			}
-		} else
-			doManifest(done, jout);
-
-		for (Map.Entry<String, Resource> entry : getResources().entrySet()) {
-			// Skip metainf contents
-			if (!done.contains(entry.getKey()))
-				writeResource(jout, directories, (String) entry.getKey(),
-						(Resource) entry.getValue());
-		}
-		jout.finish();
-	}
-
-	private void doManifest(Set<String> done, ZipOutputStream jout) throws Exception {
-		if (nomanifest)
-			return;
-
-		JarEntry ze = new JarEntry("META-INF/MANIFEST.MF");
-		jout.putNextEntry(ze);
-		writeManifest(jout);
-		jout.closeEntry();
-		done.add(ze.getName());
-	}
-
-	/**
-	 * Cleanup the manifest for writing. Cleaning up consists of adding a space
-	 * after any \n to prevent the manifest to see this newline as a delimiter.
-	 * 
-	 * @param out
-	 *            Output
-	 * @throws IOException
-	 */
-
-	public void writeManifest(OutputStream out) throws Exception {
-		writeManifest(getManifest(), out);
-	}
-
-	public static void writeManifest(Manifest manifest, OutputStream out) throws IOException {
-		if (manifest == null)
-			return;
-
-		manifest = clean(manifest);
-		outputManifest(manifest, out);
-	}
-
-	/**
-	 * Unfortunately we have to write our own manifest :-( because of a stupid
-	 * bug in the manifest code. It tries to handle UTF-8 but the way it does it
-	 * it makes the bytes platform dependent.
-	 * 
-	 * So the following code outputs the manifest.
-	 * 
-	 * A Manifest consists of
-	 * 
-	 * <pre>
-	 *   'Manifest-Version: 1.0\r\n'
-	 *   main-attributes *
-	 *   \r\n
-	 *   name-section
-	 *   
-	 *   main-attributes ::= attributes
-	 *   attributes      ::= key ': ' value '\r\n'
-	 *   name-section    ::= 'Name: ' name '\r\n' attributes
-	 * </pre>
-	 * 
-	 * Lines in the manifest should not exceed 72 bytes (! this is where the
-	 * manifest screwed up as well when 16 bit unicodes were used).
-	 * 
-	 * <p>
-	 * As a bonus, we can now sort the manifest!
-	 */
-	static byte[]	CONTINUE	=  new byte[] {'\r','\n', ' '};
-
-	/**
-	 * Main function to output a manifest properly in UTF-8.
-	 * 
-	 * @param manifest
-	 *            The manifest to output
-	 * @param out
-	 *            The output stream
-	 * @throws IOException
-	 *             when something fails
-	 */
-	public static void outputManifest(Manifest manifest, OutputStream out) throws IOException {
-		writeEntry(out, "Manifest-Version", "1.0");
-		attributes(manifest.getMainAttributes(), out);
-
-		TreeSet<String> keys = new TreeSet<String>();
-		for (Object o : manifest.getEntries().keySet())
-			keys.add(o.toString());
-
-		for (String key : keys) {
-			write(out, 0, "\r\n");
-			writeEntry(out, "Name", key);
-			attributes(manifest.getAttributes(key), out);
-		}
-	}
-
-	/**
-	 * Write out an entry, handling proper unicode and line length constraints
-	 * 
-	 */
-	private static void writeEntry(OutputStream out, String name, String value) throws IOException {
-		int n = write(out, 0, name + ": ");
-		n = write(out, n, value);
-		write(out, 0, "\r\n");
-	}
-
-	/**
-	 * Convert a string to bytes with UTF8 and then output in max 72 bytes
-	 * 
-	 * @param out
-	 *            the output string
-	 * @param i
-	 *            the current width
-	 * @param s
-	 *            the string to output
-	 * @return the new width
-	 * @throws IOException
-	 *             when something fails
-	 */
-	private static int write(OutputStream out, int i, String s) throws IOException {
-		byte[] bytes = s.getBytes("UTF8");
-		return write(out, i, bytes);
-	}
-
-	/**
-	 * Write the bytes but ensure that the line length does not exceed 72
-	 * characters. If it is more than 70 characters, we just put a cr/lf +
-	 * space.
-	 * 
-	 * @param out
-	 *            The output stream
-	 * @param width
-	 *            The nr of characters output in a line before this method
-	 *            started
-	 * @param bytes
-	 *            the bytes to output
-	 * @return the nr of characters in the last line
-	 * @throws IOException
-	 *             if something fails
-	 */
-	private static int write(OutputStream out, int width, byte[] bytes) throws IOException {
-		for (int i = 0; i < bytes.length; i++) {
-			if (width >= 72) { // we need to add the \n\r!
-				out.write(CONTINUE);
-				width = 1;
-			}
-			out.write(bytes[i]);
-			width++;
-		}
-		return width;
-	}
-
-	/**
-	 * Output an Attributes map. We will sort this map before outputing.
-	 * 
-	 * @param value
-	 *            the attrbutes
-	 * @param out
-	 *            the output stream
-	 * @throws IOException
-	 *             when something fails
-	 */
-	private static void attributes(Attributes value, OutputStream out) throws IOException {
-		TreeMap<String, String> map = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
-		for (Map.Entry<Object, Object> entry : value.entrySet()) {
-			map.put(entry.getKey().toString(), entry.getValue().toString());
-		}
-
-		map.remove("Manifest-Version"); // get rid of
-		// manifest
-		// version
-		for (Map.Entry<String, String> entry : map.entrySet()) {
-			writeEntry(out, entry.getKey(), entry.getValue());
-		}
-	}
-
-	private static Manifest clean(Manifest org) {
-
-		Manifest result = new Manifest();
-		for (Map.Entry<?, ?> entry : org.getMainAttributes().entrySet()) {
-			String nice = clean((String) entry.getValue());
-			result.getMainAttributes().put(entry.getKey(), nice);
-		}
-		for (String name : org.getEntries().keySet()) {
-			Attributes attrs = result.getAttributes(name);
-			if (attrs == null) {
-				attrs = new Attributes();
-				result.getEntries().put(name, attrs);
-			}
-
-			for (Map.Entry<?, ?> entry : org.getAttributes(name).entrySet()) {
-				String nice = clean((String) entry.getValue());
-				attrs.put((Attributes.Name) entry.getKey(), nice);
-			}
-		}
-		return result;
-	}
-
-	private static String clean(String s) {
-		if (s.indexOf('\n') < 0)
-			return s;
-
-		StringBuffer sb = new StringBuffer(s);
-		for (int i = 0; i < sb.length(); i++) {
-			if (sb.charAt(i) == '\n')
-				sb.insert(++i, ' ');
-		}
-		return sb.toString();
-	}
-
-	private void writeResource(ZipOutputStream jout, Set<String> directories, String path,
-			Resource resource) throws Exception {
-		if (resource == null)
-			return;
-
-		createDirectories(directories, jout, path);
-		ZipEntry ze = new ZipEntry(path);
-		ze.setMethod(ZipEntry.DEFLATED);
-		long lastModified = resource.lastModified();
-		if (lastModified == 0L) {
-			lastModified = System.currentTimeMillis();
-		}
-		ze.setTime(lastModified);
-		if (resource.getExtra() != null)
-			ze.setExtra(resource.getExtra().getBytes());
-		jout.putNextEntry(ze);
-		resource.write(jout);
-		jout.closeEntry();
-	}
-
-	void createDirectories(Set<String> directories, ZipOutputStream zip, String name)
-			throws IOException {
-		int index = name.lastIndexOf('/');
-		if (index > 0) {
-			String path = name.substring(0, index);
-			if (directories.contains(path))
-				return;
-			createDirectories(directories, zip, path);
-			ZipEntry ze = new ZipEntry(path + '/');
-			zip.putNextEntry(ze);
-			zip.closeEntry();
-			directories.add(path);
-		}
-	}
-
-	public String getName() {
-		return name;
-	}
-
-	/**
-	 * Add all the resources in the given jar that match the given filter.
-	 * 
-	 * @param sub
-	 *            the jar
-	 * @param filter
-	 *            a pattern that should match the resoures in sub to be added
-	 */
-	public boolean addAll(Jar sub, Instruction filter) {
-		return addAll(sub, filter, "");
-	}
-
-	/**
-	 * Add all the resources in the given jar that match the given filter.
-	 * 
-	 * @param sub
-	 *            the jar
-	 * @param filter
-	 *            a pattern that should match the resoures in sub to be added
-	 */
-	public boolean addAll(Jar sub, Instruction filter, String destination) {
-		boolean dupl = false;
-		for (String name : sub.getResources().keySet()) {
-			if ("META-INF/MANIFEST.MF".equals(name))
-				continue;
-
-			if (filter == null || filter.matches(name) != filter.isNegated())
-				dupl |= putResource(Processor.appendPath(destination, name), sub.getResource(name),
-						true);
-		}
-		return dupl;
-	}
-
-	public void close() {
-		if (zipFile != null)
-			try {
-				zipFile.close();
-			} catch (IOException e) {
-				// Ignore
-			}
-		resources = null;
-		directories = null;
-		manifest = null;
-		source = null;
-	}
-
-	public long lastModified() {
-		return lastModified;
-	}
-
-	public void updateModified(long time, String reason) {
-		if (time > lastModified) {
-			lastModified = time;
-			lastModifiedReason = reason;
-		}
-	}
-
-	public void setReporter(Reporter reporter) {
-		this.reporter = reporter;
-	}
-
-	public boolean hasDirectory(String path) {
-		return directories.get(path) != null;
-	}
-
-	public List<String> getPackages() {
-		List<String> list = new ArrayList<String>(directories.size());
-
-		for (Map.Entry<String, Map<String, Resource>> i : directories.entrySet()) {
-			if (i.getValue() != null) {
-				String path = i.getKey();
-				String pack = path.replace('/', '.');
-				list.add(pack);
-			}
-		}
-		return list;
-	}
-
-	public File getSource() {
-		return source;
-	}
-
-	public boolean addAll(Jar src) {
-		return addAll(src, null);
-	}
-
-	public boolean rename(String oldPath, String newPath) {
-		Resource resource = remove(oldPath);
-		if (resource == null)
-			return false;
-
-		return putResource(newPath, resource);
-	}
-
-	public Resource remove(String path) {
-		Resource resource = resources.remove(path);
-		String dir = getDirectory(path);
-		Map<String, Resource> mdir = directories.get(dir);
-		// must be != null
-		mdir.remove(path);
-		return resource;
-	}
-
-	/**
-	 * Make sure nobody touches the manifest! If the bundle is signed, we do not
-	 * want anybody to touch the manifest after the digests have been
-	 * calculated.
-	 */
-	public void setDoNotTouchManifest() {
-		doNotTouchManifest = true;
-	}
-
-	/**
-	 * Calculate the checksums and set them in the manifest.
-	 */
-
-	public void calcChecksums(String algorithms[]) throws Exception {
-		if (algorithms == null)
-			algorithms = new String[] { "SHA", "MD5" };
-
-		Manifest m = getManifest();
-		if ( m == null) {
-			m= new Manifest();
-			setManifest(m);
-		}
-		
-		MessageDigest digests[] = new MessageDigest[algorithms.length];
-		int n = 0;
-		for (String algorithm : algorithms)
-			digests[n++] = MessageDigest.getInstance(algorithm);
-
-		byte buffer[] = new byte[30000];
-
-		for (Map.Entry<String, Resource> entry : resources.entrySet()) {
-			
-			// Skip the manifest
-			if (entry.getKey().equals("META-INF/MANIFEST.MF"))
-				continue;
-
-			Resource r = entry.getValue();
-			Attributes attributes = m.getAttributes(entry.getKey());
-			if (attributes == null) {
-				attributes = new Attributes();
-				getManifest().getEntries().put(entry.getKey(), attributes);
-			}
-			InputStream in = r.openInputStream();
-			try {
-				for (MessageDigest d : digests)
-					d.reset();
-				int size = in.read(buffer);
-				while (size > 0) {
-					for (MessageDigest d : digests)
-						d.update(buffer, 0, size);
-					size = in.read(buffer);
-				}
-			} finally {
-				in.close();
-			}
-			for (MessageDigest d : digests)
-				attributes.putValue(d.getAlgorithm() + "-Digest", Base64.encodeBase64(d.digest()));
-		}
-	}
-
-	Pattern	BSN	= Pattern.compile("\\s*([-\\w\\d\\._]+)\\s*;?.*");
-
-	public String getBsn() throws Exception {
-		Manifest m = getManifest();
-		if (m == null)
-			return null;
-
-		String s = m.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
-		Matcher matcher = BSN.matcher(s);
-		if (matcher.matches()) {
-			return matcher.group(1);
-		}
-		return null;
-	}
-
-	public String getVersion() throws Exception {
-		Manifest m = getManifest();
-		if (m == null)
-			return null;
-
-		String s = m.getMainAttributes().getValue(Constants.BUNDLE_VERSION);
-		if (s == null)
-			return null;
-
-		return s.trim();
-	}
-
-	/**
-	 * Expand the JAR file to a directory.
-	 * 
-	 * @param dir
-	 *            the dst directory, is not required to exist
-	 * @throws Exception
-	 *             if anything does not work as expected.
-	 */
-	public void expand(File dir) throws Exception {
-		dir = dir.getAbsoluteFile();
-		dir.mkdirs();
-		if (!dir.isDirectory()) {
-			throw new IllegalArgumentException("Not a dir: " + dir.getAbsolutePath());
-		}
-
-		for (Map.Entry<String, Resource> entry : getResources().entrySet()) {
-			File f = getFile(dir, entry.getKey());
-			f.getParentFile().mkdirs();
-			copy(entry.getValue().openInputStream(), f);
-		}
-	}
-
-	/**
-	 * Make sure we have a manifest
-	 * @throws Exception
-	 */
-	public void ensureManifest() throws Exception {
-		if ( getManifest() != null)
-			return;
-		manifest = new Manifest();
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/JarResource.java b/biz.aQute.bndlib/src/aQute/lib/osgi/JarResource.java
deleted file mode 100755
index 706094f..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/JarResource.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package aQute.lib.osgi;
-
-import java.io.*;
-
-public class JarResource implements Resource {
-	Jar		jar;
-	String extra;
-	
-	public JarResource(Jar jar ) {
-		this.jar = jar;
-	}
-	
-	public String getExtra() {
-		return extra;
-	}
-
-	public long lastModified() {
-		return jar.lastModified();
-	}
-
-
-	public void write(OutputStream out) throws Exception {
-		jar.write(out);
-	}
-	
-	public InputStream openInputStream() throws Exception {
-		ByteArrayOutputStream out = new ByteArrayOutputStream();
-		write(out);
-		out.close();
-		ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
-		return in;
-	}
-
-	public void setExtra(String extra) {
-		this.extra = extra;
-	}
-	
-	public Jar getJar() { 
-	    return jar;
-	}
-	
-	public String toString() {
-	    return ":" + jar.getName() + ":";
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/Macro.java b/biz.aQute.bndlib/src/aQute/lib/osgi/Macro.java
deleted file mode 100755
index 2518178..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/Macro.java
+++ /dev/null
@@ -1,967 +0,0 @@
-package aQute.lib.osgi;
-
-import java.io.*;
-import java.lang.reflect.*;
-import java.net.*;
-import java.text.*;
-import java.util.*;
-import java.util.regex.*;
-
-import aQute.lib.io.*;
-import aQute.libg.sed.*;
-import aQute.libg.version.*;
-
-/**
- * Provide a macro processor. This processor can replace variables in strings
- * based on a properties and a domain. The domain can implement functions that
- * start with a "_" and take args[], the names of these functions are available
- * as functions in the macro processor (without the _). Macros can nest to any
- * depth but may not contain loops.
- * 
- * Add POSIX macros:
- * ${#parameter}
-    String length.
-
-${parameter%word}
-    Remove smallest suffix pattern.
-
-${parameter%%word}
-    Remove largest suffix pattern.
-
-${parameter#word}
-    Remove smallest prefix pattern.
-
-${parameter##word}
-    Remove largest prefix pattern. 
- */
-public class Macro implements Replacer {
-	Processor	domain;
-	Object		targets[];
-	boolean		flattening;
-
-	public Macro(Processor domain, Object... targets) {
-		this.domain = domain;
-		this.targets = targets;
-		if (targets != null) {
-			for (Object o : targets) {
-				assert o != null;
-			}
-		}
-	}
-
-	public String process(String line, Processor source) {
-		return process(line, new Link(source,null,line));
-	}
-
-	String process(String line, Link link) {
-		StringBuffer sb = new StringBuffer();
-		process(line, 0, '\u0000', '\u0000', sb, link);
-		return sb.toString();
-	}
-
-	int process(CharSequence org, int index, char begin, char end, StringBuffer result, Link link) {
-		StringBuilder line = new StringBuilder(org);
-		int nesting = 1;
-
-		StringBuffer variable = new StringBuffer();
-		outer: while (index < line.length()) {
-			char c1 = line.charAt(index++);
-			if (c1 == end) {
-				if (--nesting == 0) {
-					result.append(replace(variable.toString(), link));
-					return index;
-				}
-			} else if (c1 == begin)
-				nesting++;
-			else if (c1 == '\\' && index < line.length() - 1 && line.charAt(index) == '$') {
-				// remove the escape backslash and interpret the dollar as a
-				// literal
-				index++;
-				variable.append('$');
-				continue outer;
-			} else if (c1 == '$' && index < line.length() - 2) {
-				char c2 = line.charAt(index);
-				char terminator = getTerminator(c2);
-				if (terminator != 0) {
-					index = process(line, index + 1, c2, terminator, variable, link);
-					continue outer;
-				}
-			}
-			variable.append(c1);
-		}
-		result.append(variable);
-		return index;
-	}
-
-	public static char getTerminator(char c) {
-		switch (c) {
-		case '(':
-			return ')';
-		case '[':
-			return ']';
-		case '{':
-			return '}';
-		case '<':
-			return '>';
-		case '\u00ab': // Guillemet double << >>
-			return '\u00bb';
-		case '\u2039': // Guillemet single
-			return '\u203a';
-		}
-		return 0;
-	}
-
-	protected String replace(String key, Link link) {
-		if (link != null && link.contains(key))
-			return "${infinite:" + link.toString() + "}";
-
-		if (key != null) {
-			key = key.trim();
-			if (key.length() > 0) {
-				Processor source = domain;
-				String value = null;
-				while( source != null) {
-					value = source.getProperties().getProperty(key);
-					if ( value != null )
-						break;
-					
-					source = source.getParent();
-				}
-				
-				if (value != null)
-					return process(value, new Link(source,link, key));
-
-				value = doCommands(key, link);
-				if (value != null)
-					return process(value, new Link(source, link, key));
-
-				if (key != null && key.trim().length() > 0) {
-					value = System.getProperty(key);
-					if (value != null)
-						return value;
-				}
-				if (!flattening)
-					domain.warning("No translation found for macro: " + key);
-			} else {
-				domain.warning("Found empty macro key");
-			}
-		} else {
-			domain.warning("Found null macro key");
-		}
-		return "${" + key + "}";
-	}
-
-	/**
-	 * Parse the key as a command. A command consist of parameters separated by
-	 * ':'.
-	 * 
-	 * @param key
-	 * @return
-	 */
-	static Pattern	commands	= Pattern.compile("(?<!\\\\);");
-
-	private String doCommands(String key, Link source) {
-		String[] args = commands.split(key);
-		if (args == null || args.length == 0)
-			return null;
-
-		for (int i = 0; i < args.length; i++)
-			if (args[i].indexOf('\\') >= 0)
-				args[i] = args[i].replaceAll("\\\\;", ";");
-
-		
-		if ( args[0].startsWith("^")) {
-			String varname = args[0].substring(1).trim();
-			
-			Processor parent = source.start.getParent();
-			if ( parent != null)
-				return parent.getProperty(varname);
-			else
-				return null;
-		}
-		
-		
-		Processor rover = domain;
-		while (rover != null) {
-			String result = doCommand(rover, args[0], args);
-			if (result != null)
-				return result;
-
-			rover = rover.getParent();
-		}
-
-		for (int i = 0; targets != null && i < targets.length; i++) {
-			String result = doCommand(targets[i], args[0], args);
-			if (result != null)
-				return result;
-		}
-
-		return doCommand(this, args[0], args);
-	}
-
-	private String doCommand(Object target, String method, String[] args) {
-		if (target == null)
-			; // System.out.println("Huh? Target should never be null " +
-		// domain);
-		else {
-			String cname = "_" + method.replaceAll("-", "_");
-			try {
-				Method m = target.getClass().getMethod(cname, new Class[] { String[].class });
-				return (String) m.invoke(target, new Object[] { args });
-			} catch (NoSuchMethodException e) {
-				// Ignore
-			} catch (InvocationTargetException e) {
-				if ( e.getCause() instanceof IllegalArgumentException ) {
-					domain.error("%s, for cmd: %s, arguments; %s", e.getMessage(), method, Arrays.toString(args));
-				} else {
-					domain.warning("Exception in replace: " + e.getCause());
-					e.getCause().printStackTrace();
-				}
-			} catch (Exception e) {
-				domain.warning("Exception in replace: " + e + " method=" + method);
-				e.printStackTrace();
-			}
-		}
-		return null;
-	}
-
-	/**
-	 * Return a unique list where the duplicates are removed.
-	 * 
-	 * @param args
-	 * @return
-	 */
-	static String	_uniqHelp	= "${uniq;<list> ...}";
-
-	public String _uniq(String args[]) {
-		verifyCommand(args, _uniqHelp, null, 1, Integer.MAX_VALUE);
-		Set<String> set = new LinkedHashSet<String>();
-		for (int i = 1; i < args.length; i++) {
-			Processor.split(args[i], set);
-		}
-		return Processor.join(set, ",");
-	}
-
-	public String _pathseparator(String args[]) {
-		return File.pathSeparator;
-	}
-
-	public String _separator(String args[]) {
-		return File.separator;
-	}
-
-	public String _filter(String args[]) {
-		return filter(args, false);
-	}
-
-	public String _filterout(String args[]) {
-		return filter(args, true);
-
-	}
-
-	static String	_filterHelp	= "${%s;<list>;<regex>}";
-
-	String filter(String[] args, boolean include) {
-		verifyCommand(args, String.format(_filterHelp, args[0]), null, 3, 3);
-
-		Collection<String> list = new ArrayList<String>(Processor.split(args[1]));
-		Pattern pattern = Pattern.compile(args[2]);
-
-		for (Iterator<String> i = list.iterator(); i.hasNext();) {
-			if (pattern.matcher(i.next()).matches() == include)
-				i.remove();
-		}
-		return Processor.join(list);
-	}
-
-	static String	_sortHelp	= "${sort;<list>...}";
-
-	public String _sort(String args[]) {
-		verifyCommand(args, _sortHelp, null, 2, Integer.MAX_VALUE);
-
-		List<String> result = new ArrayList<String>();
-		for (int i = 1; i < args.length; i++) {
-			Processor.split(args[i], result);
-		}
-		Collections.sort(result);
-		return Processor.join(result);
-	}
-
-	static String	_joinHelp	= "${join;<list>...}";
-
-	public String _join(String args[]) {
-
-		verifyCommand(args, _joinHelp, null, 1, Integer.MAX_VALUE);
-
-		List<String> result = new ArrayList<String>();
-		for (int i = 1; i < args.length; i++) {
-			Processor.split(args[i], result);
-		}
-		return Processor.join(result);
-	}
-
-	static String	_ifHelp	= "${if;<condition>;<iftrue> [;<iffalse>] }";
-
-	public String _if(String args[]) {
-		verifyCommand(args, _ifHelp, null, 3, 4);
-		String condition = args[1].trim();
-		if (condition.length() != 0)
-			return args[2];
-		if (args.length > 3)
-			return args[3];
-		else
-			return "";
-	}
-
-	public String _now(String args[]) {
-		return new Date().toString();
-	}
-
-	public static String	_fmodifiedHelp	= "${fmodified;<list of filenames>...}, return latest modification date";
-
-	public String _fmodified(String args[]) throws Exception {
-		verifyCommand(args, _fmodifiedHelp, null, 2, Integer.MAX_VALUE);
-
-		long time = 0;
-		Collection<String> names = new ArrayList<String>();
-		for (int i = 1; i < args.length; i++) {
-			Processor.split(args[i], names);
-		}
-		for (String name : names) {
-			File f = new File(name);
-			if (f.exists() && f.lastModified() > time)
-				time = f.lastModified();
-		}
-		return "" + time;
-	}
-
-	public String _long2date(String args[]) {
-		try {
-			return new Date(Long.parseLong(args[1])).toString();
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
-		return "not a valid long";
-	}
-
-	public String _literal(String args[]) {
-		if (args.length != 2)
-			throw new RuntimeException("Need a value for the ${literal;<value>} macro");
-		return "${" + args[1] + "}";
-	}
-
-	public String _def(String args[]) {
-		if (args.length != 2)
-			throw new RuntimeException("Need a value for the ${def;<value>} macro");
-
-		return domain.getProperty(args[1], "");
-	}
-
-	/**
-	 * 
-	 * replace ; <list> ; regex ; replace
-	 * 
-	 * @param args
-	 * @return
-	 */
-	public String _replace(String args[]) {
-		if (args.length != 4) {
-			domain.warning("Invalid nr of arguments to replace " + Arrays.asList(args));
-			return null;
-		}
-
-		String list[] = args[1].split("\\s*,\\s*");
-		StringBuffer sb = new StringBuffer();
-		String del = "";
-		for (int i = 0; i < list.length; i++) {
-			String element = list[i].trim();
-			if (!element.equals("")) {
-				sb.append(del);
-				sb.append(element.replaceAll(args[2], args[3]));
-				del = ", ";
-			}
-		}
-
-		return sb.toString();
-	}
-
-	public String _warning(String args[]) {
-		for (int i = 1; i < args.length; i++) {
-			domain.warning(process(args[i]));
-		}
-		return "";
-	}
-
-	public String _error(String args[]) {
-		for (int i = 1; i < args.length; i++) {
-			domain.error(process(args[i]));
-		}
-		return "";
-	}
-
-	/**
-	 * toclassname ; <path>.class ( , <path>.class ) *
-	 * 
-	 * @param args
-	 * @return
-	 */
-	static String	_toclassnameHelp	= "${classname;<list of class names>}, convert class paths to FQN class names ";
-
-	public String _toclassname(String args[]) {
-		verifyCommand(args, _toclassnameHelp, null, 2, 2);
-		Collection<String> paths = Processor.split(args[1]);
-
-		List<String> names = new ArrayList<String>(paths.size());
-		for (String path : paths) {
-			if (path.endsWith(".class")) {
-				String name = path.substring(0, path.length() - 6).replace('/', '.');
-				names.add(name);
-			} else if (path.endsWith(".java")) {
-				String name = path.substring(0, path.length() - 5).replace('/', '.');
-				names.add(name);
-			} else {
-				domain.warning("in toclassname, " + args[1]
-						+ " is not a class path because it does not end in .class");
-			}
-		}
-		return Processor.join(names, ",");
-	}
-
-	/**
-	 * toclassname ; <path>.class ( , <path>.class ) *
-	 * 
-	 * @param args
-	 * @return
-	 */
-
-	static String	_toclasspathHelp	= "${toclasspath;<list>[;boolean]}, convert a list of class names to paths";
-
-	public String _toclasspath(String args[]) {
-		verifyCommand(args, _toclasspathHelp, null, 2, 3);
-		boolean cl = true;
-		if (args.length > 2)
-			cl = new Boolean(args[2]);
-
-		Collection<String> names = Processor.split(args[1]);
-		Collection<String> paths = new ArrayList<String>(names.size());
-		for (String name : names) {
-			String path = name.replace('.', '/') + (cl ? ".class" : "");
-			paths.add(path);
-		}
-		return Processor.join(paths, ",");
-	}
-
-	public String _dir(String args[]) {
-		if (args.length < 2) {
-			domain.warning("Need at least one file name for ${dir;...}");
-			return null;
-		} else {
-			String del = "";
-			StringBuffer sb = new StringBuffer();
-			for (int i = 1; i < args.length; i++) {
-				File f = domain.getFile(args[i]);
-				if (f.exists() && f.getParentFile().exists()) {
-					sb.append(del);
-					sb.append(f.getParentFile().getAbsolutePath());
-					del = ",";
-				}
-			}
-			return sb.toString();
-		}
-
-	}
-
-	public String _basename(String args[]) {
-		if (args.length < 2) {
-			domain.warning("Need at least one file name for ${basename;...}");
-			return null;
-		} else {
-			String del = "";
-			StringBuffer sb = new StringBuffer();
-			for (int i = 1; i < args.length; i++) {
-				File f = domain.getFile(args[i]);
-				if (f.exists() && f.getParentFile().exists()) {
-					sb.append(del);
-					sb.append(f.getName());
-					del = ",";
-				}
-			}
-			return sb.toString();
-		}
-
-	}
-
-	public String _isfile(String args[]) {
-		if (args.length < 2) {
-			domain.warning("Need at least one file name for ${isfile;...}");
-			return null;
-		} else {
-			boolean isfile = true;
-			for (int i = 1; i < args.length; i++) {
-				File f = new File(args[i]).getAbsoluteFile();
-				isfile &= f.isFile();
-			}
-			return isfile ? "true" : "false";
-		}
-
-	}
-
-	public String _isdir(String args[]) {
-		if (args.length < 2) {
-			domain.warning("Need at least one file name for ${isdir;...}");
-			return null;
-		} else {
-			boolean isdir = true;
-			for (int i = 1; i < args.length; i++) {
-				File f = new File(args[i]).getAbsoluteFile();
-				isdir &= f.isDirectory();
-			}
-			return isdir ? "true" : "false";
-		}
-
-	}
-
-	public String _tstamp(String args[]) {
-		String format = "yyyyMMddHHmm";
-		long now = System.currentTimeMillis();
-
-		if (args.length > 1) {
-			format = args[1];
-			if (args.length > 2) {
-				now = Long.parseLong(args[2]);
-				if (args.length > 3) {
-					domain.warning("Too many arguments for tstamp: " + Arrays.toString(args));
-				}
-			}
-		}
-		SimpleDateFormat sdf = new SimpleDateFormat(format);
-		return sdf.format(new Date(now));
-	}
-
-	/**
-	 * Wildcard a directory. The lists can contain Instruction that are matched
-	 * against the given directory
-	 * 
-	 * ${lsr;<dir>;<list>(;<list>)*} ${lsa;<dir>;<list>(;<list>)*}
-	 * 
-	 * @author aqute
-	 * 
-	 */
-
-	public String _lsr(String args[]) {
-		return ls(args, true);
-	}
-
-	public String _lsa(String args[]) {
-		return ls(args, false);
-	}
-
-	String ls(String args[], boolean relative) {
-		if (args.length < 2)
-			throw new IllegalArgumentException(
-					"the ${ls} macro must at least have a directory as parameter");
-
-		File dir = domain.getFile(args[1]);
-		if (!dir.isAbsolute())
-			throw new IllegalArgumentException(
-					"the ${ls} macro directory parameter is not absolute: " + dir);
-
-		if (!dir.exists())
-			throw new IllegalArgumentException(
-					"the ${ls} macro directory parameter does not exist: " + dir);
-
-		if (!dir.isDirectory())
-			throw new IllegalArgumentException(
-					"the ${ls} macro directory parameter points to a file instead of a directory: "
-							+ dir);
-
-		String[] files = dir.list();
-		List<String> result;
-
-		if (args.length < 3) {
-			result = Arrays.asList(files);
-		} else
-			result = new ArrayList<String>();
-
-		for (int i = 2; i < args.length; i++) {
-			String parts[] = args[i].split("\\s*,\\s*");
-			for (String pattern : parts) {
-				// So make it in to an instruction
-				Instruction instr = Instruction.getPattern(pattern);
-
-				// For each project, match it against the instruction
-				for (int f = 0; f < files.length; f++) {
-					if (files[f] != null) {
-						if (instr.matches(files[f])) {
-							if (!instr.isNegated()) {
-								if (relative)
-									result.add(files[f]);
-								else
-									result.add(new File(dir, files[f]).getAbsolutePath());
-							}
-							files[f] = null;
-						}
-					}
-				}
-			}
-		}
-		return Processor.join(result, ",");
-	}
-
-	public String _currenttime(String args[]) {
-		return Long.toString(System.currentTimeMillis());
-	}
-
-	/**
-	 * Modify a version to set a version policy. Thed policy is a mask that is
-	 * mapped to a version.
-	 * 
-	 * <pre>
-	 * +           increment
-	 * -           decrement
-	 * =           maintain
-	 * ˜           discard
-	 * 
-	 * ==+      = maintain major, minor, increment micro, discard qualifier
-	 * ˜˜˜=     = just get the qualifier
-	 * version="[${version;==;${@}},${version;=+;${@}})"
-	 * </pre>
-	 * 
-	 * 
-	 * 
-	 * 
-	 * @param args
-	 * @return
-	 */
-	final static String		MASK_STRING			= "[\\-+=~0123456789]{0,3}[=~]?";
-	final static Pattern	MASK				= Pattern.compile(MASK_STRING);
-	final static String		_versionHelp		= "${version;<mask>;<version>}, modify a version\n"
-														+ "<mask> ::= [ M [ M [ M [ MQ ]]]\n"
-														+ "M ::= '+' | '-' | MQ\n"
-														+ "MQ ::= '~' | '='";
-	final static Pattern	_versionPattern[]	= new Pattern[] { null, null, MASK,
-			Verifier.VERSION					};
-
-	public String _version(String args[]) {
-		verifyCommand(args, _versionHelp, null, 2, 3);
-
-		String mask = args[1];
-
-		Version version = null;
-		if (args.length >= 3)
-			version = new Version(args[2]);
-
-		return version(version, mask);
-	}
-
-	String version(Version version, String mask) {
-		if (version == null) {
-			String v = domain.getProperty("@");
-			if (v == null) {
-				domain
-						.error(
-								"No version specified for ${version} or ${range} and no implicit version ${@} either, mask=%s",
-								mask);
-				v = "0";
-			}
-			version = new Version(v);
-		}
-
-		StringBuilder sb = new StringBuilder();
-		String del = "";
-
-		for (int i = 0; i < mask.length(); i++) {
-			char c = mask.charAt(i);
-			String result = null;
-			if (c != '~') {
-				if (i == 3) {
-					result = version.getQualifier();
-				} else if (Character.isDigit(c)) {
-					// Handle masks like +00, =+0
-					result = String.valueOf(c);
-				} else {
-					int x = version.get(i);
-					switch (c) {
-					case '+':
-						x++;
-						break;
-					case '-':
-						x--;
-						break;
-					case '=':
-						break;
-					}
-					result = Integer.toString(x);
-				}
-				if (result != null) {
-					sb.append(del);
-					del = ".";
-					sb.append(result);
-				}
-			}
-		}
-		return sb.toString();
-	}
-
-	/**
-	 * Schortcut for version policy
-	 * 
-	 * <pre>
-	 * -provide-policy : ${policy;[==,=+)}
-	 * -consume-policy : ${policy;[==,+)}
-	 * </pre>
-	 * 
-	 * @param args
-	 * @return
-	 */
-
-	static Pattern	RANGE_MASK		= Pattern.compile("(\\[|\\()(" + MASK_STRING + "),(" + MASK_STRING +")(\\]|\\))");
-	static String	_rangeHelp		= "${range;<mask>[;<version>]}, range for version, if version not specified lookyp ${@}\n"
-											+ "<mask> ::= [ M [ M [ M [ MQ ]]]\n"
-											+ "M ::= '+' | '-' | MQ\n" + "MQ ::= '~' | '='";
-	static Pattern	_rangePattern[]	= new Pattern[] { null, RANGE_MASK };
-
-	public String _range(String args[]) {
-		verifyCommand(args, _rangeHelp, _rangePattern, 2, 3);
-		Version version = null;
-		if (args.length >= 3)
-			version = new Version(args[2]);
-
-		String spec = args[1];
-
-		Matcher m = RANGE_MASK.matcher(spec);
-		m.matches();
-		String floor = m.group(1);
-		String floorMask = m.group(2);
-		String ceilingMask = m.group(3);
-		String ceiling = m.group(4);
-
-		StringBuilder sb = new StringBuilder();
-		sb.append(floor);
-		sb.append(version(version, floorMask));
-		sb.append(",");
-		sb.append(version(version, ceilingMask));
-		sb.append(ceiling);
-
-		String s = sb.toString();
-		VersionRange vr = new VersionRange(s);
-		if (!(vr.includes(vr.getHigh()) || vr.includes(vr.getLow()))) {
-			domain.error("${range} macro created an invalid range %s from %s and mask %s", s,
-					version, spec);
-		}
-		return sb.toString();
-	}
-
-	/**
-	 * System command. Execute a command and insert the result.
-	 * 
-	 * @param args
-	 * @param help
-	 * @param patterns
-	 * @param low
-	 * @param high
-	 */
-	public String system_internal(boolean allowFail, String args[]) throws Exception {
-		verifyCommand(args, "${" + (allowFail ? "system-allow-fail" : "system")
-				+ ";<command>[;<in>]}, execute a system command", null, 2, 3);
-		String command = args[1];
-		String input = null;
-
-		if (args.length > 2) {
-			input = args[2];
-		}
-
-		Process process = Runtime.getRuntime().exec(command, null, domain.getBase());
-		if (input != null) {
-			process.getOutputStream().write(input.getBytes("UTF-8"));
-		}
-		process.getOutputStream().close();
-
-		String s = IO.collect(process.getInputStream(), "UTF-8");
-		int exitValue = process.waitFor();
-		if (!allowFail && (exitValue != 0)) {
-			domain.error("System command " + command + " failed with " + exitValue);
-		}
-		return s.trim();
-	}
-
-	public String _system(String args[]) throws Exception {
-		return system_internal(false, args);
-	}
-
-	public String _system_allow_fail(String args[]) throws Exception {
-		String result = "";
-		try {
-			result = system_internal(true, args);
-		} catch (Throwable t) {
-			/* ignore */
-		}
-		return result;
-	}
-
-	public String _env(String args[]) {
-		verifyCommand(args, "${env;<name>}, get the environmet variable", null, 2, 2);
-
-		try {
-			return System.getenv(args[1]);
-		} catch (Throwable t) {
-			return null;
-		}
-	}
-
-	/**
-	 * Get the contents of a file.
-	 * 
-	 * @param in
-	 * @return
-	 * @throws IOException
-	 */
-
-	public String _cat(String args[]) throws IOException {
-		verifyCommand(args, "${cat;<in>}, get the content of a file", null, 2, 2);
-		File f = domain.getFile(args[1]);
-		if (f.isFile()) {
-			return IO.collect(f);
-		} else if (f.isDirectory()) {
-			return Arrays.toString(f.list());
-		} else {
-			try {
-				URL url = new URL(args[1]);
-				return IO.collect(url, "UTF-8");
-			} catch (MalformedURLException mfue) {
-				// Ignore here
-			}
-			return null;
-		}
-	}
-
-	public static void verifyCommand(String args[], String help, Pattern[] patterns, int low,
-			int high) {
-		String message = "";
-		if (args.length > high) {
-			message = "too many arguments";
-		} else if (args.length < low) {
-			message = "too few arguments";
-		} else {
-			for (int i = 0; patterns != null && i < patterns.length && i < args.length; i++) {
-				if (patterns[i] != null) {
-					Matcher m = patterns[i].matcher(args[i]);
-					if (!m.matches())
-						message += String.format("Argument %s (%s) does not match %s\n", i,
-								args[i], patterns[i].pattern());
-				}
-			}
-		}
-		if (message.length() != 0) {
-			StringBuilder sb = new StringBuilder();
-			String del = "${";
-			for (String arg : args) {
-				sb.append(del);
-				sb.append(arg);
-				del = ";";
-			}
-			sb.append("}, is not understood. ");
-			sb.append(message);
-			throw new IllegalArgumentException(sb.toString());
-		}
-	}
-
-	// Helper class to track expansion of variables
-	// on the stack.
-	static class Link {
-		Link	previous;
-		String	key;
-		Processor start;
-
-		public Link(Processor start, Link previous, String key) {
-			this.previous = previous;
-			this.key = key;
-			this.start = start;
-		}
-
-		public boolean contains(String key) {
-			if (this.key.equals(key))
-				return true;
-
-			if (previous == null)
-				return false;
-
-			return previous.contains(key);
-		}
-
-		public String toString() {
-			StringBuffer sb = new StringBuffer();
-			String del = "[";
-			for (Link r = this; r != null; r = r.previous) {
-				sb.append(del);
-				sb.append(r.key);
-				del = ",";
-			}
-			sb.append("]");
-			return sb.toString();
-		}
-	}
-
-	/**
-	 * Take all the properties and translate them to actual values. This method
-	 * takes the set properties and traverse them over all entries, including
-	 * the default properties for that properties. The values no longer contain
-	 * macros.
-	 * 
-	 * @return A new Properties with the flattened values
-	 */
-	public Properties getFlattenedProperties() {
-		// Some macros only work in a lower processor, so we
-		// do not report unknown macros while flattening
-		flattening = true;
-		try {
-			Properties flattened = new Properties();
-			Properties source = domain.getProperties();
-			for (Enumeration<?> e = source.propertyNames(); e.hasMoreElements();) {
-				String key = (String) e.nextElement();
-				if (!key.startsWith("_"))
-					if (key.startsWith("-"))
-						flattened.put(key, source.getProperty(key));
-					else
-						flattened.put(key, process(source.getProperty(key)));
-			}
-			return flattened;
-		} finally {
-			flattening = false;
-		}
-	};
-
-	public static String	_fileHelp	= "${file;<base>;<paths>...}, create correct OS dependent path";
-
-	public String _osfile(String args[]) {
-		verifyCommand(args, _fileHelp, null, 3, 3);
-		File base = new File(args[1]);
-		File f = Processor.getFile(base, args[2]);
-		return f.getAbsolutePath();
-	}
-
-	public String _path(String args[]) {
-		List<String> list = new ArrayList<String>();
-		for (int i = 1; i < args.length; i++) {
-			list.addAll(Processor.split(args[i]));
-		}
-		return Processor.join(list, File.pathSeparator);
-	}
-
-	public static Properties getParent(Properties p) {
-		try {
-			Field f = Properties.class.getDeclaredField("defaults");
-			f.setAccessible(true);
-			return (Properties) f.get(p);
-		} catch (Exception e) {
-			Field[] fields = Properties.class.getFields();
-			System.out.println(Arrays.toString(fields));
-			return null;
-		}
-	}
-
-	public String process(String line) {
-		return process(line,domain);
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/OpCodes.java b/biz.aQute.bndlib/src/aQute/lib/osgi/OpCodes.java
deleted file mode 100755
index f0d3134..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/OpCodes.java
+++ /dev/null
@@ -1,1196 +0,0 @@
-package aQute.lib.osgi;
-
-public class OpCodes {
-	final static short	nop				= 0x00;			// [No change] performs
-														// no
-	// operation
-	final static short	aconst_null		= 0x01;			// ? null pushes a null
-	// reference onto the stack
-	final static short	iconst_m1		= 0x02;			// ? -1 loads the int
-														// value -1
-	// onto the stack
-	final static short	iconst_0		= 0x03;			// ? 0 loads the int
-														// value 0
-	// onto the stack
-	final static short	iconst_1		= 0x04;			// ? 1 loads the int
-														// value 1
-	// onto the stack
-	final static short	iconst_2		= 0x05;			// ? 2 loads the int
-														// value 2
-	// onto the stack
-	final static short	iconst_3		= 0x06;			// ? 3 loads the int
-														// value 3
-	// onto the stack
-	final static short	iconst_4		= 0x07;			// ? 4 loads the int
-														// value 4
-	// onto the stack
-	final static short	iconst_5		= 0x08;			// ? 5 loads the int
-														// value 5
-	// onto the stack
-	final static short	lconst_0		= 0x09;			// ? 0L pushes the long
-														// 0 onto
-	// the stack
-	final static short	bipush			= 0x10;			// byte ? value pushes a
-														// byte
-	// onto the stack as an integer
-	// value
-	final static short	sipush			= 0x11;			// byte1, byte2 ? value
-														// pushes a
-	// signed integer (byte1 << 8 +
-	// byte2) onto the stack
-	final static short	ldc				= 0x12;			// index ? value pushes
-														// a
-	// constant #index from a
-	// constant pool (String, int,
-	// float or class type) onto the
-	// stack
-	final static short	ldc_w			= 0x13;			// indexbyte1,
-														// indexbyte2 ?
-	// value pushes a constant
-	// #index from a constant pool
-	// (String, int, float or class
-	// type) onto the stack (wide
-	// index is constructed as
-	// indexbyte1 << 8 + indexbyte2)
-	final static short	ldc2_w			= 0x14;			// indexbyte1,
-														// indexbyte2 ?
-	// value pushes a constant
-	// #index from a constant pool
-	// (double or long) onto the
-	// stack (wide index is
-	// constructed as indexbyte1 <<
-	// 8 + indexbyte2)
-	final static short	iload			= 0x15;			// index ? value loads
-														// an int
-	// value from a variable #index
-	final static short	lload			= 0x16;			// index ? value load a
-														// long
-	// value from a local variable
-	// #index
-	final static short	fload			= 0x17;			// index ? value loads a
-														// float
-	// value from a local variable
-	// #index
-	final static short	dload			= 0x18;			// index ? value loads a
-														// double
-	// value from a local variable
-	// #index
-	final static short	aload			= 0x19;			// index ? objectref
-														// loads a
-	// reference onto the stack from
-	// a local variable #index
-	final static short	lload_2			= 0x20;			// ? value load a long
-														// value
-	// from a local variable 2
-	final static short	lload_3			= 0x21;			// ? value load a long
-														// value
-	// from a local variable 3
-	final static short	fload_0			= 0x22;			// ? value loads a float
-														// value
-	// from local variable 0
-	final static short	fload_1			= 0x23;			// ? value loads a float
-														// value
-	// from local variable 1
-	final static short	fload_2			= 0x24;			// ? value loads a float
-														// value
-	// from local variable 2
-	final static short	fload_3			= 0x25;			// ? value loads a float
-														// value
-	// from local variable 3
-	final static short	dload_0			= 0x26;			// ? value loads a
-														// double from
-	// local variable 0
-	final static short	dload_1			= 0x27;			// ? value loads a
-														// double from
-	// local variable 1
-	final static short	dload_2			= 0x28;			// ? value loads a
-														// double from
-	// local variable 2
-	final static short	dload_3			= 0x29;			// ? value loads a
-														// double from
-	// local variable 3
-	final static short	faload			= 0x30;			// arrayref, index ?
-														// value loads
-	// a float from an array
-	final static short	daload			= 0x31;			// arrayref, index ?
-														// value loads
-	// a double from an array
-	final static short	aaload			= 0x32;			// arrayref, index ?
-														// value loads
-	// onto the stack a reference
-	// from an array
-	final static short	baload			= 0x33;			// arrayref, index ?
-														// value loads
-	// a byte or Boolean value from
-	// an array
-	final static short	caload			= 0x34;			// arrayref, index ?
-														// value loads
-	// a char from an array
-	final static short	saload			= 0x35;			// arrayref, index ?
-														// value load
-	// short from array
-	final static short	istore			= 0x36;			// index value ? store
-														// int value
-	// into variable #index
-	final static short	lstore			= 0x37;			// index value ? store a
-														// long
-	// value in a local variable
-	// #index
-	final static short	fstore			= 0x38;			// index value ? stores
-														// a float
-	// value into a local variable
-	// #index
-	final static short	dstore			= 0x39;			// index value ? stores
-														// a double
-	// value into a local variable
-	// #index
-	final static short	lstore_1		= 0x40;			// value ? store a long
-														// value in
-	// a local variable 1
-	final static short	lstore_2		= 0x41;			// value ? store a long
-														// value in
-	// a local variable 2
-	final static short	lstore_3		= 0x42;			// value ? store a long
-														// value in
-	// a local variable 3
-	final static short	fstore_0		= 0x43;			// value ? stores a
-														// float value
-	// into local variable 0
-	final static short	fstore_1		= 0x44;			// value ? stores a
-														// float value
-	// into local variable 1
-	final static short	fstore_2		= 0x45;			// value ? stores a
-														// float value
-	// into local variable 2
-	final static short	fstore_3		= 0x46;			// value ? stores a
-														// float value
-	// into local variable 3
-	final static short	dstore_0		= 0x47;			// value ? stores a
-														// double into
-	// local variable 0
-	final static short	dstore_1		= 0x48;			// value ? stores a
-														// double into
-	// local variable 1
-	final static short	dstore_2		= 0x49;			// value ? stores a
-														// double into
-	// local variable 2
-	final static short	lastore			= 0x50;			// arrayref, index,
-														// value ?
-	// store a long to an array
-	final static short	fastore			= 0x51;			// arreyref, index,
-														// value ?
-	// stores a float in an array
-	final static short	dastore			= 0x52;			// arrayref, index,
-														// value ?
-	// stores a double into an array
-	final static short	aastore			= 0x53;			// arrayref, index,
-														// value ?
-	// stores into a reference to an
-	// array
-	final static short	bastore			= 0x54;			// arrayref, index,
-														// value ?
-	// stores a byte or Boolean
-	// value into an array
-	final static short	castore			= 0x55;			// arrayref, index,
-														// value ?
-	// stores a char into an array
-	final static short	sastore			= 0x56;			// arrayref, index,
-														// value ?
-	// store short to array
-	final static short	pop				= 0x57;			// value ? discards the
-														// top
-	// value on the stack
-	final static short	pop2			= 0x58;			// {value2, value1} ?
-														// discards
-	// the top two values on the
-	// stack (or one value, if it is
-	// a double or long)
-	final static short	dup				= 0x59;			// value ? value, value
-	// duplicates the value on top
-	// of the stack
-	final static short	iadd			= 0x60;			// value1, value2 ?
-														// result adds
-	// two ints together
-	final static short	ladd			= 0x61;			// value1, value2 ?
-														// result add
-	// two longs
-	final static short	fadd			= 0x62;			// value1, value2 ?
-														// result adds
-	// two floats
-	final static short	dadd			= 0x63;			// value1, value2 ?
-														// result adds
-	// two doubles
-	final static short	isub			= 0x64;			// value1, value2 ?
-														// result int
-	// subtract
-	final static short	lsub			= 0x65;			// value1, value2 ?
-														// result
-	// subtract two longs
-	final static short	fsub			= 0x66;			// value1, value2 ?
-														// result
-	// subtracts two floats
-	final static short	dsub			= 0x67;			// value1, value2 ?
-														// result
-	// subtracts a double from
-	// another
-	final static short	imul			= 0x68;			// value1, value2 ?
-														// result
-	// multiply two integers
-	final static short	lmul			= 0x69;			// value1, value2 ?
-														// result
-	// multiplies two longs
-	final static short	irem			= 0x70;			// value1, value2 ?
-														// result
-	// logical int remainder
-	final static short	lrem			= 0x71;			// value1, value2 ?
-														// result
-	// remainder of division of two
-	// longs
-	final static short	frem			= 0x72;			// value1, value2 ?
-														// result gets
-	// the remainder from a division
-	// between two floats
-	final static short	drem			= 0x73;			// value1, value2 ?
-														// result gets
-	// the remainder from a division
-	// between two doubles
-	final static short	ineg			= 0x74;			// value ? result negate
-														// int
-	final static short	lneg			= 0x75;			// value ? result
-														// negates a long
-	final static short	fneg			= 0x76;			// value ? result
-														// negates a
-	// float
-	final static short	dneg			= 0x77;			// value ? result
-														// negates a
-	// double
-	final static short	ishl			= 0x78;			// value1, value2 ?
-														// result int
-	// shift left
-	final static short	lshl			= 0x79;			// value1, value2 ?
-														// result
-	// bitwise shift left of a long
-	// value1 by value2 positions
-	final static short	ior				= 0x80;			// value1, value2 ?
-														// result
-	// logical int or
-	final static short	lor				= 0x81;			// value1, value2 ?
-														// result
-	// bitwise or of two longs
-	final static short	ixor			= 0x82;			// value1, value2 ?
-														// result int
-	// xor
-	final static short	lxor			= 0x83;			// value1, value2 ?
-														// result
-	// bitwise exclusive or of two
-	// longs
-	final static short	iinc			= 0x84;			// index, const [No
-														// change]
-	// increment local variable
-	// #index by signed byte const
-	final static short	i2l				= 0x85;			// value ? result
-														// converts an
-	// int into a long
-	final static short	i2f				= 0x86;			// value ? result
-														// converts an
-	// int into a float
-	final static short	i2d				= 0x87;			// value ? result
-														// converts an
-	// int into a double
-	final static short	l2i				= 0x88;			// value ? result
-														// converts a
-	// long to an int
-	final static short	l2f				= 0x89;			// value ? result
-														// converts a
-	// long to a float
-	final static short	d2f				= 0x90;			// value ? result
-														// converts a
-	// double to a float
-	final static short	i2b				= 0x91;			// value ? result
-														// converts an
-	// int into a byte
-	final static short	i2c				= 0x92;			// value ? result
-														// converts an
-	// int into a character
-	final static short	i2s				= 0x93;			// value ? result
-														// converts an
-	// int into a short
-	final static short	lcmp			= 0x94;			// value1, value2 ?
-														// result
-	// compares two longs values
-	final static short	fcmpl			= 0x95;			// value1, value2 ?
-														// result
-	// compares two floats
-	final static short	fcmpg			= 0x96;			// value1, value2 ?
-														// result
-	// compares two floats
-	final static short	dcmpl			= 0x97;			// value1, value2 ?
-														// result
-	// compares two doubles
-	final static short	dcmpg			= 0x98;			// value1, value2 ?
-														// result
-	// compares two doubles
-	final static short	ifeq			= 0x99;			// branchbyte1,
-														// branchbyte2
-	// value ? if value is 0, branch
-	// to instruction at
-	// branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	lconst_1		= 0x0a;			// ? 1L pushes the long
-														// 1 onto
-	// the stack
-	final static short	fconst_0		= 0x0b;			// ? 0.0f pushes 0.0f on
-														// the
-	// stack
-	final static short	fconst_1		= 0x0c;			// ? 1.0f pushes 1.0f on
-														// the
-	// stack
-	final static short	fconst_2		= 0x0d;			// ? 2.0f pushes 2.0f on
-														// the
-	// stack
-	final static short	dconst_0		= 0x0e;			// ? 0.0 pushes the
-														// constant 0.0
-	// onto the stack
-	final static short	dconst_1		= 0x0f;			// ? 1.0 pushes the
-														// constant 1.0
-	// onto the stack
-	final static short	iload_0			= 0x1a;			// ? value loads an int
-														// value
-	// from variable 0
-	final static short	iload_1			= 0x1b;			// ? value loads an int
-														// value
-	// from variable 1
-	final static short	iload_2			= 0x1c;			// ? value loads an int
-														// value
-	// from variable 2
-	final static short	iload_3			= 0x1d;			// ? value loads an int
-														// value
-	// from variable 3
-	final static short	lload_0			= 0x1e;			// ? value load a long
-														// value
-	// from a local variable 0
-	final static short	lload_1			= 0x1f;			// ? value load a long
-														// value
-	// from a local variable 1
-	final static short	aload_0			= 0x2a;			// ? objectref loads a
-														// reference
-	// onto the stack from local
-	// variable 0
-	final static short	aload_1			= 0x2b;			// ? objectref loads a
-														// reference
-	// onto the stack from local
-	// variable 1
-	final static short	aload_2			= 0x2c;			// ? objectref loads a
-														// reference
-	// onto the stack from local
-	// variable 2
-	final static short	aload_3			= 0x2d;			// ? objectref loads a
-														// reference
-	// onto the stack from local
-	// variable 3
-	final static short	iaload			= 0x2e;			// arrayref, index ?
-														// value loads
-	// an int from an array
-	final static short	laload			= 0x2f;			// arrayref, index ?
-														// value load
-	// a long from an array
-	final static short	astore			= 0x3a;			// index objectref ?
-														// stores a
-	// reference into a local
-	// variable #index
-	final static short	istore_0		= 0x3b;			// value ? store int
-														// value into
-	// variable 0
-	final static short	istore_1		= 0x3c;			// value ? store int
-														// value into
-	// variable 1
-	final static short	istore_2		= 0x3d;			// value ? store int
-														// value into
-	// variable 2
-	final static short	istore_3		= 0x3e;			// value ? store int
-														// value into
-	// variable 3
-	final static short	lstore_0		= 0x3f;			// value ? store a long
-														// value in
-	// a local variable 0
-	final static short	dstore_3		= 0x4a;			// value ? stores a
-														// double into
-	// local variable 3
-	final static short	astore_0		= 0x4b;			// objectref ? stores a
-	// reference into local variable
-	// 0
-	final static short	astore_1		= 0x4c;			// objectref ? stores a
-	// reference into local variable
-	// 1
-	final static short	astore_2		= 0x4d;			// objectref ? stores a
-	// reference into local variable
-	// 2
-	final static short	astore_3		= 0x4e;			// objectref ? stores a
-	// reference into local variable
-	// 3
-	final static short	iastore			= 0x4f;			// arrayref, index,
-														// value ?
-	// stores an int into an array
-	final static short	dup_x1			= 0x5a;			// value2, value1 ?
-														// value1,
-	// value2, value1 inserts a copy
-	// of the top value into the
-	// stack two values from the top
-	final static short	dup_x2			= 0x5b;			// value3, value2,
-														// value1 ?
-	// value1, value3, value2,
-	// value1 inserts a copy of the
-	// top value into the stack two
-	// (if value2 is double or long
-	// it takes up the entry of
-	// value3, too) or three values
-	// (if value2 is neither double
-	// nor long) from the top
-	final static short	dup2			= 0x5c;			// {value2, value1} ?
-														// {value2,
-	// value1}, {value2, value1}
-	// duplicate top two stack words
-	// (two values, if value1 is not
-	// double nor long; a single
-	// value, if value1 is double or
-	// long)
-	final static short	dup2_x1			= 0x5d;			// value3, {value2,
-														// value1} ?
-	// {value2, value1}, value3,
-	// {value2, value1} duplicate
-	// two words and insert beneath
-	// third word (see explanation
-	// above)
-	final static short	dup2_x2			= 0x5e;			// {value4, value3},
-														// {value2,
-	// value1} ? {value2, value1},
-	// {value4, value3}, {value2,
-	// value1} duplicate two words
-	// and insert beneath fourth
-	// word
-	final static short	swap			= 0x5f;			// value2, value1 ?
-														// value1,
-	// value2 swaps two top words on
-	// the stack (note that value1
-	// and value2 must not be double
-	// or long)
-	final static short	fmul			= 0x6a;			// value1, value2 ?
-														// result
-	// multiplies two floats
-	final static short	dmul			= 0x6b;			// value1, value2 ?
-														// result
-	// multiplies two doubles
-	final static short	idiv			= 0x6c;			// value1, value2 ?
-														// result
-	// divides two integers
-	final static short	ldiv			= 0x6d;			// value1, value2 ?
-														// result
-	// divide two longs
-	final static short	fdiv			= 0x6e;			// value1, value2 ?
-														// result
-	// divides two floats
-	final static short	ddiv			= 0x6f;			// value1, value2 ?
-														// result
-	// divides two doubles
-	final static short	ishr			= 0x7a;			// value1, value2 ?
-														// result int
-	// shift right
-	final static short	lshr			= 0x7b;			// value1, value2 ?
-														// result
-	// bitwise shift right of a long
-	// value1 by value2 positions
-	final static short	iushr			= 0x7c;			// value1, value2 ?
-														// result int
-	// shift right
-	final static short	lushr			= 0x7d;			// value1, value2 ?
-														// result
-	// bitwise shift right of a long
-	// value1 by value2 positions,
-	// unsigned
-	final static short	iand			= 0x7e;			// value1, value2 ?
-														// result
-	// performs a logical and on two
-	// integers
-	final static short	land			= 0x7f;			// value1, value2 ?
-														// result
-	// bitwise and of two longs
-	final static short	l2d				= 0x8a;			// value ? result
-														// converts a
-	// long to a double
-	final static short	f2i				= 0x8b;			// value ? result
-														// converts a
-	// float to an int
-	final static short	f2l				= 0x8c;			// value ? result
-														// converts a
-	// float to a long
-	final static short	f2d				= 0x8d;			// value ? result
-														// converts a
-	// float to a double
-	final static short	d2i				= 0x8e;			// value ? result
-														// converts a
-	// double to an int
-	final static short	d2l				= 0x8f;			// value ? result
-														// converts a
-	// double to a long
-	final static short	ifne			= 0x9a;			// branchbyte1,
-														// branchbyte2
-	// value ? if value is not 0,
-	// branch to instruction at
-	// branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	iflt			= 0x9b;			// branchbyte1,
-														// branchbyte2
-	// value ? if value is less than
-	// 0, branch to instruction at
-	// branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	ifge			= 0x9c;			// branchbyte1,
-														// branchbyte2
-	// value ? if value is greater
-	// than or equal to 0, branch to
-	// instruction at branchoffset
-	// (signed short constructed
-	// from unsigned bytes
-	// branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	ifgt			= 0x9d;			// branchbyte1,
-														// branchbyte2
-	// value ? if value is greater
-	// than 0, branch to instruction
-	// at branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	ifle			= 0x9e;			// branchbyte1,
-														// branchbyte2
-	// value ? if value is less than
-	// or equal to 0, branch to
-	// instruction at branchoffset
-	// (signed short constructed
-	// from unsigned bytes
-	// branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	if_icmpeq		= 0x9f;			// branchbyte1,
-														// branchbyte2
-	// value1, value2 ? if ints are
-	// equal, branch to instruction
-	// at branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	if_icmpne		= 0xa0;			// branchbyte1,
-														// branchbyte2
-	// value1, value2 ? if ints are
-	// not equal, branch to
-	// instruction at branchoffset
-	// (signed short constructed
-	// from unsigned bytes
-	// branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	if_icmplt		= 0xa1;			// branchbyte1,
-														// branchbyte2
-	// value1, value2 ? if value1 is
-	// less than value2, branch to
-	// instruction at branchoffset
-	// (signed short constructed
-	// from unsigned bytes
-	// branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	if_icmpge		= 0xa2;			// branchbyte1,
-														// branchbyte2
-	// value1, value2 ? if value1 is
-	// greater than or equal to
-	// value2, branch to instruction
-	// at branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	if_icmpgt		= 0xa3;			// branchbyte1,
-														// branchbyte2
-	// value1, value2 ? if value1 is
-	// greater than value2, branch
-	// to instruction at
-	// branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	if_icmple		= 0xa4;			// branchbyte1,
-														// branchbyte2
-	// value1, value2 ? if value1 is
-	// less than or equal to value2,
-	// branch to instruction at
-	// branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	if_acmpeq		= 0xa5;			// branchbyte1,
-														// branchbyte2
-	// value1, value2 ? if
-	// references are equal, branch
-	// to instruction at
-	// branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	if_acmpne		= 0xa6;			// branchbyte1,
-														// branchbyte2
-	// value1, value2 ? if
-	// references are not equal,
-	// branch to instruction at
-	// branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	goto_			= 0xa7;			// branchbyte1,
-														// branchbyte2 [no
-	// change] goes to another
-	// instruction at branchoffset
-	// (signed short constructed
-	// from unsigned bytes
-	// branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	jsr				= 0xa8;			// branchbyte1,
-														// branchbyte2 ?
-	// address jump to subroutine at
-	// branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2) and place the
-	// return address on the stack
-	final static short	ret				= 0xa9;			// index [No change]
-														// continue
-	// execution from address taken
-	// from a local variable #index
-	// (the asymmetry with jsr is
-	// intentional)
-	final static short	tableswitch		= 0xaa;			// [0-3 bytes padding],
-	// defaultbyte1, defaultbyte2,
-	// defaultbyte3, defaultbyte4,
-	// lowbyte1, lowbyte2, lowbyte3,
-	// lowbyte4, highbyte1,
-	// highbyte2, highbyte3,
-	// highbyte4, jump offsets...
-	// index ? continue execution
-	// from an address in the table
-	// at offset index
-	final static short	lookupswitch	= 0xab;			// <0-3 bytes padding>,
-	// defaultbyte1, defaultbyte2,
-	// defaultbyte3, defaultbyte4,
-	// npairs1, npairs2, npairs3,
-	// npairs4, match-offset
-	// pairs... key ? a target
-	// address is looked up from a
-	// table using a key and
-	// execution continues from the
-	// instruction at that address
-	final static short	ireturn			= 0xac;			// value ? [empty]
-														// returns an
-	// integer from a method
-	final static short	lreturn			= 0xad;			// value ? [empty]
-														// returns a
-	// long value
-	final static short	freturn			= 0xae;			// value ? [empty]
-														// returns a
-	// float
-	final static short	dreturn			= 0xaf;			// value ? [empty]
-														// returns a
-	// double from a method
-	final static short	areturn			= 0xb0;			// objectref ? [empty]
-														// returns a
-	// reference from a method
-	final static short	return_			= 0xb1;			// ? [empty] return void
-														// from
-	// method
-	final static short	getstatic		= 0xb2;			// index1, index2 ?
-														// value gets a
-	// static field value of a
-	// class, where the field is
-	// identified by field reference
-	// in the constant pool index
-	// (index1 << 8 + index2)
-	final static short	putstatic		= 0xb3;			// indexbyte1,
-														// indexbyte2 value
-	// ? set static field to value
-	// in a class, where the field
-	// is identified by a field
-	// reference index in constant
-	// pool (indexbyte1 << 8 +
-	// indexbyte2)
-	final static short	getfield		= 0xb4;			// index1, index2
-														// objectref ?
-	// value gets a field value of
-	// an object objectref, where
-	// the field is identified by
-	// field reference in the
-	// constant pool index (index1
-	// << 8 + index2)
-	final static short	putfield		= 0xb5;			// indexbyte1,
-														// indexbyte2
-	// objectref, value ? set field
-	// to value in an object
-	// objectref, where the field is
-	// identified by a field
-	// reference index in constant
-	// pool (indexbyte1 << 8 +
-	// indexbyte2)
-	final static short	invokevirtual	= 0xb6;			// indexbyte1,
-														// indexbyte2
-	// objectref, [arg1, arg2, ...]
-	// ? invoke virtual method on
-	// object objectref, where the
-	// method is identified by
-	// method reference index in
-	// constant pool (indexbyte1 <<
-	// 8 + indexbyte2)
-	final static short	invokespecial	= 0xb7;			// indexbyte1,
-														// indexbyte2
-	// objectref, [arg1, arg2, ...]
-	// ? invoke instance method on
-	// object objectref, where the
-	// method is identified by
-	// method reference index in
-	// constant pool (indexbyte1 <<
-	// 8 + indexbyte2)
-	final static short	invokestatic	= 0xb8;			// indexbyte1,
-														// indexbyte2 [arg1,
-	// arg2, ...] ? invoke a static
-	// method, where the method is
-	// identified by method
-	// reference index in constant
-	// pool (indexbyte1 << 8 +
-	// indexbyte2)
-	final static short	invokeinterface	= 0xb9;			// indexbyte1,
-														// indexbyte2,
-	// count, 0 objectref, [arg1,
-	// arg2, ...] ? invokes an
-	// interface method on object
-	// objectref, where the
-	// interface method is
-	// identified by method
-	// reference index in constant
-	// pool (indexbyte1 << 8 +
-	// indexbyte2)
-	final static short	xxxunusedxxx	= 0xba;			// this opcode is
-														// reserved "for
-	// historical reasons"
-	final static short	new_			= 0xbb;			// indexbyte1,
-														// indexbyte2 ?
-	// objectref creates new object
-	// of type identified by class
-	// reference in constant pool
-	// index (indexbyte1 << 8 +
-	// indexbyte2)
-	final static short	newarray		= 0xbc;			// atype count ?
-														// arrayref
-	// creates new array with count
-	// elements of primitive type
-	// identified by atype
-	final static short	anewarray		= 0xbd;			// indexbyte1,
-														// indexbyte2 count
-	// ? arrayref creates a new
-	// array of references of length
-	// count and component type
-	// identified by the class
-	// reference index (indexbyte1
-	// << 8 + indexbyte2) in the
-	// constant pool
-	final static short	arraylength		= 0xbe;			// arrayref ? length
-														// gets the
-	// length of an array
-	final static short	athrow			= 0xbf;			// objectref ? [empty],
-	// objectref throws an error or
-	// exception (notice that the
-	// rest of the stack is cleared,
-	// leaving only a reference to
-	// the Throwable)
-	final static short	checkcast		= 0xc0;			// indexbyte1,
-														// indexbyte2
-	// objectref ? objectref checks
-	// whether an objectref is of a
-	// certain type, the class
-	// reference of which is in the
-	// constant pool at index
-	// (indexbyte1 << 8 +
-	// indexbyte2)
-	final static short	instanceof_		= 0xc1;			// indexbyte1,
-														// indexbyte2
-	// objectref ? result determines
-	// if an object objectref is of
-	// a given type, identified by
-	// class reference index in
-	// constant pool (indexbyte1 <<
-	// 8 + indexbyte2)
-	final static short	monitorenter	= 0xc2;			// objectref ? enter
-														// monitor for
-	// object ("grab the lock" -
-	// start of synchronized()
-	// section)
-	final static short	monitorexit		= 0xc3;			// objectref ? exit
-														// monitor for
-	// object ("release the lock" -
-	// end of synchronized()
-	// section)
-	final static short	wide			= 0xc4;			// opcode, indexbyte1,
-	// indexbyte2
-	final static short	multianewarray	= 0xc5;			// indexbyte1,
-														// indexbyte2,
-	// dimensions count1,
-	// [count2,...] ? arrayref
-	// create a new array of
-	// dimensions dimensions with
-	// elements of type identified
-	// by class reference in
-	// constant pool index
-	// (indexbyte1 << 8 +
-	// indexbyte2); the sizes of
-	// each dimension is identified
-	// by count1, [count2, etc]
-	final static short	ifnull			= 0xc6;			// branchbyte1,
-														// branchbyte2
-	// value ? if value is null,
-	// branch to instruction at
-	// branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	ifnonnull		= 0xc7;			// branchbyte1,
-														// branchbyte2
-	// value ? if value is not null,
-	// branch to instruction at
-	// branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	goto_w			= 0xc8;			// branchbyte1,
-														// branchbyte2,
-	// branchbyte3, branchbyte4 [no
-	// change] goes to another
-	// instruction at branchoffset
-	// (signed int constructed from
-	// unsigned bytes branchbyte1 <<
-	// 24 + branchbyte2 << 16 +
-	// branchbyte3 << 8 +
-	// branchbyte4)
-	final static short	jsr_w			= 0xc9;			// branchbyte1,
-														// branchbyte2,
-	// branchbyte3, branchbyte4 ?
-	// address jump to subroutine at
-	// branchoffset (signed int
-	// constructed from unsigned
-	// bytes branchbyte1 << 24 +
-	// branchbyte2 << 16 +
-	// branchbyte3 << 8 +
-	// branchbyte4) and place the
-	// return address on the stack
-	final static short	breakpoint		= 0xca;			// reserved for
-														// breakpoints in
-	// Java debuggers; should not
-	// appear in any class file
-	final static short	impdep1			= 0xfe;			// reserved for
-	// implementation-dependent
-	// operations within debuggers;
-	// should not appear in any
-	// class file
-	final static short	impdep2			= 0xff;			// reserved for
-	// implementation-dependent
-	// operations within debuggers;
-	// should not appear in any
-	// class file
-
-	final static byte	OFFSETS[]		= new byte[256];
-
-	static {
-		OFFSETS[bipush] = 1; // byte ? value pushes a byte onto the
-		// stack as an integer value
-		OFFSETS[sipush] = 2; // byte1, byte2 ? value pushes a signed
-		// integer (byte1 << 8 + byte2) onto the
-		// stack
-		OFFSETS[ldc] = 1; // index ? value pushes a constant
-		// #index from a constant pool (String,
-		// int, float or class type) onto the
-		// stack
-		OFFSETS[ldc_w] = 2; // indexbyte1, indexbyte2 ? value pushes
-		// a constant #index from a constant
-		// pool (String, int, float or class
-		// type) onto the stack (wide index is
-		// constructed as indexbyte1 << 8 +
-		// indexbyte2)
-		OFFSETS[ldc2_w] = 2; // indexbyte1, indexbyte2 ? value pushes
-		// a constant #index from a constant
-		// pool (double or long) onto the stack
-		// (wide index is constructed as
-		// indexbyte1 << 8 + indexbyte2)
-		OFFSETS[iload] = 1; // index ? value loads an int value from
-		// a variable #index
-		OFFSETS[lload] = 1; // index ? value load a long value from
-		// a local variable #index
-		OFFSETS[fload] = 1; // index ? value loads a float value
-		// from a local variable #index
-		OFFSETS[dload] = 1; // index ? value loads a double value
-		// from a local variable #index
-		OFFSETS[aload] = 1; // index ? objectref loads a reference
-		// onto the stack from a local variable
-		// #index
-		OFFSETS[istore] = 1; // index value ? store int value into
-		// variable #index
-		OFFSETS[lstore] = 1; // index value ? store a long value in a
-		// local variable #index
-		OFFSETS[fstore] = 1; // index value ? stores a float value
-		// into a local variable #index
-		OFFSETS[dstore] = 1; // index value ? stores a double value
-		// into a local variable #index
-		OFFSETS[iinc] = 2; // index, const [No change] increment
-		// local variable #index by signed byte
-		// const
-		OFFSETS[ifeq] = 2; // branchbyte1, branchbyte2 value ? if
-		// value is 0, branch to instruction at
-		// branchoffset (signed short
-		// constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[astore] = 1; // index objectref ? stores a reference
-		// into a local variable #index
-		OFFSETS[ifne] = 2; // branchbyte1, branchbyte2 value ? if
-		// value is not 0, branch to instruction
-		// at branchoffset (signed short
-		// constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[iflt] = 2; // branchbyte1, branchbyte2 value ? if
-		// value is less than 0, branch to
-		// instruction at branchoffset (signed
-		// short constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[ifge] = 2; // branchbyte1, branchbyte2 value ? if
-		// value is greater than or equal to 0,
-		// branch to instruction at branchoffset
-		// (signed short constructed from
-		// unsigned bytes branchbyte1 << 8 +
-		// branchbyte2)
-		OFFSETS[ifgt] = 2; // branchbyte1, branchbyte2 value ? if
-		// value is greater than 0, branch to
-		// instruction at branchoffset (signed
-		// short constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[ifle] = 2; // branchbyte1, branchbyte2 value ? if
-		// value is less than or equal to 0,
-		// branch to instruction at branchoffset
-		// (signed short constructed from
-		// unsigned bytes branchbyte1 << 8 +
-		// branchbyte2)
-		OFFSETS[if_icmpeq] = 2; // branchbyte1, branchbyte2 value1,
-		// value2 ? if ints are equal,
-		// branch to instruction at
-		// branchoffset (signed short
-		// constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[if_icmpne] = 2; // branchbyte1, branchbyte2 value1,
-		// value2 ? if ints are not equal,
-		// branch to instruction at
-		// branchoffset (signed short
-		// constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[if_icmplt] = 2; // branchbyte1, branchbyte2 value1,
-		// value2 ? if value1 is less than
-		// value2, branch to instruction at
-		// branchoffset (signed short
-		// constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[if_icmpge] = 2; // branchbyte1, branchbyte2 value1,
-		// value2 ? if value1 is greater
-		// than or equal to value2, branch
-		// to instruction at branchoffset
-		// (signed short constructed from
-		// unsigned bytes branchbyte1 << 8 +
-		// branchbyte2)
-		OFFSETS[if_icmpgt] = 2; // branchbyte1, branchbyte2 value1,
-		// value2 ? if value1 is greater
-		// than value2, branch to
-		// instruction at branchoffset
-		// (signed short constructed from
-		// unsigned bytes branchbyte1 << 8 +
-		// branchbyte2)
-		OFFSETS[if_icmple] = 2; // branchbyte1, branchbyte2 value1,
-		// value2 ? if value1 is less than
-		// or equal to value2, branch to
-		// instruction at branchoffset
-		// (signed short constructed from
-		// unsigned bytes branchbyte1 << 8 +
-		// branchbyte2)
-		OFFSETS[if_acmpeq] = 2; // branchbyte1, branchbyte2 value1,
-		// value2 ? if references are equal,
-		// branch to instruction at
-		// branchoffset (signed short
-		// constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[if_acmpne] = 2; // branchbyte1, branchbyte2 value1,
-		// value2 ? if references are not
-		// equal, branch to instruction at
-		// branchoffset (signed short
-		// constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[goto_] = 2; // branchbyte1, branchbyte2 [no change]
-		// goes to another instruction at
-		// branchoffset (signed short
-		// constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[jsr] = 2; // branchbyte1, branchbyte2 ? address
-		// jump to subroutine at branchoffset
-		// (signed short constructed from
-		// unsigned bytes branchbyte1 << 8 +
-		// branchbyte2) and place the return
-		// address on the stack
-		OFFSETS[ret] = 1; // index [No change] continue execution
-		// from address taken from a local
-		// variable #index (the asymmetry with
-		// jsr is intentional)
-		OFFSETS[tableswitch] = -1; // [0-3 bytes padding],
-		// defaultbyte1, defaultbyte2,
-		// defaultbyte3, defaultbyte4,
-		// lowbyte1, lowbyte2, lowbyte3,
-		// lowbyte4, highbyte1,
-		// highbyte2, highbyte3,
-		// highbyte4, jump offsets...
-		// index ? continue execution
-		// from an address in the table
-		// at offset index
-		OFFSETS[lookupswitch] = -1; // <0-3 bytes padding>,
-		// defaultbyte1, defaultbyte2,
-		// defaultbyte3, defaultbyte4,
-		// npairs1, npairs2, npairs3,
-		// npairs4, match-offset
-		// pairs... key ? a target
-		// address is looked up from a
-		// table using a key and
-		// execution continues from the
-		// instruction at that address
-		OFFSETS[getstatic] = 2; // index1, index2 ? value gets a
-		// static field value of a class,
-		// where the field is identified by
-		// field reference in the constant
-		// pool index (index1 << 8 + index2)
-		OFFSETS[putstatic] = 2; // indexbyte1, indexbyte2 value ?
-		// set static field to value in a
-		// class, where the field is
-		// identified by a field reference
-		// index in constant pool
-		// (indexbyte1 << 8 + indexbyte2)
-		OFFSETS[getfield] = 2; // index1, index2 objectref ? value
-		// gets a field value of an object
-		// objectref, where the field is
-		// identified by field reference in
-		// the constant pool index (index1
-		// << 8 + index2)
-		OFFSETS[putfield] = 2; // indexbyte1, indexbyte2 objectref,
-		// value ? set field to value in an
-		// object objectref, where the field
-		// is identified by a field
-		// reference index in constant pool
-		// (indexbyte1 << 8 + indexbyte2)
-		OFFSETS[invokevirtual] = 2; // indexbyte1, indexbyte2
-		// objectref, [arg1, arg2, ...]
-		// ? invoke virtual method on
-		// object objectref, where the
-		// method is identified by
-		// method reference index in
-		// constant pool (indexbyte1 <<
-		// 8 + indexbyte2)
-		OFFSETS[invokespecial] = 2; // indexbyte1, indexbyte2
-		// objectref, [arg1, arg2, ...]
-		// ? invoke instance method on
-		// object objectref, where the
-		// method is identified by
-		// method reference index in
-		// constant pool (indexbyte1 <<
-		// 8 + indexbyte2)
-		OFFSETS[invokestatic] = 2; // indexbyte1, indexbyte2 [arg1,
-		// arg2, ...] ? invoke a static
-		// method, where the method is
-		// identified by method
-		// reference index in constant
-		// pool (indexbyte1 << 8 +
-		// indexbyte2)
-		OFFSETS[invokeinterface] = 2; // indexbyte1, indexbyte2,
-		// count, 0 objectref,
-		// [arg1, arg2, ...] ?
-		// invokes an interface
-		// method on object
-		// objectref, where the
-		// interface method is
-		// identified by method
-		// reference index in
-		// constant pool (indexbyte1
-		// << 8 + indexbyte2)
-		OFFSETS[new_] = 2; // indexbyte1, indexbyte2 ? objectref
-		// creates new object of type identified
-		// by class reference in constant pool
-		// index (indexbyte1 << 8 + indexbyte2)
-		OFFSETS[newarray] = 1; // atype count ? arrayref creates
-		// new array with count elements of
-		// primitive type identified by
-		// atype
-		OFFSETS[anewarray] = 2; // indexbyte1, indexbyte2 count ?
-		// arrayref creates a new array of
-		// references of length count and
-		// component type identified by the
-		// class reference index (indexbyte1
-		// << 8 + indexbyte2) in the
-		// constant pool
-		OFFSETS[checkcast] = 2; // indexbyte1, indexbyte2 objectref
-		// ? objectref checks whether an
-		// objectref is of a certain type,
-		// the class reference of which is
-		// in the constant pool at index
-		// (indexbyte1 << 8 + indexbyte2)
-		OFFSETS[instanceof_] = 2; // indexbyte1, indexbyte2 objectref
-		// ? result determines if an object
-		// objectref is of a given type,
-		// identified by class reference
-		// index in constant pool
-		// (indexbyte1 << 8 + indexbyte2)
-		OFFSETS[wide] = 3; // opcode, indexbyte1, indexbyte2
-		OFFSETS[multianewarray] = 3; // indexbyte1, indexbyte2,
-		// dimensions count1,
-		// [count2,...] ? arrayref
-		// create a new array of
-		// dimensions dimensions with
-		// elements of type identified
-		// by class reference in
-		// constant pool index
-		// (indexbyte1 << 8 +
-		// indexbyte2); the sizes of
-		// each dimension is identified
-		// by count1, [count2, etc]
-		OFFSETS[ifnull] = 2; // branchbyte1, branchbyte2 value ? if
-		// value is null, branch to instruction
-		// at branchoffset (signed short
-		// constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[ifnonnull] = 2; // branchbyte1, branchbyte2 value ?
-		// if value is not null, branch to
-		// instruction at branchoffset
-		// (signed short constructed from
-		// unsigned bytes branchbyte1 << 8 +
-		// branchbyte2)
-		OFFSETS[goto_w] = 4; // branchbyte1, branchbyte2,
-		// branchbyte3, branchbyte4 [no change]
-		// goes to another instruction at
-		// branchoffset (signed int constructed
-		// from unsigned bytes branchbyte1 << 24
-		// + branchbyte2 << 16 + branchbyte3 <<
-		// 8 + branchbyte4)
-		OFFSETS[jsr_w] = 4; // branchbyte1, branchbyte2,
-		// branchbyte3, branchbyte4 ? address
-		// jump to subroutine at branchoffset
-		// (signed int constructed from unsigned
-		// bytes branchbyte1 << 24 + branchbyte2
-		// << 16 + branchbyte3 << 8 +
-		// branchbyte4) and place the return
-		// address on the stack
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/PreprocessResource.java b/biz.aQute.bndlib/src/aQute/lib/osgi/PreprocessResource.java
deleted file mode 100644
index e77f811..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/PreprocessResource.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package aQute.lib.osgi;
-
-import java.io.*;
-
-public class PreprocessResource extends AbstractResource {
-    final Resource  resource;
-    final Processor processor;
-
-    public PreprocessResource(Processor processor, Resource r) {
-        super(r.lastModified());
-        this.processor = processor;
-        this.resource = r;
-        extra = resource.getExtra();
-    }
-
-    protected byte[] getBytes() throws Exception {
-        ByteArrayOutputStream bout = new ByteArrayOutputStream(2000);
-        OutputStreamWriter osw = new OutputStreamWriter(bout, Constants.DEFAULT_CHARSET);
-        PrintWriter pw = new PrintWriter(osw);
-        InputStream in = resource.openInputStream();
-        try {
-            BufferedReader rdr = new BufferedReader(new InputStreamReader(in,"UTF8"));
-            String line = rdr.readLine();
-            while (line != null) {
-                line = processor.getReplacer().process(line);
-                pw.println(line);
-                line = rdr.readLine();
-            }
-            pw.flush();
-            byte [] data= bout.toByteArray();
-            return data;
-                
-        } finally {
-            in.close();
-        }        
-    }
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/Processor.java b/biz.aQute.bndlib/src/aQute/lib/osgi/Processor.java
deleted file mode 100755
index fa78ca8..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/Processor.java
+++ /dev/null
@@ -1,1422 +0,0 @@
-package aQute.lib.osgi;
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.jar.*;
-import java.util.regex.*;
-
-import aQute.bnd.service.*;
-import aQute.lib.io.*;
-import aQute.libg.generics.*;
-import aQute.libg.header.*;
-import aQute.libg.reporter.*;
-
-public class Processor implements Reporter, Registry, Constants, Closeable {
-	static ThreadLocal<Processor>	current			= new ThreadLocal<Processor>();
-	static ExecutorService			executor		= Executors.newCachedThreadPool();
-	static Random					random			= new Random();
-
-	// TODO handle include files out of date
-	// TODO make splitter skip eagerly whitespace so trim is not necessary
-	public static String			LIST_SPLITTER	= "\\s*,\\s*";
-	final List<String>				errors			= new ArrayList<String>();
-	final List<String>				warnings		= new ArrayList<String>();
-	final Set<Object>				basicPlugins	= new HashSet<Object>();
-	final Set<Closeable>			toBeClosed		= new HashSet<Closeable>();
-	Set<Object>						plugins;
-
-	boolean							pedantic;
-	boolean							trace;
-	boolean							exceptions;
-	boolean							fileMustExist	= true;
-
-	private File					base			= new File("").getAbsoluteFile();
-
-	Properties						properties;
-	private Macro					replacer;
-	private long					lastModified;
-	private File					propertiesFile;
-	private boolean					fixup			= true;
-	long							modified;
-	Processor						parent;
-	Set<File>						included;
-	CL								pluginLoader;
-	Collection<String>				filter;
-	HashSet<String>					missingCommand;
-
-	public Processor() {
-		properties = new Properties();
-	}
-
-	public Processor(Properties parent) {
-		properties = new Properties(parent);
-	}
-
-	public Processor(Processor parent) {
-		this(parent.properties);
-		this.parent = parent;
-	}
-
-	public void setParent(Processor processor) {
-		this.parent = processor;
-		Properties ext = new Properties(processor.properties);
-		ext.putAll(this.properties);
-		this.properties = ext;
-	}
-
-	public Processor getParent() {
-		return parent;
-	}
-
-	public Processor getTop() {
-		if (parent == null)
-			return this;
-		else
-			return parent.getTop();
-	}
-
-	public void getInfo(Processor processor, String prefix) {
-		if (isFailOk())
-			addAll(warnings, processor.getErrors(), prefix);
-		else
-			addAll(errors, processor.getErrors(), prefix);
-		addAll(warnings, processor.getWarnings(), prefix);
-
-		processor.errors.clear();
-		processor.warnings.clear();
-	}
-
-	public void getInfo(Processor processor) {
-		getInfo(processor, "");
-	}
-
-	private <T> void addAll(List<String> to, List<? extends T> from, String prefix) {
-		for (T x : from) {
-			to.add(prefix + x);
-		}
-	}
-
-	/**
-	 * A processor can mark itself current for a thread.
-	 * 
-	 * @return
-	 */
-	private Processor current() {
-		Processor p = current.get();
-		if (p == null)
-			return this;
-		else
-			return p;
-	}
-
-	public void warning(String string, Object... args) {
-		Processor p = current();
-		String s = formatArrays(string, args);
-		if (!p.warnings.contains(s))
-			p.warnings.add(s);
-		p.signal();
-	}
-
-	public void error(String string, Object... args) {
-		Processor p = current();
-		if (p.isFailOk())
-			p.warning(string, args);
-		else {
-			String s = formatArrays(string, args);
-			if (!p.errors.contains(s))
-				p.errors.add(s);
-		}
-		p.signal();
-	}
-
-	public void error(String string, Throwable t, Object... args) {
-		Processor p = current();
-
-		if (p.isFailOk())
-			p.warning(string + ": " + t, args);
-		else {
-			p.errors.add("Exception: " + t.getMessage());
-			String s = formatArrays(string, args);
-			if (!p.errors.contains(s))
-				p.errors.add(s);
-		}
-		if (p.exceptions)
-			t.printStackTrace();
-
-		p.signal();
-	}
-
-	public void signal() {
-	}
-
-	public List<String> getWarnings() {
-		return warnings;
-	}
-
-	public List<String> getErrors() {
-		return errors;
-	}
-
-	public Map<String, Map<String, String>> parseHeader(String value) {
-		return parseHeader(value, this);
-	}
-
-	/**
-	 * Standard OSGi header parser.
-	 * 
-	 * @param value
-	 * @return
-	 */
-	static public Map<String, Map<String, String>> parseHeader(String value, Processor logger) {
-		return OSGiHeader.parseHeader(value, logger);
-	}
-
-	Map<String, Map<String, String>> getClauses(String header) {
-		return parseHeader(getProperty(header));
-	}
-
-	public void addClose(Closeable jar) {
-		toBeClosed.add(jar);
-	}
-
-	/**
-	 * Remove all entries from a map that start with a specific prefix
-	 * 
-	 * @param <T>
-	 * @param source
-	 * @param prefix
-	 * @return
-	 */
-	static <T> Map<String, T> removeKeys(Map<String, T> source, String prefix) {
-		Map<String, T> temp = new TreeMap<String, T>(source);
-		for (Iterator<String> p = temp.keySet().iterator(); p.hasNext();) {
-			String pack = (String) p.next();
-			if (pack.startsWith(prefix))
-				p.remove();
-		}
-		return temp;
-	}
-
-	public void progress(String s, Object... args) {
-		trace(s, args);
-	}
-
-	public boolean isPedantic() {
-		return current().pedantic;
-	}
-
-	public void setPedantic(boolean pedantic) {
-		this.pedantic = pedantic;
-	}
-
-	public static File getFile(File base, String file) {
-		return IO.getFile(base, file);
-	}
-
-	public File getFile(String file) {
-		return getFile(base, file);
-	}
-
-	/**
-	 * Return a list of plugins that implement the given class.
-	 * 
-	 * @param clazz
-	 *            Each returned plugin implements this class/interface
-	 * @return A list of plugins
-	 */
-	public <T> List<T> getPlugins(Class<T> clazz) {
-		List<T> l = new ArrayList<T>();
-		Set<Object> all = getPlugins();
-		for (Object plugin : all) {
-			if (clazz.isInstance(plugin))
-				l.add(clazz.cast(plugin));
-		}
-		return l;
-	}
-
-	/**
-	 * Returns the first plugin it can find of the given type.
-	 * 
-	 * @param <T>
-	 * @param clazz
-	 * @return
-	 */
-	public <T> T getPlugin(Class<T> clazz) {
-		Set<Object> all = getPlugins();
-		for (Object plugin : all) {
-			if (clazz.isInstance(plugin))
-				return clazz.cast(plugin);
-		}
-		return null;
-	}
-
-	/**
-	 * Return a list of plugins. Plugins are defined with the -plugin command.
-	 * They are class names, optionally associated with attributes. Plugins can
-	 * implement the Plugin interface to see these attributes.
-	 * 
-	 * Any object can be a plugin.
-	 * 
-	 * @return
-	 */
-	protected synchronized Set<Object> getPlugins() {
-		if (this.plugins != null)
-			return this.plugins;
-
-		missingCommand = new HashSet<String>();
-		Set<Object> list = new LinkedHashSet<Object>();
-
-		// The owner of the plugin is always in there.
-		list.add(this);
-		setTypeSpecificPlugins(list);
-
-		if (parent != null)
-			list.addAll(parent.getPlugins());
-
-		// We only use plugins now when they are defined on our level
-		// and not if it is in our parent. We inherit from our parent
-		// through the previous block.
-
-		if (properties.containsKey(PLUGIN)) {
-			String spe = getProperty(PLUGIN);
-			if (spe.equals(NONE))
-				return new LinkedHashSet<Object>();
-
-			loadPlugins(list, spe);
-		}
-
-		return this.plugins = list;
-	}
-
-	/**
-	 * @param list
-	 * @param spe
-	 */
-	protected void loadPlugins(Set<Object> list, String spe) {
-		Map<String, Map<String, String>> plugins = parseHeader(spe);
-		for (Map.Entry<String, Map<String, String>> entry : plugins.entrySet()) {
-			String key = (String) entry.getKey();
-
-			try {
-				CL loader = getLoader();
-				String path = entry.getValue().get(PATH_DIRECTIVE);
-				if (path != null) {
-					String parts[] = path.split("\\s*,\\s*");
-					for (String p : parts) {
-						File f = getFile(p).getAbsoluteFile();
-						loader.add(f.toURI().toURL());
-					}
-				}
-
-				trace("Using plugin %s", key);
-
-				// Plugins could use the same class with different
-				// parameters so we could have duplicate names Remove
-				// the ! added by the parser to make each name unique.
-				key = removeDuplicateMarker(key);
-
-				try {
-					Class<?> c = (Class<?>) loader.loadClass(key);
-					Object plugin = c.newInstance();
-					customize(plugin, entry.getValue());
-					list.add(plugin);
-				} catch (Throwable t) {
-					// We can defer the error if the plugin specifies
-					// a command name. In that case, we'll verify that
-					// a bnd file does not contain any references to a
-					// plugin
-					// command. The reason this feature was added was
-					// to compile plugin classes with the same build.
-					String commands = entry.getValue().get(COMMAND_DIRECTIVE);
-					if (commands == null)
-						error("Problem loading the plugin: %s exception: (%s)", key, t);
-					else {
-						Collection<String> cs = split(commands);
-						missingCommand.addAll(cs);
-					}
-				}
-			} catch (Throwable e) {
-				error("Problem loading the plugin: " + key + " exception: " + e);
-			}
-		}
-	}
-
-	protected void setTypeSpecificPlugins(Set<Object> list) {
-		list.add(executor);
-		list.add(random);
-		list.addAll(basicPlugins);
-	}
-
-	/**
-	 * @param plugin
-	 * @param entry
-	 */
-	protected <T> T customize(T plugin, Map<String, String> map) {
-		if (plugin instanceof Plugin) {
-			if (map != null)
-				((Plugin) plugin).setProperties(map);
-
-			((Plugin) plugin).setReporter(this);
-		}
-		if (plugin instanceof RegistryPlugin) {
-			((RegistryPlugin) plugin).setRegistry(this);
-		}
-		return plugin;
-	}
-
-	public boolean isFailOk() {
-		String v = getProperty(Analyzer.FAIL_OK, null);
-		return v != null && v.equalsIgnoreCase("true");
-	}
-
-	public File getBase() {
-		return base;
-	}
-
-	public void setBase(File base) {
-		this.base = base;
-	}
-
-	public void clear() {
-		errors.clear();
-		warnings.clear();
-	}
-
-	public void trace(String msg, Object... parms) {
-		Processor p = current();
-		if (p.trace) {
-			System.out.printf("# " + msg + "\n", parms);
-		}
-	}
-
-	public <T> List<T> newList() {
-		return new ArrayList<T>();
-	}
-
-	public <T> Set<T> newSet() {
-		return new TreeSet<T>();
-	}
-
-	public static <K, V> Map<K, V> newMap() {
-		return new LinkedHashMap<K, V>();
-	}
-
-	public static <K, V> Map<K, V> newHashMap() {
-		return new HashMap<K, V>();
-	}
-
-	public <T> List<T> newList(Collection<T> t) {
-		return new ArrayList<T>(t);
-	}
-
-	public <T> Set<T> newSet(Collection<T> t) {
-		return new TreeSet<T>(t);
-	}
-
-	public <K, V> Map<K, V> newMap(Map<K, V> t) {
-		return new LinkedHashMap<K, V>(t);
-	}
-
-	public void close() {
-		for (Closeable c : toBeClosed) {
-			try {
-				c.close();
-			} catch (IOException e) {
-				// Who cares?
-			}
-		}
-		toBeClosed.clear();
-	}
-
-	public String _basedir(String args[]) {
-		if (base == null)
-			throw new IllegalArgumentException("No base dir set");
-
-		return base.getAbsolutePath();
-	}
-
-	/**
-	 * Property handling ...
-	 * 
-	 * @return
-	 */
-
-	public Properties getProperties() {
-		if (fixup) {
-			fixup = false;
-			begin();
-		}
-
-		return properties;
-	}
-
-	public String getProperty(String key) {
-		return getProperty(key, null);
-	}
-
-	public void mergeProperties(File file, boolean override) {
-		if (file.isFile()) {
-			try {
-				Properties properties = loadProperties(file);
-				mergeProperties(properties, override);
-			} catch (Exception e) {
-				error("Error loading properties file: " + file);
-			}
-		} else {
-			if (!file.exists())
-				error("Properties file does not exist: " + file);
-			else
-				error("Properties file must a file, not a directory: " + file);
-		}
-	}
-
-	public void mergeProperties(Properties properties, boolean override) {
-		for (Enumeration<?> e = properties.propertyNames(); e.hasMoreElements();) {
-			String key = (String) e.nextElement();
-			String value = properties.getProperty(key);
-			if (override || !getProperties().containsKey(key))
-				setProperty(key, value);
-		}
-	}
-
-	public void setProperties(Properties properties) {
-		doIncludes(getBase(), properties);
-		this.properties.putAll(properties);
-	}
-
-	public void addProperties(File file) throws Exception {
-		addIncluded(file);
-		Properties p = loadProperties(file);
-		setProperties(p);
-	}
-
-	public synchronized void addIncluded(File file) {
-		if (included == null)
-			included = new HashSet<File>();
-		included.add(file);
-	}
-
-	/**
-	 * Inspect the properties and if you find -includes parse the line included
-	 * manifest files or properties files. The files are relative from the given
-	 * base, this is normally the base for the analyzer.
-	 * 
-	 * @param ubase
-	 * @param p
-	 * @param done
-	 * @throws IOException
-	 * @throws IOException
-	 */
-
-	private void doIncludes(File ubase, Properties p) {
-		String includes = p.getProperty(INCLUDE);
-		if (includes != null) {
-			includes = getReplacer().process(includes);
-			p.remove(INCLUDE);
-			Collection<String> clauses = parseHeader(includes).keySet();
-
-			for (String value : clauses) {
-				boolean fileMustExist = true;
-				boolean overwrite = true;
-				while (true) {
-					if (value.startsWith("-")) {
-						fileMustExist = false;
-						value = value.substring(1).trim();
-					} else if (value.startsWith("~")) {
-						// Overwrite properties!
-						overwrite = false;
-						value = value.substring(1).trim();
-					} else
-						break;
-				}
-				try {
-					File file = getFile(ubase, value).getAbsoluteFile();
-					if (!file.isFile() && fileMustExist) {
-						error("Included file " + file
-								+ (file.exists() ? " does not exist" : " is directory"));
-					} else
-						doIncludeFile(file, overwrite, p);
-				} catch (Exception e) {
-					if (fileMustExist)
-						error("Error in processing included file: " + value, e);
-				}
-			}
-		}
-	}
-
-	/**
-	 * @param file
-	 * @param parent
-	 * @param done
-	 * @param overwrite
-	 * @throws FileNotFoundException
-	 * @throws IOException
-	 */
-	public void doIncludeFile(File file, boolean overwrite, Properties target) throws Exception {
-		if (included != null && included.contains(file)) {
-			error("Cyclic or multiple include of " + file);
-		} else {
-			addIncluded(file);
-			updateModified(file.lastModified(), file.toString());
-			InputStream in = new FileInputStream(file);
-			Properties sub;
-			if (file.getName().toLowerCase().endsWith(".mf")) {
-				sub = getManifestAsProperties(in);
-			} else
-				sub = loadProperties(in, file.getAbsolutePath());
-
-			in.close();
-
-			doIncludes(file.getParentFile(), sub);
-			// make sure we do not override properties
-			for (Map.Entry<?, ?> entry : sub.entrySet()) {
-				if (overwrite || !target.containsKey(entry.getKey()))
-					target.setProperty((String) entry.getKey(), (String) entry.getValue());
-			}
-		}
-	}
-
-	public void unsetProperty(String string) {
-		getProperties().remove(string);
-
-	}
-
-	public boolean refresh() {
-		plugins = null; // We always refresh our plugins
-
-		if (propertiesFile == null)
-			return false;
-
-		boolean changed = updateModified(propertiesFile.lastModified(), "properties file");
-		if (included != null) {
-			for (File file : included) {
-				if (changed)
-					break;
-
-				changed |= !file.exists()
-						|| updateModified(file.lastModified(), "include file: " + file);
-			}
-		}
-
-		if (changed) {
-			forceRefresh();
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * 
-	 */
-	public void forceRefresh() {
-		included = null;
-		properties.clear();
-		setProperties(propertiesFile, base);
-		propertiesChanged();
-	}
-
-	public void propertiesChanged() {
-	}
-
-	/**
-	 * Set the properties by file. Setting the properties this way will also set
-	 * the base for this analyzer. After reading the properties, this will call
-	 * setProperties(Properties) which will handle the includes.
-	 * 
-	 * @param propertiesFile
-	 * @throws FileNotFoundException
-	 * @throws IOException
-	 */
-	public void setProperties(File propertiesFile) throws IOException {
-		propertiesFile = propertiesFile.getAbsoluteFile();
-		setProperties(propertiesFile, propertiesFile.getParentFile());
-	}
-
-	public void setProperties(File propertiesFile, File base) {
-		this.propertiesFile = propertiesFile.getAbsoluteFile();
-		setBase(base);
-		try {
-			if (propertiesFile.isFile()) {
-				// System.out.println("Loading properties " + propertiesFile);
-				long modified = propertiesFile.lastModified();
-				if (modified > System.currentTimeMillis() + 100) {
-					System.out.println("Huh? This is in the future " + propertiesFile);
-					this.modified = System.currentTimeMillis();
-				} else
-					this.modified = modified;
-
-				included = null;
-				Properties p = loadProperties(propertiesFile);
-				setProperties(p);
-			} else {
-				if (fileMustExist) {
-					error("No such properties file: " + propertiesFile);
-				}
-			}
-		} catch (IOException e) {
-			error("Could not load properties " + propertiesFile);
-		}
-	}
-
-	protected void begin() {
-		if (isTrue(getProperty(PEDANTIC)))
-			setPedantic(true);
-	}
-
-	public static boolean isTrue(String value) {
-		if (value == null)
-			return false;
-
-		return !"false".equalsIgnoreCase(value);
-	}
-
-	/**
-	 * Get a property with a proper default
-	 * 
-	 * @param headerName
-	 * @param deflt
-	 * @return
-	 */
-	public String getProperty(String key, String deflt) {
-		String value = null;
-		Processor source = this;
-
-		if (filter != null && filter.contains(key)) {
-			value = (String) getProperties().get(key);
-		} else {
-			while (source != null) {
-				value = (String) source.getProperties().get(key);
-				if (value != null)
-					break;
-
-				source = source.getParent();
-			}
-		}
-
-		if (value != null)
-			return getReplacer().process(value, source);
-		else if (deflt != null)
-			return getReplacer().process(deflt, this);
-		else
-			return null;
-	}
-
-	/**
-	 * Helper to load a properties file from disk.
-	 * 
-	 * @param file
-	 * @return
-	 * @throws IOException
-	 */
-	public Properties loadProperties(File file) throws IOException {
-		updateModified(file.lastModified(), "Properties file: " + file);
-		InputStream in = new FileInputStream(file);
-		Properties p = loadProperties(in, file.getAbsolutePath());
-		in.close();
-		return p;
-	}
-
-	Properties loadProperties(InputStream in, String name) throws IOException {
-		int n = name.lastIndexOf('/');
-		if (n > 0)
-			name = name.substring(0, n);
-		if (name.length() == 0)
-			name = ".";
-
-		try {
-			Properties p = new Properties();
-			p.load(in);
-			return replaceAll(p, "\\$\\{\\.\\}", name);
-		} catch (Exception e) {
-			error("Error during loading properties file: " + name + ", error:" + e);
-			return new Properties();
-		}
-	}
-
-	/**
-	 * Replace a string in all the values of the map. This can be used to
-	 * preassign variables that change. I.e. the base directory ${.} for a
-	 * loaded properties
-	 */
-
-	public static Properties replaceAll(Properties p, String pattern, String replacement) {
-		Properties result = new Properties();
-		for (Iterator<Map.Entry<Object, Object>> i = p.entrySet().iterator(); i.hasNext();) {
-			Map.Entry<Object, Object> entry = i.next();
-			String key = (String) entry.getKey();
-			String value = (String) entry.getValue();
-			value = value.replaceAll(pattern, replacement);
-			result.put(key, value);
-		}
-		return result;
-	}
-
-	/**
-	 * Merge the attributes of two maps, where the first map can contain
-	 * wildcarded names. The idea is that the first map contains patterns (for
-	 * example *) with a set of attributes. These patterns are matched against
-	 * the found packages in actual. If they match, the result is set with the
-	 * merged set of attributes. It is expected that the instructions are
-	 * ordered so that the instructor can define which pattern matches first.
-	 * Attributes in the instructions override any attributes from the actual.<br/>
-	 * 
-	 * A pattern is a modified regexp so it looks like globbing. The * becomes a
-	 * .* just like the ? becomes a .?. '.' are replaced with \\. Additionally,
-	 * if the pattern starts with an exclamation mark, it will remove that
-	 * matches for that pattern (- the !) from the working set. So the following
-	 * patterns should work:
-	 * <ul>
-	 * <li>com.foo.bar</li>
-	 * <li>com.foo.*</li>
-	 * <li>com.foo.???</li>
-	 * <li>com.*.[^b][^a][^r]</li>
-	 * <li>!com.foo.* (throws away any match for com.foo.*)</li>
-	 * </ul>
-	 * Enough rope to hang the average developer I would say.
-	 * 
-	 * 
-	 * @param instructions
-	 *            the instructions with patterns. A
-	 * @param actual
-	 *            the actual found packages
-	 */
-
-	public static Map<String, Map<String, String>> merge(String type,
-			Map<String, Map<String, String>> instructions, Map<String, Map<String, String>> actual,
-			Set<String> superfluous, Map<String, Map<String, String>> ignored) {
-		Map<String, Map<String, String>> toVisit = new HashMap<String, Map<String, String>>(actual); // we
-		// do
-		// not
-		// want
-		// to
-		// ruin
-		// our
-		// original
-		Map<String, Map<String, String>> result = newMap();
-		for (Iterator<String> i = instructions.keySet().iterator(); i.hasNext();) {
-			String instruction = i.next();
-			String originalInstruction = instruction;
-
-			Map<String, String> instructedAttributes = instructions.get(instruction);
-
-			// Check if we have a fixed (starts with '=') or a
-			// duplicate name. A fixed name is added to the output without
-			// checking against the contents. Duplicates are marked
-			// at the end. In that case we do not pick up any contained
-			// information but just add them to the output including the
-			// marker.
-			if (instruction.startsWith("=")) {
-				result.put(instruction.substring(1), instructedAttributes);
-				superfluous.remove(originalInstruction);
-				continue;
-			}
-			if (isDuplicate(instruction)) {
-				result.put(instruction, instructedAttributes);
-				superfluous.remove(originalInstruction);
-				continue;
-			}
-
-			Instruction instr = Instruction.getPattern(instruction);
-
-			for (Iterator<String> p = toVisit.keySet().iterator(); p.hasNext();) {
-				String packageName = p.next();
-
-				if (instr.matches(packageName)) {
-					superfluous.remove(originalInstruction);
-					if (!instr.isNegated()) {
-						Map<String, String> newAttributes = new HashMap<String, String>();
-						newAttributes.putAll(actual.get(packageName));
-						newAttributes.putAll(instructedAttributes);
-						result.put(packageName, newAttributes);
-					} else if (ignored != null) {
-						ignored.put(packageName, new HashMap<String, String>());
-					}
-					p.remove(); // Can never match again for another pattern
-				}
-			}
-
-		}
-		return result;
-	}
-
-	/**
-	 * Print a standard Map based OSGi header.
-	 * 
-	 * @param exports
-	 *            map { name => Map { attribute|directive => value } }
-	 * @return the clauses
-	 */
-	public static String printClauses(Map<String, Map<String, String>> exports) {
-		return printClauses(exports, false);
-	}
-
-	public static String printClauses(Map<String, Map<String, String>> exports,
-			boolean checkMultipleVersions) {
-		StringBuffer sb = new StringBuffer();
-		String del = "";
-		for (Iterator<String> i = exports.keySet().iterator(); i.hasNext();) {
-			String name = i.next();
-			Map<String, String> clause = exports.get(name);
-
-			// We allow names to be duplicated in the input
-			// by ending them with '~'. This is necessary to use
-			// the package names as keys. However, we remove these
-			// suffixes in the output so that you can set multiple
-			// exports with different attributes.
-			String outname = removeDuplicateMarker(name);
-			sb.append(del);
-			sb.append(outname);
-			printClause(clause, sb);
-			del = ",";
-		}
-		return sb.toString();
-	}
-
-	public static void printClause(Map<String, String> map, StringBuffer sb) {
-
-		for (Iterator<String> j = map.keySet().iterator(); j.hasNext();) {
-			String key = j.next();
-
-			// Skip directives we do not recognize
-			if (key.equals(NO_IMPORT_DIRECTIVE) || key.equals(PROVIDE_DIRECTIVE)
-					|| key.equals(SPLIT_PACKAGE_DIRECTIVE) || key.equals(FROM_DIRECTIVE))
-				continue;
-
-			String value = ((String) map.get(key)).trim();
-			sb.append(";");
-			sb.append(key);
-			sb.append("=");
-
-			boolean clean = (value.length() >= 2 && value.charAt(0) == '"' && value.charAt(value
-					.length() - 1) == '"') || Verifier.TOKEN.matcher(value).matches();
-			if (!clean)
-				sb.append("\"");
-			sb.append(value);
-			if (!clean)
-				sb.append("\"");
-		}
-	}
-
-	public Macro getReplacer() {
-		if (replacer == null)
-			return replacer = new Macro(this, getMacroDomains());
-		else
-			return replacer;
-	}
-
-	/**
-	 * This should be overridden by subclasses to add extra macro command
-	 * domains on the search list.
-	 * 
-	 * @return
-	 */
-	protected Object[] getMacroDomains() {
-		return new Object[] {};
-	}
-
-	/**
-	 * Return the properties but expand all macros. This always returns a new
-	 * Properties object that can be used in any way.
-	 * 
-	 * @return
-	 */
-	public Properties getFlattenedProperties() {
-		return getReplacer().getFlattenedProperties();
-
-	}
-
-	public boolean updateModified(long time, String reason) {
-		if (time > lastModified) {
-			lastModified = time;
-			return true;
-		}
-		return false;
-	}
-
-	public long lastModified() {
-		return lastModified;
-	}
-
-	/**
-	 * Add or override a new property.
-	 * 
-	 * @param key
-	 * @param value
-	 */
-	public void setProperty(String key, String value) {
-		checkheader: for (int i = 0; i < headers.length; i++) {
-			if (headers[i].equalsIgnoreCase(value)) {
-				value = headers[i];
-				break checkheader;
-			}
-		}
-		getProperties().put(key, value);
-	}
-
-	/**
-	 * Read a manifest but return a properties object.
-	 * 
-	 * @param in
-	 * @return
-	 * @throws IOException
-	 */
-	public static Properties getManifestAsProperties(InputStream in) throws IOException {
-		Properties p = new Properties();
-		Manifest manifest = new Manifest(in);
-		for (Iterator<Object> it = manifest.getMainAttributes().keySet().iterator(); it.hasNext();) {
-			Attributes.Name key = (Attributes.Name) it.next();
-			String value = manifest.getMainAttributes().getValue(key);
-			p.put(key.toString(), value);
-		}
-		return p;
-	}
-
-	public File getPropertiesFile() {
-		return propertiesFile;
-	}
-
-	public void setFileMustExist(boolean mustexist) {
-		fileMustExist = mustexist;
-	}
-
-	static public String read(InputStream in) throws Exception {
-		InputStreamReader ir = new InputStreamReader(in, "UTF8");
-		StringBuilder sb = new StringBuilder();
-
-		try {
-			char chars[] = new char[1000];
-			int size = ir.read(chars);
-			while (size > 0) {
-				sb.append(chars, 0, size);
-				size = ir.read(chars);
-			}
-		} finally {
-			ir.close();
-		}
-		return sb.toString();
-	}
-
-	/**
-	 * Join a list.
-	 * 
-	 * @param args
-	 * @return
-	 */
-	public static String join(Collection<?> list, String delimeter) {
-		return join(delimeter, list);
-	}
-
-	public static String join(String delimeter, Collection<?>... list) {
-		StringBuilder sb = new StringBuilder();
-		String del = "";
-		for (Collection<?> l : list) {
-			if (list != null) {
-				for (Object item : l) {
-					sb.append(del);
-					sb.append(item);
-					del = delimeter;
-				}
-			}
-		}
-		return sb.toString();
-	}
-
-	public static String join(Object[] list, String delimeter) {
-		if (list == null)
-			return "";
-		StringBuilder sb = new StringBuilder();
-		String del = "";
-		for (Object item : list) {
-			sb.append(del);
-			sb.append(item);
-			del = delimeter;
-		}
-		return sb.toString();
-	}
-
-	public static String join(Collection<?>... list) {
-		return join(",", list);
-	}
-
-	public static <T> String join(T list[]) {
-		return join(list, ",");
-	}
-
-	public static void split(String s, Collection<String> set) {
-
-		String elements[] = s.trim().split(LIST_SPLITTER);
-		for (String element : elements) {
-			if (element.length() > 0)
-				set.add(element);
-		}
-	}
-
-	public static Collection<String> split(String s) {
-		return split(s, LIST_SPLITTER);
-	}
-
-	public static Collection<String> split(String s, String splitter) {
-		if (s != null)
-			s = s.trim();
-		if (s == null || s.trim().length() == 0)
-			return Collections.emptyList();
-
-		return Arrays.asList(s.split(splitter));
-	}
-
-	public static String merge(String... strings) {
-		ArrayList<String> result = new ArrayList<String>();
-		for (String s : strings) {
-			if (s != null)
-				split(s, result);
-		}
-		return join(result);
-	}
-
-	public boolean isExceptions() {
-		return exceptions;
-	}
-
-	public void setExceptions(boolean exceptions) {
-		this.exceptions = exceptions;
-	}
-
-	/**
-	 * Make the file short if it is inside our base directory, otherwise long.
-	 * 
-	 * @param f
-	 * @return
-	 */
-	public String normalize(String f) {
-		if (f.startsWith(base.getAbsolutePath() + "/"))
-			return f.substring(base.getAbsolutePath().length() + 1);
-		else
-			return f;
-	}
-
-	public String normalize(File f) {
-		return normalize(f.getAbsolutePath());
-	}
-
-	public static String removeDuplicateMarker(String key) {
-		int i = key.length() - 1;
-		while (i >= 0 && key.charAt(i) == DUPLICATE_MARKER)
-			--i;
-
-		return key.substring(0, i + 1);
-	}
-
-	public static boolean isDuplicate(String name) {
-		return name.length() > 0 && name.charAt(name.length() - 1) == DUPLICATE_MARKER;
-	}
-
-	public void setTrace(boolean x) {
-		trace = x;
-	}
-
-	static class CL extends URLClassLoader {
-
-		CL() {
-			super(new URL[0], Processor.class.getClassLoader());
-		}
-
-		void add(URL url) {
-			URL urls[] = getURLs();
-			for (URL u : urls) {
-				if (u.equals(url))
-					return;
-			}
-			super.addURL(url);
-		}
-
-		public Class<?> loadClass(String name) throws NoClassDefFoundError {
-			try {
-				Class<?> c = super.loadClass(name);
-				return c;
-			} catch (Throwable t) {
-				StringBuilder sb = new StringBuilder();
-				sb.append(name);
-				sb.append(" not found, parent:  ");
-				sb.append(getParent());
-				sb.append(" urls:");
-				sb.append(Arrays.toString(getURLs()));
-				sb.append(" exception:");
-				sb.append(t);
-				throw new NoClassDefFoundError(sb.toString());
-			}
-		}
-	}
-
-	private CL getLoader() {
-		if (pluginLoader == null) {
-			pluginLoader = new CL();
-		}
-		return pluginLoader;
-	}
-
-	/*
-	 * Check if this is a valid project.
-	 */
-	public boolean exists() {
-		return base != null && base.isDirectory() && propertiesFile != null
-				&& propertiesFile.isFile();
-	}
-
-	public boolean isOk() {
-		return isFailOk() || (getErrors().size() == 0);
-	}
-
-	public boolean isPerfect() {
-		return getErrors().size() == 0 && getWarnings().size() == 0;
-	}
-
-	public void setForceLocal(Collection<String> local) {
-		filter = local;
-	}
-
-	/**
-	 * Answer if the name is a missing plugin's command name. If a bnd file
-	 * contains the command name of a plugin, and that plugin is not available,
-	 * then an error is reported during manifest calculation. This allows the
-	 * plugin to fail to load when it is not needed.
-	 * 
-	 * We first get the plugins to ensure it is properly initialized.
-	 * 
-	 * @param name
-	 * @return
-	 */
-	public boolean isMissingPlugin(String name) {
-		getPlugins();
-		return missingCommand != null && missingCommand.contains(name);
-	}
-
-	/**
-	 * Append two strings to for a path in a ZIP or JAR file. It is guaranteed
-	 * to return a string that does not start, nor ends with a '/', while it is
-	 * properly separated with slashes. Double slashes are properly removed.
-	 * 
-	 * <pre>
-	 *  "/" + "abc/def/" becomes "abc/def"
-	 *  
-	 * @param prefix
-	 * @param suffix
-	 * @return
-	 * 
-	 */
-	public static String appendPath(String... parts) {
-		StringBuilder sb = new StringBuilder();
-		boolean lastSlash = true;
-		for (String part : parts) {
-			for (int i = 0; i < part.length(); i++) {
-				char c = part.charAt(i);
-				if (c == '/') {
-					if (!lastSlash)
-						sb.append('/');
-					lastSlash = true;
-				} else {
-					sb.append(c);
-					lastSlash = false;
-				}
-			}
-			if (!lastSlash & sb.length() > 0) {
-				sb.append('/');
-				lastSlash = true;
-			}
-		}
-		if (lastSlash && sb.length() > 0)
-			sb.deleteCharAt(sb.length() - 1);
-
-		return sb.toString();
-	}
-
-	/**
-	 * Parse the a=b strings and return a map of them.
-	 * 
-	 * @param attrs
-	 * @param clazz
-	 * @return
-	 */
-	public static Map<String, String> doAttrbutes(Object[] attrs, Clazz clazz, Macro macro) {
-		if (attrs == null || attrs.length == 0)
-			return Collections.emptyMap();
-
-		Map<String, String> map = newMap();
-		for (Object a : attrs) {
-			String attr = (String) a;
-			int n = attr.indexOf("=");
-			if (n > 0) {
-				map.put(attr.substring(0, n), macro.process(attr.substring(n + 1)));
-			} else
-				throw new IllegalArgumentException(formatArrays(
-						"Invalid attribute on package-info.java in %s , %s. Must be <key>=<name> ",
-						clazz, attr));
-		}
-		return map;
-	}
-
-	/**
-	 * This method is the same as String.format but it makes sure that any
-	 * arrays are transformed to strings.
-	 * 
-	 * @param string
-	 * @param parms
-	 * @return
-	 */
-	public static String formatArrays(String string, Object... parms) {
-		Object[] parms2 = parms;
-		Object[] output = new Object[parms.length];
-		for (int i = 0; i < parms.length; i++) {
-			output[i] = makePrintable(parms[i]);
-		}
-		return String.format(string, parms2);
-	}
-
-	/**
-	 * Check if the object is an array and turn it into a string if it is,
-	 * otherwise unchanged.
-	 * 
-	 * @param object
-	 *            the object to make printable
-	 * @return a string if it was an array or the original object
-	 */
-	public static Object makePrintable(Object object) {
-		if (object == null)
-			return object;
-
-		if (object.getClass().isArray()) {
-			Object[] array = (Object[]) object;
-			Object[] output = new Object[array.length];
-			for (int i = 0; i < array.length; i++) {
-				output[i] = makePrintable(array[i]);
-			}
-			return Arrays.toString(output);
-		}
-		return object;
-	}
-
-	public static String append(String... strings) {
-		List<String> result = Create.list();
-		for (String s : strings) {
-			result.addAll(split(s));
-		}
-		return join(result);
-	}
-
-	public synchronized Class<?> getClass(String type, File jar) throws Exception {
-		CL cl = getLoader();
-		cl.add(jar.toURI().toURL());
-		return cl.loadClass(type);
-	}
-
-	public boolean isTrace() {
-		return current().trace;
-	}
-
-	public static long getDuration(String tm, long dflt) {
-		if (tm == null)
-			return dflt;
-
-		tm = tm.toUpperCase();
-		TimeUnit unit = TimeUnit.MILLISECONDS;
-		Matcher m = Pattern
-				.compile(
-						"\\s*(\\d+)\\s*(NANOSECONDS|MICROSECONDS|MILLISECONDS|SECONDS|MINUTES|HOURS|DAYS)?")
-				.matcher(tm);
-		if (m.matches()) {
-			long duration = Long.parseLong(tm);
-			String u = m.group(2);
-			if (u != null)
-				unit = TimeUnit.valueOf(u);
-			duration = TimeUnit.MILLISECONDS.convert(duration, unit);
-			return duration;
-		}
-		return dflt;
-	}
-
-	/**
-	 * Generate a random string, which is guaranteed to be a valid Java
-	 * identifier (first character is an ASCII letter, subsequent characters are
-	 * ASCII letters or numbers). Takes an optional parameter for the length of
-	 * string to generate; default is 8 characters.
-	 */
-	public String _random(String[] args) {
-		int numchars = 8;
-		if (args.length > 1) {
-			try {
-				numchars = Integer.parseInt(args[1]);
-			} catch (NumberFormatException e) {
-				throw new IllegalArgumentException(
-						"Invalid character count parameter in ${random} macro.");
-			}
-		}
-
-		if (random == null)
-			random = new Random();
-
-		char[] letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
-		char[] alphanums = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
-				.toCharArray();
-
-		char[] array = new char[numchars];
-		for (int i = 0; i < numchars; i++) {
-			char c;
-			if (i == 0)
-				c = letters[random.nextInt(letters.length)];
-			else
-				c = alphanums[random.nextInt(alphanums.length)];
-			array[i] = c;
-		}
-
-		return new String(array);
-	}
-
-	/**
-	 * Set the current command thread. This must be balanced with the
-	 * {@link #end(Processor)} method. The method returns the previous command
-	 * owner or null.
-	 * 
-	 * The command owner will receive all warnings and error reports.
-	 */
-
-	protected Processor beginHandleErrors(String message) {
-		trace("begin %s", message);
-		Processor previous = current.get();
-		current.set(this);
-		return previous;
-	}
-
-	/**
-	 * End a command. Will restore the previous command owner.
-	 * 
-	 * @param previous
-	 */
-	protected void endHandleErrors(Processor previous) {
-		trace("end");
-		current.set(previous);
-	}
-
-	public static Executor getExecutor() {
-		return executor;
-	}
-
-	/**
-	 * These plugins are added to the total list of plugins. The separation is
-	 * necessary because the list of plugins is refreshed now and then so we
-	 * need to be able to add them at any moment in time.
-	 * 
-	 * @param plugin
-	 */
-	public synchronized void addBasicPlugin(Object plugin) {
-		basicPlugins.add(plugin);
-		if (plugins != null)
-			plugins.add(plugin);
-	}
-
-	public synchronized void removeBasicPlugin(Object plugin) {
-		basicPlugins.remove(plugin);
-		if (plugins != null)
-			plugins.remove(plugin);
-	}
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/Resource.java b/biz.aQute.bndlib/src/aQute/lib/osgi/Resource.java
deleted file mode 100755
index 85756d5..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/Resource.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package aQute.lib.osgi;
-
-import java.io.*;
-
-public interface Resource {
-	InputStream openInputStream() throws Exception ;
-	void write(OutputStream out) throws Exception;
-	long lastModified();
-	void setExtra(String extra);
-	String getExtra();
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/TagResource.java b/biz.aQute.bndlib/src/aQute/lib/osgi/TagResource.java
deleted file mode 100644
index a793326..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/TagResource.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package aQute.lib.osgi;
-
-import java.io.*;
-
-import aQute.lib.io.*;
-import aQute.lib.tag.*;
-
-public class TagResource implements Resource {
-	final Tag	tag;
-	String		extra;
-
-	public TagResource(Tag tag) {
-		this.tag = tag;
-	}
-
-	public InputStream openInputStream() throws Exception {
-		final PipedInputStream pin = new PipedInputStream();
-		final PipedOutputStream pout = new PipedOutputStream(pin);
-		Processor.getExecutor().execute(new Runnable() {
-			public void run() {
-				try {
-					write(pout);
-				} catch (Exception e) {
-					e.printStackTrace();
-					// ignore
-				}
-				IO.close(pout);
-			}
-		});
-		return pin;
-	}
-
-	public void write(OutputStream out) throws UnsupportedEncodingException {
-		OutputStreamWriter ow = new OutputStreamWriter(out, "UTF-8");
-		PrintWriter pw = new PrintWriter(ow);
-		pw.println("<?xml version='1.1'?>");
-		try {
-			tag.print(0, pw);
-		} finally {
-			pw.flush();
-		}
-	}
-
-	public long lastModified() {
-		return 0;
-	}
-
-	public void setExtra(String extra) {
-		this.extra = extra;
-	}
-
-	public String getExtra() {
-		return extra;
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/URLResource.java b/biz.aQute.bndlib/src/aQute/lib/osgi/URLResource.java
deleted file mode 100755
index 9f0af59..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/URLResource.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package aQute.lib.osgi;
-
-import java.io.*;
-import java.net.*;
-
-public class URLResource implements Resource {
-	URL	url;
-	String	extra;
-	
-	public URLResource(URL url) {
-		this.url = url;
-	}
-
-	public InputStream openInputStream() throws IOException {
-		return url.openStream();
-	}
-
-	public String toString() {
-		return ":" + url.getPath() + ":";
-	}
-
-	public void write(OutputStream out) throws Exception {
-		FileResource.copy(this, out);
-	}
-
-	public long lastModified() {
-		return -1;
-	}
-
-	public String getExtra() {
-		return extra;
-	}
-
-	public void setExtra(String extra) {
-		this.extra = extra;
-	}
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/Verifier.java b/biz.aQute.bndlib/src/aQute/lib/osgi/Verifier.java
deleted file mode 100755
index 00cd67e..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/Verifier.java
+++ /dev/null
@@ -1,959 +0,0 @@
-package aQute.lib.osgi;
-
-import java.util.*;
-import java.util.jar.*;
-import java.util.regex.*;
-
-import aQute.libg.qtokens.*;
-
-public class Verifier extends Analyzer {
-
-    Jar                              dot;
-    Manifest                         manifest;
-    Map<String, Map<String, String>> referred  = newHashMap();
-    Map<String, Map<String, String>> contained = newHashMap();
-    Map<String, Set<String>>         uses      = newHashMap();
-    Map<String, Map<String, String>> mimports;
-    Map<String, Map<String, String>> mdynimports;
-    Map<String, Map<String, String>> mexports;
-    List<Jar>                        bundleClasspath;
-    Map<String, Map<String, String>> ignore    = newHashMap();                                    // Packages
-    // to
-    // ignore
-
-    Map<String, Clazz>               classSpace;
-    boolean                          r3;
-    boolean                          usesRequire;
-    boolean                          fragment;
-    Attributes                       main;
-
-    final static Pattern             EENAME    = Pattern
-                                                       .compile("CDC-1\\.0/Foundation-1\\.0"
-                                                               + "|CDC-1\\.1/Foundation-1\\.1"
-                                                               + "|OSGi/Minimum-1\\.[1-9]"
-                                                               + "|JRE-1\\.1"
-                                                               + "|J2SE-1\\.2"
-                                                               + "|J2SE-1\\.3"
-                                                               + "|J2SE-1\\.4"
-                                                               + "|J2SE-1\\.5"
-                                                               + "|JavaSE-1\\.6"
-                                                               + "|JavaSE-1\\.7"
-                                                               + "|PersonalJava-1\\.1"
-                                                               + "|PersonalJava-1\\.2"
-                                                               + "|CDC-1\\.0/PersonalBasis-1\\.0"
-                                                               + "|CDC-1\\.0/PersonalJava-1\\.0");
-
-    final static int                 V1_1      = 45;
-    final static int                 V1_2      = 46;
-    final static int                 V1_3      = 47;
-    final static int                 V1_4      = 48;
-    final static int                 V1_5      = 49;
-    final static int                 V1_6      = 50;
-    final static int                 V1_7      = 51;
-
-    static class EE {
-        String name;
-        int    target;
-
-        EE(String name, int source, int target) {
-            this.name = name;
-            this.target = target;
-        }
-    }
-
-    final static EE[]           ees                            = {
-            new EE("CDC-1.0/Foundation-1.0", V1_3, V1_1),
-            new EE("CDC-1.1/Foundation-1.1", V1_3, V1_2),
-            new EE("OSGi/Minimum-1.0", V1_3, V1_1),
-            new EE("OSGi/Minimum-1.1", V1_3, V1_2),
-            new EE("JRE-1.1", V1_1, V1_1), //
-            new EE("J2SE-1.2", V1_2, V1_1), //
-            new EE("J2SE-1.3", V1_3, V1_1), //
-            new EE("J2SE-1.4", V1_3, V1_2), //
-            new EE("J2SE-1.5", V1_5, V1_5), //
-            new EE("JavaSE-1.6", V1_6, V1_6),
-            new EE("PersonalJava-1.1", V1_1, V1_1),
-            new EE("PersonalJava-1.2", V1_1, V1_1),
-            new EE("CDC-1.0/PersonalBasis-1.0", V1_3, V1_1),
-            new EE("CDC-1.0/PersonalJava-1.0", V1_3, V1_1),
-            new EE("CDC-1.1/PersonalBasis-1.1", V1_3, V1_2),
-            new EE("CDC-1.1/PersonalJava-1.1", V1_3, V1_2)    };
-
-    final static Pattern        BUNDLEMANIFESTVERSION          = Pattern
-                                                                       .compile("2");
-    public final static String  SYMBOLICNAME_STRING            = "[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)*";
-    public final static Pattern SYMBOLICNAME                   = Pattern
-                                                                       .compile(SYMBOLICNAME_STRING);
-
-    public final static String  VERSION_STRING                 = "[0-9]+(\\.[0-9]+(\\.[0-9]+(\\.[0-9A-Za-z_-]+)?)?)?";
-    public final static Pattern VERSION                        = Pattern
-                                                                       .compile(VERSION_STRING);
-    final static Pattern        FILTEROP                       = Pattern
-                                                                       .compile("=|<=|>=|~=");
-    public final static Pattern VERSIONRANGE                   = Pattern
-                                                                       .compile("((\\(|\\[)"
-                                                                               + VERSION_STRING
-                                                                               + ","
-                                                                               + VERSION_STRING
-                                                                               + "(\\]|\\)))|"
-                                                                               + VERSION_STRING);
-    final static Pattern        FILE                           = Pattern
-                                                                       .compile("/?[^/\"\n\r\u0000]+(/[^/\"\n\r\u0000]+)*");
-    final static Pattern        WILDCARDPACKAGE                = Pattern
-                                                                       .compile("((\\p{Alnum}|_)+(\\.(\\p{Alnum}|_)+)*(\\.\\*)?)|\\*");
-    public final static Pattern ISO639                         = Pattern
-                                                                       .compile("[A-Z][A-Z]");
-    public final static Pattern HEADER_PATTERN                 = Pattern
-                                                                       .compile("[A-Za-z0-9][-a-zA-Z0-9_]+");
-    public final static Pattern TOKEN                          = Pattern
-                                                                       .compile("[-a-zA-Z0-9_]+");
-
-    public final static Pattern NUMBERPATTERN                  = Pattern
-                                                                       .compile("\\d+");
-    public final static Pattern PATHPATTERN                    = Pattern
-                                                                       .compile(".*");
-    public final static Pattern FQNPATTERN                     = Pattern
-                                                                       .compile(".*");
-    public final static Pattern URLPATTERN                     = Pattern
-                                                                       .compile(".*");
-    public final static Pattern ANYPATTERN                     = Pattern
-                                                                       .compile(".*");
-    public final static Pattern FILTERPATTERN                  = Pattern
-                                                                       .compile(".*");
-    public final static Pattern TRUEORFALSEPATTERN             = Pattern
-                                                                       .compile("true|false|TRUE|FALSE");
-    public static final Pattern WILDCARDNAMEPATTERN            = Pattern
-                                                                       .compile(".*");
-    public static final Pattern BUNDLE_ACTIVATIONPOLICYPATTERN = Pattern
-                                                                       .compile("lazy");
-
-    public final static String  EES[]                          = {
-            "CDC-1.0/Foundation-1.0", "CDC-1.1/Foundation-1.1",
-            "OSGi/Minimum-1.0", "OSGi/Minimum-1.1", "OSGi/Minimum-1.2",
-            "JRE-1.1", "J2SE-1.2", "J2SE-1.3", "J2SE-1.4", "J2SE-1.5",
-            "JavaSE-1.6", "JavaSE-1.7", "PersonalJava-1.1", "PersonalJava-1.2",
-            "CDC-1.0/PersonalBasis-1.0", "CDC-1.0/PersonalJava-1.0" };
-
-    public final static String  OSNAMES[]                      = {
-            "AIX", // IBM
-            "DigitalUnix", // Compaq
-            "Embos", // Segger Embedded Software Solutions
-            "Epoc32", // SymbianOS Symbian OS
-            "FreeBSD", // Free BSD
-            "HPUX", // hp-ux Hewlett Packard
-            "IRIX", // Silicon Graphics
-            "Linux", // Open source
-            "MacOS", // Apple
-            "NetBSD", // Open source
-            "Netware", // Novell
-            "OpenBSD", // Open source
-            "OS2", // OS/2 IBM
-            "QNX", // procnto QNX
-            "Solaris", // Sun (almost an alias of SunOS)
-            "SunOS", // Sun Microsystems
-            "VxWorks", // WindRiver Systems
-            "Windows95", "Win32", "Windows98", "WindowsNT", "WindowsCE",
-            "Windows2000", // Win2000
-            "Windows2003", // Win2003
-            "WindowsXP", "WindowsVista",                      };
-
-    public final static String  PROCESSORNAMES[]               = { "68k", // Motorola
-            // 68000
-            "ARM_LE", // Intel Strong ARM. Deprecated because it does not
-            // specify the endianness. See the following two rows.
-            "arm_le", // Intel Strong ARM Little Endian mode
-            "arm_be", // Intel String ARM Big Endian mode
-            "Alpha", //
-            "ia64n",// Hewlett Packard 32 bit
-            "ia64w",// Hewlett Packard 64 bit mode
-            "Ignite", // psc1k PTSC
-            "Mips", // SGI
-            "PArisc", // Hewlett Packard
-            "PowerPC", // power ppc Motorola/IBM Power PC
-            "Sh4", // Hitachi
-            "Sparc", // SUN
-            "Sparcv9", // SUN
-            "S390", // IBM Mainframe 31 bit
-            "S390x", // IBM Mainframe 64-bit
-            "V850E", // NEC V850E
-            "x86", // pentium i386
-            "i486", // i586 i686 Intel& AMD 32 bit
-            "x86-64",                                         };
-
-    Properties                  properties;
-
-    public Verifier(Jar jar) throws Exception {
-        this(jar, null);
-    }
-
-    public Verifier(Jar jar, Properties properties) throws Exception {
-        this.dot = jar;
-        this.properties = properties;
-        this.manifest = jar.getManifest();
-        if (manifest == null) {
-            manifest = new Manifest();
-            error("This file contains no manifest and is therefore not a bundle");
-        }
-        main = this.manifest.getMainAttributes();
-        verifyHeaders(main);
-        r3 = getHeader(Analyzer.BUNDLE_MANIFESTVERSION) == null;
-        usesRequire = getHeader(Analyzer.REQUIRE_BUNDLE) != null;
-        fragment = getHeader(Analyzer.FRAGMENT_HOST) != null;
-
-        bundleClasspath = getBundleClassPath();
-        mimports = parseHeader(manifest.getMainAttributes().getValue(
-                Analyzer.IMPORT_PACKAGE));
-        mdynimports = parseHeader(manifest.getMainAttributes().getValue(
-                Analyzer.DYNAMICIMPORT_PACKAGE));
-        mexports = parseHeader(manifest.getMainAttributes().getValue(
-                Analyzer.EXPORT_PACKAGE));
-
-        ignore = parseHeader(manifest.getMainAttributes().getValue(
-                Analyzer.IGNORE_PACKAGE));
-    }
-
-    public Verifier() {
-        // TODO Auto-generated constructor stub
-    }
-
-    private void verifyHeaders(Attributes main) {
-        for (Object element : main.keySet()) {
-            Attributes.Name header = (Attributes.Name) element;
-            String h = header.toString();
-            if (!HEADER_PATTERN.matcher(h).matches())
-                error("Invalid Manifest header: " + h + ", pattern="
-                        + HEADER_PATTERN);
-        }
-    }
-
-    private List<Jar> getBundleClassPath() {
-        List<Jar> list = newList();
-        String bcp = getHeader(Analyzer.BUNDLE_CLASSPATH);
-        if (bcp == null) {
-            list.add(dot);
-        } else {
-            Map<String, Map<String, String>> entries = parseHeader(bcp);
-            for (Map.Entry<String, Map<String, String>> ex : entries.entrySet()) {
-                String jarOrDir = ex.getKey();
-                if (jarOrDir.equals(".")) {
-                    list.add(dot);
-                } else {
-                    if (jarOrDir.equals("/"))
-                        jarOrDir = "";
-                    if (jarOrDir.endsWith("/")) {
-                        error("Bundle-Classpath directory must not end with a slash: "
-                                + jarOrDir);
-                        jarOrDir = jarOrDir.substring(0, jarOrDir.length() - 1);
-                    }
-
-                    Resource resource = dot.getResource(jarOrDir);
-                    if (resource != null) {
-                        try {
-                            Jar sub = new Jar(jarOrDir);
-                            addClose(sub);
-                            EmbeddedResource.build(sub, resource);
-                            if (!jarOrDir.endsWith(".jar"))
-                                warning("Valid JAR file on Bundle-Classpath does not have .jar extension: "
-                                        + jarOrDir);
-                            list.add(sub);
-                        } catch (Exception e) {
-                            error("Invalid embedded JAR file on Bundle-Classpath: "
-                                    + jarOrDir + ", " + e);
-                        }
-                    } else if (dot.getDirectories().containsKey(jarOrDir)) {
-                        if (r3)
-                            error("R3 bundles do not support directories on the Bundle-ClassPath: "
-                                    + jarOrDir);
-
-                        try {
-                            Jar sub = new Jar(jarOrDir);
-                            addClose(sub);
-                            for (Map.Entry<String, Resource> entry : dot
-                                    .getResources().entrySet()) {
-                                if (entry.getKey().startsWith(jarOrDir))
-                                    sub.putResource(entry.getKey().substring(
-                                            jarOrDir.length() + 1), entry
-                                            .getValue());
-                            }
-                            list.add(sub);
-                        } catch (Exception e) {
-                            error("Invalid embedded directory file on Bundle-Classpath: "
-                                    + jarOrDir + ", " + e);
-                        }
-                    } else {
-                        // Map<String, String> info = ex.getValue();
-                        // if (! "optional".equals(
-                        // info.get(RESOLUTION_DIRECTIVE)))
-                        // warning("Cannot find a file or directory for
-                        // Bundle-Classpath entry: %s",
-                        // jarOrDir);
-                    }
-                }
-            }
-        }
-        return list;
-    }
-
-    /*
-     * Bundle-NativeCode ::= nativecode ( ',' nativecode )* ( ’,’ optional) ?
-     * nativecode ::= path ( ';' path )* // See 1.4.2 ( ';' parameter )+
-     * optional ::= ’*’
-     */
-    public void verifyNative() {
-        String nc = getHeader("Bundle-NativeCode");
-        doNative(nc);
-    }
-
-    public void doNative(String nc) {
-        if (nc != null) {
-            QuotedTokenizer qt = new QuotedTokenizer(nc, ",;=", false);
-            char del;
-            do {
-                do {
-                    String name = qt.nextToken();
-                    if (name == null) {
-                        error("Can not parse name from bundle native code header: "
-                                + nc);
-                        return;
-                    }
-                    del = qt.getSeparator();
-                    if (del == ';') {
-                        if (dot != null && !dot.exists(name)) {
-                            error("Native library not found in JAR: " + name);
-                        }
-                    } else {
-                        String value = null;
-                        if (del == '=')
-                            value = qt.nextToken();
-
-                        String key = name.toLowerCase();
-                        if (key.equals("osname")) {
-                            // ...
-                        } else if (key.equals("osversion")) {
-                            // verify version range
-                            verify(value, VERSIONRANGE);
-                        } else if (key.equals("language")) {
-                            verify(value, ISO639);
-                        } else if (key.equals("processor")) {
-                            // verify(value, PROCESSORS);
-                        } else if (key.equals("selection-filter")) {
-                            // verify syntax filter
-                            verifyFilter(value);
-                        } else if (name.equals("*") && value == null) {
-                            // Wildcard must be at end.
-                            if (qt.nextToken() != null)
-                                error("Bundle-Native code header may only END in wildcard: nc");
-                        } else {
-                            warning("Unknown attribute in native code: " + name
-                                    + "=" + value);
-                        }
-                        del = qt.getSeparator();
-                    }
-                } while (del == ';');
-            } while (del == ',');
-        }
-    }
-
-    public boolean verifyFilter(String value) {
-        try {
-            verifyFilter(value, 0);
-            return true;
-        } catch (Exception e) {
-            error("Not a valid filter: " + value + e.getMessage());
-            return false;
-        }
-    }
-
-    private void verifyActivator() {
-        String bactivator = getHeader("Bundle-Activator");
-        if (bactivator != null) {
-            Clazz cl = loadClass(bactivator);
-            if (cl == null) {
-                int n = bactivator.lastIndexOf('.');
-                if (n > 0) {
-                    String pack = bactivator.substring(0, n);
-                    if (mimports.containsKey(pack))
-                        return;
-                    error("Bundle-Activator not found on the bundle class path nor in imports: "
-                            + bactivator);
-                } else
-                    error("Activator uses default package and is not local (default package can not be imported): "
-                            + bactivator);
-            }
-        }
-    }
-
-    private Clazz loadClass(String className) {
-        String path = className.replace('.', '/') + ".class";
-        return (Clazz) classSpace.get(path);
-    }
-
-    private void verifyComponent() {
-        String serviceComponent = getHeader("Service-Component");
-        if (serviceComponent != null) {
-            Map<String, Map<String, String>> map = parseHeader(serviceComponent);
-            for (String component : map.keySet()) {
-                if (component.indexOf("*") < 0 && !dot.exists(component)) {
-                    error("Service-Component entry can not be located in JAR: "
-                            + component);
-                } else {
-                    // validate component ...
-                }
-            }
-        }
-    }
-
-    public void info() {
-        System.out.println("Refers                           : " + referred);
-        System.out.println("Contains                         : " + contained);
-        System.out.println("Manifest Imports                 : " + mimports);
-        System.out.println("Manifest Exports                 : " + mexports);
-    }
-
-    /**
-     * Invalid exports are exports mentioned in the manifest but not found on
-     * the classpath. This can be calculated with: exports - contains.
-     * 
-     * Unfortunately, we also must take duplicate names into account. These
-     * duplicates are of course no erroneous.
-     */
-    private void verifyInvalidExports() {
-        Set<String> invalidExport = newSet(mexports.keySet());
-        invalidExport.removeAll(contained.keySet());
-
-        // We might have duplicate names that are marked for it. These
-        // should not be counted. Should we test them against the contained
-        // set? Hmm. If someone wants to hang himself by using duplicates than
-        // I guess he can go ahead ... This is not a recommended practice
-        for (Iterator<String> i = invalidExport.iterator(); i.hasNext();) {
-            String pack = i.next();
-            if (isDuplicate(pack))
-                i.remove();
-        }
-
-        if (!invalidExport.isEmpty())
-            error("Exporting packages that are not on the Bundle-Classpath"
-                    + bundleClasspath + ": " + invalidExport);
-    }
-
-    /**
-     * Invalid imports are imports that we never refer to. They can be
-     * calculated by removing the refered packages from the imported packages.
-     * This leaves packages that the manifest imported but that we never use.
-     */
-    private void verifyInvalidImports() {
-        Set<String> invalidImport = newSet(mimports.keySet());
-        invalidImport.removeAll(referred.keySet());
-        // TODO Added this line but not sure why it worked before ...
-        invalidImport.removeAll(contained.keySet());
-        String bactivator = getHeader(Analyzer.BUNDLE_ACTIVATOR);
-        if (bactivator != null) {
-            int n = bactivator.lastIndexOf('.');
-            if (n > 0) {
-                invalidImport.remove(bactivator.substring(0, n));
-            }
-        }
-        if (isPedantic() && !invalidImport.isEmpty())
-            warning("Importing packages that are never refered to by any class on the Bundle-Classpath"
-                    + bundleClasspath + ": " + invalidImport);
-    }
-
-    /**
-     * Check for unresolved imports. These are referals that are not imported by
-     * the manifest and that are not part of our bundle classpath. The are
-     * calculated by removing all the imported packages and contained from the
-     * refered packages.
-     */
-    private void verifyUnresolvedReferences() {
-        Set<String> unresolvedReferences = new TreeSet<String>(referred
-                .keySet());
-        unresolvedReferences.removeAll(mimports.keySet());
-        unresolvedReferences.removeAll(contained.keySet());
-
-        // Remove any java.** packages.
-        for (Iterator<String> p = unresolvedReferences.iterator(); p.hasNext();) {
-            String pack = p.next();
-            if (pack.startsWith("java.") || ignore.containsKey(pack))
-                p.remove();
-            else {
-                // Remove any dynamic imports
-                if (isDynamicImport(pack))
-                    p.remove();
-            }
-        }
-
-        if (!unresolvedReferences.isEmpty()) {
-            // Now we want to know the
-            // classes that are the culprits
-            Set<String> culprits = new HashSet<String>();
-            for (Clazz clazz : classSpace.values()) {
-                if (hasOverlap(unresolvedReferences, clazz.getReferred()))
-                    culprits.add(clazz.getPath());
-            }
-
-            error("Unresolved references to " + unresolvedReferences
-                    + " by class(es) on the Bundle-Classpath" + bundleClasspath
-                    + ": " + culprits);
-        }
-    }
-
-    /**
-     * @param p
-     * @param pack
-     */
-    private boolean isDynamicImport(String pack) {
-        for (String pattern : mdynimports.keySet()) {
-            // Wildcard?
-            if (pattern.equals("*"))
-                return true; // All packages can be dynamically imported
-
-            if (pattern.endsWith(".*")) {
-                pattern = pattern.substring(0, pattern.length() - 2);
-                if (pack.startsWith(pattern)
-                        && (pack.length() == pattern.length() || pack
-                                .charAt(pattern.length()) == '.'))
-                    return true;
-            } else {
-                if (pack.equals(pattern))
-                    return true;
-            }
-        }
-        return false;
-    }
-
-    private boolean hasOverlap(Set<?> a, Set<?> b) {
-        for (Iterator<?> i = a.iterator(); i.hasNext();) {
-            if (b.contains(i.next()))
-                return true;
-        }
-        return false;
-    }
-
-    public void verify() throws Exception {
-        if (classSpace == null)
-            classSpace = analyzeBundleClasspath(dot,
-                    parseHeader(getHeader(Analyzer.BUNDLE_CLASSPATH)),
-                    contained, referred, uses);
-        
-        
-        verifyDirectives("Export-Package", "uses:|mandatory:|include:|exclude:|" + IMPORT_DIRECTIVE);
-        verifyDirectives("Import-Package", "resolution:");
-        verifyDirectives("Require-Bundle", "visibility:|resolution:");
-        verifyDirectives("Fragment-Host", "resolution:");
-        verifyDirectives("Provide-Capability", "effective:|uses:");
-        verifyDirectives("Require-Capability", "effective:|resolve:|filter:");
-        verifyDirectives("Bundle-SymbolicName", "singleton:|fragment-attachment:|mandatory:");
-        
-        
-        verifyManifestFirst();
-        verifyActivator();
-        verifyActivationPolicy();
-        verifyComponent();
-        verifyNative();
-        verifyInvalidExports();
-        verifyInvalidImports();
-        verifyUnresolvedReferences();
-        verifySymbolicName();
-        verifyListHeader("Bundle-RequiredExecutionEnvironment", EENAME, false);
-        verifyHeader("Bundle-ManifestVersion", BUNDLEMANIFESTVERSION, false);
-        verifyHeader("Bundle-Version", VERSION, true);
-        verifyListHeader("Bundle-Classpath", FILE, false);
-        verifyDynamicImportPackage();
-        verifyBundleClasspath();
-        verifyUses();
-        if (usesRequire) {
-            if (!getErrors().isEmpty()) {
-                getWarnings()
-                        .add(
-                                0,
-                                "Bundle uses Require Bundle, this can generate false errors because then not enough information is available without the required bundles");
-            }
-        }
-    }
-
-    /**
-     * Verify if the header does not contain any other directives
-     * 
-     * @param header
-     * @param directives
-     */
-    private void verifyDirectives(String header, String directives) {
-    	Pattern pattern = Pattern.compile(directives);
-    	Map<String,Map<String,String>> map = parseHeader(manifest.getMainAttributes().getValue(header));
-    	for ( Map.Entry<String, Map<String,String>> entry : map.entrySet()) {
-    		for ( String key : entry.getValue().keySet()) {
-    			if ( key.endsWith(":")) {
-    				if ( ! key.startsWith("x-")) {
-    					Matcher m = pattern.matcher(key);
-    					if ( m.matches())
-    						continue;
-    					
-    					warning("Unknown directive %s in %s, allowed directives are %s, and 'x-*'.", key, header, directives.replace('|', ','));
-    				}
-    			}
-    		}
-    	}
-	}
-
-	/**
-     * Verify the use clauses
-     */
-    private void verifyUses() {
-    }
-
-    public boolean verifyActivationPolicy() {
-        String policy = getHeader(Constants.BUNDLE_ACTIVATIONPOLICY);
-        if (policy == null)
-            return true;
-
-        return verifyActivationPolicy(policy);
-    }
-
-    public boolean verifyActivationPolicy(String policy) {
-        Map<String, Map<String, String>> map = parseHeader(policy);
-        if (map.size() == 0)
-            warning("Bundle-ActivationPolicy is set but has no argument %s",
-                    policy);
-        else if (map.size() > 1)
-            warning("Bundle-ActivationPolicy has too many arguments %s", policy);
-        else {
-            Map<String, String> s = map.get("lazy");
-            if (s == null)
-                warning(
-                        "Bundle-ActivationPolicy set but is not set to lazy: %s",
-                        policy);
-            else
-                return true;
-        }
-
-        return false;
-    }
-
-    public void verifyBundleClasspath() {
-        Map<String, Map<String, String>> bcp = parseHeader(getHeader(Analyzer.BUNDLE_CLASSPATH));
-        if (bcp.isEmpty() || bcp.containsKey("."))
-            return;
-
-        for ( String path : bcp.keySet() ) {
-            if ( path.endsWith("/"))
-                error("A Bundle-ClassPath entry must not end with '/': %s", path);
-            
-            if ( dot.getDirectories().containsKey(path))
-                // We assume that any classes are in a directory
-                // and therefore do not care when the bundle is included
-                return;
-        }
-        
-        for (String path : dot.getResources().keySet()) {
-            if (path.endsWith(".class")) {
-                warning("The Bundle-Classpath does not contain the actual bundle JAR (as specified with '.' in the Bundle-Classpath) but the JAR does contain classes. Is this intentional?");
-                return;
-            }
-        }
-    }
-
-    /**
-     * <pre>
-     *          DynamicImport-Package ::= dynamic-description
-     *              ( ',' dynamic-description )*
-     *              
-     *          dynamic-description::= wildcard-names ( ';' parameter )*
-     *          wildcard-names ::= wildcard-name ( ';' wildcard-name )*
-     *          wildcard-name ::= package-name 
-     *                         | ( package-name '.*' ) // See 1.4.2
-     *                         | '*'
-     * </pre>
-     */
-    private void verifyDynamicImportPackage() {
-        verifyListHeader("DynamicImport-Package", WILDCARDPACKAGE, true);
-        String dynamicImportPackage = getHeader("DynamicImport-Package");
-        if (dynamicImportPackage == null)
-            return;
-
-        Map<String, Map<String, String>> map = parseHeader(dynamicImportPackage);
-        for (String name : map.keySet()) {
-            name = name.trim();
-            if (!verify(name, WILDCARDPACKAGE))
-                error("DynamicImport-Package header contains an invalid package name: "
-                        + name);
-
-            Map<String, String> sub = map.get(name);
-            if (r3 && sub.size() != 0) {
-                error("DynamicPackage-Import has attributes on import: "
-                        + name
-                        + ". This is however, an <=R3 bundle and attributes on this header were introduced in R4. ");
-            }
-        }
-    }
-
-    private void verifyManifestFirst() {
-        if (!dot.manifestFirst) {
-            error("Invalid JAR stream: Manifest should come first to be compatible with JarInputStream, it was not");
-        }
-    }
-
-    private void verifySymbolicName() {
-        Map<String, Map<String, String>> bsn = parseHeader(getHeader(Analyzer.BUNDLE_SYMBOLICNAME));
-        if (!bsn.isEmpty()) {
-            if (bsn.size() > 1)
-                error("More than one BSN specified " + bsn);
-
-            String name = (String) bsn.keySet().iterator().next();
-            if (!SYMBOLICNAME.matcher(name).matches()) {
-                error("Symbolic Name has invalid format: " + name);
-            }
-        }
-    }
-
-    /**
-     * <pre>
-     *         filter ::= ’(’ filter-comp ’)’
-     *         filter-comp ::= and | or | not | operation
-     *         and ::= ’&’ filter-list
-     *         or ::= ’|’ filter-list
-     *         not ::= ’!’ filter
-     *         filter-list ::= filter | filter filter-list
-     *         operation ::= simple | present | substring
-     *         simple ::= attr filter-type value
-     *         filter-type ::= equal | approx | greater | less
-     *         equal ::= ’=’
-     *         approx ::= ’˜=’
-     *         greater ::= ’>=’
-     *         less ::= ’<=’
-     *         present ::= attr ’=*’
-     *         substring ::= attr ’=’ initial any final
-     *         inital ::= () | value
-     *         any ::= ’*’ star-value
-     *         star-value ::= () | value ’*’ star-value
-     *         final ::= () | value
-     *         value ::= <see text>
-     * </pre>
-     * 
-     * @param expr
-     * @param index
-     * @return
-     */
-
-    public static int verifyFilter(String expr, int index) {
-        try {
-            while (Character.isWhitespace(expr.charAt(index)))
-                index++;
-
-            if (expr.charAt(index) != '(')
-                throw new IllegalArgumentException(
-                        "Filter mismatch: expected ( at position " + index
-                                + " : " + expr);
-
-            index++; // skip (
-
-            while (Character.isWhitespace(expr.charAt(index)))
-                index++;
-
-            switch (expr.charAt(index)) {
-            case '!':
-                index++; // skip !
-                while (Character.isWhitespace(expr.charAt(index)))
-                    index++;
-
-                if (expr.charAt(index) != '(')
-                    throw new IllegalArgumentException(
-                            "Filter mismatch: ! (not) must have one sub expression "
-                                    + index + " : " + expr);
-                while (Character.isWhitespace(expr.charAt(index)))
-                    index++;
-
-                index = verifyFilter(expr, index);
-                while (Character.isWhitespace(expr.charAt(index)))
-                    index++;
-                if (expr.charAt(index) != ')')
-                    throw new IllegalArgumentException(
-                            "Filter mismatch: expected ) at position " + index
-                                    + " : " + expr);
-                return index + 1;
-
-            case '&':
-            case '|':
-                index++; // skip operator
-                while (Character.isWhitespace(expr.charAt(index)))
-                    index++;
-                while (expr.charAt(index) == '(') {
-                    index = verifyFilter(expr, index);
-                    while (Character.isWhitespace(expr.charAt(index)))
-                        index++;
-                }
-
-                if (expr.charAt(index) != ')')
-                    throw new IllegalArgumentException(
-                            "Filter mismatch: expected ) at position " + index
-                                    + " : " + expr);
-                return index + 1; // skip )
-
-            default:
-                index = verifyFilterOperation(expr, index);
-                if (expr.charAt(index) != ')')
-                    throw new IllegalArgumentException(
-                            "Filter mismatch: expected ) at position " + index
-                                    + " : " + expr);
-                return index + 1;
-            }
-        } catch (IndexOutOfBoundsException e) {
-            throw new IllegalArgumentException(
-                    "Filter mismatch: early EOF from " + index);
-        }
-    }
-
-    static private int verifyFilterOperation(String expr, int index) {
-        StringBuffer sb = new StringBuffer();
-        while ("=><~()".indexOf(expr.charAt(index)) < 0) {
-            sb.append(expr.charAt(index++));
-        }
-        String attr = sb.toString().trim();
-        if (attr.length() == 0)
-            throw new IllegalArgumentException(
-                    "Filter mismatch: attr at index " + index + " is 0");
-        sb = new StringBuffer();
-        while ("=><~".indexOf(expr.charAt(index)) >= 0) {
-            sb.append(expr.charAt(index++));
-        }
-        String operator = sb.toString();
-        if (!verify(operator, FILTEROP))
-            throw new IllegalArgumentException(
-                    "Filter error, illegal operator " + operator + " at index "
-                            + index);
-
-        sb = new StringBuffer();
-        while (")".indexOf(expr.charAt(index)) < 0) {
-            switch (expr.charAt(index)) {
-            case '\\':
-                if ("\\)(*".indexOf(expr.charAt(index + 1)) >= 0 )
-                    index++;
-                else
-                    throw new IllegalArgumentException(
-                            "Filter error, illegal use of backslash at index "
-                                    + index
-                                    + ". Backslash may only be used before * or () or \\");
-            }
-            sb.append(expr.charAt(index++));
-        }
-        return index;
-    }
-
-    private String getHeader(String string) {
-        return main.getValue(string);
-    }
-
-    private boolean verifyHeader(String name, Pattern regex, boolean error) {
-        String value = manifest.getMainAttributes().getValue(name);
-        if (value == null)
-            return false;
-
-        QuotedTokenizer st = new QuotedTokenizer(value.trim(), ",");
-        for (Iterator<String> i = st.getTokenSet().iterator(); i.hasNext();) {
-            if (!verify((String) i.next(), regex)) {
-                String msg = "Invalid value for " + name + ", " + value
-                        + " does not match " + regex.pattern();
-                if (error)
-                    error(msg);
-                else
-                    warning(msg);
-            }
-        }
-        return true;
-    }
-
-    static private boolean verify(String value, Pattern regex) {
-        return regex.matcher(value).matches();
-    }
-
-    private boolean verifyListHeader(String name, Pattern regex, boolean error) {
-        String value = manifest.getMainAttributes().getValue(name);
-        if (value == null)
-            return false;
-
-        Map<String, Map<String, String>> map = parseHeader(value);
-        for (String header : map.keySet()) {
-            if (!regex.matcher(header).matches()) {
-                String msg = "Invalid value for " + name + ", " + value
-                        + " does not match " + regex.pattern();
-                if (error)
-                    error(msg);
-                else
-                    warning(msg);
-            }
-        }
-        return true;
-    }
-
-    public String getProperty(String key, String deflt) {
-        if (properties == null)
-            return deflt;
-        return properties.getProperty(key, deflt);
-    }
-
-    public void setClassSpace(Map<String, Clazz> classspace,
-            Map<String, Map<String, String>> contained,
-            Map<String, Map<String, String>> referred,
-            Map<String, Set<String>> uses) {
-        this.classSpace = classspace;
-        this.contained = contained;
-        this.referred = referred;
-        this.uses = uses;
-    }
-
-    public static boolean isVersion(String version) {
-        return VERSION.matcher(version).matches();
-    }
-
-    public static boolean isIdentifier(String value) {
-        if (value.length() < 1)
-            return false;
-
-        if (!Character.isJavaIdentifierStart(value.charAt(0)))
-            return false;
-
-        for (int i = 1; i < value.length(); i++) {
-            if (!Character.isJavaIdentifierPart(value.charAt(i)))
-                return false;
-        }
-        return true;
-    }
-
-    public static boolean isMember(String value, String[] matches) {
-        for (String match : matches) {
-            if (match.equals(value))
-                return true;
-        }
-        return false;
-    }
-
-	public static boolean isFQN(String name) {
-		if ( name.length() == 0)
-			return false;
-		if ( !Character.isJavaIdentifierStart(name.charAt(0)))
-			return false;
-		
-		for ( int i=1; i<name.length(); i++) {
-			char c = name.charAt(i);
-			if (Character.isJavaIdentifierPart(c) || c == '$' || c == '.')
-				continue;
-			
-			return false;
-		}
-		
-		return true;
-	}
-
-    /*
-     * public int verifyFilter(StringBuffer sb, String s, int rover) { rover =
-     * skip(s, rover); char c = s.charAt(rover); if (c == '(') { sb.append('(');
-     * char type; rover = skip(s, ++rover); c = s.charAt(rover); switch (c) {
-     * case '!': // not case '&': // and case '|': // or sb.append(c); type = c;
-     * while(true) { rover = skip(++rover); c = s.charAt(rover); if ( c != '(')
-     * break; rover = verifyFilter(s, rover); } break;
-     * 
-     * case ')': return rover + 1;
-     * 
-     * default: rover = skip(s,rover); c = s.charAt(rover); while (
-     * Character.isLetterOrDigit(c) || ) } } }
-     */
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/WriteResource.java b/biz.aQute.bndlib/src/aQute/lib/osgi/WriteResource.java
deleted file mode 100644
index 99f7dae..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/WriteResource.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package aQute.lib.osgi;
-
-import java.io.*;
-
-public abstract class WriteResource implements Resource {
-	long 	lastModified;
-	String	extra;
-
-	public InputStream openInputStream() throws Exception {
-	    PipedInputStream pin = new PipedInputStream();
-	    final PipedOutputStream pout = new PipedOutputStream(pin);
-	    Thread t = new Thread() {
-	        public void run() {
-	            try {
-                    write(pout);
-                } catch (Exception e) {
-                    e.printStackTrace();
-                } finally {
-                    try {
-                        pout.close();
-                    } catch (IOException e) {
-                        // Ignore
-                    }
-                }
-	        }
-	    };
-	    t.start();
-	    return pin;
-	}
-
-	public abstract void write(OutputStream out) throws IOException, Exception;
-	
-	public abstract long lastModified();
-
-	public String getExtra() {
-		return extra;
-	}
-
-	public void setExtra(String extra) {
-		this.extra = extra;
-	}
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/ZipResource.java b/biz.aQute.bndlib/src/aQute/lib/osgi/ZipResource.java
deleted file mode 100755
index 83dcce3..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/ZipResource.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package aQute.lib.osgi;
-
-import java.io.*;
-import java.util.*;
-import java.util.regex.*;
-import java.util.zip.*;
-
-public class ZipResource implements Resource {
-    ZipFile  zip;
-    ZipEntry entry;
-    long     lastModified;
-    String   extra;
-
-    ZipResource(ZipFile zip, ZipEntry entry, long lastModified) {
-        this.zip = zip;
-        this.entry = entry;
-        this.lastModified = lastModified;
-        byte[] data = entry.getExtra();
-        if (data != null)
-            this.extra = new String(data);
-    }
-
-    public InputStream openInputStream() throws IOException {
-        return zip.getInputStream(entry);
-    }
-
-    public String toString() {
-        return ":" + zip.getName() + "(" + entry.getName() + "):";
-    }
-
-    public static ZipFile build(Jar jar, File file) throws ZipException,
-            IOException {
-        return build(jar, file, null);
-    }
-
-    public static ZipFile build(Jar jar, File file, Pattern pattern)
-            throws ZipException, IOException {
-
-        try {
-            ZipFile zip = new ZipFile(file);
-            nextEntry: for (Enumeration<? extends ZipEntry> e = zip.entries(); e
-                    .hasMoreElements();) {
-                ZipEntry entry = e.nextElement();
-                if (pattern != null) {
-                    Matcher m = pattern.matcher(entry.getName());
-                    if (!m.matches())
-                        continue nextEntry;
-                }
-                if (!entry.isDirectory()) {
-                    long time = entry.getTime();
-                    if (time <= 0)
-                        time = file.lastModified();
-                    jar.putResource(entry.getName(), new ZipResource(zip,
-                            entry, time), true);
-                }
-            }
-            return zip;
-        } catch (ZipException ze) {
-            throw new ZipException("The JAR/ZIP file ("
-                    + file.getAbsolutePath() + ") seems corrupted, error: "
-                    + ze.getMessage());
-        } catch (FileNotFoundException e) {
-            throw new IllegalArgumentException("Problem opening JAR: "
-                    + file.getAbsolutePath());
-        }
-    }
-
-    public void write(OutputStream out) throws Exception {
-        FileResource.copy(this, out);
-    }
-
-    public long lastModified() {
-        return lastModified;
-    }
-
-    public String getExtra() {
-        return extra;
-    }
-
-    public void setExtra(String extra) {
-        this.extra = extra;
-    }
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/bnd.info b/biz.aQute.bndlib/src/aQute/lib/osgi/bnd.info
deleted file mode 100644
index b1706a5..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/bnd.info
+++ /dev/null
@@ -1,2 +0,0 @@
-modified=${currenttime}
-version=${Bundle-Version}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/eclipse/EclipseClasspath.java b/biz.aQute.bndlib/src/aQute/lib/osgi/eclipse/EclipseClasspath.java
deleted file mode 100755
index 60ef309..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/eclipse/EclipseClasspath.java
+++ /dev/null
@@ -1,248 +0,0 @@
-package aQute.lib.osgi.eclipse;
-
-import java.io.*;
-import java.util.*;
-import java.util.regex.*;
-
-import javax.xml.parsers.*;
-
-import org.w3c.dom.*;
-import org.xml.sax.*;
-
-import aQute.libg.reporter.*;
-
-/**
- * Parse the Eclipse project information for the classpath. Unfortunately, it is
- * impossible to read the variables. They are ignored but that can cause
- * problems.
- * 
- * @version $Revision: 1.2 $
- */
-public class EclipseClasspath {
-    static DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
-                                                                 .newInstance();
-    DocumentBuilder               db;
-    File                          project;
-    File                          workspace;
-    Set<File>                     sources                = new LinkedHashSet<File>();
-    Set<File>                     allSources                = new LinkedHashSet<File>();
-    
-    Set<File>                     classpath              = new LinkedHashSet<File>();
-    List<File>                    dependents             = new ArrayList<File>();
-    File                          output;
-    boolean                       recurse                = true;
-    Set<File>                     exports                = new LinkedHashSet<File>();
-    Map<String, String>           properties             = new HashMap<String, String>();
-    Reporter                      reporter;
-    int                           options;
-    Set<File>                     bootclasspath          = new LinkedHashSet<File>();
-
-    public final static int       DO_VARIABLES           = 1;
-
-    /**
-     * Parse an Eclipse project structure to discover the classpath.
-     * 
-     * @param workspace
-     *            Points to workspace
-     * @param project
-     *            Points to project
-     * @throws ParserConfigurationException
-     * @throws SAXException
-     * @throws IOException
-     */
-
-    public EclipseClasspath(Reporter reporter, File workspace, File project,
-            int options) throws Exception {
-        this.project = project.getCanonicalFile();
-        this.workspace = workspace.getCanonicalFile();
-        this.reporter = reporter;
-        db = documentBuilderFactory.newDocumentBuilder();
-        parse(this.project, true);
-        db = null;
-    }
-
-    public EclipseClasspath(Reporter reporter, File workspace, File project)
-            throws Exception {
-        this(reporter, workspace, project, 0);
-    }
-
-    /**
-     * Recursive routine to parse the files. If a sub project is detected, it is
-     * parsed before the parsing continues. This should give the right order.
-     * 
-     * @param project
-     *            Project directory
-     * @param top
-     *            If this is the top project
-     * @throws ParserConfigurationException
-     * @throws SAXException
-     * @throws IOException
-     */
-    void parse(File project, boolean top) throws ParserConfigurationException,
-            SAXException, IOException {
-        File file = new File(project, ".classpath");
-        if (!file.exists())
-            throw new FileNotFoundException(".classpath file not found: "
-                    + file.getAbsolutePath());
-
-        Document doc = db.parse(file);
-        NodeList nodelist = doc.getDocumentElement().getElementsByTagName(
-                "classpathentry");
-
-        if (nodelist == null)
-            throw new IllegalArgumentException(
-                    "Can not find classpathentry in classpath file");
-
-        for (int i = 0; i < nodelist.getLength(); i++) {
-            Node node = nodelist.item(i);
-            NamedNodeMap attrs = node.getAttributes();
-            String kind = get(attrs, "kind");
-            if ("src".equals(kind)) {
-                String path = get(attrs, "path");
-                // TODO boolean exported = "true".equalsIgnoreCase(get(attrs,
-                // "exported"));
-                if (path.startsWith("/")) {
-                    // We have another project
-                    File subProject = getFile(workspace, project, path);
-                    if (recurse)
-                        parse(subProject, false);
-                    dependents.add(subProject.getCanonicalFile());
-                } else {
-                    File src = getFile(workspace, project, path);
-                    allSources.add(src);
-                    if (top) {
-                        // We only want the sources for our own project
-                        // or we'll compile all at once. Not a good idea
-                        // because project settings can differ.
-                        sources.add(src);
-                    }
-                }
-            } else if ("lib".equals(kind)) {
-                String path = get(attrs, "path");
-                boolean exported = "true".equalsIgnoreCase(get(attrs,
-                        "exported"));
-                if (top || exported) {
-                    File jar = getFile(workspace, project, path);
-                    if (jar.getName().startsWith("ee."))
-                        bootclasspath.add(jar);
-                    else
-                        classpath.add(jar);
-                    if (exported)
-                        exports.add(jar);
-                }
-            } else if ("output".equals(kind)) {
-                String path = get(attrs, "path");
-                path = path.replace('/', File.separatorChar);
-                output = getFile(workspace, project, path);
-                classpath.add(output);
-                exports.add(output);
-            } else if ("var".equals(kind)) {
-                boolean exported = "true".equalsIgnoreCase(get(attrs,
-                        "exported"));
-                File lib = replaceVar(get(attrs, "path"));
-                File slib = replaceVar(get(attrs, "sourcepath"));
-                if (lib != null) {
-                    classpath.add(lib);
-                    if (exported)
-                        exports.add(lib);
-                }
-                if (slib != null)
-                    sources.add(slib);
-            } else if ("con".equals(kind)) {
-                // Should do something useful ...
-            }
-        }
-    }
-
-    private File getFile(File abs, File relative, String opath) {
-        String path = opath.replace('/', File.separatorChar);
-        File result = new File(path);
-        if (result.isAbsolute() && result.isFile()) {
-            return result;
-        }
-        if (path.startsWith(File.separator)) {
-            result = abs;
-            path = path.substring(1);
-        } else
-            result = relative;
-
-        StringTokenizer st = new StringTokenizer(path, File.separator);
-        while (st.hasMoreTokens()) {
-            String token = st.nextToken();
-            result = new File(result, token);
-        }
-
-        if (!result.exists())
-            System.err.println("File not found: project=" + project
-                    + " workspace=" + workspace + " path=" + opath + " file="
-                    + result);
-        return result;
-    }
-
-    static Pattern PATH = Pattern.compile("([A-Z_]+)/(.*)");
-
-    private File replaceVar(String path) {
-        if ((options & DO_VARIABLES) == 0)
-            return null;
-
-        Matcher m = PATH.matcher(path);
-        if (m.matches()) {
-            String var = m.group(1);
-            String remainder = m.group(2);
-            String base = (String) properties.get(var);
-            if (base != null) {
-                File b = new File(base);
-                File f = new File(b, remainder.replace('/', File.separatorChar));
-                return f;
-            } else
-                reporter.error("Can't find replacement variable for: " + path);
-        } else
-            reporter.error("Cant split variable path: " + path);
-        return null;
-    }
-
-    private String get(NamedNodeMap map, String name) {
-        Node node = map.getNamedItem(name);
-        if (node == null)
-            return null;
-
-        return node.getNodeValue();
-    }
-
-    public Set<File> getClasspath() {
-        return classpath;
-    }
-
-    public Set<File> getSourcepath() {
-        return sources;
-    }
-
-    public File getOutput() {
-        return output;
-    }
-
-    public List<File> getDependents() {
-        return dependents;
-    }
-
-    public void setRecurse(boolean recurse) {
-        this.recurse = recurse;
-    }
-
-    public Set<File> getExports() {
-        return exports;
-    }
-
-    public void setProperties(Map<String, String> map) {
-        this.properties = map;
-    }
-
-    public Set<File> getBootclasspath() {
-        return bootclasspath;
-    }
-
-    public Set<File> getAllSources() {
-        return allSources;
-    }
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/lib/osgi/packageinfo b/biz.aQute.bndlib/src/aQute/lib/osgi/packageinfo
deleted file mode 100644
index ec0efd4..0000000
--- a/biz.aQute.bndlib/src/aQute/lib/osgi/packageinfo
+++ /dev/null
@@ -1 +0,0 @@
-version 1.43.1
diff --git a/biz.aQute.bndlib/src/aQute/lib/spring/JPAComponent.java b/biz.aQute.bndlib/src/aQute/lib/spring/JPAComponent.java
index 131709c..fc219c1 100644
--- a/biz.aQute.bndlib/src/aQute/lib/spring/JPAComponent.java
+++ b/biz.aQute.bndlib/src/aQute/lib/spring/JPAComponent.java
@@ -1,25 +1,23 @@
 package aQute.lib.spring;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
 
-import aQute.lib.osgi.Analyzer;
+import aQute.bnd.osgi.*;
 
 /**
  * This component is called when we find a resource in the META-INF/*.xml
- * pattern. We parse the resource and and the imports to the builder.
- * 
- * Parsing is done with XSLT (first time I see the use of having XML for the
- * Spring configuration files!).
+ * pattern. We parse the resource and and the imports to the builder. Parsing is
+ * done with XSLT (first time I see the use of having XML for the Spring
+ * configuration files!).
  * 
  * @author aqute
- * 
  */
 public class JPAComponent extends XMLTypeProcessor {
-    
-    protected List<XMLType> getTypes(Analyzer analyzer) throws Exception {
-        List<XMLType> types = new ArrayList<XMLType>();        
-        process(types,"jpa.xsl", "META-INF", "persistence.xml");
-        return types;
-    }
+
+	@Override
+	protected List<XMLType> getTypes(Analyzer analyzer) throws Exception {
+		List<XMLType> types = new ArrayList<XMLType>();
+		process(types, "jpa.xsl", "META-INF", "persistence.xml");
+		return types;
+	}
 }
diff --git a/biz.aQute.bndlib/src/aQute/lib/spring/SpringComponent.java b/biz.aQute.bndlib/src/aQute/lib/spring/SpringComponent.java
index 3318a0e..eff6ef4 100644
--- a/biz.aQute.bndlib/src/aQute/lib/spring/SpringComponent.java
+++ b/biz.aQute.bndlib/src/aQute/lib/spring/SpringComponent.java
@@ -2,34 +2,34 @@ package aQute.lib.spring;
 
 import java.io.*;
 import java.util.*;
+import java.util.Map.Entry;
 import java.util.regex.*;
 
 import javax.xml.transform.*;
 import javax.xml.transform.stream.*;
 
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Descriptors.PackageRef;
 import aQute.bnd.service.*;
-import aQute.lib.osgi.*;
 
 /**
  * This component is called when we find a resource in the META-INF/*.xml
- * pattern. We parse the resource and and the imports to the builder.
- * 
- * Parsing is done with XSLT (first time I see the use of having XML for the
- * Spring configuration files!).
+ * pattern. We parse the resource and and the imports to the builder. Parsing is
+ * done with XSLT (first time I see the use of having XML for the Spring
+ * configuration files!).
  * 
  * @author aqute
- * 
  */
 public class SpringComponent implements AnalyzerPlugin {
-	static Transformer transformer;
-	static Pattern SPRING_SOURCE = Pattern.compile("META-INF/spring/.*\\.xml");
-	static Pattern QN = Pattern.compile("[_A-Za-z$][_A-Za-z0-9$]*(\\.[_A-Za-z$][_A-Za-z0-9$]*)*");
+	static Transformer	transformer;
+	static Pattern		SPRING_SOURCE	= Pattern.compile("META-INF/spring/.*\\.xml");
+	static Pattern		QN				= Pattern.compile("[_A-Za-z$][_A-Za-z0-9$]*(\\.[_A-Za-z$][_A-Za-z0-9$]*)*");
 
 	public static Set<CharSequence> analyze(InputStream in) throws Exception {
 		if (transformer == null) {
 			TransformerFactory tf = TransformerFactory.newInstance();
-			Source source = new StreamSource(SpringComponent.class
-					.getResourceAsStream("extract.xsl"));
+			Source source = new StreamSource(SpringComponent.class.getResourceAsStream("extract.xsl"));
 			transformer = tf.newTransformer(source);
 		}
 
@@ -63,31 +63,32 @@ public class SpringComponent implements AnalyzerPlugin {
 		return refers;
 	}
 
-	@SuppressWarnings("unchecked")
-    public boolean analyzeJar(Analyzer analyzer) throws Exception {
-	    Jar jar = analyzer.getJar();
-		Map dir = (Map) jar.getDirectories().get("META-INF/spring");
-		if ( dir == null || dir.isEmpty())
+	public boolean analyzeJar(Analyzer analyzer) throws Exception {
+		Jar jar = analyzer.getJar();
+		Map<String,Resource> dir = jar.getDirectories().get("META-INF/spring");
+		if (dir == null || dir.isEmpty())
 			return false;
-		
-		for (Iterator i = dir.entrySet().iterator(); i.hasNext();) {
-			Map.Entry entry = (Map.Entry) i.next();
-			String path = (String) entry.getKey();
-			Resource resource = (Resource) entry.getValue();
+
+		for (Iterator<Entry<String,Resource>> i = dir.entrySet().iterator(); i.hasNext();) {
+			Entry<String,Resource> entry = i.next();
+			String path = entry.getKey();
+			Resource resource = entry.getValue();
 			if (SPRING_SOURCE.matcher(path).matches()) {
 				try {
-				InputStream in = resource.openInputStream();
-				Set set = analyze(in);
-				in.close();
-				for (Iterator r = set.iterator(); r.hasNext();) {
-					String pack = (String) r.next();
-					if ( !QN.matcher(pack).matches())
-					    analyzer.warning("Package does not seem a package in spring resource ("+path+"): " + pack );
-					if (!analyzer.getReferred().containsKey(pack))
-						analyzer.getReferred().put(pack, new LinkedHashMap());
+					InputStream in = resource.openInputStream();
+					Set<CharSequence> set = analyze(in);
+					in.close();
+					for (Iterator<CharSequence> r = set.iterator(); r.hasNext();) {
+						PackageRef pack = analyzer.getPackageRef((String) r.next());
+						if (!QN.matcher(pack.getFQN()).matches())
+							analyzer.warning("Package does not seem a package in spring resource (" + path + "): "
+									+ pack);
+						if (!analyzer.getReferred().containsKey(pack))
+							analyzer.getReferred().put(pack, new Attrs());
+					}
 				}
-				} catch( Exception e ) {
-					analyzer.error("Unexpected exception in processing spring resources("+path+"): " + e );
+				catch (Exception e) {
+					analyzer.error("Unexpected exception in processing spring resources(" + path + "): " + e);
 				}
 			}
 		}
diff --git a/biz.aQute.bndlib/src/aQute/lib/spring/SpringXMLType.java b/biz.aQute.bndlib/src/aQute/lib/spring/SpringXMLType.java
index 35b59a9..5ec76b0 100644
--- a/biz.aQute.bndlib/src/aQute/lib/spring/SpringXMLType.java
+++ b/biz.aQute.bndlib/src/aQute/lib/spring/SpringXMLType.java
@@ -2,32 +2,28 @@ package aQute.lib.spring;
 
 import java.util.*;
 
-import aQute.lib.osgi.*;
+import aQute.bnd.osgi.*;
 
 /**
  * This component is called when we find a resource in the META-INF/*.xml
- * pattern. We parse the resource and and the imports to the builder.
- * 
- * Parsing is done with XSLT (first time I see the use of having XML for the
- * Spring configuration files!).
+ * pattern. We parse the resource and and the imports to the builder. Parsing is
+ * done with XSLT (first time I see the use of having XML for the Spring
+ * configuration files!).
  * 
  * @author aqute
- * 
  */
 public class SpringXMLType extends XMLTypeProcessor {
 
-    protected List<XMLType> getTypes(Analyzer analyzer) throws Exception {
-        List<XMLType> types = new ArrayList<XMLType>();
-        
-        String header = analyzer.getProperty("Bundle-Blueprint", "META-INF/blueprint");
-        process(types,"extract.xsl", header, ".*\\.xml");
-        header = analyzer.getProperty("Spring-Context", "META-INF/spring");
-        process(types,"extract.xsl", header, ".*\\.xml"); 
-        
-        return types;
-    }
+	@Override
+	protected List<XMLType> getTypes(Analyzer analyzer) throws Exception {
+		List<XMLType> types = new ArrayList<XMLType>();
 
- 
+		String header = analyzer.getProperty("Bundle-Blueprint", "OSGI-INF/blueprint");
+		process(types, "extract.xsl", header, ".*\\.xml");
+		header = analyzer.getProperty("Spring-Context", "META-INF/spring");
+		process(types, "extract.xsl", header, ".*\\.xml");
 
+		return types;
+	}
 
 }
diff --git a/biz.aQute.bndlib/src/aQute/lib/spring/XMLType.java b/biz.aQute.bndlib/src/aQute/lib/spring/XMLType.java
index 9fadb35..d01fd57 100644
--- a/biz.aQute.bndlib/src/aQute/lib/spring/XMLType.java
+++ b/biz.aQute.bndlib/src/aQute/lib/spring/XMLType.java
@@ -8,101 +8,96 @@ import java.util.regex.*;
 import javax.xml.transform.*;
 import javax.xml.transform.stream.*;
 
-import aQute.lib.osgi.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.osgi.Descriptors.PackageRef;
 
 public class XMLType {
-    
-    Transformer    transformer;
-    Pattern        paths;
-    String          root;
-    
-    
-    static Pattern QN = Pattern
-                              .compile("[_A-Za-z$][_A-Za-z0-9$]*(\\.[_A-Za-z$][_A-Za-z0-9$]*)*");
-
-    public XMLType(URL source, String root, String paths ) throws Exception {
-        transformer = getTransformer(source);
-        this.paths = Pattern.compile(paths);
-        this.root = root;
-    }
-    
-    public Set<String> analyze(InputStream in) throws Exception {
-        Set<String> refers = new HashSet<String>();
-
-        ByteArrayOutputStream bout = new ByteArrayOutputStream();
-        Result r = new StreamResult(bout);
-        Source s = new StreamSource(in);
-        transformer.transform(s, r);
-
-        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
-        bout.close();
-
-        BufferedReader br = new BufferedReader(new InputStreamReader(bin, "UTF8"));
-
-        String line = br.readLine();
-        while (line != null) {
-            line = line.trim();
-            if (line.length() > 0) {
-                String parts[] = line.split("\\s*,\\s*");
-                for (int i = 0; i < parts.length; i++) {
-                    int n = parts[i].lastIndexOf('.');
-                    if (n > 0) {
-                        refers.add(parts[i].subSequence(0, n).toString());
-                    }
-                }
-            }
-            line = br.readLine();
-        }
-        br.close();
-        return refers;
-    }
-
-    public boolean analyzeJar(Analyzer analyzer) throws Exception {
-        Jar jar = analyzer.getJar();
-        Map<String,Resource> dir = jar.getDirectories().get(root);
-        if (dir == null || dir.isEmpty()) {
-            Resource resource  = jar.getResource(root);
-            if ( resource != null )
-                process(analyzer, root, resource);
-            return false;
-        }
-
-        for (Iterator<Map.Entry<String,Resource>> i = dir.entrySet().iterator(); i.hasNext();) {
-            Map.Entry<String,Resource> entry = i.next();
-            String path = entry.getKey();
-            Resource resource = entry.getValue();
-            if (paths.matcher(path).matches()) {
-                process(analyzer, path, resource);
-            }
-        }
-        return false;
-    }
-
-    private void process(Analyzer analyzer, String path, Resource resource) {
-        try {
-            InputStream in = resource.openInputStream();
-            Set<String> set = analyze(in);
-            in.close();
-            for (Iterator<String> r = set.iterator(); r.hasNext();) {
-                String pack = r.next();
-                if (!QN.matcher(pack).matches())
-                    analyzer
-                            .warning("Package does not seem a package in spring resource ("
-                                    + path + "): " + pack);
-                if (!analyzer.getReferred().containsKey(pack))
-                    analyzer.getReferred().put(pack,
-                            new LinkedHashMap<String,String>());
-            }
-        } catch (Exception e) {
-            analyzer
-                    .error("Unexpected exception in processing spring resources("
-                            + path + "): " + e);
-        }
-    }
-
-    protected Transformer getTransformer(java.net.URL url) throws Exception {
-        TransformerFactory tf = TransformerFactory.newInstance();
-        Source source = new StreamSource(url.openStream());
-        return tf.newTransformer(source);
-    }
+
+	Transformer		transformer;
+	Pattern			paths;
+	String			root;
+
+	static Pattern	QN	= Pattern.compile("[_A-Za-z$][_A-Za-z0-9$]*(\\.[_A-Za-z$][_A-Za-z0-9$]*)*");
+
+	public XMLType(URL source, String root, String paths) throws Exception {
+		transformer = getTransformer(source);
+		this.paths = Pattern.compile(paths);
+		this.root = root;
+	}
+
+	public Set<String> analyze(InputStream in) throws Exception {
+		Set<String> refers = new HashSet<String>();
+
+		ByteArrayOutputStream bout = new ByteArrayOutputStream();
+		Result r = new StreamResult(bout);
+		Source s = new StreamSource(in);
+		transformer.transform(s, r);
+
+		ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+		bout.close();
+
+		BufferedReader br = new BufferedReader(new InputStreamReader(bin, "UTF8"));
+
+		String line = br.readLine();
+		while (line != null) {
+			line = line.trim();
+			if (line.length() > 0) {
+				String parts[] = line.split("\\s*,\\s*");
+				for (int i = 0; i < parts.length; i++) {
+					int n = parts[i].lastIndexOf('.');
+					if (n > 0) {
+						refers.add(parts[i].subSequence(0, n).toString());
+					}
+				}
+			}
+			line = br.readLine();
+		}
+		br.close();
+		return refers;
+	}
+
+	public boolean analyzeJar(Analyzer analyzer) throws Exception {
+		Jar jar = analyzer.getJar();
+		Map<String,Resource> dir = jar.getDirectories().get(root);
+		if (dir == null || dir.isEmpty()) {
+			Resource resource = jar.getResource(root);
+			if (resource != null)
+				process(analyzer, root, resource);
+			return false;
+		}
+
+		for (Iterator<Map.Entry<String,Resource>> i = dir.entrySet().iterator(); i.hasNext();) {
+			Map.Entry<String,Resource> entry = i.next();
+			String path = entry.getKey();
+			Resource resource = entry.getValue();
+			if (paths.matcher(path).matches()) {
+				process(analyzer, path, resource);
+			}
+		}
+		return false;
+	}
+
+	private void process(Analyzer analyzer, String path, Resource resource) {
+		try {
+			InputStream in = resource.openInputStream();
+			Set<String> set = analyze(in);
+			in.close();
+			for (Iterator<String> r = set.iterator(); r.hasNext();) {
+				PackageRef pack = analyzer.getPackageRef(r.next());
+				if (!QN.matcher(pack.getFQN()).matches())
+					analyzer.warning("Package does not seem a package in spring resource (" + path + "): " + pack);
+				if (!analyzer.getReferred().containsKey(pack))
+					analyzer.getReferred().put(pack);
+			}
+		}
+		catch (Exception e) {
+			analyzer.error("Unexpected exception in processing spring resources(" + path + "): " + e);
+		}
+	}
+
+	protected Transformer getTransformer(java.net.URL url) throws Exception {
+		TransformerFactory tf = TransformerFactory.newInstance();
+		Source source = new StreamSource(url.openStream());
+		return tf.newTransformer(source);
+	}
 }
diff --git a/biz.aQute.bndlib/src/aQute/lib/spring/XMLTypeProcessor.java b/biz.aQute.bndlib/src/aQute/lib/spring/XMLTypeProcessor.java
index dde8b7e..e8ca286 100644
--- a/biz.aQute.bndlib/src/aQute/lib/spring/XMLTypeProcessor.java
+++ b/biz.aQute.bndlib/src/aQute/lib/spring/XMLTypeProcessor.java
@@ -2,32 +2,30 @@ package aQute.lib.spring;
 
 import java.util.*;
 
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.*;
 import aQute.bnd.service.*;
-import aQute.lib.osgi.*;
 
 public class XMLTypeProcessor implements AnalyzerPlugin {
-    
-    public boolean analyzeJar(Analyzer analyzer) throws Exception {
-        List<XMLType> types = getTypes(analyzer);
-        for ( XMLType type : types ) {
-            type.analyzeJar(analyzer);
-        }
-        return false;
-    }
-    
-    protected List<XMLType> getTypes(Analyzer analyzer) throws Exception {
-        return new ArrayList<XMLType>();
-    }
-
-
-    protected void process(List<XMLType> types, String resource, String paths,
-            String pattern) throws Exception {
-        
-        Map<String,Map<String,String>> map = Processor.parseHeader(paths,null);
-        for ( String path : map.keySet() ) {
-            types.add( new XMLType( getClass().getResource(resource), path, pattern ));
-        }
-    }
 
+	public boolean analyzeJar(Analyzer analyzer) throws Exception {
+		List<XMLType> types = getTypes(analyzer);
+		for (XMLType type : types) {
+			type.analyzeJar(analyzer);
+		}
+		return false;
+	}
+
+	protected List<XMLType> getTypes(@SuppressWarnings("unused") Analyzer analyzer) throws Exception {
+		return new ArrayList<XMLType>();
+	}
+
+	protected void process(List<XMLType> types, String resource, String paths, String pattern) throws Exception {
+
+		Parameters map = Processor.parseHeader(paths, null);
+		for (String path : map.keySet()) {
+			types.add(new XMLType(getClass().getResource(resource), path, pattern));
+		}
+	}
 
 }
diff --git a/biz.aQute.bndlib/src/aQute/lib/spring/extract.xsl b/biz.aQute.bndlib/src/aQute/lib/spring/extract.xsl
index efad6cd..11726b6 100644
--- a/biz.aQute.bndlib/src/aQute/lib/spring/extract.xsl
+++ b/biz.aQute.bndlib/src/aQute/lib/spring/extract.xsl
@@ -1,6 +1,21 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
-<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:jms="http://www.springframework.org/schema/jms" xmlns:lang="http://www.springframework.org/schema/lang" xmlns:osgi-compendium="http://www.springframework.org/schema/osgi-compendiu [...]
+<xsl:stylesheet version="1.0" 
+	xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
+	xmlns:beans="http://www.springframework.org/schema/beans" 
+	xmlns:aop="http://www.springframework.org/schema/aop" 
+	xmlns:context="http://www.springframework.org/schema/context" 
+	xmlns:jee="http://www.springframework.org/schema/jee" 
+	xmlns:jms="http://www.springframework.org/schema/jms" 
+	xmlns:lang="http://www.springframework.org/schema/lang" 
+	xmlns:osgi-compendium="http://www.springframework.org/schema/osgi-compendium" 
+	xmlns:osgi="http://www.springframework.org/schema/osgi" 
+	xmlns:tool="http://www.springframework.org/schema/tool" 
+	xmlns:tx="http://www.springframework.org/schema/tx" 
+	xmlns:util="http://www.springframework.org/schema/util" 
+	xmlns:webflow-config="http://www.springframework.org/schema/webflow-config" 
+	xmlns:gemini-blueprint="http://www.eclipse.org/gemini/blueprint/schema/blueprint"
+	xmlns:blueprint="http://www.osgi.org/xmlns/blueprint/v1.0.0">
 	<xsl:output method="text" />
 
 	<xsl:template match="/">
@@ -20,6 +35,9 @@
 			|	//jee:*/@business-interface
 			|	//lang:*/@script-interfaces
 			|	//osgi:*/@interface
+			|	//gemini-blueprint:*/@interface
+			|   //blueprint:*/@interface
+			|   //blueprint:*/@class
 			|	//util:list/@list-class
 			|	//util:set/@set-class
 			|	//util:map/@map-class
diff --git a/biz.aQute.bndlib/src/test/AnalyzerTest.java b/biz.aQute.bndlib/src/test/AnalyzerTest.java
deleted file mode 100755
index 6bb7cc3..0000000
--- a/biz.aQute.bndlib/src/test/AnalyzerTest.java
+++ /dev/null
@@ -1,540 +0,0 @@
-package test;
-
-import java.io.*;
-import java.util.*;
-import java.util.jar.*;
-
-import aQute.bnd.test.*;
-import aQute.lib.osgi.*;
-
-class T0 {
-}
-
-abstract class T1 extends T0 {
-}
-
-class T2 extends T1 {
-}
-
-class T3 extends T2 {
-}
-
-public class AnalyzerTest extends BndTestCase {
-
-	
-	/**
-	 * Fastest way to create a manifest
-	 * @throws Exception 
-	 */
-	
-	public void testGenerateManifest() throws Exception {
-		Analyzer analyzer = new Analyzer();
-		Jar bin = new Jar( new File("jar/osgi.jar"));
-		bin.setManifest(new Manifest());
-		analyzer.setJar( bin );
-		analyzer.addClasspath( new File("jar/spring.jar"));
-		analyzer.setProperty("Bundle-SymbolicName","org.osgi.core");
-		analyzer.setProperty("Export-Package","org.osgi.framework,org.osgi.service.event");
-		analyzer.setProperty("Bundle-Version","1.0");
-		analyzer.setProperty("Import-Package","*");
-		Manifest manifest = analyzer.calcManifest();
-		manifest.write(System.out);
-		String export = manifest.getMainAttributes().getValue("Export-Package");
-		assertEquals("org.osgi.framework;version=\"1.3\",org.osgi.service.event;uses:=\"org.osgi.framework\";version=\"1.0.1\"",export);
-		assertEquals("1.0",manifest.getMainAttributes().getValue("Bundle-Version"));
-		assertEquals(analyzer.getErrors().toString(), 0, analyzer.getErrors().size());
-		assertEquals(analyzer.getWarnings().toString(), 0, analyzer.getWarnings().size());
-	}
-	
-	/**
-	 * 
-	 * Make sure packages from embedded directories referenced from
-	 * 
-	 * Bundle-Classpath are considered during import/export calculation.
-	 */
-
-	public void testExportContentsDirectory() throws Exception {
-		Builder b = new Builder();
-		File embedded = new File("bin/aQute/lib").getCanonicalFile();
-		assertTrue(embedded.isDirectory()); // sanity check
-		b.setProperty("Bundle-ClassPath", ".,jars/some.jar");
-		b.setProperty("-includeresource", "jars/some.jar/aQute/lib=" + embedded.getAbsolutePath());
-		b.setProperty("-exportcontents", "aQute.lib.osgi");
-		b.build();
-
-		assertTrue(b.getExports().toString(), b.getExports().containsKey("aQute.lib.osgi"));
-
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(b.getErrors().toString(), 0, b.getErrors().size());
-		assertEquals(b.getWarnings().toString(), 1, b.getWarnings().size());
-
-	}
-
-	/**
-	 * Uses constraints must be filtered by imports or exports.
-	 * 
-	 * @throws Exception
-	 */
-
-	public void testUsesFiltering() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("jar/osgi.jar"));
-		b.setProperty("Export-Package", "org.osgi.service.event");
-		Jar jar = b.build();
-
-		String exports = jar.getManifest().getMainAttributes().getValue("Export-Package");
-		System.out.println(exports);
-		assertTrue(exports.contains("uses:=\"org.osgi.framework\""));
-
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		b = new Builder();
-		b.addClasspath(new File("jar/osgi.jar"));
-		b.setProperty("Import-Package", "");
-		b.setProperty("Export-Package", "org.osgi.service.event");
-		jar = b.build();
-		exports = jar.getManifest().getMainAttributes().getValue("Export-Package");
-		assertFalse(exports.contains("uses:=\"org.osgi.framework\""));
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(1, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-	}
-
-	/**
-	 * Test if require works
-	 * 
-	 * @throws Exception
-	 */
-
-	public void testRequire() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("jar/osgi.jar"));
-		b.setProperty("Private-Package", "org.osgi.framework");
-		b.setProperty("-require-bnd", "10000");
-		b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(1, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-	}
-
-	public void testComponentImportReference() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("jar/osgi.jar"));
-		b.setProperty("Private-Package", "org.osgi.framework");
-		b.setProperty("Import-Package", "not.here,*");
-		b.setProperty("Service-Component", "org.osgi.framework.Bundle;ref=not.here.Reference");
-		b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-	}
-
-	public void testFindClass() throws Exception {
-		Builder a = new Builder();
-		a.setProperty("Export-Package", "org.osgi.service.io");
-		a.addClasspath(new File("jar/osgi.jar"));
-		a.build();
-		System.out.println(a.getErrors());
-		System.out.println(a.getWarnings());
-
-		Collection<Clazz> c = a.getClasses("", "IMPORTS", "javax.microedition.io");
-		System.out.println(c);
-	}
-
-	public void testMultilevelInheritance() throws Exception {
-		Analyzer a = new Analyzer();
-		a.setJar(new File("bin"));
-		a.analyze();
-
-		String result = a._classes("cmd", "named", "*T?", "extends", "test.T0", "concrete");
-		System.out.println(result);
-		assertTrue(result.contains("test.T2"));
-		assertTrue(result.contains("test.T3"));
-	}
-
-	public void testClassQuery() throws Exception {
-		Analyzer a = new Analyzer();
-		a.setJar(new File("jar/osgi.jar"));
-		a.analyze();
-
-		String result = a._classes("cmd", "named", "org.osgi.service.http.*", "abstract");
-		TreeSet<String> r = new TreeSet<String>(Processor.split(result));
-		assertEquals(
-				new TreeSet<String>(Arrays.asList("org.osgi.service.http.HttpContext",
-						"org.osgi.service.http.HttpService")), r);
-	}
-
-	/**
-	 * Use a private activator, check it is not imported.
-	 * 
-	 * @throws Exception
-	 */
-	public void testEmptyHeader() throws Exception {
-		Builder a = new Builder();
-		a.setProperty("Bundle-Blueprint", "  <<EMPTY>> ");
-		a.setProperty("Export-Package", "org.osgi.framework");
-		a.addClasspath(new File("jar/osgi.jar"));
-		a.build();
-		Manifest manifest = a.getJar().getManifest();
-		System.out.println(a.getErrors());
-		System.out.println(a.getWarnings());
-		assertEquals(0, a.getErrors().size());
-		assertEquals(0, a.getWarnings().size());
-		String bb = manifest.getMainAttributes().getValue("Bundle-Blueprint");
-		System.out.println(bb);
-		assertNotNull(bb);
-		assertEquals("", bb);
-	}
-
-	/**
-	 * Test name section.
-	 */
-
-	public void testNameSection() throws Exception {
-		Builder a = new Builder();
-		a.setProperty("Export-Package", "org.osgi.service.event, org.osgi.service.io");
-		a.addClasspath(new File("jar/osgi.jar"));
-		a.setProperty("@org at osgi@service at event@Specification-Title", "spec title");
-		a.setProperty("@org at osgi@service at io@Specification-Title", "spec title io");
-		a.setProperty("@org at osgi@service at event@Specification-Version", "1.1");
-		a.setProperty("@org at osgi@service at event@Implementation-Version", "5.1");
-		Jar jar = a.build();
-		Manifest m = jar.getManifest();
-		Attributes attrs = m.getAttributes("org/osgi/service/event");
-		assertNotNull(attrs);
-		assertEquals("5.1", attrs.getValue("Implementation-Version"));
-		assertEquals("1.1", attrs.getValue("Specification-Version"));
-		assertEquals("spec title", attrs.getValue("Specification-Title"));
-
-		attrs = m.getAttributes("org/osgi/service/io");
-		assertNotNull(attrs);
-		assertEquals("spec title io", attrs.getValue("Specification-Title"));
-	}
-
-	/**
-	 * Check if calcManifest sets the version
-	 */
-
-	/**
-	 * Test if mandatory attributes are augmented even when the version is not
-	 * set.
-	 */
-	public void testMandatoryWithoutVersion() throws Exception {
-		Builder a = new Builder();
-		Properties p = new Properties();
-		p.put("Import-Package", "*");
-		p.put("Private-Package", "org.apache.mina.management.*");
-		a.setClasspath(new Jar[] { new Jar(new File("jar/mandatorynoversion.jar")) });
-		a.setProperties(p);
-		Jar jar = a.build();
-		String imports = jar.getManifest().getMainAttributes().getValue("Import-Package");
-		System.out.println(imports);
-		assertTrue(imports.indexOf("x=1") >= 0);
-		assertTrue(imports.indexOf("y=2") >= 0);
-	}
-
-	/**
-	 * Use a private activator, check it is not imported.
-	 * 
-	 * @throws Exception
-	 */
-	public void testPrivataBundleActivatorNotImported() throws Exception {
-		Builder a = new Builder();
-		Properties p = new Properties();
-		p.put("Import-Package", "*");
-		p.put("Private-Package", "org.objectweb.*");
-		p.put("Bundle-Activator", "org.objectweb.asm.Item");
-		a.setClasspath(new Jar[] { new Jar(new File("jar/asm.jar")) });
-		a.setProperties(p);
-		a.build();
-		Manifest manifest = a.getJar().getManifest();
-		System.out.println(a.getErrors());
-		System.out.println(a.getWarnings());
-		assertEquals(0, a.getErrors().size());
-		assertEquals(0, a.getWarnings().size());
-		String imports = manifest.getMainAttributes().getValue("Import-Package");
-		System.out.println(imports);
-		assertNull(imports);
-	}
-
-	/**
-	 * Use an activator that is not in the bundle but do not allow it to be
-	 * imported, this should generate an error.
-	 * 
-	 * @throws Exception
-	 */
-	public void testBundleActivatorNotImported() throws Exception {
-		Builder a = new Builder();
-		Properties p = new Properties();
-		p.put("Import-Package", "!org.osgi.framework,*");
-		p.put("Private-Package", "org.objectweb.*");
-		p.put("Bundle-Activator", "org.osgi.framework.BundleActivator");
-		a.setClasspath(new Jar[] { new Jar(new File("jar/asm.jar")),
-				new Jar(new File("jar/osgi.jar")) });
-		a.setProperties(p);
-		a.build();
-		Manifest manifest = a.getJar().getManifest();
-		System.out.println(a.getErrors());
-		System.out.println(a.getWarnings());
-		assertEquals(1, a.getErrors().size());
-		assertTrue(a.getErrors().get(0).indexOf("Bundle-Activator not found") >= 0);
-		// assertTrue(a.getErrors().get(1).indexOf("Unresolved references to")
-		// >= 0);
-		assertEquals(0, a.getWarnings().size());
-		String imports = manifest.getMainAttributes().getValue("Import-Package");
-		assertNull(imports);
-	}
-
-	/**
-	 * Use an activator that is on the class path but that is not in the bundle.
-	 * 
-	 * @throws Exception
-	 */
-	public void testBundleActivatorImport() throws Exception {
-		Builder a = new Builder();
-		Properties p = new Properties();
-		p.put("Private-Package", "org.objectweb.*");
-		p.put("Bundle-Activator", "org.osgi.framework.BundleActivator");
-		a.setClasspath(new Jar[] { new Jar(new File("jar/asm.jar")),
-				new Jar(new File("jar/osgi.jar")) });
-		a.setProperties(p);
-		a.build();
-		Manifest manifest = a.getJar().getManifest();
-		System.out.println(a.getErrors());
-		System.out.println(a.getWarnings());
-		assertEquals(0, a.getErrors().size());
-		assertEquals(0, a.getWarnings().size());
-		String imports = manifest.getMainAttributes().getValue("Import-Package");
-		assertNotNull(imports);
-		assertTrue(imports.indexOf("org.osgi.framework") >= 0);
-	}
-
-	/**
-	 * The -removeheaders header removes any necessary after the manifest is
-	 * calculated.
-	 */
-
-	public void testRemoveheaders() throws Exception {
-		Analyzer a = new Analyzer();
-		a.setJar(new File("jar/asm.jar"));
-		Manifest m = a.calcManifest();
-		assertNotNull(m.getMainAttributes().getValue("Implementation-Title"));
-		a = new Analyzer();
-		a.setJar(new File("jar/asm.jar"));
-		a.setProperty("-removeheaders", "Implementation-Title");
-		m = a.calcManifest();
-		assertNull(m.getMainAttributes().getValue("Implementation-Title"));
-	}
-
-	/**
-	 * There was an export generated for a jar file.
-	 * 
-	 * @throws Exception
-	 */
-	public void testExportForJar() throws Exception {
-		Jar jar = new Jar("dot");
-		jar.putResource("target/aopalliance.jar", new FileResource(new File("jar/asm.jar")));
-		Analyzer an = new Analyzer();
-		an.setJar(jar);
-		Properties p = new Properties();
-		p.put("Export-Package", "*");
-		an.setProperties(p);
-		Manifest manifest = an.calcManifest();
-		String exports = manifest.getMainAttributes().getValue(Analyzer.EXPORT_PACKAGE);
-		Map<String, Map<String, String>> map = Analyzer.parseHeader(exports, null);
-		assertEquals(1, map.size());
-		assertEquals("target", map.keySet().iterator().next());
-	}
-
-	/**
-	 * Test if version works
-	 */
-
-	public void testVersion() {
-		Analyzer a = new Analyzer();
-		String v = a.getBndVersion();
-		assertNotNull(v);
-	}
-
-	/**
-	 * asm is a simple library with two packages. No imports are done.
-	 * 
-	 */
-	public void testAsm() throws Exception {
-		Properties base = new Properties();
-		base.put(Analyzer.IMPORT_PACKAGE, "*");
-		base.put(Analyzer.EXPORT_PACKAGE, "*;-noimport:=true");
-
-		Analyzer analyzer = new Analyzer();
-		analyzer.setJar(new File("jar/asm.jar"));
-		analyzer.setProperties(base);
-		analyzer.calcManifest().write(System.out);
-		assertTrue(analyzer.getExports().containsKey("org.objectweb.asm.signature"));
-		assertTrue(analyzer.getExports().containsKey("org.objectweb.asm"));
-		assertFalse(analyzer.getImports().containsKey("org.objectweb.asm.signature"));
-		assertFalse(analyzer.getImports().containsKey("org.objectweb.asm"));
-		assertEquals("Expected size", 2, analyzer.getExports().size());
-	}
-
-	/**
-	 * See if we set attributes on export
-	 * 
-	 * @throws IOException
-	 */
-	public void testAsm2() throws Exception {
-		Properties base = new Properties();
-		base.put(Analyzer.IMPORT_PACKAGE, "*");
-		base.put(Analyzer.EXPORT_PACKAGE,
-				"org.objectweb.asm;name=short, org.objectweb.asm.signature;name=long");
-		Analyzer h = new Analyzer();
-		h.setJar(new File("jar/asm.jar"));
-		h.setProperties(base);
-		h.calcManifest().write(System.out);
-		assertPresent(h.getExports(), "org.objectweb.asm.signature, org.objectweb.asm");
-		assertTrue(Arrays.asList("org.objectweb.asm", "org.objectweb.asm.signature").removeAll(
-				h.getImports().keySet()) == false);
-		assertEquals("Expected size", 2, h.getExports().size());
-		assertEquals("short", get(h.getExports(), "org.objectweb.asm", "name"));
-		assertEquals("long", get(h.getExports(), "org.objectweb.asm.signature", "name"));
-	}
-
-	public void testDs() throws Exception {
-		Properties base = new Properties();
-		base.put(Analyzer.IMPORT_PACKAGE, "*");
-		base.put(Analyzer.EXPORT_PACKAGE, "*;-noimport:=true");
-		File tmp = new File("jar/ds.jar");
-		Analyzer analyzer = new Analyzer();
-		analyzer.setJar(tmp);
-		analyzer.setProperties(base);
-		System.out.println(analyzer.calcManifest());
-		assertPresent(analyzer.getImports(), "org.osgi.service.packageadmin, "
-				+ "org.xml.sax, org.osgi.service.log," + " javax.xml.parsers,"
-				+ " org.xml.sax.helpers," + " org.osgi.framework," + " org.eclipse.osgi.util,"
-				+ " org.osgi.util.tracker, " + "org.osgi.service.component, "
-				+ "org.osgi.service.cm");
-		assertPresent(analyzer.getExports(), "org.eclipse.equinox.ds.parser, "
-				+ "org.eclipse.equinox.ds.tracker, " + "org.eclipse.equinox.ds, "
-				+ "org.eclipse.equinox.ds.instance, " + "org.eclipse.equinox.ds.model, "
-				+ "org.eclipse.equinox.ds.resolver, " + "org.eclipse.equinox.ds.workqueue");
-
-	}
-
-	public void testDsSkipOsgiImport() throws Exception {
-		Properties base = new Properties();
-		base.put(Analyzer.IMPORT_PACKAGE, "!org.osgi.*, *");
-		base.put(Analyzer.EXPORT_PACKAGE, "*;-noimport:=true");
-		File tmp = new File("jar/ds.jar");
-		Analyzer h = new Analyzer();
-		h.setJar(tmp);
-		h.setProperties(base);
-		h.calcManifest().write(System.out);
-		assertPresent(h.getImports(), "org.xml.sax, " + " javax.xml.parsers,"
-				+ " org.xml.sax.helpers," + " org.eclipse.osgi.util");
-
-		System.out.println("IMports " + h.getImports());
-		assertNotPresent(h.getImports(), "org.osgi.service.packageadmin, "
-				+ "org.osgi.service.log," + " org.osgi.framework," + " org.osgi.util.tracker, "
-				+ "org.osgi.service.component, " + "org.osgi.service.cm");
-		assertPresent(h.getExports(), "org.eclipse.equinox.ds.parser, "
-				+ "org.eclipse.equinox.ds.tracker, " + "org.eclipse.equinox.ds, "
-				+ "org.eclipse.equinox.ds.instance, " + "org.eclipse.equinox.ds.model, "
-				+ "org.eclipse.equinox.ds.resolver, " + "org.eclipse.equinox.ds.workqueue");
-	}
-
-	public void testDsNoExport() throws Exception {
-		Properties base = new Properties();
-		base.put(Analyzer.IMPORT_PACKAGE, "*");
-		base.put(Analyzer.EXPORT_PACKAGE, "!*");
-		File tmp = new File("jar/ds.jar");
-		Analyzer h = new Analyzer();
-		h.setJar(tmp);
-		h.setProperties(base);
-		h.calcManifest().write(System.out);
-		assertPresent(h.getImports(), "org.osgi.service.packageadmin, "
-				+ "org.xml.sax, org.osgi.service.log," + " javax.xml.parsers,"
-				+ " org.xml.sax.helpers," + " org.osgi.framework," + " org.eclipse.osgi.util,"
-				+ " org.osgi.util.tracker, " + "org.osgi.service.component, "
-				+ "org.osgi.service.cm");
-		assertNotPresent(h.getExports(), "org.eclipse.equinox.ds.parser, "
-				+ "org.eclipse.equinox.ds.tracker, " + "org.eclipse.equinox.ds, "
-				+ "org.eclipse.equinox.ds.instance, " + "org.eclipse.equinox.ds.model, "
-				+ "org.eclipse.equinox.ds.resolver, " + "org.eclipse.equinox.ds.workqueue");
-		System.out.println(h.getUnreachable());
-	}
-
-	public void testClasspath() throws Exception {
-		Properties base = new Properties();
-		base.put(Analyzer.IMPORT_PACKAGE, "*");
-		base.put(Analyzer.EXPORT_PACKAGE, "*;-noimport:=true");
-		File tmp = new File("jar/ds.jar");
-		File osgi = new File("jar/osgi.jar");
-		Analyzer h = new Analyzer();
-		h.setJar(tmp);
-		h.setProperties(base);
-		h.setClasspath(new File[] { osgi });
-		h.calcManifest().write(System.out);
-		assertEquals("Version from osgi.jar", "[1.2,2)",
-				get(h.getImports(), "org.osgi.service.packageadmin", "version"));
-		assertEquals("Version from osgi.jar", "[1.3,2)",
-				get(h.getImports(), "org.osgi.util.tracker", "version"));
-		assertEquals("Version from osgi.jar", null, get(h.getImports(), "org.xml.sax", "version"));
-
-	}
-
-	/**
-	 * We detect that there are instruction on im/export package headers that
-	 * are never used. This usually indicates a misunderstanding or a change in
-	 * the underlying classpath. These are reflected as warnings. If there is an
-	 * extra import, and it contains no wildcards, then it is treated as a
-	 * wildcard
-	 * 
-	 * @throws IOException
-	 */
-	public void testSuperfluous() throws Exception {
-		Properties base = new Properties();
-		base.put(Analyzer.IMPORT_PACKAGE, "*, com.foo, com.foo.bar.*");
-		base.put(Analyzer.EXPORT_PACKAGE, "*, com.bar");
-		File tmp = new File("jar/ds.jar");
-		Analyzer h = new Analyzer();
-		h.setJar(tmp);
-		h.setProperties(base);
-		h.calcManifest().write(System.out);
-		List<String> warnings = h.getWarnings();
-		assertEquals(warnings.size(), 2);
-		assertEquals("Superfluous export-package instructions: [com.bar]", warnings.get(0));
-		assertEquals("Did not find matching referal for com.foo.bar.*", warnings.get(1));
-		assertTrue(h.getImports().containsKey("com.foo"));
-	}
-
-	void assertNotPresent(Map<String, ?> map, String string) {
-		StringTokenizer st = new StringTokenizer(string, ", ");
-		while (st.hasMoreTokens()) {
-			String packageName = st.nextToken();
-			assertFalse("Must not contain package " + packageName, map.containsKey(packageName));
-		}
-	}
-
-	void assertPresent(Map<String, ?> map, String string) {
-		StringTokenizer st = new StringTokenizer(string, ", ");
-		while (st.hasMoreTokens()) {
-			String packageName = st.nextToken();
-			assertTrue("Must contain package " + packageName, map.containsKey(packageName));
-		}
-	}
-
-	String get(Map<String, Map<String, String>> headers, String packageName, String attr) {
-		Map<String, String> clauses = headers.get(packageName);
-		if (clauses == null)
-			return null;
-		return (String) clauses.get(attr);
-	}
-}
diff --git a/biz.aQute.bndlib/src/test/AnnotationsTest.java b/biz.aQute.bndlib/src/test/AnnotationsTest.java
deleted file mode 100644
index 1a4bc97..0000000
--- a/biz.aQute.bndlib/src/test/AnnotationsTest.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package test;
-
-import java.io.*;
-import java.util.*;
-
-import junit.framework.*;
-
-import org.osgi.service.log.*;
-import org.osgi.service.packageadmin.*;
-
-import aQute.bnd.annotation.component.*;
-import aQute.bnd.make.component.*;
-import aQute.lib.osgi.*;
-
-public class AnnotationsTest extends TestCase {
-    
-    @Component(name="mycomp", enabled=true, factory="abc", immediate=false, provide=LogService.class, servicefactory=true)
-    static class MyComponent implements Serializable {        
-        private static final long serialVersionUID = 1L;
-        LogService log;
-        
-        @Activate
-        protected void activatex() {            
-        }
-        @Deactivate
-        protected void deactivatex() {            
-        }
-        @Modified
-        protected void modifiedx() {            
-        }
-        
-        @Reference(type='~',target="(abc=3)")
-        protected void setLog(LogService log) {
-            this.log = log;
-        }
-        
-        @Reference(type='1')
-        protected void setPackageAdmin(PackageAdmin pa) {
-        }
-        
-        protected void unsetLog(LogService log) {
-            this.log = null;
-        }
-    }
-    
-    public void testComponentReader() throws Exception {
-        File f = new File("bin/test/AnnotationsTest$MyComponent.class");
-        Clazz c = new Clazz("test.AnnotationsTest.MyComponent", new FileResource(f));
-        Map<String,String> map = ComponentAnnotationReader.getDefinition(c);
-        System.out.println(map);
-        assertEquals("mycomp", map.get("name:"));
-        assertEquals( "true", map.get("servicefactory:"));
-        assertEquals("activatex", map.get("activate:"));
-        assertEquals("deactivatex", map.get("deactivate:"));
-        assertEquals("modifiedx", map.get("modified:"));
-              assertEquals("org.osgi.service.log.LogService(abc=3)~", map.get("log/setLog"));
-        assertEquals("org.osgi.service.packageadmin.PackageAdmin", map.get("packageAdmin/setPackageAdmin"));
-    }
-    
-    public void testSimple() throws Exception {
-        Clazz clazz = new Clazz("", null);
-        ClassDataCollector cd = new ClassDataCollector() {
-            public void addReference(String token) {
-            }
-
-            public void annotation(Annotation annotation) {
-                System.out.println("Annotation " + annotation);
-            }
-
-            public void classBegin(int access, String name) {
-                System.out.println("Class " + name);
-            }
-
-            public void classEnd() {
-                System.out.println("Class end ");
-            }
-
-            public void extendsClass(String name) {
-                System.out.println("extends " + name);                
-            }
-
-            public void implementsInterfaces(String[] name) {
-                System.out.println("implements " + Arrays.toString(name));
-                
-            }
-
-            public void constructor(int access, String descriptor) {
-                System.out.println("constructor " + descriptor);
-            }
-
-            public void method(int access, String name, String descriptor) {
-                System.out.println("method " + name + descriptor);
-            }
-
-            public void parameter(int p) {
-                System.out.println("parameter " + p);
-            }
-            
-        };
-        
-        clazz.parseClassFile(getClass().getResourceAsStream("Target.class"), cd);
-    }
-}
-
- at Component
-class Target implements Serializable {
-    private static final long serialVersionUID = 1L;
-    
-    @Activate
-    void activate() {
-        
-    }
-    @Deactivate
-    void deactivate() {
-        
-    }
-    
-    @Modified
-    void modified() {
-        
-    }
-    
-    @Reference
-    void setLog(LogService log) {
-        
-    }
-
-    void unsetLog(LogService log) {
-        
-    }
-}
diff --git a/biz.aQute.bndlib/src/test/AttributesTest.java b/biz.aQute.bndlib/src/test/AttributesTest.java
deleted file mode 100644
index b5acc05..0000000
--- a/biz.aQute.bndlib/src/test/AttributesTest.java
+++ /dev/null
@@ -1,139 +0,0 @@
-package test;
-
-import java.io.*;
-import java.util.*;
-import java.util.jar.*;
-
-import junit.framework.*;
-import aQute.lib.osgi.*;
-
-public class AttributesTest extends TestCase {
-
-	/**
-	 * Remove a version attribute 
-	 * 
-	 * A mandatory attribute adds the common and tst properties to the
-	 * import. We remove them using remove:=*
-	 * @throws Exception
-	 */
-	public void testRemoveDirective() throws Exception {
-		Jar javax  = new Jar("test");
-		Manifest m = new Manifest();
-		m.getMainAttributes().putValue("Export-Package", "javax.microedition.io;a1=exp-1;a2=exp-2;a3=exp-3;x1=x1;x2=x2;x3=x3;mandatory:=\"a1,a2,a3,x1,x2,x3\"");
-		javax.setManifest(m);
-		
-		Jar cp[] = { javax, new Jar(new File("jar/osgi.jar")) };
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.put("Import-Package", "javax.microedition.io;-remove-attribute:=a1|x?;a2=imp-2,*");
-		p.put("Export-Package", "org.osgi.service.io");
-		bmaker.setClasspath(cp);
-		bmaker.setProperties(p);
-		Jar jar = bmaker.build();
-		// System.out.println(bmaker.getExports());
-		System.out.println("Warnings: " + bmaker.getWarnings());
-		System.out.println("Errors  : " + bmaker.getErrors());
-		jar.getManifest().write(System.out);
-		Manifest manifest = jar.getManifest();
-		Attributes main = manifest.getMainAttributes();
-		String imprt = main.getValue("Import-Package");
-		assertNotNull("Import package header", imprt );
-		Map<String,Map<String,String>> map = Processor.parseHeader(imprt, null);
-		Map<String,String> attrs = map.get("javax.microedition.io");
-		assertNotNull(attrs);
-		assertNull(attrs.get("a1"));
-		assertNull(attrs.get("x1"));
-		assertNull(attrs.get("x2"));
-		assertNull(attrs.get("x3"));
-		assertEquals("imp-2", attrs.get("a2"));
-		assertEquals("exp-3", attrs.get("a3"));
-	}
-
-	/**
-	 * Remove a version attribute 
-	 * 
-	 * @throws Exception
-	 */
-	public void testRemoveAttribute() throws Exception {
-		Jar javax  = new Jar("test");
-		Manifest m = new Manifest();
-		m.getMainAttributes().putValue("Export-Package", "javax.microedition.io;common=split;test=abc;mandatory:=\"common,test\"");
-		javax.setManifest(m);
-		
-		Jar cp[] = { javax, new Jar(new File("jar/osgi.jar")) };
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.put("Import-Package", "javax.microedition.io;common=!;test=abc,*");
-		p.put("Export-Package", "org.osgi.service.io");
-		bmaker.setClasspath(cp);
-		bmaker.setProperties(p);
-		Jar jar = bmaker.build();
-		System.out.println(jar.getResources());
-		// System.out.println(bmaker.getExports());
-		System.out.println("Warnings: " + bmaker.getWarnings());
-		System.out.println("Errors  : " + bmaker.getErrors());
-		jar.getManifest().write(System.out);
-		Manifest manifest = jar.getManifest();
-		Attributes main = manifest.getMainAttributes();
-		String imprt = main.getValue("Import-Package");
-		assertNotNull("Import package header", imprt );
-		Map<String,Map<String,String>> map = Processor.parseHeader(imprt, null);
-		Map<String,String> attrs = map.get("javax.microedition.io");
-		assertNotNull(attrs);
-		assertNull(attrs.get("common"));
-	}
-	
-	/**
-	 * Override a version attribute 
-	 * 
-	 * @throws Exception
-	 */
-	public void testOverrideAttribute() throws Exception {
-		File cp[] = { new File("jar/osgi.jar") };
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.put("Export-Package", "org.osgi.framework;version=1.1");
-		bmaker.setClasspath(cp);
-		bmaker.setProperties(p);
-		Jar jar = bmaker.build();
-		System.out.println(jar.getResources());
-		// System.out.println(bmaker.getExports());
-		System.out.println("Warnings: " + bmaker.getWarnings());
-		System.out.println("Errors  : " + bmaker.getErrors());
-		jar.getManifest().write(System.out);
-		Manifest manifest = jar.getManifest();
-		Attributes main = manifest.getMainAttributes();
-		String export = main.getValue("Export-Package");
-		assertNotNull("Export package header", export );
-		Map<String,Map<String,String>> map = Processor.parseHeader(export, null);
-		assertEquals( "1.1", map.get("org.osgi.framework").get("version"));
-	}
-
-	
-	/**
-	 * See if we inherit the version from the osgi.jar file.
-	 * 
-	 * @throws Exception
-	 */
-	public void testSimple() throws Exception {
-		File cp[] = { new File("jar/osgi.jar") };
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.put("Export-Package", "org.osgi.framework");
-		bmaker.setClasspath(cp);
-		bmaker.setProperties(p);
-		Jar jar = bmaker.build();
-		System.out.println(jar.getResources());
-		// System.out.println(bmaker.getExports());
-		System.out.println("Warnings: " + bmaker.getWarnings());
-		System.out.println("Errors  : " + bmaker.getErrors());
-		jar.getManifest().write(System.out);
-		Manifest manifest = jar.getManifest();
-		Attributes main = manifest.getMainAttributes();
-		String export = main.getValue("Export-Package");
-		assertNotNull("Export package header", export );
-		Map<String,Map<String,String>> map = Processor.parseHeader(export, null);
-		assertEquals( "1.3", map.get("org.osgi.framework").get("version"));
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/test/BuilderTest.java b/biz.aQute.bndlib/src/test/BuilderTest.java
deleted file mode 100755
index df262ce..0000000
--- a/biz.aQute.bndlib/src/test/BuilderTest.java
+++ /dev/null
@@ -1,1648 +0,0 @@
-package test;
-
-import java.io.*;
-import java.util.*;
-import java.util.jar.*;
-
-import javax.print.attribute.standard.MediaSize.*;
-
-import aQute.bnd.test.*;
-import aQute.lib.osgi.*;
-import aQute.libg.header.*;
-
-public class BuilderTest extends BndTestCase {
-
-	/**
-	 * Test the name section
-	 */
-	
-	public void testNamesection() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath( new File("jar/osgi.jar"));
-		b.setProperty(Constants.NAMESECTION, "org/osgi/service/event/*;MD5='${md5;${@}}';SHA1='${sha1;${@}}';MD5H='${md5;${@};hex}'");
-		b.setProperty(Constants.PRIVATE_PACKAGE, "org.osgi.service.event");
-		Jar build = b.build();
-		assertOk(b);
-		build.calcChecksums(new String[]{"MD5","SHA1"});
-		Manifest m = build.getManifest();
-		m.write(System.out);
-		
-		assertNotNull(m.getAttributes("org/osgi/service/event/EventAdmin.class").getValue("MD5"));
-		assertNotNull(m.getAttributes("org/osgi/service/event/EventAdmin.class").getValue("SHA1"));
-		assertEquals( m.getAttributes("org/osgi/service/event/EventAdmin.class").getValue("MD5-Digest"),  m.getAttributes("org/osgi/service/event/EventAdmin.class").getValue("MD5"));
-		
-	}
-	
-
-	/**
-	 * Check of the use of x- directives are not skipped. bnd allows x-
-	 * directives in the import/export clauses but strips other ones.
-	 * @throws Exception 
-	 */
-	public void testXDirectives() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath( new File("jar/osgi.jar"));
-		b.setProperty("Export-Package", "org.osgi.framework;x-foo:=true;bar:=false");
-		Jar jar = b.build();
-		Manifest m = jar.getManifest();
-		String s = m.getMainAttributes().getValue("Export-Package");
-		assertTrue( s.contains("x-foo:"));
-		assertEquals( 1, b.getWarnings().size());
-		assertTrue( b.getWarnings().get(0).contains("bar:"));
-	}
-
-	/**
-	 * Check of SNAPSHOT is replaced with the -snapshot instr
-	 * @throws Exception 
-	 */
-	public void testSnapshot() throws Exception {
-		Builder b = new Builder();
-		b.setProperty("-resourceonly", "true");
-		b.setProperty("-snapshot", "TIMESTAMP");
-		b.setProperty("Bundle-Version", "1.0-SNAPSHOT");
-		Jar jar = b.build();
-		Manifest m = jar.getManifest();
-		assertEquals("1.0.0.TIMESTAMP",m.getMainAttributes().getValue("Bundle-Version"));
-	}
-
-	/**
-	 * Check if do not copy works on files
-	 */
-
-	public void testDoNotCopy() throws Exception {
-		Builder b = new Builder();
-		b.setProperty("-resourceonly", "true");
-		b.setProperty("-donotcopy", ".*\\.jar|\\..*");
-		b.setProperty("Include-Resource", "jar");
-		b.build();
-		System.out.println(Processor.join(b.getErrors(), "\n"));
-		System.out.println(Processor.join(b.getWarnings(), "\n"));
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		Set<String> names = b.getJar().getResources().keySet();
-		assertEquals(6, names.size());
-		assertTrue(names.contains("AnnotationWithJSR14.jclass"));
-		assertTrue(names.contains("mandatorynoversion.bnd"));
-		assertTrue(names.contains("mina.bar"));
-		assertTrue(names.contains("minax.bnd"));
-		assertTrue(names.contains("rox.bnd"));
-		assertTrue(names.contains("WithAnnotations.jclass"));
-	}
-	/**
-	 * Check if do not copy works on files
-	 */
-
-	public void testDoNotCopyDS() throws Exception {
-		Builder b = new Builder();
-		b.setProperty("-resourceonly", "true");
-		b.setProperty("Include-Resource", "jar/");
-		b.build();
-		System.out.println(Processor.join(b.getErrors(), "\n"));
-		System.out.println(Processor.join(b.getWarnings(), "\n"));
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		Set<String> names = b.getJar().getResources().keySet();
-		assertFalse(names.contains(".DS_Store"));
-	}
-
-	/**
-	 * No error is generated when a file is not found.
-	 * 
-	 */
-
-	public void testFileNotFound() throws Exception {
-		Builder b = new Builder();
-		b.setPedantic(true);
-		b.setProperty("-classpath", "xyz.jar");
-		b.setProperty("Include-Resource", "lib=lib, jar/osgi.jar");
-		b.setProperty("-resourceonly", "true");
-		b.build();
-		System.out.println(Processor.join(b.getErrors(), "\n"));
-		System.out.println("xx");
-		System.out.println(Processor.join(b.getWarnings(), "\n"));
-		assertEquals(1, b.getErrors().size());
-		assertEquals(1, b.getWarnings().size());
-	}
-
-	/**
-	 * bnd seems to pick the wrong version if a packageinfo is available
-	 * multiple times.
-	 * 
-	 * @throws Exception
-	 */
-
-	public void testMultiplePackageInfo() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("jar/osgi.jar"));
-		b.addClasspath(new File("jar/osgi.core.jar"));
-		b.setProperty(Constants.PRIVATE_PACKAGE, "org.osgi.service.packageadmin");
-		b.build();
-		String version = b.getImports().get("org.osgi.framework").get(Constants.VERSION_ATTRIBUTE);
-		assertEquals("[1.3,2)", version);
-	}
-
-	/**
-	 * Test the from: directive on expanding packages.
-	 */
-	public void testFromOSGiDirective() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("jar/osgi.jar"));
-		b.addClasspath(new File("jar/org.eclipse.osgi-3.5.0.jar"));
-		b.setProperty("Export-Package", "org.osgi.framework;from:=osgi");
-		b.build();
-		System.out.println(Processor.join(b.getErrors(), "\n"));
-		System.out.println(Processor.join(b.getWarnings(), "\n"));
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		assertEquals("1.3", b.getExports().get("org.osgi.framework").get("version"));
-	}
-
-	public void testFromEclipseDirective() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("jar/osgi.jar"));
-		b.addClasspath(new File("jar/org.eclipse.osgi-3.5.0.jar"));
-		b.setProperty("Export-Package", "org.osgi.framework;from:=org.eclipse.osgi-3.5.0");
-		b.build();
-		System.out.println(Processor.join(b.getErrors(), "\n"));
-		System.out.println(Processor.join(b.getWarnings(), "\n"));
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		assertEquals("1.3", b.getExports().get("org.osgi.framework").get("version"));
-	}
-
-	/**
-	 * Test the provide package
-	 */
-	public void testProvidedVersion() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("jar/osgi.jar"));
-		b.addClasspath(new File("bin"));
-		b.setProperty(Constants.EXPORT_PACKAGE, "org.osgi.service.event;provide:=true");
-		b.setProperty("Private-Package", "test.refer");
-		Jar jar = b.build();
-		String ip = jar.getManifest().getMainAttributes().getValue(Constants.IMPORT_PACKAGE);
-		Map<String, Map<String, String>> map = Processor.parseHeader(ip, null);
-		assertEquals("[1.0,1.1)", map.get("org.osgi.service.event").get("version"));
-
-	}
-
-	public void testUnProvidedVersion() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("jar/osgi.jar"));
-		b.addClasspath(new File("bin"));
-		b.setProperty(Constants.EXPORT_PACKAGE, "org.osgi.service.event;provide:=false");
-		b.setProperty("Private-Package", "test.refer");
-		Jar jar = b.build();
-		String ip = jar.getManifest().getMainAttributes().getValue(Constants.IMPORT_PACKAGE);
-		Map<String, Map<String, String>> map = Processor.parseHeader(ip, null);
-		assertEquals("[1.0,2)", map.get("org.osgi.service.event").get("version"));
-	}
-
-	/**
-	 * Complaint that exported versions were not picked up from external bundle.
-	 */
-
-	public void testExportedVersionsNotPickedUp() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("jar/jsr311-api-1.1.1.jar"));
-		b.setProperty("Export-Package", "javax.ws.rs.core");
-		Jar jar = b.build();
-		String ip = jar.getManifest().getMainAttributes().getValue(Constants.EXPORT_PACKAGE);
-		Map<String, Map<String, String>> map = Processor.parseHeader(ip, null);
-		assertEquals("1.1.1", map.get("javax.ws.rs.core").get("version"));
-	}
-
-	/**
-	 * Test where the version comes from: Manifest or packageinfo
-	 * 
-	 * @throws Exception
-	 */
-	public void testExportVersionSource() throws Exception {
-		Manifest manifest = new Manifest();
-		manifest.getMainAttributes().putValue("Export-Package",
-				"org.osgi.service.event;version=100");
-
-		// Remove packageinfo
-		Jar manifestOnly = new Jar(new File("jar/osgi.jar"));
-		manifestOnly.remove("org/osgi/service/event/packageinfo");
-		manifestOnly.setManifest(manifest);
-
-		// Remove manifest
-		Jar packageInfoOnly = new Jar(new File("jar/osgi.jar"));
-		packageInfoOnly.setManifest(new Manifest());
-
-		Jar both = new Jar(new File("jar/osgi.jar"));
-		both.setManifest(manifest);
-
-		// Only version in manifest
-		Builder bms = new Builder();
-		bms.addClasspath(manifestOnly);
-		bms.setProperty("Export-Package", "org.osgi.service.event");
-		bms.build();
-		String s = bms.getExports().get("org.osgi.service.event").get("version");
-		assertEquals("100", s);
-
-		// Only version in packageinfo
-		Builder bpinfos = new Builder();
-		bpinfos.addClasspath(packageInfoOnly);
-		bpinfos.setProperty("Export-Package", "org.osgi.service.event");
-		bpinfos.build();
-		s = bpinfos.getExports().get("org.osgi.service.event").get("version");
-		assertEquals("1.0.1", s);
-
-		// // Version in manifest + packageinfo
-		// Builder bboth = new Builder();
-		// bboth.addClasspath(both);
-		// bboth.setProperty("Export-Package", "org.osgi.service.event");
-		// bboth.build();
-		// s = bboth.getExports().get("org.osgi.service.event").get("version");
-		// assertEquals("100", s);
-	}
-
-	/**
-	 * Test where the version comes from: Manifest or packageinfo
-	 * 
-	 * @throws Exception
-	 */
-	public void testImportVersionSource() throws Exception {
-		Jar ms = new Jar("manifestsource");
-		Jar pinfos = new Jar("packageinfosource");
-		Jar both = new Jar("both");
-
-		Manifest mms = new Manifest();
-		mms.getMainAttributes().putValue("Export-Package", "org.osgi.service.event; version=100");
-		ms.setManifest(mms);
-
-		pinfos.putResource("org/osgi/service/event/packageinfo",
-				new EmbeddedResource("version 99".getBytes(), 0));
-
-		Manifest mboth = new Manifest();
-		mboth.getMainAttributes().putValue("Export-Package", "org.osgi.service.event; version=100");
-		both.putResource("org/osgi/service/event/packageinfo",
-				new EmbeddedResource("version 99".getBytes(), 0));
-		both.setManifest(mboth);
-
-		// Only version in manifest
-		Builder bms = new Builder();
-		bms.addClasspath(ms);
-		bms.setProperty("Import-Package", "org.osgi.service.event");
-		bms.build();
-		String s = bms.getImports().get("org.osgi.service.event").get("version");
-		assertEquals("[100.0,101)", s);
-
-		// Only version in packageinfo
-		Builder bpinfos = new Builder();
-		bpinfos.addClasspath(pinfos);
-		bpinfos.setProperty("Import-Package", "org.osgi.service.event");
-		bpinfos.build();
-		s = bpinfos.getImports().get("org.osgi.service.event").get("version");
-		assertEquals("[99.0,100)", s);
-
-		// Version in manifest + packageinfo
-		Builder bboth = new Builder();
-		bboth.addClasspath(both);
-		bboth.setProperty("Import-Package", "org.osgi.service.event");
-		bboth.build();
-		s = bboth.getImports().get("org.osgi.service.event").get("version");
-		assertEquals("[100.0,101)", s);
-
-	}
-
-	public void testNoImportDirective() throws Exception {
-		Builder b = new Builder();
-		b.setProperty("Export-Package",
-				"org.osgi.util.measurement, org.osgi.service.http;-noimport:=true");
-		b.setProperty("Private-Package", "org.osgi.framework, test.refer");
-		b.addClasspath(new File("jar/osgi.jar"));
-		b.addClasspath(new File("bin"));
-		Jar jar = b.build();
-		Manifest m = jar.getManifest();
-		String imports = m.getMainAttributes().getValue("Import-Package");
-		assertTrue(imports.contains("org.osgi.util.measurement")); // referred
-																	// to but no
-																	// private
-																	// references
-																	// (does not
-																	// use fw).
-		assertFalse(imports.contains("org.osgi.service.http")); // referred to
-																// but no
-																// private
-																// references
-																// (does not use
-																// fw).
-
-	}
-
-	public void testNoImportDirective2() throws Exception {
-		Builder b = new Builder();
-		b.setProperty("Export-Package",
-				"org.osgi.util.measurement;-noimport:=true, org.osgi.service.http");
-		b.setProperty("Private-Package", "org.osgi.framework, test.refer");
-		b.addClasspath(new File("jar/osgi.jar"));
-		b.addClasspath(new File("bin"));
-		Jar jar = b.build();
-		Manifest m = jar.getManifest();
-		String imports = m.getMainAttributes().getValue("Import-Package");
-		assertFalse(imports.contains("org.osgi.util.measurement")); // referred
-																	// to but no
-																	// private
-																	// references
-																	// (does not
-																	// use fw).
-		assertTrue(imports.contains("org.osgi.service.http")); // referred to
-																// but no
-																// private
-																// references
-																// (does not use
-																// fw).
-
-	}
-
-	public void testAutoNoImport() throws Exception {
-		Builder b = new Builder();
-		b.setProperty(
-				"Export-Package",
-				"org.osgi.service.event, org.osgi.service.packageadmin, org.osgi.util.measurement, org.osgi.service.http;-noimport:=true");
-		b.setProperty("Private-Package", "org.osgi.framework, test.refer");
-		b.addClasspath(new File("jar/osgi.jar"));
-		b.addClasspath(new File("bin"));
-		Jar jar = b.build();
-		Manifest m = jar.getManifest();
-		String imports = m.getMainAttributes().getValue("Import-Package");
-		assertFalse(imports.contains("org.osgi.service.packageadmin")); // no
-																		// internal
-																		// references
-		assertFalse(imports.contains("org.osgi.util.event")); // refers to
-																// private
-																// framework
-		assertTrue(imports.contains("org.osgi.util.measurement")); // referred
-																	// to but no
-																	// private
-																	// references
-																	// (does not
-																	// use fw).
-		assertFalse(imports.contains("org.osgi.service.http")); // referred to
-																// but no
-																// private
-																// references
-																// (does not use
-																// fw).
-	}
-
-	public void testWab() throws Exception {
-		Builder b = new Builder();
-		b.setProperty("-wablib", "jar/asm.jar, jar/easymock.jar");
-		b.setProperty("-wab", "jar/osgi.jar");
-		b.setProperty("-includeresource", "OSGI-INF/xml/x.xml;literal=\"text\"");
-		b.setProperty("Private-Package", "org.osgi.framework");
-		b.addClasspath(new File("jar/osgi.jar"));
-		Jar jar = b.build();
-		diagnose(b);
-
-		Manifest m = jar.getManifest();
-		assertNotNull(m);
-		assertEquals("WEB-INF/classes,WEB-INF/lib/asm.jar,WEB-INF/lib/easymock.jar", m
-				.getMainAttributes().getValue("Bundle-ClassPath"));
-		assertNotNull(jar.getResource("WEB-INF/lib/asm.jar"));
-		assertNotNull(jar.getResource("WEB-INF/classes/org/osgi/framework/BundleContext.class"));
-		assertNotNull(jar.getResource("osgi.jar"));
-		assertNotNull(jar.getResource("OSGI-INF/xml/x.xml"));
-	}
-
-	private void diagnose(Builder b) {
-		System.out.println(Processor.join(b.getErrors(), "\n"));
-		System.out.println(Processor.join(b.getWarnings(), "\n"));
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-	}
-
-	public void testRemoveHeaders() throws Exception {
-		Builder b = new Builder();
-		b.setProperty("Private-Package", "org.osgi.framework");
-		b.setProperty("T1", "1");
-		b.setProperty("T2", "1");
-		b.setProperty("T1_2", "1");
-		b.setProperty("-removeheaders", "!T1_2,T1*");
-		b.addClasspath(new File("jar/osgi.jar"));
-		Jar jar = b.build();
-
-		diagnose(b);
-
-		Manifest m = jar.getManifest();
-		assertNotNull(m);
-		assertEquals("1", m.getMainAttributes().getValue("T2"));
-		assertEquals("1", m.getMainAttributes().getValue("T1_2"));
-		assertEquals(null, m.getMainAttributes().getValue("T1"));
-
-	}
-
-	public void testNoManifest() throws Exception {
-		Builder b = new Builder();
-		b.setProperty("-nomanifest", "true");
-		b.setProperty("Include-Resource", "WEB-INF/classes=@jar/asm.jar");
-		Jar jar = b.build();
-		diagnose(b);
-
-		File f = new File("tmp.jar");
-		f.deleteOnExit();
-		jar.write(f);
-
-		JarInputStream jin = new JarInputStream(new FileInputStream(f));
-		Manifest m = jin.getManifest();
-		assertNull(m);
-
-	}
-
-	public void testClassesonNoBCP() throws Exception {
-		Builder b = new Builder();
-		b.setProperty("-resourceonly", "true");
-		b.setProperty("Include-Resource", "WEB-INF/classes=@jar/asm.jar");
-		b.setProperty("-nomanifest", "true");
-		b.build();
-		diagnose(b);
-	}
-
-	public void testClassesonBCP() throws Exception {
-		Builder b = new Builder();
-		b.setProperty("-resourceonly", "true");
-		b.setProperty("Include-Resource", "WEB-INF/classes=@jar/asm.jar");
-		b.setProperty("Bundle-ClassPath", "WEB-INF/classes");
-		b.build();
-		diagnose(b);
-	}
-
-	public void testInScopeExport() throws Exception {
-		Builder b = new Builder();
-		b.setProperty("Export-Package", "aQute.bnd.*");
-		b.addClasspath(new File("bin"));
-		List<File> project = Arrays.asList(b.getFile("bin/aQute/bnd/build/Project.class"));
-		assertTrue(b.isInScope(project));
-		List<File> nonexistent = Arrays.asList(b.getFile("bin/aQute/bnd/build/Abc.xyz"));
-		assertTrue(b.isInScope(nonexistent));
-		List<File> outside = Arrays.asList(b.getFile("bin/test/AnalyzerTest.class"));
-		assertFalse(b.isInScope(outside));
-	}
-
-	public void testInScopePrivate() throws Exception {
-		Builder b = new Builder();
-		b.setProperty("Private-Package", "!aQute.bnd.build,aQute.bnd.*");
-		b.addClasspath(new File("bin"));
-		List<File> project = Arrays.asList(b.getFile("bin/aQute/bnd/build/Project.class"));
-		assertFalse(b.isInScope(project));
-		List<File> nonexistent = Arrays.asList(b.getFile("bin/aQute/bnd/acb/Def.xyz"));
-		assertTrue(b.isInScope(nonexistent));
-		List<File> outside = Arrays.asList(b.getFile("bin/test/AnalyzerTest.class"));
-		assertFalse(b.isInScope(outside));
-	}
-
-	public void testExtra() throws Exception {
-		Builder b = new Builder();
-		b.setProperty("Include-Resource",
-				"jar/osgi.jar;extra=itworks, www/xyz.jar=jar/osgi.jar;extra='italsoworks'");
-		b.setProperty("-resourceonly", "true");
-		Jar jar = b.build();
-		Resource r = jar.getResource("osgi.jar");
-		assertNotNull(r);
-		assertEquals("itworks", r.getExtra());
-		Resource r2 = jar.getResource("www/xyz.jar");
-		assertNotNull(r2);
-		assertEquals("italsoworks", r2.getExtra());
-	}
-
-	/**
-	 * Create a jar with something in the default package.
-	 */
-
-	public void testIncludeDefaultPackage() {
-		Builder b = new Builder();
-		b.setProperty("Private-Package", ".");
-	}
-
-	/**
-	 * Got a split package warning during verify when private overlaps with
-	 * export
-	 */
-	public void testSplitWhenPrivateOverlapsExport() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("jar/osgi.jar"));
-		b.setProperty("Private-Package", "org.osgi.service.*");
-		b.setProperty("Export-Package", "org.osgi.service.event");
-		b.build();
-		ok(b);
-	}
-
-	static void ok(Processor p) {
-		System.out.println("Errors  " + p.getErrors());
-		System.out.println("Warnings  " + p.getWarnings());
-		assertEquals(0, p.getErrors().size());
-		assertEquals(0, p.getWarnings().size());
-	}
-
-	public void testMacroBasedExpansion() throws Exception {
-		Processor proc = new Processor();
-
-		Builder builder = new Builder(proc);
-		builder.setProperty("Export-Package", "${spec.packages}");
-		proc.setProperty("spec.packages", "${core.packages}, ${cmpn.packages}, ${mobile.packages}");
-		proc.setProperty("core.specs",
-				"org.osgi.service.packageadmin, org.osgi.service.permissionadmin");
-		proc.setProperty("core.packages", "${replace;${core.specs};.+;$0.*}");
-		proc.setProperty("cmpn.specs", "org.osgi.service.event, org.osgi.service.cu");
-		proc.setProperty("cmpn.packages", "${replace;${cmpn.specs};.+;$0.*}");
-		proc.setProperty("mobile.specs",
-				"org.osgi.service.wireadmin, org.osgi.service.log, org.osgi.service.cu");
-		proc.setProperty("mobile.packages", "${replace;${mobile.specs};.+;$0.*}");
-		builder.addClasspath(new File("jar/osgi.jar"));
-
-		Jar jar = builder.build();
-
-		System.out.println("Warnings: " + builder.getWarnings());
-		System.out.println("Errors  : " + builder.getErrors());
-		assertEquals(1, builder.getErrors().size());
-		assertEquals(0, builder.getWarnings().size());
-		assertTrue(builder.getErrors().get(0).contains("service.cu.*"));
-		Manifest m = jar.getManifest();
-		String exports = m.getMainAttributes().getValue("Export-Package");
-		System.out.println(exports);
-		assertTrue(exports.contains("*"));
-	}
-
-	/**
-	 * Make resolution dependent on the fact that a package is on the classpath
-	 * or not
-	 */
-
-	public void testConditionalResolution() throws Exception {
-		Builder b = new Builder();
-		b.setProperty("res", "${if;${exporters;${@package}};mandatory;optional}");
-		b.setProperty("Import-Package", "*;resolution:=\\${res}");
-		b.setProperty("Export-Package", "org.osgi.service.io, org.osgi.service.log");
-		b.addClasspath(new File("jar/osgi.jar"));
-		b.build();
-
-		Map<String, String> ioimports = b.getImports().get("javax.microedition.io");
-		Map<String, String> fwimports = b.getImports().get("org.osgi.framework");
-
-		assertNotNull(ioimports);
-		assertNotNull(fwimports);
-		assertTrue(ioimports.containsKey("resolution:"));
-		assertTrue(fwimports.containsKey("resolution:"));
-		assertEquals("optional", ioimports.get("resolution:"));
-		assertEquals("mandatory", fwimports.get("resolution:"));
-	}
-
-	/**
-	 * Test private imports. We first build a jar with a import:=private packge.
-	 * Then place it
-	 * 
-	 * @throws Exception
-	 */
-
-	// public void testPrivateImport() throws Exception {
-	// Builder b = new Builder();
-	// b.addClasspath(new File("jar/osgi.jar"));
-	// b
-	// .setProperty("Export-Package",
-	// "org.osgi.service.cm;-import:=private,
-	// org.osgi.framework;-import:=private");
-	// Jar osgi = b.build();
-	// assertTrue(osgi.hasDirectory("org/osgi/framework"));
-	// assertTrue(osgi.hasDirectory("org/osgi/service/cm"));
-	// System.out.println("export " +
-	// b.getExports().get("org.osgi.service.cm"));
-	// assertTrue(b.getExports().get("org.osgi.service.cm").containsKey(Constants.IMPORT_DIRECTIVE));
-	// assertTrue(b.getExports().get("org.osgi.framework").containsKey(Constants.IMPORT_DIRECTIVE));
-	//
-	// Builder c = new Builder();
-	// c.addClasspath(osgi);
-	// c.addClasspath(new File("bin"));
-	// c.setProperty("Private-Package", "test.privateimport");
-	// Jar pi = c.build();
-	//
-	// assertTrue(pi.getDirectories().containsKey("org/osgi/framework"));
-	// assertTrue(pi.getDirectories().containsKey("org/osgi/service/cm"));
-	// assertEquals("no error", 0, b.getErrors().size());
-	// assertEquals("no error", 0, c.getErrors().size());
-	// assertEquals("no warning", 0, b.getWarnings().size());
-	// assertEquals("no warning", 0, c.getWarnings().size());
-	// }
-	public void testClassnames() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("jar/osgi.jar"));
-		b.addClasspath(new File("jar/ds.jar"));
-		b.addClasspath(new File("jar/ifc112.jar"));
-		b.setProperty("Export-Package", "*");
-		b.setProperty("C1", "${classes;implementing;org.osgi.service.component.*}");
-		b.setProperty("C2", "${classes;extending;org.xml.sax.helpers.*}");
-		b.setProperty("C3", "${classes;importing;org.xml.sax}");
-		b.setProperty("C3", "${classes;importing;org.xml.sax}");
-		b.setProperty("C4", "${classes;named;*Parser*}");
-		b.setProperty("C5", "${classes;named;*Parser*;version;45.*}");
-		Jar jar = b.build();
-		Manifest m = jar.getManifest();
-		Attributes main = m.getMainAttributes();
-		assertList(
-				asl("org.eclipse.equinox.ds.service.ComponentContextImpl,org.eclipse.equinox.ds.service.ComponentFactoryImpl,org.eclipse.equinox.ds.service.ComponentInstanceImpl"),
-				asl(main.getValue("C1")));
-		assertList(asl("org.eclipse.equinox.ds.parser.ElementHandler, "
-				+ "org.eclipse.equinox.ds.parser.IgnoredElement,"
-				+ "org.eclipse.equinox.ds.parser.ImplementationElement,"
-				+ "org.eclipse.equinox.ds.parser.ParserHandler, "
-				+ "org.eclipse.equinox.ds.parser.PropertiesElement,"
-				+ "org.eclipse.equinox.ds.parser.PropertyElement, "
-				+ "org.eclipse.equinox.ds.parser.ProvideElement, "
-				+ "org.eclipse.equinox.ds.parser.ReferenceElement, "
-				+ "org.eclipse.equinox.ds.parser.ServiceElement,"
-				+ "org.eclipse.equinox.ds.parser.ComponentElement"), asl(main.getValue("C2")));
-		assertList(
-				asl("org.eclipse.equinox.ds.parser.ComponentElement,org.eclipse.equinox.ds.parser.ElementHandler,org.eclipse.equinox.ds.parser.IgnoredElement,org.eclipse.equinox.ds.parser.ImplementationElement,org.eclipse.equinox.ds.parser.Parser,org.eclipse.equinox.ds.parser.ParserHandler,org.eclipse.equinox.ds.parser.PropertiesElement,org.eclipse.equinox.ds.parser.PropertyElement,org.eclipse.equinox.ds.parser.ProvideElement,org.eclipse.equinox.ds.parser.ReferenceElement,org.eclipse.equinox.ds.pars [...]
-				asl(main.getValue("C3")));
-		assertList(
-				asl("org.eclipse.equinox.ds.parser.XMLParserNotAvailableException,org.eclipse.equinox.ds.parser.Parser,org.eclipse.equinox.ds.parser.ParserHandler,netscape.application.HTMLParser,org.eclipse.equinox.ds.parser.ParserConstants,org.osgi.util.xml.XMLParserActivator"),
-				asl(main.getValue("C4")));
-		assertEquals("netscape.application.HTMLParser", main.getValue("C5"));
-	}
-
-	void assertList(Collection<String> a, Collection<String> b) {
-		List<String> onlyInA = new ArrayList<String>();
-		onlyInA.addAll(a);
-		onlyInA.removeAll(b);
-
-		List<String> onlyInB = new ArrayList<String>();
-		onlyInB.addAll(b);
-		onlyInB.removeAll(a);
-
-		if (onlyInA.isEmpty() && onlyInB.isEmpty())
-			return;
-
-		fail("Lists are not equal, only in A: " + onlyInA + ",\n   and only in B: " + onlyInB);
-	}
-
-	Collection<String> asl(String s) {
-		return new TreeSet<String>(Processor.split(s));
-	}
-
-	public void testImportMicroNotTruncated() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("jar/osgi.jar"));
-		b.setProperty("Import-Package", "org.osgi.service.event;version=${@}");
-		b.build();
-		String s = b.getImports().get("org.osgi.service.event").get("version");
-		assertEquals("1.0.1", s);
-	}
-
-	public void testImportMicroTruncated() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("jar/osgi.jar"));
-		b.setProperty("Import-Package", "org.osgi.service.event");
-		b.build();
-		String s = b.getImports().get("org.osgi.service.event").get("version");
-		assertEquals("[1.0,2)", s);
-	}
-
-	/*
-	 * Bnd must expand the bnd.info file in a package.
-	 */
-	public void testBndInfo() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("bin"));
-		b.setProperty("Export-Package", "test");
-		b.setProperty("a", "aaa");
-		Jar jar = b.build();
-
-		Resource r = jar.getResource("test/bnd.info");
-		Properties bndinfo = new Properties();
-		InputStream in = r.openInputStream();
-		bndinfo.load(in);
-		in.close();
-		assertEquals("aaa", bndinfo.getProperty("a"));
-		assertEquals("${b}", bndinfo.getProperty("b"));
-	}
-
-	public void testMultipleExport2() throws Exception {
-		File cp[] = { new File("jar/asm.jar") };
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.setProperty("Import-Package", "*");
-		p.setProperty("Export-Package",
-				"org.objectweb.asm;version=1.1, org.objectweb.asm~;version=1.2, org.objectweb.asm~~;version=1.3");
-		bmaker.setProperties(p);
-		bmaker.setClasspath(cp);
-		Jar jar = bmaker.build();
-		System.out.println(jar.getResources());
-		// System.out.println(bmaker.getExports());
-		System.out.println("Warnings: " + bmaker.getWarnings());
-		System.out.println("Errors  : " + bmaker.getErrors());
-		jar.getManifest().write(System.out);
-		System.out.println("Warnings " + bmaker.getWarnings());
-		System.out.println("Errors   " + bmaker.getErrors());
-		assertEquals(0, bmaker.getWarnings().size());
-		assertEquals(0, bmaker.getErrors().size());
-		Manifest m = jar.getManifest();
-		String ip = m.getMainAttributes().getValue("Export-Package");
-		assertTrue(ip.indexOf("org.objectweb.asm;version=\"1.1\"") >= 0);
-		assertTrue(ip.indexOf("org.objectweb.asm;version=\"1.2\"") >= 0);
-		assertTrue(ip.indexOf("org.objectweb.asm;version=\"1.3\"") >= 0);
-	}
-
-	public void testBsnAssignmentNoFile() throws Exception {
-		Properties p = new Properties();
-		p.setProperty("Private-Package", "org.objectweb.asm");
-		Attributes m = setup(p, null).getMainAttributes();
-
-		// We use properties so the default BSN is then the project name
-		// because that is the base directory
-		assertEquals(m.getValue("Bundle-SymbolicName"), "biz.aQute.bndlib");
-
-		// The file name for the properties is not bnd.bnd, so the
-		// name of the properties file is the default bsn
-		m = setup(null, new File("src/test/com.acme/defaultbsn.bnd")).getMainAttributes();
-		assertEquals("com.acme.defaultbsn", m.getValue("Bundle-SymbolicName"));
-
-		// If the file is called bnd.bnd, then we take the parent directory
-		m = setup(null, new File("src/test/com.acme/bnd.bnd")).getMainAttributes();
-		assertEquals("com.acme", m.getValue("Bundle-SymbolicName"));
-
-		// If the file is called bnd.bnd, then we take the parent directory
-		m = setup(null, new File("src/test/com.acme/setsbsn.bnd")).getMainAttributes();
-		assertEquals("is.a.set.bsn", m.getValue("Bundle-SymbolicName"));
-
-		// This sets the bsn, se we should see it back
-		p.setProperty("Bundle-SymbolicName", "this.is.my.test");
-		m = setup(p, null).getMainAttributes();
-		assertEquals(m.getValue("Bundle-SymbolicName"), "this.is.my.test");
-	}
-
-	public Manifest setup(Properties p, File f) throws Exception {
-		File cp[] = { new File("jar/asm.jar") };
-		Builder bmaker = new Builder();
-		if (f != null)
-			bmaker.setProperties(f);
-		else
-			bmaker.setProperties(p);
-		bmaker.setClasspath(cp);
-		Jar jar = bmaker.build();
-		System.out.println(jar.getResources());
-		// System.out.println(bmaker.getExports());
-		System.out.println("Warnings: " + bmaker.getWarnings());
-		System.out.println("Errors  : " + bmaker.getErrors());
-		jar.getManifest().write(System.out);
-		assertEquals(0, bmaker.getWarnings().size());
-		assertEquals(0, bmaker.getErrors().size());
-		Manifest m = jar.getManifest();
-		return m;
-	}
-
-	public void testDuplicateExport() throws Exception {
-		File cp[] = { new File("jar/asm.jar") };
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.setProperty("Import-Package", "*");
-		p.setProperty("Export-Package", "org.*;version=1.2,org.objectweb.asm~;version=1.3");
-		bmaker.setProperties(p);
-		bmaker.setClasspath(cp);
-		Jar jar = bmaker.build();
-		System.out.println(jar.getResources());
-		// System.out.println(bmaker.getExports());
-		System.out.println("Warnings: " + bmaker.getWarnings());
-		System.out.println("Errors  : " + bmaker.getErrors());
-		jar.getManifest().write(System.out);
-		assertEquals(0, bmaker.getWarnings().size());
-		assertEquals(0, bmaker.getErrors().size());
-		Manifest m = jar.getManifest();
-		String ip = m.getMainAttributes().getValue("Export-Package");
-		assertTrue(ip.indexOf("org.objectweb.asm;version=\"1.2\"") >= 0);
-	}
-
-	public void testNoExport() throws Exception {
-		File cp[] = { new File("jar/asm.jar") };
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.setProperty("Import-Package", "*");
-		p.setProperty("Export-Package", "org.*'");
-		bmaker.setProperties(p);
-		bmaker.setClasspath(cp);
-		Jar jar = bmaker.build();
-		System.out.println(jar.getResources());
-		// System.out.println(bmaker.getExports());
-		System.out.println("Warnings: " + bmaker.getWarnings());
-		System.out.println("Errors  : " + bmaker.getErrors());
-		jar.getManifest().write(System.out);
-		assertEquals(0, bmaker.getWarnings().size());
-		assertEquals(0, bmaker.getErrors().size());
-		Manifest m = jar.getManifest();
-		String ip = m.getMainAttributes().getValue("Export-Package");
-		assertTrue(ip.indexOf("org.objectweb.asm") >= 0);
-	}
-
-	public void testHardcodedImport() throws Exception {
-		File cp[] = { new File("jar/asm.jar") };
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.setProperty("Import-Package", "whatever,*");
-		p.setProperty("Export-Package", "org.*");
-		bmaker.setProperties(p);
-		bmaker.setClasspath(cp);
-		Jar jar = bmaker.build();
-		System.out.println(jar.getResources());
-		// System.out.println(bmaker.getExports());
-		System.out.println("Warnings: " + bmaker.getWarnings());
-		System.out.println("Errors  : " + bmaker.getErrors());
-		jar.getManifest().write(System.out);
-		assertEquals(0, bmaker.getWarnings().size());
-		assertEquals(0, bmaker.getErrors().size());
-		Manifest m = jar.getManifest();
-		String ip = m.getMainAttributes().getValue("Import-Package");
-		assertTrue(ip.indexOf("whatever") >= 0);
-	}
-
-	public void testCopyDirectory() throws Exception {
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.setProperty("-resourceonly", "true");
-		p.setProperty("Include-Resource", "bnd=bnd");
-		bmaker.setProperties(p);
-		Jar jar = bmaker.build();
-		Map<String, Resource> map = jar.getDirectories().get("bnd");
-		assertNotNull(map);
-		assertEquals(2, map.size());
-		assertEquals(0, bmaker.getErrors().size());
-		assertEquals(0, bmaker.getWarnings().size());
-	}
-
-	/**
-	 * There is an error that gives a split package when you export a package
-	 * that is also private I think.
-	 * 
-	 * @throws Exception
-	 */
-	public void testSplitOnExportAndPrivate() throws Exception {
-		File cp[] = { new File("jar/asm.jar") };
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.setProperty("Export-Package", "org.objectweb.asm.signature");
-		p.setProperty("Private-Package", "org.objectweb.asm");
-		bmaker.setProperties(p);
-		bmaker.setClasspath(cp);
-		bmaker.build();
-		System.out.println("Warnings: " + bmaker.getWarnings());
-		System.out.println("Errors  : " + bmaker.getErrors());
-		assertEquals(0, bmaker.getWarnings().size());
-		assertEquals(0, bmaker.getErrors().size());
-	}
-
-	public void testConduit() throws Exception {
-		Properties p = new Properties();
-		p.setProperty("-conduit", "jar/asm.jar");
-		Builder b = new Builder();
-		b.setProperties(p);
-		Jar jars[] = b.builds();
-		assertNotNull(jars);
-		assertEquals(1, jars.length);
-		assertEquals("ASM",
-				jars[0].getManifest().getMainAttributes().getValue("Implementation-Title"));
-	}
-
-	/**
-	 * Export a package that was loaded with resources
-	 * 
-	 * @throws Exception
-	 */
-	public void testExportSyntheticPackage() throws Exception {
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.setProperty("-resourceonly", "true");
-		p.setProperty("Include-Resource", "resources=jar");
-		p.setProperty("-exportcontents", "resources");
-		bmaker.setProperties(p);
-		Jar jar = bmaker.build();
-		System.out.println(jar.getResources());
-		// System.out.println(bmaker.getExports());
-		System.out.println("Errors  : " + bmaker.getErrors());
-		System.out.println("Warnings  : " + bmaker.getWarnings());
-		assertEquals("Warnings: ", 0, bmaker.getWarnings().size());
-		assertEquals("Errors  : ", 0, bmaker.getErrors().size());
-		Manifest manifest = jar.getManifest();
-		String header = manifest.getMainAttributes().getValue("Export-Package");
-		System.out.println(header);
-		assertTrue(header.indexOf("resources") >= 0);
-	}
-
-	/**
-	 * Exporting packages in META-INF
-	 * 
-	 * @throws Exception
-	 */
-	public void testMETAINF() throws Exception {
-		File cp[] = { new File("src"), new File("jar/asm.jar") };
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.setProperty("Include-Resource", "META-INF/xyz/asm.jar=jar/asm.jar");
-		p.setProperty("Export-Package", "META-INF/xyz, org.*");
-		bmaker.setProperties(p);
-		bmaker.setClasspath(cp);
-		Jar jar = bmaker.build();
-		System.out.println(jar.getResources());
-		// System.out.println(bmaker.getExports());
-		System.out.println("Warnings: " + bmaker.getWarnings());
-		System.out.println("Errors  : " + bmaker.getErrors());
-		jar.getManifest().write(System.out);
-		Manifest manifest = jar.getManifest();
-		String header = manifest.getMainAttributes().getValue("Export-Package");
-		assertTrue(header.indexOf("META-INF") > 0);
-	}
-
-	/**
-	 * Bnd cleans up versions if they do not follow the OSGi rule. Check a
-	 * number of those versions.
-	 * 
-	 * @throws Exception
-	 */
-	public void testVersionCleanup() throws Exception {
-		assertVersion("000001.0003.00000-SNAPSHOT", "1.3.0.SNAPSHOT");
-		assertVersion("000000.0000.00000-SNAPSHOT", "0.0.0.SNAPSHOT");
-		assertVersion("0-SNAPSHOT", "0.0.0.SNAPSHOT");
-		assertVersion("1.3.0.0-0-01-0-SNAPSHOT", "1.3.0.0-0-01-0-SNAPSHOT");
-		assertVersion("1.3.0.0-0-01-0", "1.3.0.0-0-01-0");
-		assertVersion("0.9.0.1.2.3.4.5-incubator-SNAPSHOT", "0.9.0.incubator-SNAPSHOT");
-		assertVersion("0.4aug123", "0.0.0.4aug123");
-		assertVersion("0.9.4aug123", "0.9.0.4aug123");
-		assertVersion("0.9.0.4aug123", "0.9.0.4aug123");
-
-		assertVersion("1.2.3", "1.2.3");
-		assertVersion("1.2.3-123", "1.2.3.123");
-		assertVersion("1.2.3.123", "1.2.3.123");
-		assertVersion("1.2.3.123x", "1.2.3.123x");
-		assertVersion("1.123x", "1.0.0.123x");
-
-		assertVersion("0.9.0.4.3.2.1.0.4aug123", "0.9.0.4aug123");
-		assertVersion("0.9.0.4aug123", "0.9.0.4aug123");
-
-		assertVersion("0.9.0.4.3.4.5.6.6", "0.9.0.6");
-
-		assertVersion("0.9.0-incubator-SNAPSHOT", "0.9.0.incubator-SNAPSHOT");
-		assertVersion("1.2.3.x", "1.2.3.x");
-		assertVersion("1.2.3", "1.2.3");
-		assertVersion("1.2", "1.2");
-		assertVersion("1", "1");
-		assertVersion("1.2.x", "1.2.0.x");
-		assertVersion("1.x", "1.0.0.x");
-		assertVersion("1.2.3-x", "1.2.3.x");
-		assertVersion("1.2:x", "1.2.0.x");
-		assertVersion("1.2-snapshot", "1.2.0.snapshot");
-		assertVersion("1#x", "1.0.0.x");
-		assertVersion("1.&^%$#date2007/03/04", "1.0.0.date20070304");
-	}
-
-	void assertVersion(String input, String expected) {
-		assertEquals(expected, Builder.cleanupVersion(input));
-	}
-
-	/**
-	 * -exportcontents provides a header that is only relevant in the analyze
-	 * phase, it augments the Export-Package header.
-	 */
-
-	public void testExportContents() throws Exception {
-		Builder builder = new Builder();
-		builder.setProperty(Analyzer.INCLUDE_RESOURCE,
-				"test/activator/inherits=src/test/activator/inherits");
-		builder.setProperty("-exportcontents", "*;x=true;version=1");
-		builder.build();
-		Manifest manifest = builder.calcManifest();
-		Attributes main = manifest.getMainAttributes();
-		Map<String, Map<String, String>> map = OSGiHeader.parseHeader(main
-				.getValue("Export-Package"));
-		Map<String, String> export = map.get("test.activator.inherits");
-		assertNotNull(export);
-		assertEquals("1", export.get("version"));
-		assertEquals("true", export.get("x"));
-	}
-
-	/**
-	 * I am having some problems with split packages in 170. I get this output:
-	 * 
-	 * [java] 1 : There are split packages, use directive split-package:=merge
-	 * on instruction to get rid of this warning: my.package
-	 * 
-	 * First of all, this warning is falsely occurring. The classpath to the bnd
-	 * task contains something like:
-	 * 
-	 * my/package/foo.class my/package/sub/bar.class
-	 * 
-	 * and the export is:
-	 * 
-	 * Export-Package: my.package*;version=${version}
-	 * 
-	 * so my.package and my.package.sub are being incorrectly considered as the
-	 * same package by bnd.
-	 * 
-	 */
-	public void testSplitOverlappingPackages() throws Exception {
-		Builder b = new Builder();
-		b.setClasspath(new File[] { new File("bin") });
-		Properties p = new Properties();
-		p.put("build", "xyz");
-		p.put("Export-Package", "test*;version=3.1");
-		b.setProperties(p);
-		b.setPedantic(true);
-		b.build();
-		System.out.println("Errors     :" + b.getErrors());
-		System.out.println("Warnings   :" + b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-	}
-
-	/**
-	 * Check Conditional package. First import a subpackage then let the
-	 * subpackage import a super package. This went wrong in the OSGi build. We
-	 * see such a pattern in the Spring jar. The package
-	 * org.springframework.beans.factory.access refers to
-	 * org.springframework.beans.factory and org.springframework.beans. The
-	 */
-	public void testConditionalBaseSuper() throws Exception {
-		Builder b = new Builder();
-		b.setProperty(Constants.CONDITIONAL_PACKAGE, "test.top.*");
-		b.setProperty(Constants.PRIVATE_PACKAGE, "test.top.middle.bottom");
-		b.addClasspath(new File("bin"));
-		Jar dot = b.build();
-		System.out.println("Errors: " + b.getErrors());
-		System.out.println("Warnings: " + b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		assertNotNull(dot.getResource("test/top/middle/bottom/Bottom.class"));
-		assertNotNull(dot.getResource("test/top/middle/Middle.class"));
-		assertNotNull(dot.getResource("test/top/Top.class"));
-
-		assertFalse(b.getImports().containsKey("test.top"));
-		assertFalse(b.getImports().containsKey("test.top.middle"));
-		assertFalse(b.getImports().containsKey("test.top.middle.bottom"));
-	}
-
-	/**
-	 * It looks like Conditional-Package can add the same package multiple
-	 * times. So lets test this.
-	 */
-	public void testConditional2() throws Exception {
-		Properties base = new Properties();
-		base.put(Analyzer.EXPORT_PACKAGE, "org.osgi.service.log");
-		base.put(Analyzer.CONDITIONAL_PACKAGE, "org.osgi.*");
-		Builder analyzer = new Builder();
-		analyzer.setProperties(base);
-		analyzer.setClasspath(new File[] { new File("jar/osgi.jar") });
-		analyzer.build();
-		Jar jar = analyzer.getJar();
-		assertNotNull(jar.getDirectories().get("org/osgi/framework"));
-		System.out.println("Errors: " + analyzer.getErrors());
-		System.out.println("Warnings: " + analyzer.getWarnings());
-		assertEquals(0, analyzer.getErrors().size());
-		assertEquals(0, analyzer.getWarnings().size());
-	}
-
-	/**
-	 * Test the strategy: error
-	 */
-	public void testStrategyError() throws Exception {
-		Properties base = new Properties();
-		base.put(Analyzer.EXPORT_PACKAGE, "*;-split-package:=error");
-		Builder analyzer = new Builder();
-		analyzer.setClasspath(new File[] { new File("jar/asm.jar"), new File("jar/asm.jar") });
-		analyzer.setProperties(base);
-		analyzer.build();
-		System.out.println("Errors: " + analyzer.getErrors());
-		assertEquals(3, analyzer.getErrors().size());
-		assertEquals(0, analyzer.getWarnings().size());
-		assertTrue(((String) analyzer.getErrors().get(0)).indexOf("Split package") >= 0);
-	}
-
-	/**
-	 * Test the strategy: default
-	 */
-	public void testStrategyDefault() throws Exception {
-		Properties base = new Properties();
-		base.put(Analyzer.EXPORT_PACKAGE, "*");
-		Builder analyzer = new Builder();
-		analyzer.setClasspath(new File[] { new File("jar/asm.jar"), new File("jar/asm.jar") });
-		analyzer.setProperties(base);
-		analyzer.build();
-		System.out.println("Warnings: " + analyzer.getWarnings());
-		assertEquals(0, analyzer.getErrors().size());
-		assertEquals(3, analyzer.getWarnings().size());
-		assertTrue(((String) analyzer.getWarnings().get(0)).indexOf("split-package") >= 0);
-	}
-
-	/**
-	 * Test the strategy: merge-first
-	 */
-	public void testStrategyMergeFirst() throws Exception {
-		Properties base = new Properties();
-		base.put(Analyzer.EXPORT_PACKAGE, "*;-split-package:=merge-first");
-		Builder analyzer = new Builder();
-		analyzer.setClasspath(new File[] { new File("jar/asm.jar"), new File("jar/asm.jar") });
-		analyzer.setProperties(base);
-		analyzer.build();
-		System.out.println("Errors: " + analyzer.getErrors());
-		assertEquals(0, analyzer.getErrors().size());
-		assertEquals(0, analyzer.getWarnings().size());
-		// assertTrue( ((String)analyzer.getErrors().get(0)).contains("file does
-		// not exist"));
-	}
-
-	/**
-	 * Test the strategy: merge-last
-	 */
-	public void testStrategyMergeLast() throws Exception {
-		Properties base = new Properties();
-		base.put(Analyzer.EXPORT_PACKAGE, "*;-split-package:=merge-last");
-		Builder analyzer = new Builder();
-		analyzer.setClasspath(new File[] { new File("jar/asm.jar"), new File("jar/asm.jar") });
-		analyzer.setProperties(base);
-		analyzer.build();
-		System.out.println("Errors: " + analyzer.getErrors());
-		assertEquals(0, analyzer.getErrors().size());
-		assertEquals(0, analyzer.getWarnings().size());
-		// assertTrue( ((String)analyzer.getErrors().get(0)).contains("file does
-		// not exist"));
-	}
-
-	/**
-	 * Test Resource inclusion that do not exist
-	 * 
-	 * @throws Exception
-	 */
-	public void testResourceNotFound() throws Exception {
-		Properties base = new Properties();
-		base.put(Analyzer.EXPORT_PACKAGE, "*;test:=true");
-		base.put(Analyzer.INCLUDE_RESOURCE, "does_not_exist");
-		Builder analyzer = new Builder();
-		analyzer.setClasspath(new File[] { new File("jar/asm.jar") });
-		analyzer.setProperties(base);
-		analyzer.build();
-		System.out.println("Errors: " + analyzer.getErrors());
-		assertEquals(1, analyzer.getErrors().size());
-		assertTrue(((String) analyzer.getErrors().get(0)).indexOf("file does not exist") >= 0);
-	}
-
-	/**
-	 * Spaces at the end of a clause cause the preprocess to fail.
-	 * 
-	 * @throws Exception
-	 */
-	public void testPreProcess() throws Exception {
-		Properties base = new Properties();
-		base.put(Analyzer.INCLUDE_RESOURCE, "{src/test/top.mf}     ");
-		Builder analyzer = new Builder();
-		analyzer.setProperties(base);
-		analyzer.build();
-		Jar jar = analyzer.getJar();
-		assertTrue(jar.getResource("top.mf") != null);
-	}
-
-	/**
-	 * Check if we can use findpath to build the Bundle-Classpath.
-	 */
-
-	public void testFindPathInBundleClasspath() throws Exception {
-		Properties base = new Properties();
-		base.put(Analyzer.INCLUDE_RESOURCE, "jar=jar");
-		base.put(Analyzer.BUNDLE_CLASSPATH, "${findpath;jar/.{1,4}\\.jar}");
-		Builder analyzer = new Builder();
-		analyzer.setProperties(base);
-		analyzer.build();
-
-		Manifest manifest = analyzer.getJar().getManifest();
-		String bcp = manifest.getMainAttributes().getValue("Bundle-Classpath");
-
-		assertTrue(bcp.indexOf("ds.jar") >= 0);
-		assertTrue(bcp.indexOf("asm.jar") >= 0);
-		assertTrue(bcp.indexOf("bcel.jar") >= 0);
-		assertTrue(bcp.indexOf("mina.jar") >= 0);
-		assertTrue(bcp.indexOf("rox.jar") >= 0);
-		assertTrue(bcp.indexOf("osgi.jar") >= 0);
-	}
-
-	/**
-	 * Check if we export META-INF when we export the complete classpath.
-	 */
-
-	public void testVersionCleanupAll() throws Exception {
-		Properties base = new Properties();
-		base.put(Analyzer.EXPORT_PACKAGE, "*");
-		base.put(Analyzer.BUNDLE_VERSION, "0.9.0-incubator-SNAPSHOT");
-		Builder analyzer = new Builder();
-		analyzer.setClasspath(new File[] { new File("jar/asm.jar") });
-		analyzer.setProperties(base);
-		analyzer.build();
-		Manifest manifest = analyzer.getJar().getManifest();
-		String version = manifest.getMainAttributes().getValue(Analyzer.BUNDLE_VERSION);
-		assertEquals("0.9.0.incubator-SNAPSHOT", version);
-	}
-
-	/**
-	 * We are only adding privately the core equinox ds package. We then add
-	 * conditionally all packages that should belong to this as well as any OSGi
-	 * interfaces.
-	 * 
-	 * @throws Exception
-	 */
-	public void testConditional() throws Exception {
-		File cp[] = { new File("jar/osgi.jar"), new File("jar/ds.jar") };
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.put("Import-Package", "*");
-		p.put("Private-Package", "org.eclipse.equinox.ds");
-		p.put("Conditional-Package", "org.eclipse.equinox.ds.*, org.osgi.service.*");
-		bmaker.setProperties(p);
-		bmaker.setClasspath(cp);
-		bmaker.build();
-		assertTrue(bmaker.getContained().containsKey("org.eclipse.equinox.ds.instance"));
-		assertTrue(bmaker.getContained().containsKey("org.eclipse.equinox.ds.model"));
-		assertTrue(bmaker.getContained().containsKey("org.eclipse.equinox.ds.parser"));
-		assertTrue(bmaker.getContained().containsKey("org.osgi.service.cm"));
-		assertTrue(bmaker.getContained().containsKey("org.osgi.service.component"));
-		assertFalse(bmaker.getContained().containsKey("org.osgi.service.wireadmin"));
-	}
-
-	/**
-	 * Check if we export META-INF when we export the complete classpath.
-	 */
-
-	public void testMetaInfExport() throws Exception {
-		Properties base = new Properties();
-		base.put(Analyzer.EXPORT_PACKAGE, "*");
-		Builder analyzer = new Builder();
-		analyzer.setClasspath(new File[] { new File("jar/asm.jar") });
-		analyzer.setProperties(base);
-		analyzer.build();
-		assertFalse(analyzer.getExports().containsKey("META-INF"));
-		assertTrue(analyzer.getExports().containsKey("org.objectweb.asm"));
-	}
-
-	/**
-	 * Check that the activator is found.
-	 * 
-	 * @throws Exception
-	 */
-	public void testFindActivator() throws Exception {
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.put("Bundle-Activator", "test.activator.Activator");
-		p.put("build", "xyz"); // for @Version annotation
-		p.put("Private-Package", "test.*");
-		bmaker.setProperties(p);
-		bmaker.setClasspath(new File[] { new File("bin") });
-		Jar jar = bmaker.build();
-		report("testFindActivator", bmaker, jar);
-		assertEquals(0, bmaker.getErrors().size());
-		assertEquals(0, bmaker.getWarnings().size());
-	}
-
-	public void testImportVersionRange() throws Exception {
-		assertVersionEquals("[1.1,2.0)", "[1.1,2.0)");
-		assertVersionEquals("[${@},2.0)", "[1.3,2.0)");
-		assertVersionEquals("[${@},${@}]", "[1.3,1.3]");
-	}
-
-	void assertVersionEquals(String input, String output) throws Exception {
-		File cp[] = { new File("jar/osgi.jar") };
-		Builder bmaker = new Builder();
-		bmaker.setClasspath(cp);
-		Properties p = new Properties();
-		p.put(Analyzer.EXPORT_PACKAGE, "test.activator");
-		p.put(Analyzer.IMPORT_PACKAGE, "org.osgi.framework;version=\"" + input + "\"");
-		bmaker.setProperties(p);
-		bmaker.build();
-		Map<String, Map<String, String>> imports = bmaker.getImports();
-		Map<String, String> framework = imports.get("org.osgi.framework");
-		assertEquals(output, framework.get("version"));
-	}
-
-	public void testImportExportBadVersion() throws Exception {
-		File cp[] = { new File("jar/asm.jar") };
-		Builder bmaker = new Builder();
-		bmaker.setClasspath(cp);
-		Properties p = new Properties();
-		p.put(Analyzer.BUNDLE_VERSION, "0.9.5-@#SNAPSHOT");
-		p.put(Analyzer.EXPORT_PACKAGE, "*;version=0.9.5-@#SNAPSHOT");
-		p.put(Analyzer.IMPORT_PACKAGE, "*;version=0.9.5-@#SNAPSHOT");
-		bmaker.setProperties(p);
-		Jar jar = bmaker.build();
-		assertEquals(jar.getManifest().getMainAttributes().getValue("Bundle-Version"),
-				"0.9.5.SNAPSHOT");
-		Map<String, String> map = bmaker.getExports().get("org.objectweb.asm");
-		assertEquals(map.get("version"), "0.9.5.SNAPSHOT");
-		map = bmaker.getImports().get("java.lang.reflect");
-		assertEquals(map.get("version"), "0.9.5.SNAPSHOT");
-	}
-
-	/**
-	 * Check if can find an activator in the bundle while using a complex bundle
-	 * classpath.
-	 * 
-	 * @throws Exception
-	 */
-	public void testBundleClasspath3() throws Exception {
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.put("Export-Package", "test.activator;-split-package:=merge-first");
-		p.put("Bundle-Activator", "test.activator.Activator");
-		p.put("Import-Package", "*");
-		p.put("Include-Resource", "ds.jar=jar/ds.jar");
-		p.put("Bundle-ClassPath", ".,ds.jar");
-		bmaker.setProperties(p);
-		bmaker.setClasspath(new File[] { new File("bin"), new File("src") });
-		Jar jar = bmaker.build();
-		report("testBundleClasspath3", bmaker, jar);
-		assertEquals(0, bmaker.getErrors().size());
-		assertEquals(0, bmaker.getWarnings().size());
-	}
-
-	/**
-	 * Check if can find an activator in a embedded jar while using a complex
-	 * bundle classpath.
-	 * 
-	 * @throws Exception
-	 */
-	public void testBundleClasspath2() throws Exception {
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.put("Bundle-Activator", "org.eclipse.equinox.ds.Activator");
-		p.put("Private-Package", "test.activator;-split-package:=merge-first");
-		p.put("Import-Package", "*");
-		p.put("Include-Resource", "ds.jar=jar/ds.jar");
-		p.put("Bundle-ClassPath", ".,ds.jar");
-		bmaker.setProperties(p);
-		bmaker.setClasspath(new File[] { new File("bin"), new File("src") });
-		Jar jar = bmaker.build();
-		report("testBundleClasspath2", bmaker, jar);
-		assertEquals(bmaker.getErrors().size(), 0);
-		assertEquals(bmaker.getWarnings().size(), 0);
-	}
-
-	public void testBundleClasspath() throws Exception {
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.put("Export-Package", "test.activator;-split-package:=merge-first");
-		p.put("Bundle-Activator", "test.activator.Activator");
-		p.put("Import-Package", "*");
-		p.put("Bundle-ClassPath", ".");
-		bmaker.setProperties(p);
-		bmaker.setClasspath(new File[] { new File("bin"), new File("src") });
-		Jar jar = bmaker.build();
-		report("testBundleClasspath", bmaker, jar);
-		jar.exists("test/activator/Activator.class");
-		assertEquals(bmaker.getErrors().size(), 0);
-		assertEquals(bmaker.getWarnings().size(), 0);
-	}
-
-	public void testUnreferredImport() throws Exception {
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-
-		p.put("-classpath", "jar/mina.jar");
-		p.put("Export-Package", "!META-INF.*,*");
-		p.put("Import-Package", "org.apache.commons.collections.map,*");
-		bmaker.setProperties(p);
-		Jar jar = bmaker.build();
-		report("testUnreferredImport", bmaker, jar);
-
-	}
-
-	public void testIncludeResourceResourcesOnlyJar2() throws Exception {
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-
-		p.put("-classpath", "jar/ro.jar");
-		p.put("Export-Package", "*");
-		p.put("Import-Package", "");
-		bmaker.setProperties(p);
-		Jar jar = bmaker.build();
-		report("testIncludeResourceResourcesOnlyJar2", bmaker, jar);
-		assertTrue(bmaker.getExports().containsKey("ro"));
-		assertFalse(bmaker.getExports().containsKey("META-INF"));
-
-		assertEquals(0, bmaker.getWarnings().size());
-		assertEquals(0, bmaker.getErrors().size());
-		assertEquals(3, jar.getResources().size());
-
-	}
-
-	public void testClasspathFileNotExist() throws Exception {
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		File cp[] = new File[] { new File("jar/idonotexist.jar") };
-
-		bmaker.setProperties(p);
-		bmaker.setClasspath(cp);
-		bmaker.build();
-		assertEquals(2, bmaker.getErrors().size());
-	}
-
-	public void testExpandWithNegate() throws Exception {
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		File cp[] = new File[] { new File("jar/asm.jar") };
-
-		p.put("Export-Package", "!org.objectweb.asm,*");
-		bmaker.setProperties(p);
-		bmaker.setClasspath(cp);
-		Jar jar = bmaker.build();
-		assertNull(jar.getDirectories().get("org/objectweb/asm"));
-		assertNotNull(jar.getDirectories().get("org/objectweb/asm/signature"));
-		assertEquals(0, bmaker.getWarnings().size());
-		assertEquals(0, bmaker.getErrors().size());
-		assertEquals(3, jar.getResources().size());
-	}
-
-	public void testIncludeResourceResourcesOnlyJar() throws Exception {
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		File cp[] = new File[] { new File("jar/ro.jar") };
-
-		p.put("Export-Package", "*");
-		p.put("Import-Package", "");
-		bmaker.setProperties(p);
-		bmaker.setClasspath(cp);
-		Jar jar = bmaker.build();
-		assertEquals(0, bmaker.getWarnings().size());
-		assertEquals(0, bmaker.getErrors().size());
-		assertEquals(3, jar.getResources().size());
-
-	}
-
-	public void testIncludeResourceResourcesOnly() throws Exception {
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		File cp[] = new File[] { new File("src") };
-
-		p.put("Import-Package", "");
-		p.put("Private-Package", "test.resourcesonly");
-		bmaker.setProperties(p);
-		bmaker.setClasspath(cp);
-		Jar jar = bmaker.build();
-		assertEquals(0, bmaker.getWarnings().size());
-		assertEquals(0, bmaker.getErrors().size());
-		assertEquals(4, jar.getResources().size());
-
-	}
-
-	public void testIncludeResourceFromZipDefault() throws Exception {
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.put("Include-Resource", "@jar/easymock.jar");
-		bmaker.setProperties(p);
-		Jar jar = bmaker.build();
-
-		assertEquals(1, bmaker.getWarnings().size());
-		assertEquals(0, bmaker.getErrors().size());
-		assertEquals(59, jar.getResources().size());
-
-	}
-
-	public void testIncludeResourceFromZipDeep() throws Exception {
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.put("Include-Resource", "@jar/easymock.jar!/**");
-		bmaker.setProperties(p);
-		Jar jar = bmaker.build();
-
-		assertEquals(1, bmaker.getWarnings().size());
-		assertEquals(0, bmaker.getErrors().size());
-		assertEquals(59, jar.getResources().size());
-
-	}
-
-	public void testIncludeResourceFromZipOneDirectory() throws Exception {
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.put("Import-Package", "!*");
-		p.put("Include-Resource", "@jar/easymock.jar!/org/easymock/**");
-		bmaker.setProperties(p);
-		Jar jar = bmaker.build();
-		assertEquals(1, bmaker.getWarnings().size());
-		assertEquals(0, bmaker.getErrors().size());
-		assertEquals(59, jar.getResources().size());
-		assertNotNull(jar.getResource("org/easymock/AbstractMatcher.class"));
-	}
-
-	public void testIncludeResourceFromZipOneDirectoryOther() throws Exception {
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.put("Import-Package", "!*");
-		p.put("-resourceonly", "true");
-		p.put("Include-Resource", "OPT-INF/test=@jar/osgi.jar!/org/osgi/service/event/**");
-		bmaker.setProperties(p);
-		Jar jar = bmaker.build();
-		System.out.println("warnings: " + Processor.join(bmaker.getWarnings(), "\n"));
-		System.out.println("errors: " + Processor.join(bmaker.getErrors(), "\n"));
-		assertEquals(0, bmaker.getWarnings().size());
-
-		assertEquals(0, bmaker.getErrors().size());
-		assertEquals(7, jar.getResources().size());
-		System.out.println(jar.getResources().keySet());
-		assertNotNull(jar.getResource("OPT-INF/test/org/osgi/service/event/EventAdmin.class"));
-	}
-
-	public void testIncludeResourceFromZipRecurseDirectory() throws Exception {
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.put("Import-Package", "!*");
-		p.put("Include-Resource", "@jar/easymock.jar!/org/easymock/**");
-		bmaker.setProperties(p);
-		Jar jar = bmaker.build();
-
-		assertEquals(1, bmaker.getWarnings().size());
-		assertEquals(0, bmaker.getErrors().size());
-		assertEquals(59, jar.getResources().size());
-	}
-
-	public void testIncludeLicenseFromZip() throws Exception {
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.put("Import-Package", "");
-		p.put("Include-Resource", "@jar/osgi.jar!/LICENSE");
-		bmaker.setProperties(p);
-		Jar jar = bmaker.build();
-		assertEquals(1, jar.getResources().size());
-		assertNotNull(jar.getResource("LICENSE"));
-		assertEquals(1, bmaker.getWarnings().size());
-		assertEquals(0, bmaker.getErrors().size());
-	}
-
-	public void testEasymock() throws Exception {
-		File cp[] = { new File("jar/easymock.jar") };
-		Builder bmaker = new Builder();
-		Properties p = new Properties();
-		p.put("Import-Package", "*");
-		p.put("Export-Package", "*");
-		p.put("Bundle-SymbolicName", "easymock");
-		p.put("Bundle-Version", "2.2");
-		bmaker.setProperties(p);
-		bmaker.setClasspath(cp);
-		Jar jar = bmaker.build();
-		jar.getManifest().write(System.out);
-	}
-
-	public void testSources() throws Exception {
-		File cp[] = { new File("src"), new File("jar/asm.jar") };
-		Builder bmaker = new Builder();
-		bmaker.setClasspath(cp);
-		bmaker.setSourcepath(new File[] { new File("src") });
-		Properties properties = new Properties();
-		properties.put("-sources", "true");
-		properties.put("Export-Package", "*");
-		bmaker.setProperties(properties);
-		Jar jar = bmaker.build();
-		System.out.println(jar.getResources());
-		// System.out.println(bmaker.getExports());
-		System.out.println("Warnings: " + bmaker.getWarnings());
-		System.out.println("Errors  : " + bmaker.getErrors());
-		jar.getManifest().write(System.out);
-	}
-
-	public void testSimple() throws Exception {
-		File cp[] = { new File("src"), new File("jar/asm.jar") };
-		Builder bmaker = new Builder();
-		bmaker.setProperties(new File("src/test/simple.mf"));
-		bmaker.setClasspath(cp);
-		Jar jar = bmaker.build();
-		System.out.println(jar.getResources());
-		// System.out.println(bmaker.getExports());
-		System.out.println("Warnings: " + bmaker.getWarnings());
-		System.out.println("Errors  : " + bmaker.getErrors());
-		jar.getManifest().write(System.out);
-	}
-
-	public void testVerifyResult() throws Exception {
-		System.out.println("Verify what we just built: test.jar");
-		Jar jar = new Jar("test", getClass().getResourceAsStream("test.jar"));
-		Verifier verifier = new Verifier(jar);
-		verifier.verify();
-		System.out.println("Warnings: " + verifier.getWarnings());
-		System.out.println("Errors  : " + verifier.getErrors());
-	}
-
-	public void testVerify() throws Exception {
-		System.out.println("Erroneous bundle: tb1.jar");
-		Jar jar = new Jar("test", getClass().getResourceAsStream("tb1.jar"));
-		Verifier verifier = new Verifier(jar);
-		verifier.verify();
-		System.out.println("Warnings: " + verifier.getWarnings());
-		System.out.println("Errors  : " + verifier.getErrors());
-		verifier.info();
-	}
-
-	public void report(String title, Analyzer builder, Jar jar) {
-		System.out.println("Directories " + jar.getDirectories().keySet());
-		System.out.println("Warnings    " + builder.getWarnings());
-		System.out.println("Errors      " + builder.getErrors());
-		System.out.println("Exports     " + builder.getExports());
-		System.out.println("Imports     " + builder.getImports());
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/test/CachingURLResourceHandleTest.java b/biz.aQute.bndlib/src/test/CachingURLResourceHandleTest.java
deleted file mode 100644
index 2fc886c..0000000
--- a/biz.aQute.bndlib/src/test/CachingURLResourceHandleTest.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package test;
-
-import java.io.File;
-import java.io.IOException;
-
-import junit.framework.TestCase;
-import aQute.lib.deployer.obr.CachingURLResourceHandle;
-import aQute.lib.deployer.obr.CachingURLResourceHandle.CachingMode;
-
-public class CachingURLResourceHandleTest extends TestCase {
-	
-	File currentDir = new File(System.getProperty("user.dir"));
-	
-	public void testResolveAbsolute() throws IOException {
-		CachingURLResourceHandle handle;
-		
-		File testFile = new File(currentDir, "bnd.bnd").getAbsoluteFile();
-		String testUrl = testFile.toURI().toURL().toExternalForm();
-		
-		// Ignore base
-		handle = new CachingURLResourceHandle(testUrl, "http://ignored", null, CachingMode.PreferCache);
-		assertEquals(testUrl, handle.getResolvedUrl().toExternalForm());
-		
-		// Base may be null
-		handle = new CachingURLResourceHandle(testUrl, null, null, CachingMode.PreferCache);
-		assertEquals(testUrl, handle.getResolvedUrl().toExternalForm());
-	}
-	
-}
diff --git a/biz.aQute.bndlib/src/test/CalltreeTest.java b/biz.aQute.bndlib/src/test/CalltreeTest.java
deleted file mode 100644
index 6724c0b..0000000
--- a/biz.aQute.bndlib/src/test/CalltreeTest.java
+++ /dev/null
@@ -1,164 +0,0 @@
-package test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import junit.framework.TestCase;
-import aQute.bnd.make.calltree.CalltreeResource;
-import aQute.bnd.make.coverage.Coverage;
-import aQute.bnd.make.coverage.CoverageResource;
-import aQute.lib.osgi.Analyzer;
-import aQute.lib.osgi.Builder;
-import aQute.lib.osgi.Clazz;
-import aQute.lib.osgi.Processor;
-import aQute.lib.osgi.Resource;
-import aQute.lib.osgi.Clazz.MethodDef;
-import aQute.lib.tag.Tag;
-
-public class CalltreeTest extends TestCase {
-	public void testCalltree() throws Exception {
-		StringWriter sw = new StringWriter();
-		PrintWriter pw = new PrintWriter(sw);
-		Builder b = new Builder();
-		b.addClasspath(new File("bin"));
-		b.setProperty("Private-Package", "test");
-		b.build();
-		Collection<Clazz> clazzes = b.getClassspace().values();
-		assertTrue(clazzes.size() > 10);
-
-		CalltreeResource.writeCalltree(pw, clazzes);
-		pw.close();
-		System.out.println(sw.toString());
-	}
-
-	static class Implements implements Resource {
-
-		public String getExtra() {
-			// TODO Auto-generated method stub
-			return null;
-		}
-
-		public long lastModified() {
-			// TODO Auto-generated method stub
-			return 0;
-		}
-
-		public InputStream openInputStream() throws IOException {
-			// TODO Auto-generated method stub
-			return null;
-		}
-
-		public void setExtra(String extra) {
-			// TODO Auto-generated method stub
-
-		}
-
-		public void write(OutputStream out) throws IOException {
-			// TODO Auto-generated method stub
-
-		}
-	}
-
-	public void testCoverage() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("bin"));
-		b.setProperty("Private-Package", "test");
-		b.build();
-		Collection<Clazz> testsuite = b.getClassspace().values();
-
-		Builder c = new Builder();
-		c.addClasspath(new File("bin"));
-		c.setProperty("Private-Package", "aQute.lib.osgi");
-		c.build();
-		Collection<Clazz> target = c.getClassspace().values();
-
-		Map<Clazz.MethodDef, List<Clazz.MethodDef>> xref = Coverage.getCrossRef(testsuite, target);
-		System.out.println(xref);
-
-		List<Clazz.MethodDef> refs = xref.get(new Clazz.MethodDef(0, Resource.class.getName(),
-				"write", "(Ljava/io/OutputStream;)V"));
-
-		assertNotNull("The write(OutputStream) method is implemented by Resource", xref);
-
-		assertTrue("We must have at least one reference", refs.size() > 0);
-		// MethodDef md = refs.get(0);
-		boolean found = false;
-		for (MethodDef md : refs) {
-			if (md.clazz.equals("test.CalltreeTest$Implements")) {
-				found = true;
-				assertEquals(md.name, "<implements>");
-				assertEquals(md.descriptor, "()V");
-			}
-		}
-		assertTrue( found);
-		
-		assertTrue(xref.containsKey(new Clazz.MethodDef(0, Analyzer.class.getName(), "analyze",
-				"()V")));
-		assertTrue(xref.containsKey(new Clazz.MethodDef(0, Builder.class.getName(), "build",
-				"()LaQute/lib/osgi/Jar;")));
-		assertTrue(xref
-				.get(
-						new Clazz.MethodDef(0, "aQute.lib.osgi.Builder", "build",
-								"()LaQute/lib/osgi/Jar;")).contains(
-						new Clazz.MethodDef(0, "test.CalltreeTest", "testCoverage", "()V")));
-
-		Tag tag = CoverageResource.toTag(xref);
-		PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
-		tag.print(0, pw);
-		pw.close();
-	}
-
-	public void testCatalog() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("jar/osgi.jar"));
-		b.setProperty("Private-Package", "org.osgi.framework");
-		b.build();
-		Collection<Clazz> target = b.getClassspace().values();
-
-		Map<MethodDef, List<MethodDef>> xref = Coverage.getCrossRef(new ArrayList<Clazz>(), target);
-
-		System.out.println(Processor.join(xref.keySet(), "\n"));
-
-		assertTrue(xref.containsKey(new Clazz.MethodDef(0, "org.osgi.framework.AdminPermission",
-				"<init>", "()V")));
-		assertTrue(xref.containsKey(new Clazz.MethodDef(0, "org.osgi.framework.AdminPermission",
-				"<init>", "(Lorg/osgi/framework/Bundle;Ljava/lang/String;)V")));
-		assertTrue(xref.containsKey(new Clazz.MethodDef(0, "org.osgi.framework.AdminPermission",
-				"<init>", "(Ljava/lang/String;Ljava/lang/String;)V")));
-		assertFalse(xref.containsKey(new Clazz.MethodDef(0, "org.osgi.framework.AdminPermission$1",
-				"run", "()Ljava/lang/Object;")));
-		assertFalse(xref.containsKey(new Clazz.MethodDef(0, "org.osgi.framework.AdminPermission",
-				"createName", "(Lorg/osgi/framework/Bundle;)Ljava/lang/String;")));
-	}
-
-	public void testResource() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("jar/osgi.jar"));
-		b.setProperty("Private-Package", "org.osgi.framework");
-		b.build();
-		Collection<Clazz> target = b.getClassspace().values();
-
-		Resource r = new CoverageResource(target, target);
-		InputStream in = r.openInputStream();
-		ByteArrayOutputStream out = new ByteArrayOutputStream();
-		byte[] buffer = new byte[1000];
-		int size = in.read(buffer);
-		while (size > 0) {
-			out.write(buffer, 0, size);
-			size = in.read(buffer);
-		}
-		out.close();
-		assertTrue(out.toByteArray().length > 1000);
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/test/ClassParserTest.java b/biz.aQute.bndlib/src/test/ClassParserTest.java
deleted file mode 100755
index 8d12fcd..0000000
--- a/biz.aQute.bndlib/src/test/ClassParserTest.java
+++ /dev/null
@@ -1,352 +0,0 @@
-package test;
-
-import java.io.*;
-import java.lang.reflect.*;
-import java.net.*;
-import java.util.*;
-
-import junit.framework.*;
-import aQute.bnd.service.*;
-import aQute.lib.io.*;
-import aQute.lib.osgi.*;
-import aQute.libg.generics.*;
-import aQute.libg.reporter.*;
-
-class ConstantValues {
-	public static final boolean	f		= false;
-	public static final boolean	t		= true;
-	public static final byte	bt		= Byte.MAX_VALUE;
-	public static final short	shrt	= Short.MAX_VALUE;
-	public static final char	chr		= Character.MAX_VALUE;
-	public static final int		intgr	= Integer.MAX_VALUE;
-	public static final long	lng		= Long.MAX_VALUE;
-	public static final float	flt		= Float.MAX_VALUE;
-	public static final double	dbl		= Double.MAX_VALUE;
-	public static final String	strng	= "blabla";
-	// Classes somehow are not treated as constants
-//	public static final Class			clss	= Object.class;
-}
-
-interface WithGenerics<VERYLONGTYPE, X extends Jar> {
-	List<? super VERYLONGTYPE> baz2();
-
-	List<? extends Jar>		field	= null;
-
-	WithGenerics<URL, Jar>	x		= null;
-}
-
-class Generics {
-	Map<ClassParserTest, ?> baz() {
-		return null;
-	}
-
-	Map<ClassParserTest, ?> baz1() {
-		return null;
-	}
-
-	Map<? extends String, ?> baz2() {
-		return null;
-	}
-
-	List<ClassParserTest> foo() {
-		return null;
-	}
-
-	Map<ClassParserTest, Clazz> bar() {
-		return null;
-	}
-
-	WithGenerics<List<Jar>, Jar> xyz() {
-		return null;
-	}
-}
-
-class Implemented implements Plugin {
-	public void setProperties(Map<String, String> map) {
-	}
-
-	public void setReporter(Reporter processor) {
-	}
-}
-
-public class ClassParserTest extends TestCase {
-
-	/**
-	 * Test the constant values
-	 * 
-	 * @throws Exception
-	 */
-
-
-	public void testConstantValues() throws Exception {
-		final Map<String, Object> values = new HashMap<String, Object>();
-		Clazz c = new Clazz("ConstantValues", new FileResource(IO.getFile(
-				new File("").getAbsoluteFile(), "bin/test/ConstantValues.class")));
-		c.parseClassFileWithCollector(new ClassDataCollector() {
-			Clazz.FieldDef	last;
-
-			@Override public void field(Clazz.FieldDef referenced) {
-				last = referenced;
-			}
-
-			@Override public void constant(Object value) {
-				values.put(last.name, value);
-			}
-
-		});
-
-		assertEquals(1, values.get("t"));
-		assertEquals(0, values.get("f"));
-		assertEquals((int) Byte.MAX_VALUE, values.get("bt"));
-		assertEquals((int) Short.MAX_VALUE, values.get("shrt"));
-		assertEquals((int) Character.MAX_VALUE, values.get("chr"));
-		assertEquals(Integer.MAX_VALUE, values.get("intgr"));
-		assertEquals(Long.MAX_VALUE, values.get("lng"));
-		assertEquals(Float.MAX_VALUE, values.get("flt"));
-		assertEquals(Double.MAX_VALUE, values.get("dbl"));
-		assertEquals("blabla", values.get("strng"));
-
-//		Classes are special
-//		assertEquals("java.lang.Object", ((Clazz.ClassConstant) values.get("clss")).getName());
-	}
-
-	public void testGeneric() throws Exception {
-		print(System.out, WithGenerics.class.getField("field").getGenericType());
-		System.out.println();
-		print(System.out, Class.class);
-		System.out.println();
-		print(System.out, WithGenerics.class);
-		System.out.println();
-	}
-
-	public void print(Appendable sb, Type t) throws Exception {
-		if (t instanceof ParameterizedType) {
-			ParameterizedType pt = (ParameterizedType) t;
-			Class<?> c = (Class<?>) pt.getRawType();
-			sb.append("L");
-			sb.append(c.getCanonicalName().replace('.', '/'));
-			sb.append("<");
-			for (Type arg : pt.getActualTypeArguments()) {
-				print(sb, arg);
-			}
-			sb.append(">");
-			sb.append(";");
-			return;
-		} else if (t instanceof WildcardType) {
-			sb.append("yyyy");
-		} else if (t instanceof GenericArrayType) {
-			sb.append("[" + ((GenericArrayType) t).getGenericComponentType());
-		} else if (t instanceof TypeVariable) {
-			TypeVariable tv = (TypeVariable<?>) t;
-			sb.append("T");
-			sb.append(tv.getName());
-			for (Type upper : tv.getBounds()) {
-				if (upper != Object.class) {
-					sb.append(":");
-					print(sb, upper);
-				}
-			}
-			sb.append(";");
-		} else {
-			Class<?> c = (Class<?>) t;
-			sb.append("L");
-			sb.append(c.getCanonicalName().replace('.', '/'));
-			if (c instanceof GenericDeclaration) {
-				GenericDeclaration gd = (GenericDeclaration) c;
-				if (gd.getTypeParameters().length != 0) {
-					sb.append("<");
-					for (Type arg : gd.getTypeParameters()) {
-						print(sb, arg);
-					}
-					sb.append(">");
-				}
-			}
-			sb.append(";");
-		}
-	}
-
-	/**
-	 * Included an aop alliance class that is not directly referenced.
-	 * 
-	 */
-	public void testUnacceptableReference() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("jar/nl.fuji.general.jar"));
-		b.addClasspath(new File("jar/spring.jar"));
-		b.setProperty("Export-Package", "nl.fuji.log");
-		b.build();
-		assertFalse(b.getImports().containsKey("org.aopalliance.aop"));
-	}
-
-	public void testImplemented() throws Exception {
-		Builder a = new Builder();
-		a.addClasspath(new File("bin"));
-		a.setProperty("Private-Package", "test");
-		a.build();
-		Clazz c = a.getClassspace().get("test/Implemented.class");
-		Set<String> s = Create.set();
-		Clazz.getImplementedPackages(s, a, c);
-		assertTrue(s.contains("aQute.bnd.service"));
-	}
-
-	public void testWildcards() throws Exception {
-		Clazz c = new Clazz("genericstest", null);
-		c.parseClassFile(getClass().getResourceAsStream("WithGenerics.class"));
-		System.out.println(c.getReferred());
-		assertEquals("size ", 5, c.getReferred().size());
-		assertTrue(c.getReferred().contains("aQute.lib.osgi"));
-		assertTrue(c.getReferred().contains("java.util"));
-		assertTrue(c.getReferred().contains("java.net"));
-		assertTrue(c.getReferred().contains("java.lang"));
-	}
-
-	public void testGenericsSignature3() throws Exception {
-		Clazz c = new Clazz("genericstest", null);
-		c.parseClassFile(getClass().getResourceAsStream("Generics.class"));
-		assertTrue(c.getReferred().contains("test"));
-		assertTrue(c.getReferred().contains("aQute.lib.osgi"));
-	}
-
-	public void testGenericsSignature2() throws Exception {
-		Clazz c = new Clazz("genericstest", new FileResource(new File("src/test/generics.clazz")));
-		c.parseClassFile();
-		assertTrue(c.getReferred().contains("javax.swing.table"));
-		assertTrue(c.getReferred().contains("javax.swing"));
-	}
-
-	public void testGenericsSignature() throws Exception {
-		Clazz c = new Clazz("genericstest", new FileResource(new File("src/test/generics.clazz")));
-		c.parseClassFile();
-		assertTrue(c.getReferred().contains("javax.swing.table"));
-		assertTrue(c.getReferred().contains("javax.swing"));
-	}
-
-	/**
-	 * @Neil: I'm trying to use bnd to bundleize a library called JQuantLib, but
-	 *        it causes an ArrayIndexOutOfBoundsException while parsing a class.
-	 *        The problem is reproducible and I have even rebuilt the library
-	 *        from source and get the same problem.
-	 * 
-	 *        Here's the stack trace:
-	 * 
-	 *        java.lang.ArrayIndexOutOfBoundsException: -29373 at
-	 *        aQute.lib.osgi.Clazz.parseClassFile(Clazz.java:262) at
-	 *        aQute.lib.osgi.Clazz.<init>(Clazz.java:101) at
-	 *        aQute.lib.osgi.Analyzer.analyzeJar(Analyzer.java:1647) at
-	 *        aQute.lib.osgi.Analyzer.analyzeBundleClasspath(Analyzer.java:1563)
-	 *        at aQute.lib.osgi.Analyzer.analyze(Analyzer.java:108) at
-	 *        aQute.lib.osgi.Builder.analyze(Builder.java:192) at
-	 *        aQute.lib.osgi.Builder.doConditional(Builder.java:158) at
-	 *        aQute.lib.osgi.Builder.build(Builder.java:71) at
-	 *        aQute.bnd.main.bnd.doBuild(bnd.java:379) at
-	 *        aQute.bnd.main.bnd.run(bnd.java:130) at
-	 *        aQute.bnd.main.bnd.main(bnd.java:39)
-	 * 
-	 * @throws Exception
-	 */
-
-	public void testJQuantlib() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("test/jquantlib-0.1.2.jar"));
-		b.setProperty("Export-Package", "*");
-		b.build();
-	}
-
-	public void testMissingPackage2() throws Exception {
-		InputStream in = getClass().getResourceAsStream("JobsService.clazz");
-		assertNotNull(in);
-		Clazz clazz = new Clazz("test", null);
-		clazz.parseClassFile(in);
-		assertTrue(clazz.getReferred().contains("com.linkedin.member2.pub.profile.core.view"));
-	}
-
-	public void testMissingPackage1() throws Exception {
-		InputStream in = getClass().getResourceAsStream("JobsService.clazz");
-		assertNotNull(in);
-		Clazz clazz = new Clazz("test", null);
-		clazz.parseClassFile(in);
-
-		System.out.println(clazz.getReferred());
-		clazz.parseDescriptor("(IILcom/linkedin/member2/pub/profile/core/view/I18nPositionViews;)Lcom/linkedin/leo/cloud/overlap/api/OverlapQuery;");
-		assertTrue(clazz.getReferred().contains("com.linkedin.member2.pub.profile.core.view"));
-	}
-
-	public void testGeneratedClass() throws IOException {
-		InputStream in = getClass().getResourceAsStream("XDbCmpXView.clazz");
-		assertNotNull(in);
-		Clazz clazz = new Clazz("test", null);
-		clazz.parseClassFile(in);
-		clazz.getReferred();
-	}
-
-	public void testParameterAnnotation() throws IOException {
-		InputStream in = getClass().getResourceAsStream("Test2.jclass");
-		assertNotNull(in);
-		Clazz clazz = new Clazz("test", null);
-		clazz.parseClassFile(in);
-		Set<String> set = clazz.getReferred();
-		assertTrue(set.contains("test"));
-		assertTrue(set.contains("test.annotations"));
-	}
-
-	public void testLargeClass2() throws IOException {
-		try {
-			URL url = new URL(
-					"jar:file:jar/ecj_3.2.2.jar!/org/eclipse/jdt/internal/compiler/parser/Parser.class");
-			InputStream in = url.openStream();
-			assertNotNull(in);
-			Clazz clazz = new Clazz("test", null);
-			clazz.parseClassFile(in);
-		} catch (Exception e) {
-			e.printStackTrace();
-			fail();
-		}
-	}
-
-	/**
-	 * Still problems with the stuff in ecj
-	 */
-	public void testEcj() throws Exception {
-		Builder builder = new Builder();
-		builder.setClasspath(new File[] { new File("jar/ecj_3.2.2.jar") });
-		builder.setProperty(Analyzer.EXPORT_PACKAGE, "org.eclipse.*");
-		builder.build();
-		System.out.println(builder.getErrors());
-		assertEquals(0, builder.getErrors().size());
-		assertEquals(0, builder.getWarnings().size());
-		System.out.println(builder.getErrors());
-		System.out.println(builder.getWarnings());
-	}
-
-	/**
-	 * This class threw an exception because we were using skip instead of
-	 * skipBytes. skip is not guaranteed to real skip the amount of bytes, not
-	 * even if there are still bytes left. It seems to be able to stop skipping
-	 * if it is at the end of a buffer or so :-( Idiots.
-	 * 
-	 * The DataInputStream.skipBytes works correctly.
-	 * 
-	 * @throws IOException
-	 */
-	public void testLargeClass() throws IOException {
-		InputStream in = getClass().getResourceAsStream("Parser.jclass");
-		assertNotNull(in);
-		try {
-			Clazz clazz = new Clazz("test", null);
-			clazz.parseClassFile(in);
-		} catch (Exception e) {
-			e.printStackTrace();
-			fail();
-		}
-	}
-
-	public void testSimple() throws IOException {
-		InputStream in = getClass().getResourceAsStream("WithAnnotations.jclass");
-		assertNotNull(in);
-		Clazz clazz = new Clazz("test", null);
-		clazz.parseClassFile(in);
-		Set<String> set = clazz.getReferred();
-		assertTrue(set.contains("test"));
-		assertTrue(set.contains("test.annotations"));
-	}
-}
diff --git a/biz.aQute.bndlib/src/test/ClassReferenceTest.java b/biz.aQute.bndlib/src/test/ClassReferenceTest.java
deleted file mode 100755
index 1b2100f..0000000
--- a/biz.aQute.bndlib/src/test/ClassReferenceTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package test;
-
-import java.util.*;
-import java.util.jar.*;
-
-import junit.framework.*;
-import aQute.lib.osgi.*;
-
-public class ClassReferenceTest extends TestCase {
-	class Inner {
-		
-	}
-	
-	static {
-		System.out.println(Inner.class);
-	}
-	/**
-	 * We create a JAR with the test.classreferenc.ClassReference class. This
-	 * class contains a javax.swing.Box.class reference Prior to Java 1.5, this
-	 * was done in a silly way that is handled specially. After 1.5 it is a
-	 * normal reference.
-	 * 
-	 * @throws Exception
-	 */
-	public void testReference() throws Exception {
-		Properties properties = new Properties();
-		properties.put("-classpath", "compilerversions/compilerversions.jar");
-		String[] packages = { "sun_1_1", "sun_1_6", "eclipse_1_1", "sun_1_2", "sun_1_3", "sun_1_4",
-				"sun_1_5", "sun_jsr14", "eclipse_1_5", "eclipse_1_6", "eclipse_1_2",
-				"eclipse_1_3", "eclipse_1_4", "eclipse_jsr14" };
-		for ( int i =0; i<packages.length; i++ ) {
-			Builder builder = new Builder();
-			properties.put("Export-Package", packages[i]);
-			builder.setProperties(properties);
-			Jar jar = builder.build();
-			System.out.println(builder.getErrors());
-			System.out.println(builder.getWarnings());
-			assertEquals(0,builder.getErrors().size());
-			assertEquals(0,builder.getWarnings().size());
-
-			Manifest manifest = jar.getManifest();
-			String imports = manifest.getMainAttributes()
-					.getValue("Import-Package");
-			assertTrue("Package " + packages[i] + "contains swing ref", imports.indexOf("javax.swing")>=0);			
-			assertFalse("Package " + packages[i] + "should not contain ClassRef", imports.indexOf("ClassRef")>=0);			
-		}
-	}
-}
diff --git a/biz.aQute.bndlib/src/test/ClasspathTest.java b/biz.aQute.bndlib/src/test/ClasspathTest.java
deleted file mode 100755
index 4162a05..0000000
--- a/biz.aQute.bndlib/src/test/ClasspathTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package test;
-
-import java.io.*;
-import java.util.*;
-import java.util.jar.*;
-
-import junit.framework.*;
-import aQute.lib.osgi.*;
-
-public class ClasspathTest extends TestCase {
-
-    /**
-     * Test if we can refer to the jars on the classpath by their file name (
-     * ignoring the path)
-     * 
-     * @throws Exception
-     */
-    public void testBundleClasspath() throws Exception {
-        Builder b = new Builder();
-        b.setProperty("Include-Resource", "bin=bin");
-        b.setProperty("Bundle-Classpath", "bin");
-
-        Jar jar = b.build();
-        assertNotNull(jar.getResource("bin/aQute/lib/osgi/Verifier.class")); // from
-                                                                    // test.jar
-    }
-    
-	/**
-	 * Test if we can refer to the jars on the classpath by their file name (
-	 * ignoring the path)
-	 * 
-	 * @throws Exception
-	 */
-	public void testFindJarOnClasspath() throws Exception {
-		Properties p = new Properties();
-		p.put("Include-Resource", "tb1.jar, @test.jar");
-
-		Builder b = new Builder();
-		b.setClasspath(new String[] { "src", "src/test/test.jar",
-				"src/test/tb1.jar" });
-		b.setProperties(p);
-		Jar jar = b.build();
-		assertNotNull(jar.getResource("aQute/lib/aim/AIM.class")); // from
-																	// test.jar
-		assertNotNull(jar.getResource("tb1.jar"));
-	}
-
-	/**
-	 * Test if we can use URLs on the classpath
-	 * 
-	 * @throws Exception
-	 */
-	public void testSimple() throws Exception {
-		Properties p = new Properties();
-		p.put("-classpath", new File("jar/osgi.jar").toURI().toURL().toString());
-		p.put("Export-Package", "org.osgi.service.event");
-		p.put("Private-Package", "test.refer");
-
-		Builder b = new Builder();
-		b.setClasspath(new String[] { "bin" });
-		b.setProperties(p);
-		Jar jar = b.build();
-		Manifest m = jar.getManifest();
-		String importPackage = m.getMainAttributes().getValue("Import-Package");
-		assertTrue(importPackage.contains("org.osgi.framework;version=\"[1.3,2)\""));
-		assertTrue(importPackage.contains("org.osgi.service.event;version=\"[1.0,2)\""));
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/test/ClazzTest.java b/biz.aQute.bndlib/src/test/ClazzTest.java
deleted file mode 100644
index 082939d..0000000
--- a/biz.aQute.bndlib/src/test/ClazzTest.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package test;
-
-import aQute.lib.osgi.*;
-import junit.framework.*;
-
-public class ClazzTest extends TestCase {
-
-	
-	
-	/**
-	 * Test the uncamel
-	 */
-	
-	public void testUncamel() throws Exception {
-		assertEquals("New", Clazz.unCamel("_new"));
-		assertEquals("An XMLMessage", Clazz.unCamel("anXMLMessage"));
-		assertEquals("A message", Clazz.unCamel("aMessage"));
-		assertEquals("URL", Clazz.unCamel("URL"));
-		assertEquals("A nice party", Clazz.unCamel("aNiceParty"));
-	}
-}
diff --git a/biz.aQute.bndlib/src/test/CompareTest.java b/biz.aQute.bndlib/src/test/CompareTest.java
deleted file mode 100644
index 3ef8c99..0000000
--- a/biz.aQute.bndlib/src/test/CompareTest.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package test;
-
-import java.io.*;
-import java.lang.reflect.*;
-import java.util.*;
-
-import junit.framework.*;
-
-public class CompareTest<O extends Serializable> extends TestCase {
-	
-	
-	interface I<T> {}
-	
-	class B {
-		class C<X extends O> {}
-	}
-	
-	class A0 {}
-	
-	// Declarations
-	class A1<T> { // 
-	}
-	class A2<T extends Serializable> { // 
-	}
-	
-	class A3<T extends Exception & Serializable> { // 
-	}	
-	public String foo0() { return null; }
-	public <T> T foo1() { return null; }
-	public <T extends Serializable> T foo2() {return null; }
-	public <T extends Exception & I<String>> T foo3() {return null;}
-	public <T extends O> T foo4() { return null; }
-	
-	public void testGenericDeclaration() throws Exception {
-		assertTrue( A0.class.getTypeParameters().length == 0 );
-		
-		assertTrue( A1.class.getTypeParameters().length == 1 );
-		assertEquals( "T", A1.class.getTypeParameters()[0].getName() );
-		assertEquals( 1, A1.class.getTypeParameters()[0].getBounds().length);
-		assertEquals( Object.class, A1.class.getTypeParameters()[0].getBounds()[0]);
-		
-		assertTrue( A2.class.getTypeParameters().length == 1 );
-		assertEquals( "T", A2.class.getTypeParameters()[0].getName() );
-		assertEquals( 1, A2.class.getTypeParameters()[0].getBounds().length);
-		assertEquals( Serializable.class, A2.class.getTypeParameters()[0].getBounds()[0]);
-
-		assertTrue( A3.class.getTypeParameters().length == 1 );
-		assertEquals( "T", A3.class.getTypeParameters()[0].getName() );
-		assertEquals( 2, A3.class.getTypeParameters()[0].getBounds().length);
-		assertEquals( Exception.class, A3.class.getTypeParameters()[0].getBounds()[0]);
-		assertEquals( Serializable.class, A3.class.getTypeParameters()[0].getBounds()[1]);
-
-		Method m = getClass().getMethod("foo0");
-		assertEquals( 0, m.getTypeParameters().length);
-		
-		m = getClass().getMethod("foo1");
-		assertEquals( 1, m.getTypeParameters().length);
-		assertEquals( "T", m.getTypeParameters()[0].getName() );
-		assertEquals( 1, m.getTypeParameters()[0].getBounds().length);
-		assertEquals( Object.class, m.getTypeParameters()[0].getBounds()[0]);
-		
-		m = getClass().getMethod("foo3");
-		assertEquals( 1, m.getTypeParameters().length);
-		assertEquals( "T", m.getTypeParameters()[0].getName() );
-		assertEquals( 2, m.getTypeParameters()[0].getBounds().length);
-		assertEquals( Exception.class, m.getTypeParameters()[0].getBounds()[0]);
-		
-		m = getClass().getMethod("foo4");
-		assertEquals( 1, m.getTypeParameters().length);
-		assertEquals( "T", m.getTypeParameters()[0].getName() );
-		assertEquals( 1, m.getTypeParameters()[0].getBounds().length);
-		assertTrue( m.getTypeParameters()[0].getBounds()[0] instanceof TypeVariable );
-		assertEquals( getClass(), ((TypeVariable)m.getTypeParameters()[0].getBounds()[0]).getGenericDeclaration());
-		
-	}
-	
-	public A1<Collection<String>[]> a1;
-	
-	<X extends A1> A1<? extends X> bar() { return null; }
-	
-	
-	public void testSimple() throws IOException {
-		
-		
-		
-		
-//		Scope root = new Scope(Access.PUBLIC, Kind.ROOT, ".");
-//		RuntimeSignatureBuilder pc = new RuntimeSignatureBuilder(root);
-//		pc.add(CompareTest.class);
-//		pc.add(A.class);
-//		pc.add(A.B.class);
-//
-//		A a = new A<String, String, String, String, String>();
-//
-//		pc.add(a.bar().getClass());
-//		pc.add(a.bar().foo().getClass());
-//
-//		// ParseSignatureBuilder pb = new ParseSignatureBuilder(root);
-//		// pb.parse(new FileInputStream("bin/test/CompareTest$A$B$1.class"));
-//		// pb.parse(new FileInputStream("bin/test/CompareTest$A$1.class"));
-//		// pb.parse(new FileInputStream("bin/test/CompareTest$Z.class"));
-//
-//		root.cleanRoot();
-//		PrintWriter pw = new PrintWriter(System.out);
-//		root.report(pw, 0);
-//		pw.flush();
-//
-//		root.prune(EnumSet.of(Access.PUBLIC, Access.PROTECTED));
-//		root.report(pw, 0);
-//		pw.flush();
-
-	}
-}
diff --git a/biz.aQute.bndlib/src/test/ComponentTest.java b/biz.aQute.bndlib/src/test/ComponentTest.java
deleted file mode 100755
index 6935532..0000000
--- a/biz.aQute.bndlib/src/test/ComponentTest.java
+++ /dev/null
@@ -1,1129 +0,0 @@
-package test;
-
-import java.io.*;
-import java.util.*;
-import java.util.jar.*;
-
-import javax.xml.namespace.*;
-import javax.xml.parsers.*;
-import javax.xml.xpath.*;
-
-import junit.framework.*;
-
-import org.osgi.framework.*;
-import org.osgi.service.component.*;
-import org.osgi.service.event.*;
-import org.osgi.service.log.*;
-import org.w3c.dom.*;
-import org.xml.sax.*;
-
-import aQute.bnd.annotation.component.*;
-import aQute.bnd.annotation.metatype.*;
-import aQute.lib.io.*;
-import aQute.lib.osgi.*;
-import aQute.lib.osgi.Constants;
-
-public class ComponentTest extends TestCase {
-	final DocumentBuilderFactory	dbf		= DocumentBuilderFactory.newInstance();
-	final XPathFactory				xpathf	= XPathFactory.newInstance();
-	final XPath						xpath	= xpathf.newXPath();
-	DocumentBuilder					db;
-
-	{
-		try {
-			dbf.setNamespaceAware(true);
-			db = dbf.newDocumentBuilder();
-			xpath.setNamespaceContext(new NamespaceContext() {
-
-				public Iterator getPrefixes(String namespaceURI) {
-					return Arrays.asList("md", "scr").iterator();
-				}
-
-				public String getPrefix(String namespaceURI) {
-					if (namespaceURI.equals("http://www.osgi.org/xmlns/metatype/v1.1.0"))
-						return "md";
-					if (namespaceURI.equals("http://www.osgi.org/xmlns/scr/v1.1.0"))
-						return "scr";
-
-					return null;
-				}
-
-				public String getNamespaceURI(String prefix) {
-					if (prefix.equals("md"))
-						return "http://www.osgi.org/xmlns/metatype/v1.1.0";
-					else if (prefix.equals("scr"))
-						return "http://www.osgi.org/xmlns/scr/v1.1.0";
-					else
-						return null;
-				}
-			});
-		} catch (ParserConfigurationException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		}
-	}
-
-	/**
-	 * Can we order the references? References are ordered by their name as Java does not
-	 * define the order of the methods.
-	 * 
-	 * @throws Exception 
-	 */
-	
-	@Component static class TestReferenceOrdering {
-		
-		@Reference(service=LogService.class)
-		void setA(ServiceReference ref) {}
-		@Reference
-		void setC(LogService log) {}
-		@Reference(service=LogService.class)
-		void setB(Map<String,Object> map) {}
-	}
-	
-	public void testReferenceOrdering () throws Exception {
-		Builder b = new Builder();
-		b.addClasspath( new File( "bin"));
-		b.setProperty("Service-Component", "*TestReferenceOrdering");
-		b.setProperty("Private-Package", "test");
-		Jar jar = b.build();
-		Document doc = doc(b, "test.ComponentTest$TestReferenceOrdering");
-		NodeList nodes = (NodeList) xpath.evaluate("//reference", doc, XPathConstants.NODESET);
-		assertEquals("a", nodes.item(0).getAttributes().getNamedItem("name").getTextContent());
-		assertEquals("b", nodes.item(1).getAttributes().getNamedItem("name").getTextContent());
-		assertEquals("c", nodes.item(2).getAttributes().getNamedItem("name").getTextContent());
-	}
-
-	
-	
-	/**
-	 * Test to see if we ignore scala.ScalaObject as interface
-	 * @throws Exception 
-	 */
-	public void testScalaObject () throws Exception {
-		Builder b = new Builder();
-		b.addClasspath( new File( "jar/com.test.scala.jar"));
-		b.setProperty("Service-Component", "*");
-		b.setProperty("Export-Package", "com.test.scala.*");
-		Jar jar = b.build();
-		Manifest m = jar.getManifest();
-		System.out.println(Processor.join(b.getErrors()));
-		System.out.println(Processor.join(b.getWarnings()));
-		System.out.println(m.getMainAttributes().getValue("Service-Component"));
-		IO.copy(jar.getResource("OSGI-INF/com.test.scala.Service.xml").openInputStream(), System.out);
-		Document doc = doc(b, "com.test.scala.Service");
-		assertEquals("com.test.scala.Service", xpath.evaluate("component/implementation/@class", doc));
-		assertEquals("", xpath.evaluate("component/service/provide/@interface", doc));
-		
-	}
-	
-	
-	
-	
-	/**
-	 * Test config with metatype
-	 */
-
-	@Component(name = "config", designateFactory = Config.class, configurationPolicy = ConfigurationPolicy.require) static class MetatypeConfig {
-		interface Config {
-			String name();
-		}
-	}
-
-	@Component(designate = Config.class) static class MetatypeConfig2 {
-		interface Config {
-			String name();
-		}
-	}
-
-	public void testConfig() throws Exception {
-		Builder b = new Builder();
-		b.setExceptions(true);
-		b.setClasspath(new File[] { new File("bin") });
-		b.setProperty("Service-Component", "*MetatypeConfig*");
-		b.setProperty("Private-Package", "test");
-		b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-		System.out.println(b.getJar().getResources().keySet());
-
-		// Check component name
-		{
-			Resource cr = b.getJar().getResource("OSGI-INF/config.xml");
-			cr.write(System.out);
-			Document d = db.parse(cr.openInputStream());
-			assertEquals("config", xpath.evaluate("/scr:component/@name", d, XPathConstants.STRING));
-		}
-
-		// Check if config properly linked
-		{
-			Resource mr = b.getJar().getResource("OSGI-INF/metatype/config.xml");
-			mr.write(System.out);
-			Document d = db.parse(mr.openInputStream());
-			assertEquals("config", xpath.evaluate("//Designate/@factoryPid", d,
-					XPathConstants.STRING));
-			assertEquals("config", xpath.evaluate("//Object/@ocdref", d,
-					XPathConstants.STRING));
-		}
-
-		// Now with default name
-		{
-			Resource cr2 = b.getJar()
-					.getResource("OSGI-INF/test.ComponentTest$MetatypeConfig2.xml");
-			cr2.write(System.out);
-			Document d = db.parse(cr2.openInputStream());
-			assertEquals("test.ComponentTest$MetatypeConfig2", xpath.evaluate("//scr:component/@name",
-					d, XPathConstants.STRING));
-		}
-		{
-			Resource mr2 = b.getJar().getResource(
-					"OSGI-INF/metatype/test.ComponentTest$MetatypeConfig2.xml");
-			mr2.write(System.out);
-			Document d = db.parse(mr2.openInputStream());
-			assertEquals("test.ComponentTest$MetatypeConfig2", xpath.evaluate(
-					"//Designate/@pid", d, XPathConstants.STRING));
-			assertEquals("test.ComponentTest$MetatypeConfig2", xpath.evaluate("//Object/@ocdref", d,
-					XPathConstants.STRING));
-		}
-	}
-
-	/**
-	 * Test properties
-	 */
-	@Meta.OCD static interface Config {
-		String name();
-	}
-
-	@Component(name = "props", properties = { "a=1", "b=3", "c=1|2|3" }, designate = Config.class, designateFactory = Config.class) static class PropertiesAndConfig {
-		@Activate protected void activate(ComponentContext c) {
-		}
-	}
-
-	public void testPropertiesAndConfig() throws Exception {
-		Builder b = new Builder();
-		b.setExceptions(true);
-		b.setClasspath(new File[] { new File("bin") });
-		b.setProperty("Service-Component", "*PropertiesAndConfig");
-		b.setProperty("Private-Package", "test");
-		b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		Resource cr = b.getJar().getResource("OSGI-INF/props.xml");
-		cr.write(System.out);
-		{
-			Document doc = doc(b, "props");
-			assertEquals("1", xpath.evaluate("scr:component/property[@name='a']/@value", doc));
-			assertEquals("3", xpath.evaluate("scr:component/property[@name='b']/@value", doc));
-			assertEquals("\n1\n2\n3\n", xpath.evaluate("scr:component/property[@name='c']", doc));
-		}
-
-	}
-
-	/**
-	 * Test if a reference is made to an interface implemented on a superclass.
-	 * 
-	 * This is from https://github.com/bndtools/bnd/issues#issue/23
-	 */
-
-	public void testProvideFromSuperClass() throws Exception {
-		Builder b = new Builder();
-		b.setClasspath(new File[] { new File("bin") });
-		b.setProperty("Service-Component", "*InheritedActivator");
-		b.setProperty("Private-Package", "test.activator.inherits");
-		b.addClasspath(new File("jar/osgi.jar"));
-		b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		Manifest m = b.getJar().getManifest();
-		String imports = m.getMainAttributes().getValue("Import-Package");
-		assertTrue(imports.contains("org.osgi.framework"));
-	}
-
-	/**
-	 * Test if a package private method gives us 1.1 + namespace in the XML
-	 */
-
-	@Component(name = "packageprotected") static class PackageProtectedActivateMethod {
-		@Activate protected void activate(ComponentContext c) {
-		}
-	}
-
-	@Component(name = "packageprivate") static class PackagePrivateActivateMethod {
-		@Activate void activate(ComponentContext c) {
-		}
-	}
-
-	public void testPackagePrivateActivateMethod() throws Exception {
-		Builder b = new Builder();
-		b.setClasspath(new File[] { new File("bin") });
-		b.setProperty("Service-Component", "*Package*ActivateMethod");
-		b.setProperty("Private-Package", "test");
-		b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		{
-			Document doc = doc(b, "packageprotected");
-			Object o = xpath.evaluate("component", doc, XPathConstants.NODE);
-			assertNotNull(o);
-		}
-		{
-			Resource r = b.getJar().getResource("OSGI-INF/packageprivate.xml");
-			r.write(System.out);
-			assertNotNull(r);
-			Document doc = db.parse(r.openInputStream());
-			assertNotNull(xpath.evaluate("//scr:component/@name", doc, XPathConstants.STRING));
-		}
-
-	}
-
-	/**
-	 * Test an attribute on an annotation
-	 */
-
-	@Component(name = "annotated") static class Annotated {
-
-		@Reference protected void setLog(LogService log) {
-		}
-
-	}
-
-	public void testAnnotatedWithAttribute() throws Exception {
-		Builder b = new Builder();
-		b.setClasspath(new File[] { new File("bin") });
-		b.setProperty("Service-Component", "*NoUnbind;log=org.osgi.service.log.LogService");
-		b.setProperty("Private-Package", "test");
-		Jar jar = b.build();
-		Manifest manifest = jar.getManifest();
-		String sc = manifest.getMainAttributes().getValue(Constants.SERVICE_COMPONENT);
-		assertFalse(sc.contains(";"));
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-	}
-
-	/**
-	 * A non-FQN entry but we demand no annotations, should generate an error
-	 * and no component
-	 */
-
-	public void testNonFQNAndNoAnnotations() throws Exception {
-		Builder b = new Builder();
-		b
-				.setProperty("Include-Resource",
-						"org/osgi/impl/service/coordinator/AnnotationWithJSR14.class=jar/AnnotationWithJSR14.jclass");
-		b.setProperty("Service-Component", "*;" + Constants.NOANNOTATIONS + "=true");
-		b.setProperty("-resourceonly", "true");
-		Jar jar = b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(1, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		Manifest manifest = jar.getManifest();
-		String component = manifest.getMainAttributes().getValue("Service-Component");
-		System.out.println(component);
-		assertNull(component);
-	}
-
-	/**
-	 * Imported default package because JSR14 seems to do something weird with
-	 * annotations.
-	 * 
-	 * @throws Exception
-	 */
-	public void testJSR14ComponentAnnotations() throws Exception {
-		Builder b = new Builder();
-		b
-				.setProperty("Include-Resource",
-						"org/osgi/impl/service/coordinator/AnnotationWithJSR14.class=jar/AnnotationWithJSR14.jclass");
-		b.setProperty("Service-Component", "*");
-		b.setProperty("-resourceonly", "true");
-		Jar jar = b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(1, b.getWarnings().size());
-
-		Manifest manifest = jar.getManifest();
-		String component = manifest.getMainAttributes().getValue("Service-Component");
-		System.out.println(component);
-		assertNull(component);
-	}
-
-	@Component(name = "nounbind") static class NoUnbind {
-
-		@Reference protected void setLog(LogService log) {
-		}
-
-	}
-
-	public void testNoUnbind() throws Exception {
-		Builder b = new Builder();
-		b.setClasspath(new File[] { new File("bin") });
-		b.setProperty("Service-Component", "*NoUnbind");
-		b.setProperty("Private-Package", "test");
-		b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		Document doc = doc(b, "nounbind");
-		assertEquals("setLog", xpath.evaluate("component/reference/@bind", doc));
-		assertEquals("", xpath.evaluate("component/reference/@unbind", doc));
-	}
-
-	@Component(name = "explicitunbind") static class ExplicitUnbind {
-
-		@Reference(unbind = "killLog") protected void setLog(LogService log) {
-		}
-
-	}
-
-	public void testExplicitUnbind() throws Exception {
-		Builder b = new Builder();
-		b.setClasspath(new File[] { new File("bin") });
-		b.setProperty("Service-Component", "*ExplicitUnbind");
-		b.setProperty("Private-Package", "test");
-		b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(1, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		Document doc = doc(b, "explicitunbind");
-		assertEquals("setLog", xpath.evaluate("component/reference/@bind", doc));
-		assertEquals("killLog", xpath.evaluate("component/reference/@unbind", doc));
-	}
-
-	/**
-	 * Test to see if we get a namespace when we use 1.1 semantics on the
-	 * activate and deactivate
-	 */
-
-	@Component(name = "ncomp", provide = {}) static class NewActivateVersion {
-
-		@Activate protected void activate(ComponentContext context) {
-		}
-
-	}
-
-	@Component(name = "ndcomp", provide = {}) static class NewDeActivateVersion {
-		@Deactivate protected void deactivate() {
-		}
-
-	}
-
-	@Component(name = "nbcomp", provide = {}) static class NewBindVersion {
-
-		@Reference protected void bind(ServiceReference ref, Map<String, Object> map) {
-		}
-
-	}
-
-	public void testNewVersion() throws Exception {
-		Builder b = new Builder();
-		b.setClasspath(new File[] { new File("bin") });
-		b.setProperty("Service-Component", "*Version");
-		b.setProperty("Private-Package", "test");
-		b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		{
-			Document doc = doc(b, "ncomp");
-			Node o = (Node) xpath.evaluate("component", doc, XPathConstants.NODE);
-			assertNotNull("Expected ncomp to have old namespace", o);
-		}
-
-		// Node node = doc.getElementsByTagName("component").item(0);
-		// assertNotNull(node.getNamespaceURI());
-		// doc = doc(b, "ndcomp");
-		// assertNotNull(doc.getElementsByTagName("component").item(0).getNamespaceURI());
-		// doc = doc(b, "nbcomp");
-		// assertNotNull(doc.getElementsByTagName("component").item(0).getNamespaceURI());
-	}
-
-	/**
-	 * Test the same bind method names
-	 */
-
-	@Component(name = "cpcomp") static class SameRefName {
-
-		@Reference protected void bind(LogService log) {
-
-		}
-
-		@Reference protected void bind(EventAdmin event) {
-
-		}
-	}
-
-	public void testSameRefName() throws Exception {
-		Builder b = new Builder();
-		b.setClasspath(new File[] { new File("bin") });
-		b.setProperty("Service-Component", "*.SameRefName");
-		b.setProperty("Private-Package", "test");
-		b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(1, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		// Document doc = doc(b, "cpcomp");
-	}
-
-	/**
-	 * Test the configuration policy
-	 */
-
-	@Component(name = "cpcomp", configurationPolicy = ConfigurationPolicy.require, provide = {
-			Serializable.class, EventAdmin.class }) static class ConfigurationPolicyTest {
-
-	}
-
-	public void testConfigurationPolicy() throws Exception {
-		Builder b = new Builder();
-		b.setClasspath(new File[] { new File("bin") });
-		b.setProperty("Service-Component", "*.ConfigurationPolicyTest");
-		b.setProperty("Private-Package", "test");
-		b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		Document doc = doc(b, "cpcomp");
-		assertEquals("java.io.Serializable", doc.getElementsByTagName("provide").item(0)
-				.getAttributes().getNamedItem("interface").getTextContent());
-		assertEquals("org.osgi.service.event.EventAdmin", doc.getElementsByTagName("provide").item(
-				1).getAttributes().getNamedItem("interface").getTextContent());
-
-	}
-
-	/**
-	 * Test to see if we use defaults we get the old version of the namespace
-	 */
-
-	@Component(name = "vcomp", provide = {}) static class OldVersion {
-
-		@Activate protected void activate(ComponentContext cc) {
-		}
-
-		@Deactivate protected void deactivate(ComponentContext cc) {
-		}
-
-		@Reference protected void bindLog(LogService log) {
-
-		}
-	}
-
-	public void testOldVersion() throws Exception {
-		Builder b = new Builder();
-		b.setClasspath(new File[] { new File("bin") });
-		b.setProperty("Service-Component", "*.OldVersion");
-		b.setProperty("Private-Package", "test");
-		b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		Document doc = doc(b, "vcomp");
-		assertEquals(null, doc.getElementsByTagName("component").item(0).getNamespaceURI());
-	}
-
-	/**
-	 * Test if an activate/deactivate method that has wrong prototype
-	 */
-
-	@Component(name = "wacomp", provide = {}) static class ActivateWithWrongArguments {
-
-		@Activate// Is not allowed, must give an error
-		protected void whatever(String x) {
-		}
-
-	}
-
-	public void testActivateWithActivateWithWrongArguments() throws Exception {
-		Builder b = new Builder();
-		b.setClasspath(new File[] { new File("bin") });
-		b.setProperty("Service-Component", "*.ActivateWithWrongArguments");
-		b.setProperty("Private-Package", "test");
-		b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(1, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		Document doc = doc(b, "wacomp");
-		assertEquals("whatever", xpath.evaluate("scr:component/@activate",doc,XPathConstants.STRING));
-		assertAttribute(doc, "whatever", "scr:component/@activate");
-	}
-
-	/**
-	 * Test if an activate/deactivate method can have multiple args
-	 */
-
-	@Component(name = "amcomp", provide = {}) static class ActivateWithMultipleArguments {
-
-		@Activate protected void whatever(Map<?, ?> map, ComponentContext cc, BundleContext bc,
-				Map<?, ?> x) {
-		}
-
-	}
-
-	public void testActivateWithMultipleArguments() throws Exception {
-		Builder b = new Builder();
-		b.setClasspath(new File[] { new File("bin") });
-		b.setProperty("Service-Component", "*.ActivateWithMultipleArguments");
-		b.setProperty("Private-Package", "test");
-		b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		Document doc = doc(b, "amcomp");
-		assertAttribute(doc, "whatever", "scr:component/@activate");
-	}
-
-	/**
-	 * Test components with references that have multiple arguments.
-	 */
-	@Component(name = "mcomp", provide = {}) static class MultipleArguments {
-
-		@Reference protected void bindWithMap(LogService log, Map<?, ?> map) {
-		}
-
-	}
-
-	@Component(name = "rcomp", provide = {}) static class ReferenceArgument {
-
-		@Reference(service = LogService.class) protected void bindReference(ServiceReference ref) {
-		}
-
-	}
-
-	public void testMultipleArguments() throws Exception {
-		Builder b = new Builder();
-		b.setClasspath(new File[] { new File("bin") });
-		b.setProperty("Service-Component", "*.(MultipleArguments|ReferenceArgument)");
-		b.setProperty("Private-Package", "test");
-		b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		Document doc = doc(b, "mcomp");
-		assertAttribute(doc, "bindWithMap", "scr:component/reference/@bind");
-		assertAttribute(doc, "org.osgi.service.log.LogService",
-				"scr:component/reference/@interface");
-
-		doc = doc(b, "rcomp");
-		assertAttribute(doc, "bindReference", "scr:component/reference/@bind");
-		assertAttribute(doc, "org.osgi.service.log.LogService",
-				"scr:component/reference/@interface");
-	}
-
-	/**
-	 * Test components with weird bind methods.
-	 */
-	@Component(name = "xcomp", provide = {}) static class TypeVersusDetailed {
-
-		@Reference(type = '*') protected void bind(LogService log) {
-		}
-
-		@Reference(multiple = true, optional = true, dynamic = true) protected void bind2(
-				LogService log) {
-		}
-	}
-
-	public void testTypeVersusDetailed() throws Exception {
-		Builder b = new Builder();
-		b.setClasspath(new File[] { new File("bin") });
-		b.setProperty("Service-Component", "*.TypeVersusDetailed");
-		b.setProperty("Private-Package", "test");
-		b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		Document doc = doc(b, "xcomp");
-		print(doc, "");
-		assertAttribute(doc, "bind2", "component/reference[1]/@bind");
-		assertAttribute(doc, "dynamic", "component/reference[1]/@policy");
-		assertAttribute(doc, "0..n", "component/reference[1]/@cardinality");
-		assertAttribute(doc, "bind", "component/reference[2]/@bind");
-		assertAttribute(doc, "dynamic", "component/reference[2]/@policy");
-		assertAttribute(doc, "0..n", "component/reference[2]/@cardinality");
-	}
-
-	/**
-	 * Test components with weird bind methods.
-	 */
-	@Component(name = "acomp", provide = {}) static class MyComponent4 {
-		@Activate protected void xyz() {
-		}
-	}
-
-	public void testAnnotationsNamespaceVersion() throws Exception {
-		Builder b = new Builder();
-		b.setClasspath(new File[] { new File("bin") });
-		b.setProperty("Service-Component", "*.MyComponent4");
-		b.setProperty("Private-Package", "test");
-		b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		Document doc = doc(b, "acomp");
-		System.out.println(doc.getDocumentElement().getNamespaceURI());
-	}
-
-	/**
-	 * Test components with weird bind methods.
-	 */
-	@Component(name = "acomp", configurationPolicy = ConfigurationPolicy.require) static class MyComponent2 {
-		@Reference protected void addLogMultiple(LogService log) {
-
-		}
-	}
-
-	public void testAnnotationsStrangeBindMethods() throws Exception {
-		Builder b = new Builder();
-		b.setClasspath(new File[] { new File("bin") });
-		b.setProperty("Service-Component", "*.MyComponent2");
-		b.setProperty("Private-Package", "test");
-		b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		Document doc = doc(b, "acomp");
-		assertEquals("addLogMultiple", xpath.evaluate("//@bind", doc));
-		assertEquals("", xpath.evaluate("//@unbind", doc));
-
-		assertAttribute(doc, "logMultiple", "scr:component/reference[1]/@name");
-		assertAttribute(doc, "addLogMultiple", "scr:component/reference[1]/@bind");
-
-	}
-
-	/**
-	 * Test setting the unbind method
-	 */
-	@Component(name = "acomp", configurationPolicy = ConfigurationPolicy.ignore) static class MyComponent3 {
-		@Reference(unbind = "destroyX") protected void putX(LogService log) {
-
-		}
-	}
-
-	public void testAnnotationsSettingUnbind() throws Exception {
-		Builder b = new Builder();
-		b.setClasspath(new File[] { new File("bin") });
-		b.setProperty("Service-Component", "*.MyComponent3");
-		b.setProperty("Private-Package", "test");
-		b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(1, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		Document doc = doc(b, "acomp");
-		assertAttribute(doc, "putx", "scr:component/reference[1]/@name");
-		assertAttribute(doc, "putX", "scr:component/reference[1]/@bind");
-		assertAttribute(doc, "destroyX", "scr:component/reference[1]/@unbind");
-	}
-
-	/**
-	 * Test some more components
-	 * 
-	 * @author aqute
-	 * 
-	 */
-	@Component(name = "acomp", enabled = true, factory = "abc", immediate = false, provide = LogService.class, servicefactory = true, configurationPolicy = ConfigurationPolicy.optional) static class MyComponent
-			implements Serializable {
-		private static final long	serialVersionUID	= 1L;
-		LogService					log;
-
-		@Activate protected void activatex() {
-		}
-
-		@Deactivate protected void deactivatex() {
-		}
-
-		@Modified protected void modifiedx() {
-		}
-
-		@Reference(type = '~', target = "(abc=3)") protected void setLog(LogService log) {
-			this.log = log;
-		}
-
-		protected void unsetLog(LogService log) {
-			this.log = null;
-		}
-
-	}
-
-	public void testAnnotations() throws Exception {
-		Builder b = new Builder();
-		b.setClasspath(new File[] { new File("bin") });
-		b.setProperty("Service-Component", "*.MyComponent");
-		b.setProperty("Private-Package", "test");
-		b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		Document doc = doc(b, "acomp");
-		print(doc, "");
-		assertAttribute(doc, "test.ComponentTest$MyComponent",
-				"scr:component/implementation/@class");
-		assertAttribute(doc, "acomp", "scr:component/@name");
-		assertAttribute(doc, "abc", "scr:component/@factory");
-		assertAttribute(doc, "true", "scr:component/service/@servicefactory");
-		assertAttribute(doc, "activatex", "scr:component/@activate");
-		assertAttribute(doc, "modifiedx", "scr:component/@modified");
-		assertAttribute(doc, "deactivatex", "scr:component/@deactivate");
-		assertAttribute(doc, "org.osgi.service.log.LogService",
-				"scr:component/service/provide/@interface");
-		assertAttribute(doc, "(abc=3)", "scr:component/reference/@target");
-		assertAttribute(doc, "setLog", "scr:component/reference/@bind");
-		assertAttribute(doc, "unsetLog", "scr:component/reference/@unbind");
-		assertAttribute(doc, "0..1", "scr:component/reference/@cardinality");
-	}
-
-	public void assertAttribute(Document doc, String value, String expr)
-			throws XPathExpressionException {
-		System.out.println(expr);
-		String o = (String) xpath.evaluate(expr, doc, XPathConstants.STRING);
-		if ( o == null ) {
-			
-		}
-		assertNotNull(o);
-		assertEquals(value, o);
-	}
-
-	Document doc(Builder b, String name) throws Exception {
-		Jar jar = b.getJar();
-		Resource r = jar.getResource("OSGI-INF/" + name + ".xml");
-		assertNotNull(r);
-		Document doc = db.parse(r.openInputStream());
-		r.write(System.out);
-		return doc;
-	}
-
-	public void testV1_1Directives() throws Exception {
-		Element component = setup("test.activator.Activator;factory:=blabla;immediate:=true;enabled:=false;configuration-policy:=optional;activate:=start;deactivate:=stop;modified:=modified");
-		assertEquals("http://www.osgi.org/xmlns/scr/v1.1.0", component.getNamespaceURI());
-		assertEquals("blabla", component.getAttribute("factory"));
-		assertEquals("false", component.getAttribute("enabled"));
-		assertEquals("optional", component.getAttribute("configuration-policy"));
-		assertEquals("start", component.getAttribute("activate"));
-		assertEquals("stop", component.getAttribute("deactivate"));
-		assertEquals("modified", component.getAttribute("modified"));
-
-	}
-
-	public void testNoNamespace() throws Exception {
-		Element component = setup("test.activator.Activator");
-		assertEquals(null, component.getNamespaceURI());
-	}
-
-	public void testAutoNamespace() throws Exception {
-		Element component = setup("test.activator.Activator;activate:='start';deactivate:='stop'");
-		assertEquals("http://www.osgi.org/xmlns/scr/v1.1.0", component.getNamespaceURI());
-
-	}
-
-	public void testCustomNamespace() throws Exception {
-		Element component = setup("test.activator.Activator;version:=2");
-		assertEquals("http://www.osgi.org/xmlns/scr/v2.0.0", component.getNamespaceURI());
-
-	}
-
-	Element setup(String header) throws Exception {
-		Builder b = new Builder();
-		b.setProperty(Analyzer.SERVICE_COMPONENT, header);
-		b.setClasspath(new File[] { new File("bin"), new File("jar/osgi.jar") });
-		b.setProperty("Private-Package", "test.activator, org.osgi.service.http.*");
-		b.build();
-
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		print(b.getJar().getResource("OSGI-INF/test.activator.Activator.xml"), System.out);
-		Document doc = db.parse(new InputSource(b.getJar().getResource(
-				"OSGI-INF/test.activator.Activator.xml").openInputStream()));
-
-		return doc.getDocumentElement();
-	}
-
-	private void print(Resource resource, OutputStream out) throws Exception {
-		InputStream in = resource.openInputStream();
-		try {
-			byte[] buffer = new byte[1024];
-			int size = in.read(buffer);
-			while (size > 0) {
-				out.write(buffer, 0, size);
-				size = in.read(buffer);
-			}
-			out.flush();
-		} finally {
-			in.close();
-		}
-	}
-
-	/*
-	 * public void testWildcards() throws Exception { Builder b = new Builder();
-	 * b .setProperty(Analyzer.SERVICE_COMPONENT, "test/component/*.xml");
-	 * b.setProperty("-resourceonly", "true"); b.setProperty("Include-Resource",
-	 * "test/component=test/component"); Jar jar = b.build();
-	 * System.out.println(b.getErrors()); System.out.println(b.getWarnings());
-	 * assertEquals(0, b.getErrors().size()); assertEquals(0,
-	 * b.getWarnings().size()); }
-	 */
-	public void testImplementation() throws Exception {
-		Builder b = new Builder();
-		b
-				.setProperty(
-						Analyzer.SERVICE_COMPONENT,
-						"silly.name;implementation:=test.activator.Activator;provide:=java.io.Serialization;servicefactory:=true");
-		b.setClasspath(new File[] { new File("bin"), new File("jar/osgi.jar") });
-		b.setProperty("Private-Package", "test.activator");
-		b.build();
-		System.out.println(b.getErrors());
-		System.out.println(b.getWarnings());
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		Jar jar = b.getJar();
-
-		Document doc = db.parse(new InputSource(jar.getResource("OSGI-INF/silly.name.xml")
-				.openInputStream()));
-
-		assertEquals("test.activator.Activator", doc.getElementsByTagName("implementation").item(0)
-				.getAttributes().getNamedItem("class").getNodeValue());
-		assertEquals("true", doc.getElementsByTagName("service").item(0).getAttributes()
-				.getNamedItem("servicefactory").getNodeValue());
-	}
-
-	/**
-	 * Standard activator with reference to http.
-	 * 
-	 * @throws Exception
-	 */
-	public void testProperties() throws Exception {
-		java.util.Properties p = new Properties();
-		p.put(Analyzer.EXPORT_PACKAGE, "test.activator,org.osgi.service.http");
-		p.put(Analyzer.IMPORT_PACKAGE, "*");
-		p.put(Analyzer.SERVICE_COMPONENT, "test.activator.Activator;properties:=\"a=3|4,b=1|2|3\"");
-		Builder b = new Builder();
-		b.setClasspath(new File[] { new File("bin"), new File("jar/osgi.jar") });
-		b.setProperties(p);
-		b.build();
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		Jar jar = b.getJar();
-
-		Document doc = db.parse(new InputSource(jar.getResource(
-				"OSGI-INF/test.activator.Activator.xml").openInputStream()));
-
-		NodeList l = doc.getElementsByTagName("property");
-		assertEquals(2, l.getLength());
-		Node n = l.item(0);
-		System.out.println(n.getFirstChild().getNodeValue());
-		assertEquals("3\n4", l.item(0).getFirstChild().getNodeValue().trim());
-		assertEquals("1\n2\n3", l.item(1).getFirstChild().getNodeValue().trim());
-
-		assertEquals("test.activator.Activator", doc.getElementsByTagName("implementation").item(0)
-				.getAttributes().getNamedItem("class").getNodeValue());
-		// assertEquals("test.activator.Activator", xp.evaluate(
-		// "/component/implementation/@class", doc));
-		// assertEquals("org.osgi.service.http.HttpService", xp.evaluate(
-		// "/component/reference[@name='http']/@interface", doc));
-		// assertEquals("setHttp", xp.evaluate(
-		// "/component/reference[@name='http']/@bind", doc));
-		// assertEquals("unsetHttp", xp.evaluate(
-		// "/component/reference[@name='http']/@unbind", doc));
-		// assertEquals("", xp.evaluate(
-		// "/component/reference[@name='http']/@target", doc));
-	}
-
-	/**
-	 * Check if all the directives work
-	 * 
-	 * @throws Exception
-	 */
-	public void testUnknownDirective() throws Exception {
-		java.util.Properties p = new Properties();
-		p.put(Analyzer.EXPORT_PACKAGE, "test.activator,org.osgi.service.http");
-		p.put(Analyzer.IMPORT_PACKAGE, "*");
-		p.put(Analyzer.SERVICE_COMPONENT, "test.activator.Activator;provides:=true");
-		Builder b = new Builder();
-		b.setClasspath(new File[] { new File("bin"), new File("jar/osgi.jar") });
-		b.setProperties(p);
-		b.build();
-		assertEquals(1, b.getErrors().size());
-		assertTrue(((String) b.getErrors().get(0)).indexOf("Unrecognized directive") >= 0);
-		assertEquals(0, b.getWarnings().size());
-	}
-
-	/**
-	 * Check if all the directives work
-	 * 
-	 * @throws Exception
-	 */
-	public void testDirectives() throws Exception {
-		// Element component =
-		// setup("test.activator.Activator;http=org.osgi.service.http.HttpService;dynamic:=http;optional:=http;provide:=test.activator.Activator; multiple:=http");
-
-		// assertEquals("test.activator.Activator", xp.evaluate(
-		// "/component/implementation/@class", doc));
-		// assertEquals("org.osgi.service.http.HttpService", xp.evaluate(
-		// "/component/reference[@name='http']/@interface", doc));
-		// assertEquals("setHttp", xp.evaluate(
-		// "/component/reference[@name='http']/@bind", doc));
-		// assertEquals("unsetHttp", xp.evaluate(
-		// "/component/reference[@name='http']/@unbind", doc));
-		// assertEquals("0..n", xp.evaluate(
-		// "/component/reference[@name='http']/@cardinality", doc));
-		// assertEquals("dynamic", xp.evaluate(
-		// "/component/reference[@name='http']/@policy", doc));
-		// assertEquals("test.activator.Activator", xp.evaluate(
-		// "/component/service/provide/@interface", doc));
-	}
-
-	/**
-	 * Check if a bad filter on a service component causes an error.
-	 * 
-	 * @throws Exception
-	 */
-	public void testBadFilter() throws Exception {
-		// java.util.Properties p = new Properties();
-		// p.put(Analyzer.EXPORT_PACKAGE,
-		// "test.activator,org.osgi.service.http");
-		// p.put(Analyzer.IMPORT_PACKAGE, "*");
-		// p
-		// .put(
-		// Analyzer.SERVICE_COMPONENT,
-		// "test.activator.Activator;http=\"org.osgi.service.http.HttpService(|p=1)(p=2))\"");
-		// Builder b = new Builder();
-		// b
-		// .setClasspath(new File[] { new File("bin"),
-		// new File("jar/osgi.jar") });
-		// b.setProperties(p);
-		// b.build();
-		// assertEquals(1, b.getErrors().size());
-		// assertTrue(((String) b.getErrors().get(0))
-		// .indexOf("is not a correct filter") >= 0);
-		// assertEquals(0, b.getWarnings().size());
-	}
-
-	/**
-	 * Check if we can set a target filter
-	 * 
-	 * @throws Exception
-	 */
-	public void testFilter() throws Exception {
-		Element component = setup("test.activator.Activator;http=\"org.osgi.service.http.HttpService(|(p=1)(p=2))\"");
-		Element implementation = (Element) component.getElementsByTagName("implementation").item(0);
-		assertEquals(null, implementation.getNamespaceURI());
-		assertEquals("test.activator.Activator", implementation.getAttribute("class"));
-
-		Element reference = (Element) component.getElementsByTagName("reference").item(0);
-		assertEquals("org.osgi.service.http.HttpService", reference.getAttribute("interface"));
-		assertEquals("setHttp", reference.getAttribute("bind"));
-		assertEquals("unsetHttp", reference.getAttribute("unbind"));
-		assertEquals("(|(p=1)(p=2))", reference.getAttribute("target"));
-	}
-
-	/**
-	 * Standard activator with reference to http.
-	 * 
-	 * @throws Exception
-	 */
-	public void testSimple() throws Exception {
-		Element component = setup("test.activator.Activator;http=org.osgi.service.http.HttpService?");
-		Element implementation = (Element) component.getElementsByTagName("implementation").item(0);
-		assertEquals(null, implementation.getNamespaceURI());
-		assertEquals("test.activator.Activator", implementation.getAttribute("class"));
-
-		Element reference = (Element) component.getElementsByTagName("reference").item(0);
-		assertEquals("org.osgi.service.http.HttpService", reference.getAttribute("interface"));
-		assertEquals("setHttp", reference.getAttribute("bind"));
-		assertEquals("unsetHttp", reference.getAttribute("unbind"));
-		assertEquals("", reference.getAttribute("target"));
-		assertEquals("0..1", reference.getAttribute("cardinality"));
-		assertEquals("dynamic", reference.getAttribute("policy"));
-	}
-
-	/**
-	 * Standard activator with reference to http.
-	 * 
-	 * @throws Exception
-	 */
-	public void testQuestion() throws Exception {
-		Element component = setup("test.activator.Activator;http=org.osgi.service.http.HttpService?");
-		Element reference = (Element) component.getElementsByTagName("reference").item(0);
-		assertEquals("0..1", reference.getAttribute("cardinality"));
-		assertEquals("dynamic", reference.getAttribute("policy"));
-	}
-
-	public void testStar() throws Exception {
-		Element component = setup("test.activator.Activator;http=org.osgi.service.http.HttpService*");
-		Element reference = (Element) component.getElementsByTagName("reference").item(0);
-		assertEquals("0..n", reference.getAttribute("cardinality"));
-		assertEquals("dynamic", reference.getAttribute("policy"));
-	}
-
-	public void testPlus() throws Exception {
-		Element component = setup("test.activator.Activator;http=org.osgi.service.http.HttpService+");
-		Element reference = (Element) component.getElementsByTagName("reference").item(0);
-		assertEquals("1..n", reference.getAttribute("cardinality"));
-		assertEquals("dynamic", reference.getAttribute("policy"));
-	}
-
-	public void testTilde() throws Exception {
-		Element component = setup("test.activator.Activator;http=org.osgi.service.http.HttpService~");
-		Element reference = (Element) component.getElementsByTagName("reference").item(0);
-		assertEquals("0..1", reference.getAttribute("cardinality"));
-		assertEquals("", reference.getAttribute("policy"));
-	}
-
-	private void print(Node doc, String indent) {
-		System.out.println(indent + doc);
-		NamedNodeMap attributes = doc.getAttributes();
-		if (attributes != null)
-			for (int i = 0; i < attributes.getLength(); i++) {
-				print(attributes.item(i), indent + "  ");
-			}
-		NodeList nl = doc.getChildNodes();
-		for (int i = 0; i < nl.getLength(); i++) {
-			print(nl.item(i), indent + "  ");
-		}
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/test/CorruptManifest.java b/biz.aQute.bndlib/src/test/CorruptManifest.java
deleted file mode 100755
index d2b033e..0000000
--- a/biz.aQute.bndlib/src/test/CorruptManifest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package test;
-
-import java.io.*;
-import java.util.jar.*;
-
-import junit.framework.*;
-import aQute.lib.osgi.*;
-
-public class CorruptManifest extends TestCase {
-	static String ltext= "bla bla \nbla bla bla bla \nbla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla b [...]
-	
-	public void testCorruptJar() throws Exception  {
-		Builder b = new Builder();
-		b.setProperty("NL1", "\n");
-		b.setProperty("NL2", "\r\n");
-		b.setProperty("NL3", ".");
-		b.setProperty("NL4", ".\n.\n");
-		b.setProperty("NL5", ltext);
-		b.setProperty("Export-Package", "*");
-		b.setClasspath( new File[] {new File("jar/asm.jar")});
-		Jar jar  = b.build();
-		Manifest manifest = jar.getManifest();
-		jar.writeManifest(System.out);
-		
-		Attributes main = manifest.getMainAttributes();
-		assertNull(main.getValue("NL1"));
-		assertNull(main.getValue("NL2"));
-		assertEquals(".", main.getValue("NL3"));
-		assertEquals(".\n.\n", main.getValue("NL4"));
-		assertEquals(ltext, main.getValue("NL5"));
-		
-		ByteArrayOutputStream bout = new ByteArrayOutputStream();
-		jar.writeManifest(bout);
-		bout.flush();
-		System.out.println("-----");
-		System.out.write(bout.toByteArray());
-        System.out.println("-----");
-		ByteArrayInputStream bin = new ByteArrayInputStream( bout.toByteArray());
-		manifest = new Manifest(bin);
-		
-		main = manifest.getMainAttributes();
-		assertNull(main.getValue("NL1"));
-		assertNull(main.getValue("NL2"));
-		assertEquals(".", main.getValue("NL3"));
-		assertEquals("..", main.getValue("NL4"));
-	}
-}
diff --git a/biz.aQute.bndlib/src/test/DSAnnotationTest.java b/biz.aQute.bndlib/src/test/DSAnnotationTest.java
deleted file mode 100644
index 3cccf7a..0000000
--- a/biz.aQute.bndlib/src/test/DSAnnotationTest.java
+++ /dev/null
@@ -1,180 +0,0 @@
-package test;
-
-import java.io.*;
-
-import org.osgi.service.component.annotations.*;
-import org.osgi.service.log.*;
-
-import aQute.bnd.test.*;
-import aQute.lib.osgi.*;
-
-public class DSAnnotationTest extends BndTestCase {
-
-	@Component public class Defaults implements Serializable, Runnable {
-
-		@Activate void open() {
-		}
-
-		@Deactivate void close() {
-		}
-
-		@Modified void modified() {
-		}
-
-		@Reference void setLogService(LogService log) {
-
-		}
-
-		void unsetLogService(LogService log) {
-
-		}
-
-		void modifiedLogService(LogService log) {
-
-		}
-
-		public void run() {
-			// TODO Auto-generated method stub
-
-		}
-	}
-
-	@Component(service = Object.class, configurationPolicy = ConfigurationPolicy.IGNORE, enabled = false, factory = "factory", immediate = false, name = "name", property = {
-			"a=1", "a=2", "b=3" }, properties = "resource.props", servicefactory = false) public class Explicit
-			implements Serializable, Runnable {
-
-		@Activate void open() {
-		}
-
-		@Deactivate void close() {
-		}
-
-		@Modified void changed() {
-		}
-
-		@Reference(cardinality = ReferenceCardinality.AT_LEAST_ONE, name = "foo", policy = ReferencePolicy.DYNAMIC, service = Object.class, target = "(objectclass=*)", unbind = "unset" /*
-																																														 * ,
-																																														 * modified
-																																														 */) void setLogService(
-				LogService log) {
-
-		}
-
-		void unset(Object log) {
-
-		}
-
-		void unset() {
-
-		}
-
-		void unsetLogService(LogService log) {
-
-		}
-
-		void modifiedLogService(Object log) {
-
-		}
-
-		public void run() {
-			// TODO Auto-generated method stub
-
-		}
-	}
-
-	public void testBasic() throws Exception {
-		Builder b = new Builder();
-		b.setProperty("-dsannotations", "test.*");
-		b.setProperty("Private-Package", "test");
-		b.addClasspath(new File("bin"));
-
-		Jar jar = b.build();
-		assertOk(b);
-
-		{
-			//
-			// Test all the defaults
-			//
-
-			Resource r = jar.getResource("OSGI-INF/test.DSAnnotationTest$Defaults.xml");
-			System.out.println(Processor.join(jar.getResources().keySet(),"\n"));
-			assertNotNull(r);
-			r.write(System.out);
-			XmlTester xt = new XmlTester(r.openInputStream(), "scr",
-					"http://www.osgi.org/xmlns/scr/1.1.0");
-
-			// Test the defaults
-			xt.assertAttribute("test.DSAnnotationTest$Defaults",
-					"scr:component/implementation/@class");
-
-			// Default must be the implementation class
-			xt.assertAttribute("test.DSAnnotationTest$Defaults", "scr:component/@name");
-
-			xt.assertAttribute("", "scr:component/@configuration-policy");
-			xt.assertAttribute("", "scr:component/@immediate");
-			xt.assertAttribute("", "scr:component/@enabled");
-			xt.assertAttribute("", "scr:component/@factory");
-			xt.assertAttribute("", "scr:component/@servicefactory");
-			xt.assertAttribute("open", "scr:component/@activate");
-			xt.assertAttribute("close", "scr:component/@deactivate");
-			xt.assertAttribute("modified", "scr:component/@modified");
-			xt.assertAttribute("java.io.Serializable",
-					"scr:component/service/provide[1]/@interface");
-			xt.assertAttribute("java.lang.Runnable", "scr:component/service/provide[2]/@interface");
-
-			xt.assertAttribute("0", "count(scr:component/properties)");
-			xt.assertAttribute("0", "count(scr:component/property)");
-
-			xt.assertAttribute("", "scr:component/reference[1]/@target");
-			xt.assertAttribute("setLogService", "scr:component/reference[1]/@bind");
-			xt.assertAttribute("unsetLogService", "scr:component/reference[1]/@unbind");
-			xt.assertAttribute("", "scr:component/reference[1]/@cardinality");
-			xt.assertAttribute("", "scr:component/reference[1]/@policy");
-			xt.assertAttribute("", "scr:component/reference[1]/@target");
-		}
-		{
-			//
-			// Test explicit
-			//
-
-			Resource r = jar.getResource("OSGI-INF/test.DSAnnotationTest$Explicit.xml");
-			assertNotNull(r);
-			r.write(System.out);
-			XmlTester xt = new XmlTester(r.openInputStream(), "scr",
-					"http://www.osgi.org/xmlns/scr/1.1.0");
-
-			// Test the defaults
-			xt.assertAttribute("test.DSAnnotationTest$Explicit",
-					"scr:component/implementation/@class");
-
-			// Default must be the implementation class
-			xt.assertAttribute("test.DSAnnotationTest$Explicit", "scr:component/@name");
-
-			xt.assertAttribute("ignore", "scr:component/@configuration-policy");
-			xt.assertAttribute("false", "scr:component/@immediate");
-			xt.assertAttribute("false", "scr:component/@enabled");
-			xt.assertAttribute("factory", "scr:component/@factory");
-			xt.assertAttribute("false", "scr:component/@servicefactory");
-			xt.assertAttribute("open", "scr:component/@activate");
-			xt.assertAttribute("close", "scr:component/@deactivate");
-			xt.assertAttribute("changed", "scr:component/@modified");
-			xt.assertAttribute("java.lang.Object", "scr:component/service/provide[1]/@interface");
-			xt.assertAttribute("1", "count(scr:component/service/provide)");
-
-			xt.assertAttribute("1", "count(scr:component/properties)");
-			xt.assertAttribute("2", "count(scr:component/property)");
-
-			xt.assertAttribute("(objectclass=*)", "scr:component/reference[1]/@target");
-			xt.assertAttribute("setLogService", "scr:component/reference[1]/@bind");
-			xt.assertAttribute("unset", "scr:component/reference[1]/@unbind");
-			xt.assertAttribute("modifiedLogService", "scr:component/reference[1]/@modified");
-			xt.assertAttribute("1..n", "scr:component/reference[1]/@cardinality");
-			xt.assertAttribute("dynamic", "scr:component/reference[1]/@policy");
-			xt.assertAttribute("(objectclass=*)", "scr:component/reference[1]/@target");
-			
-			xt.assertAttribute("2", "count(scr:component/property)");
-			xt.assertAttribute("1", "count(scr:component/properties)");
-			xt.assertAttribute("resource.props", "scr:component/properties[1]/@entry");
-		}
-	}
-}
diff --git a/biz.aQute.bndlib/src/test/DiffTest.java b/biz.aQute.bndlib/src/test/DiffTest.java
deleted file mode 100644
index 13ec7fc..0000000
--- a/biz.aQute.bndlib/src/test/DiffTest.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package test;
-
-import java.io.*;
-import java.util.*;
-
-import junit.framework.*;
-import aQute.lib.jardiff.*;
-import aQute.lib.osgi.*;
-
-public class DiffTest extends TestCase {
-
-    public void testSimple() throws Exception {
-        aQute.lib.jardiff.Diff diff = new Diff();
-        Map<String,Object> map = diff.diff(new Jar(new File("jar/ds.jar")), new Jar(new File("jar/asm.jar")), false);
-        
-        diff.print(System.out, map, 0);
-    }
-}
diff --git a/biz.aQute.bndlib/src/test/ExportHeaderTest.java b/biz.aQute.bndlib/src/test/ExportHeaderTest.java
deleted file mode 100644
index b494d78..0000000
--- a/biz.aQute.bndlib/src/test/ExportHeaderTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package test;
-
-import java.io.*;
-import java.util.*;
-import java.util.jar.*;
-
-import junit.framework.*;
-import aQute.lib.osgi.*;
-
-public class ExportHeaderTest extends TestCase {
-    
-
-    /**
-     * If you import a range then the maven guys can have the silly -SNAPSHOT in the
-     * version. This tests if ranges are correcly cleaned up.
-     * @throws Exception
-     */
-    public void testImportHeaderWithMessedUpRange() throws Exception {
-        Builder builder = new Builder();
-        Jar bin = new Jar( new File("bin") );
-        builder.setClasspath( new Jar[]{bin});
-        Properties p = new Properties();
-        p.setProperty("Private-Package", "test.packageinfo.ref");
-        p.setProperty("Import-Package", "test.packageinfo;version=\"[1.1.1-SNAPSHOT,1.1.1-SNAPSHOT]");
-        builder.setProperties(p);
-        Jar jar = builder.build();
-        Manifest manifest = jar.getManifest();
-        
-        String imph = manifest.getMainAttributes().getValue("Import-Package");
-        assertEquals("test.packageinfo;version=\"[1.1.1.SNAPSHOT,1.1.1.SNAPSHOT]\"", imph);   
-    }
-    
-    public void testPickupExportVersion() throws Exception {
-        Builder builder = new Builder();
-        Jar bin = new Jar( new File("bin") );
-        builder.setClasspath( new Jar[]{bin});
-        Properties p = new Properties();
-        p.setProperty("Private-Package", "test.packageinfo.ref");
-        builder.setProperties(p);
-        Jar jar = builder.build();
-        Manifest manifest = jar.getManifest();
-        
-        String imph = manifest.getMainAttributes().getValue("Import-Package");
-        assertEquals("test.packageinfo;version=\"[1.0,2)\"", imph);     
-    }
-    public void testExportVersionWithPackageInfo() throws Exception {
-        Builder builder = new Builder();
-        Jar bin = new Jar( new File("bin") );
-        builder.setClasspath( new Jar[]{bin});
-        Properties p = new Properties();
-        p.setProperty("Export-Package", "test.packageinfo");
-        builder.setProperties(p);
-
-        Jar jar = builder.build();
-        Manifest manifest = jar.getManifest();
-        
-        String exph = manifest.getMainAttributes().getValue("Export-Package");
-        assertEquals("test.packageinfo;version=\"1.0.0.SNAPSHOT\"", exph);
-    }
-}
diff --git a/biz.aQute.bndlib/src/test/FilterTest.java b/biz.aQute.bndlib/src/test/FilterTest.java
deleted file mode 100644
index 41b7112..0000000
--- a/biz.aQute.bndlib/src/test/FilterTest.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package test;
-
-import junit.framework.*;
-import aQute.lib.osgi.*;
-
-public class FilterTest extends TestCase {
-
-    public void testFilter() {
-        Verifier v = new Verifier();
-        v.verifyFilter("(org.osgi.framework.windowing.system=xyz)");
-        System.out.println(v.getErrors());
-        System.out.println(v.getWarnings());
-        assertEquals(0, v.getErrors().size());
-        assertEquals(0, v.getWarnings().size());
-    }
-}
diff --git a/biz.aQute.bndlib/src/test/GlobTest.java b/biz.aQute.bndlib/src/test/GlobTest.java
deleted file mode 100644
index 1d39cb8..0000000
--- a/biz.aQute.bndlib/src/test/GlobTest.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package test;
-
-import aQute.libg.glob.Glob;
-import junit.framework.TestCase;
-
-public class GlobTest extends TestCase {
-	public void testSimple() {
-		Glob glob = new Glob("*foo*");
-		assertTrue(glob.matcher("foo").find());
-		assertTrue(glob.matcher("food").find());
-		assertTrue(glob.matcher("Xfoo").find());
-		assertTrue(glob.matcher("XfooY").find());
-		assertFalse(glob.matcher("ood").find());
-	}
-	
-	public void testUrl() {
-		Glob glob;
-		
-		glob = new Glob("http://www.example.com/*");
-		assertTrue(glob.matcher("http://www.example.com/repository.xml").find());
-		assertFalse(glob.matcher("https://www.example.com/repository.xml").find());
-		
-		glob = new Glob("http://*.example.com/*");
-		assertTrue(glob.matcher("http://www.example.com/repository.xml").find());
-		assertTrue(glob.matcher("http://foo.example.com/repository.xml").find());
-		assertFalse(glob.matcher("http://example.com/repository.xml").find());
-		assertFalse(glob.matcher("http://foo.exampleXcom/repository.xml").find());
-	}
-}
diff --git a/biz.aQute.bndlib/src/test/GroupsTest.java b/biz.aQute.bndlib/src/test/GroupsTest.java
deleted file mode 100644
index beebbea..0000000
--- a/biz.aQute.bndlib/src/test/GroupsTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package test;
-
-import java.io.*;
-import java.util.*;
-
-import junit.framework.*;
-import aQute.lib.collections.*;
-import aQute.lib.osgi.*;
-import static aQute.lib.collections.Logic.*;
-
-public class GroupsTest extends TestCase{
-
-	static class Group implements Comparable<Group>{
-		final Set<String>    name;
-		final Set<String>		refs;
-		
-		public Group(Set<String> key, Set<String> value) {
-			
-			name = key;
-			refs = value;
-		}
-
-		public int compareTo(Group o) {
-			int n = o.name.size()-name.size();
-			if ( n != 0) 
-				return n;
-
-			n = o.refs.size() - refs.size();
-			
-			if ( n != 0) 
-				return n;
-			
-			String s1 = name.iterator().next();
-			String s2 = o.name.iterator().next();
-			return s1.compareTo(s2);
-		}
-		
-		public String toString() {
-			return name.toString();
-		}
-	}
-	
-	public void testSimple() throws Exception {
-		Builder	b = new Builder();
-//		b.addClasspath(new File("../biz.aQute.bnd/tmp/biz.aQute.bnd.jar"));
-		b.addClasspath(new File("jar/spring.jar"));
-//		b.addClasspath(new File("/Ws/aQute.old/aQute.google/lib/gwt-dev-windows.jar"));
-		b.setProperty("Private-Package", "*");
-		Jar build = b.build();
-			
-		System.out.println(b.getUses());
-		
-        MultiMap<Set<String>, String> x = b.getGroups();
-        SortedSet<Group> groups = new TreeSet<Group>();
-        
-        for ( Map.Entry<Set<String>,Set<String>> entry : x.entrySet()) {
-        	groups.add( new Group(entry.getKey(), entry.getValue()));
-        }
-
-        Iterator<Group> i = groups.iterator();
-        Group main = i.next();
-        System.out.println("Main " + main);
-
-        while (  i.hasNext() ) {
-        	Group g = i.next();
-        	System.out.println("Trying " + g);
-        	if ( !retain(main.refs,g.name).isEmpty()) {        		
-        		Collection<String> newReferences = remove(g.refs, main.refs, main.name, g.name);
-        		if ( newReferences.isEmpty()) {
-        			System.out.println("merging " + g);
-        			main.name.addAll(g.name);
-        			i.remove();
-        		}
-            	else System.out.println("  would add " + newReferences);
-        	}
-        	else System.out.println("  main does not refer");
-        }
-        
-        for ( Group g : groups) {
-        	System.out.println(g);
-        }
-	}
-}
diff --git a/biz.aQute.bndlib/src/test/IncludeHeaderTest.java b/biz.aQute.bndlib/src/test/IncludeHeaderTest.java
deleted file mode 100755
index 2f30924..0000000
--- a/biz.aQute.bndlib/src/test/IncludeHeaderTest.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package test;
-
-import java.io.*;
-import java.util.*;
-
-import junit.framework.*;
-import aQute.lib.osgi.*;
-
-public class IncludeHeaderTest extends TestCase {
-
-//	public void testMavenInclude() throws Exception {
-//		String b = "pom.modelVersion=b\n";
-//		File bb = new File("b.props");
-//		write(bb, b );
-//		bb.deleteOnExit();
-//		
-//		Analyzer analyzer = new Analyzer();
-//		Properties x = new Properties();
-//		x.put("pom.modelVersion", "set");		
-//		x.put("pom.scope.test", "set");		
-//		x.put("-include", "~maven/pom.xml,b.props");
-//		analyzer.setProperties(x);
-//		System.out.println(analyzer.getErrors());
-//		System.out.println(analyzer.getWarnings());
-//		assertEquals("b", analyzer.getProperty("pom.modelVersion")); // from b
-//		assertEquals("org.apache.felix.metatype", analyzer.getProperty("pom.artifactId")); // from pom
-//		assertEquals("org.apache.felix", analyzer.getProperty("pom.groupId")); // from parent pom
-//		assertEquals("set", analyzer.getProperty("pom.scope.test")); // Set
-//	}
-	
-    public void testTopBottom() throws Exception {
-        Analyzer analyzer = new Analyzer();
-        analyzer.setProperties(new File("src/test/include.bnd/top.bnd"));
-        assertEquals("0.0.257", analyzer.getProperty("Bundle-Version"));
-    }
-
-	public void testPrecedence() throws Exception {
-		File base  = new File("src/test");
-		String a = "a=a.props\n";
-		String b = "a=b.props\n";
-		File aa = new File(base,"a.props");
-		File bb = new File(base,"b.props");
-		write(aa, a);
-		write(bb, b );
-		
-		
-		Analyzer analyzer = new Analyzer();
-		analyzer.setBase(base);
-		Properties x = new Properties();
-		x.put("a", "x");		
-		x.put("-include", "a.props, b.props");
-		analyzer.setProperties(x);		
-		assertEquals("b.props", analyzer.getProperty("a")); 	// from org
-		
-		analyzer = new Analyzer();
-        analyzer.setBase(base);
-		x = new Properties();
-		x.put("a", "x");		
-		x.put("-include", "~a.props, b.props");
-		analyzer.setProperties(x);		
-		assertEquals("b.props", analyzer.getProperty("a")); 	// from org
-
-        analyzer = new Analyzer();
-        analyzer.setBase(base);
-		x = new Properties();
-		x.put("a", "x");		
-		x.put("-include", "a.props, ~b.props");
-		analyzer.setProperties(x);		
-		assertEquals("a.props", analyzer.getProperty("a")); 	// from org
-
-        analyzer = new Analyzer();
-        analyzer.setBase(base);
-		x = new Properties();
-		x.put("a", "x");		
-		x.put("-include", "~a.props, ~b.props");
-		analyzer.setProperties(x);		
-		assertEquals("x", analyzer.getProperty("a")); 	// from org
-
-		aa.delete();
-		bb.delete();
-	}
-	
-	private void write(File file, String b) throws Exception {
-		FileOutputStream out = new FileOutputStream( file);
-		out.write( b.getBytes());
-		out.close();		
-	}
-
-	public void testAbsentIncludes() throws IOException {
-		Analyzer analyzer = new Analyzer();
-		analyzer.setBase(new File("src/test"));
-		Properties p = new Properties();
-		p.put("-include", "-iamnotthere.txt");
-		analyzer.setProperties(p);
-		System.out.println(analyzer.getErrors());
-		assertEquals(0, analyzer.getErrors().size());
-	}
-
-	public void testIncludeWithProperty() throws IOException {
-		File home = new File(System.getProperty("user.home"));
-		File include = new File(home, "includeheadertest.txt");
-		try {
-			FileOutputStream fw = new FileOutputStream(include);
-			fw.write("IncludeHeaderTest: yes\n\r".getBytes());
-			fw.write("a: 2\n\r".getBytes());
-			fw.write("b: ${a}\n\r".getBytes());
-			fw.close();
-			Analyzer analyzer = new Analyzer();
-			analyzer.setBase(new File("src/test"));
-			Properties p = new Properties();
-			p.put("a", "1");
-			p
-					.put("-include",
-							"-iamnotthere.txt, ${user.home}/includeheadertest.txt");
-			analyzer.setProperties(p);
-			String value = analyzer.getProperty("IncludeHeaderTest");
-			assertEquals("yes", value);
-			assertEquals("2", analyzer.getProperty("a"));
-			assertEquals("2", analyzer.getProperty("b"));
-			assertEquals(0, analyzer.getErrors().size());
-		} finally {
-			include.delete();
-		}
-	}
-
-	public void testIncludeHeader() throws IOException {
-		Analyzer analyzer = new Analyzer();
-		analyzer.setBase(new File("src/test"));
-		Properties p = new Properties();
-		p.put("a", "1");
-		p.put("-include", "includeheadertest.mf, includeheadertest.prop");
-		analyzer.setProperties(p);
-		System.out.println(analyzer.getProperties());
-		assertEquals("1", analyzer.getProperty("a"));
-		assertEquals("end", analyzer.getProperty("last-props"));
-		assertEquals("end", analyzer.getProperty("last-manifest"));
-		assertEquals("abcd", analyzer.getProperty("manifest"));
-		assertEquals("abcd", analyzer.getProperty("props"));
-		assertEquals("1", analyzer.getProperty("test"));
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/test/InlineTest.java b/biz.aQute.bndlib/src/test/InlineTest.java
deleted file mode 100644
index 66319d8..0000000
--- a/biz.aQute.bndlib/src/test/InlineTest.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package test;
-
-import java.util.jar.*;
-
-import aQute.lib.osgi.*;
-
-import junit.framework.*;
-
-public class InlineTest extends TestCase {
-	public void testSimple() throws Exception {
-		Builder builder = new Builder();
-		builder.setProperty("Include-Resource", "@jar/osgi.jar");
-		Jar jar = builder.build();
-		Manifest manifest = jar.getManifest();
-		
-		// See if the version is the default and not copied from the inline
-		// bundle.
-		String version = manifest.getMainAttributes().getValue("Bundle-Version");
-		assertEquals("0", version );
-		
-		// Check if we got some relevant directories
-		assertTrue(jar.getDirectories().containsKey("org/osgi/framework"));
-		assertTrue(jar.getDirectories().containsKey("org/osgi/util/tracker"));
-	}
-}
diff --git a/biz.aQute.bndlib/src/test/JarSignerTest.java b/biz.aQute.bndlib/src/test/JarSignerTest.java
deleted file mode 100644
index 47ec517..0000000
--- a/biz.aQute.bndlib/src/test/JarSignerTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package test;
-
-import java.io.*;
-import java.util.*;
-import java.util.jar.*;
-
-import junit.framework.*;
-import aQute.bnd.signing.*;
-import aQute.lib.osgi.*;
-import aQute.libg.generics.*;
-
-public class JarSignerTest extends TestCase {
-
-    public void testNoManifest() throws Exception {
-        Builder b = new Builder();
-        b.setProperty("-sign", "test");
-        b.setProperty(Constants.PLUGIN,JartoolSigner.class.getName()+";keystore=test/keystore;keypass=testtest;storepass=testtest;sigfile=test");
-        b.setProperty("-nomanifest","true");
-        b.setProperty("-resourceonly","true");
-        b.setProperty("Include-Resource", "WEB-INF/classes=@jar/osgi.jar");
- 
-        Jar jar = b.build();
-        File tmp = new File("xyztmp.jar");
-        tmp.deleteOnExit();
-        
-        jar.write( tmp );
-
-        Jar jar2 = new Jar(tmp); 
-        Manifest manifest = jar2.getManifest();
-        assertEquals( "1.0", manifest.getMainAttributes().getValue("Manifest-Version"));
-        assertNotNull( manifest.getAttributes("WEB-INF/classes/org/osgi/framework/BundleContext.class"));
-     }
-
-    public void testError() throws Exception {
-        JartoolSigner signer = new JartoolSigner();
-        Map<String,String> properties = Create.map();
-        properties.put("keystore", "test/keystore");
-        properties.put("keypass", "testtest");
-        properties.put("storepass", "notvalid");
-        signer.setProperties(properties);
-        
-        Jar jar = new Jar( new File("test/test.jar"));
-        Builder b = new Builder();
-        b.setTrace(true);
-        b.setJar(jar);
-        signer.sign(b, "test");
-        System.out.println( Processor.join(b.getErrors(),"\n"));
-        assertEquals( 1, b.getErrors().size() );
-        assertEquals( 0, b.getWarnings().size() );
-    }
-    
-    public void testSimple() throws Exception {
-        JartoolSigner signer = new JartoolSigner();
-        Map<String,String> properties = Create.map();
-        properties.put("keystore", "test/keystore");
-        properties.put("keypass", "testtest");
-        properties.put("storepass", "testtest");
-        properties.put("sigfile", "test");
-        signer.setProperties(properties);
-        
-        Jar jar = new Jar( new File("test/test.jar"));
-        Set<String> names = new HashSet<String>(jar.getResources().keySet());
-        names.remove("META-INF/MANIFEST.MF");
-        Builder b = new Builder();
-        b.setJar(jar);
-        signer.sign(b, "test");
-        System.out.println( Processor.join(b.getErrors(), "\n"));
-        System.out.println( Processor.join(b.getWarnings(), "\n"));
-        assertEquals( 0, b.getErrors().size() );
-        assertEquals( 0, b.getWarnings().size() );
-        assertNotNull( jar.getResource("META-INF/TEST.SF") );
-        Manifest m = jar.getManifest();
-        
-        
-        // Should have added 2 new resources: TEST.SF and TEST.DSA/RSA
-        assertEquals( names.size(), b.getJar().getResources().size()-3);
-
-        
-        Attributes a = m.getAttributes("aQute/rendezvous/DNS.class");
-        assertNotNull(a);
-        assertEquals("G0/1CIZlB4eIVyY8tU/ZfMCqZm4=", a.getValue("SHA1-Digest"));
- 
-        // Check if all resources are named
-        for ( String name : names ) {
-            System.out.println("name: " + name);
-            assertNotNull( m.getAttributes(name));
-        }
-    }
-
-}
diff --git a/biz.aQute.bndlib/src/test/JarTest.java b/biz.aQute.bndlib/src/test/JarTest.java
deleted file mode 100755
index 44645f0..0000000
--- a/biz.aQute.bndlib/src/test/JarTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package test;
-
-import java.io.*;
-import java.util.jar.*;
-import java.util.zip.*;
-
-import junit.framework.*;
-import aQute.lib.osgi.*;
-
-public class JarTest extends TestCase {
-
-    public void testNoManifest() throws Exception {
-        Jar jar = new Jar("dot");
-        jar.setManifest(new Manifest());
-        jar.setDoNotTouchManifest();
-        jar.putResource("a/b", new FileResource(new File("test/bnd.jar")));
-
-        ByteArrayOutputStream bout = new ByteArrayOutputStream();
-        jar.write(bout);
-
-        Jar jin = new Jar("dotin", new ByteArrayInputStream(bout.toByteArray()));
-        Resource m = jin.getResource("META-INF/MANIFEST.MF");
-        assertNull(m);
-        Resource r = jin.getResource("a/b");
-        assertNotNull(r);
-    }
-
-    public void testManualManifest() throws Exception {
-        Jar jar = new Jar("dot");
-        jar.setManifest(new Manifest());
-        jar.setDoNotTouchManifest();
-        jar.putResource("a/b", new FileResource(new File("test/bnd.jar")));
-        jar.putResource("META-INF/MANIFEST.MF", new EmbeddedResource(
-                "Manifest-Version: 1\r\nX: 1\r\n\r\n".getBytes(), 0));
-
-        ByteArrayOutputStream bout = new ByteArrayOutputStream();
-        jar.write(bout);
-        
-        JarInputStream jin = new JarInputStream(new ByteArrayInputStream(bout.toByteArray()));
-        Manifest m = jin.getManifest();
-        assertNotNull(m);
-        assertEquals("1", m.getMainAttributes().getValue("X"));
-        jin.close();
-    }
-
-    public void testSimple() throws ZipException, IOException {
-        File file = new File("jar/asm.jar");
-        Jar jar = new Jar("asm.jar", file);
-        long jarTime = jar.lastModified();
-        long fileTime = file.lastModified();
-        long now = System.currentTimeMillis();
-
-        // Sanity check
-        assertTrue(jarTime < fileTime);
-        assertTrue(fileTime <= now);
-
-        
-        // TODO see if we can improve this test case
-//        // We should use the highest modification time
-//        // of the files in the JAR not the JAR (though
-//        // this is a backup if time is not set in the jar)
-//        assertEquals(1144412850000L, jarTime);
-
-        // Now add the file and check that
-        // the modification time has changed
-        jar.putResource("asm", new FileResource(file));
-        assertEquals(file.lastModified(), jar.lastModified());
-    }
-}
diff --git a/biz.aQute.bndlib/src/test/LauncherTest.java b/biz.aQute.bndlib/src/test/LauncherTest.java
deleted file mode 100644
index 3546232..0000000
--- a/biz.aQute.bndlib/src/test/LauncherTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package test;
-
-import java.io.*;
-import java.util.concurrent.*;
-
-import junit.framework.*;
-import aQute.bnd.build.*;
-import aQute.lib.osgi.*;
-
-public class LauncherTest extends TestCase {
-
-	public void testSimple() throws Exception{
-		Project project = Workspace.getProject(Processor.getFile(new File("").getAbsoluteFile().getParentFile(), "demo"));
-		project.clear();
-		
-		ProjectLauncher l = project.getProjectLauncher();
-		l.setTrace(true);
-		l.getRunProperties().put("test.cmd", "exit");
-		assertEquals(42,l.launch());
-	}
-	
-	public void testTester() throws Exception {
-		Project project = Workspace.getProject(Processor.getFile(new File("").getAbsoluteFile().getParentFile(), "demo"));
-		project.clear();
-		project.build();
-		
-		ProjectTester pt = project.getProjectTester();
-		pt.addTest("test.TestCase1");
-				
-		assertEquals(2,pt.test());
-	}
-	
-	
-	
-	
-	
-	public void testTimeoutActivator() throws Exception {
-		Project project = Workspace.getProject(Processor.getFile(new File("").getAbsoluteFile().getParentFile(), "demo"));
-		project.clear();
-		
-		ProjectLauncher l = project.getProjectLauncher();
-		l.setTimeout(100, TimeUnit.MILLISECONDS);
-		l.setTrace(false);
-		assertEquals(ProjectLauncher.TIMEDOUT,l.launch());
-		
-	}
-	
-	public void testTimeout() throws Exception {
-		Project project = Workspace.getProject(Processor.getFile(new File("").getAbsoluteFile().getParentFile(), "demo"));
-		project.clear();
-		
-		ProjectLauncher l = project.getProjectLauncher();
-		l.setTimeout(100, TimeUnit.MILLISECONDS);
-		l.setTrace(false);
-		l.getRunProperties().put("test.cmd", "timeout");
-		assertEquals(ProjectLauncher.TIMEDOUT,l.launch());
-	}
-	
-	public void testMainThread() throws Exception {
-		Project project = Workspace.getProject(Processor.getFile(new File("").getAbsoluteFile().getParentFile(), "demo"));
-		project.clear();
-		
-		ProjectLauncher l = project.getProjectLauncher();
-		l.setTimeout(10000, TimeUnit.MILLISECONDS);
-		l.setTrace(false);
-		l.getRunProperties().put("test.cmd", "main.thread");
-		assertEquals(ProjectLauncher.OK,l.launch());
-	}
-}
diff --git a/biz.aQute.bndlib/src/test/MacroTest.java b/biz.aQute.bndlib/src/test/MacroTest.java
deleted file mode 100755
index 84731eb..0000000
--- a/biz.aQute.bndlib/src/test/MacroTest.java
+++ /dev/null
@@ -1,480 +0,0 @@
-package test;
-
-import java.io.*;
-import java.util.*;
-import java.util.jar.*;
-
-import junit.framework.*;
-import aQute.lib.osgi.*;
-
-public class MacroTest extends TestCase {
-	public void testEnv() {
-		Processor proc = new Processor();
-		String s = proc.getReplacer().process("${env;USER}");
-		assertNotNull(s);
-	}
-	
-	/**
-	 * Test the random macro
-	 */
-	public void testRandom() {
-		Processor top = new Processor();
-		top.setProperty("a","${random}");
-		top.setProperty("a12","${random;12}");
-		String a = top.getProperty("a");
-		System.out.println(a);
-		assertEquals(8, a.length());
-		String a12 = top.getProperty("a12");
-		System.out.println(a12);
-		assertEquals(12, a12.length());
-		assertNotSame(a, a12);
-	}
-	
-	/**
-	 * Testing an example with nesting that was supposd not to work
-	 */
-
-	public void testSuper() {
-		Processor top = new Processor();
-		Processor middle = new Processor(top);
-		Processor bottom = new Processor(middle);
-		
-		top.setProperty("a", "top.a");
-		top.setProperty("b", "top.b");
-		top.setProperty("c", "top.c");
-		top.setProperty("Bundle-Version", "0.0.0");
-		middle.setProperty("a", "middle.a");
-		middle.setProperty("b", "${^a}");
-		middle.setProperty("c", "-${^c}-");
-		middle.setProperty("Bundle-Version", "${^Bundle-Version}");
-		assertEquals("middle.a", bottom.getProperty("a"));
-		assertEquals("top.a", bottom.getProperty("b"));
-		assertEquals("-top.c-", bottom.getProperty("c"));
-		assertEquals("0.0.0", bottom.getProperty("Bundle-Version"));
-	}
-
-	/**
-	 * Testing an example with nesting that was supposd not to work
-	 */
-
-	public void testNesting2() {
-		Processor p = new Processor();
-		p.setProperty("groupId", "com.trivadis.tomas");
-		p.setProperty("artifactId", "common");
-		p.setProperty("bsn", "${if;${symbolicName};${symbolicName};${groupId}.${artifactId}}");
-		p.setProperty("Bundle-SymbolicName", "${bsn}");
-		p.setProperty("symbolicName", "");
-
-		// Not set, so get the maven name
-		assertEquals("com.trivadis.tomas.common", p.getProperty("Bundle-SymbolicName"));
-
-		// Set it
-		p.setProperty("symbolicName", "testing");
-		assertEquals("testing", p.getProperty("Bundle-SymbolicName"));
-
-		// And remove it
-		p.setProperty("symbolicName", "");
-		assertEquals("com.trivadis.tomas.common", p.getProperty("Bundle-SymbolicName"));
-	}
-
-	/**
-	 * Verify system command
-	 */
-
-	public void testSystem() throws Exception {
-		Processor p = new Processor();
-		Macro macro = new Macro(p);
-		assertEquals("Hello World", macro.process("${system;echo Hello World}"));
-		assertTrue(macro.process("${system;wc;Hello World}").matches("\\s*[0-9]+\\s+[0-9]+\\s+[0-9]+\\s*"));
-	}
-
-	public void testSystemFail() throws Exception {
-		Processor p = new Processor();
-		Macro macro = new Macro(p);
-		String cmd = "${system;mostidioticcommandthatwillsurelyfail}";
-		assertEquals(cmd, macro.process(cmd));
-	}
-
-	/**
-	 * Verify system-allow-fail command
-	 */
-
-	public void testSystemAllowFail() throws Exception {
-		Processor p = new Processor();
-		Macro macro = new Macro(p);
-		assertEquals("", macro.process("${system-allow-fail;mostidioticcommandthatwillsurelyfail}"));
-	}
-
-	/**
-	 * Check that variables override macros.
-	 */
-	public void testPriority() {
-		Processor p = new Processor();
-		p.setProperty("now", "not set");
-		Macro macro = new Macro(p);
-		assertEquals("not set", macro.process("${now}"));
-
-	}
-
-	public void testNames() {
-		Processor p = new Processor();
-		p.setProperty("a", "a");
-		p.setProperty("aa", "aa");
-		Macro macro = new Macro(p);
-
-		assertEquals("aa", macro.process("${${a}${a}}"));
-	}
-
-	public void testVersion() throws Exception {
-		Processor proc = new Processor();
-		Macro macro = new Macro(proc);
-		assertEquals("1.0.0", macro.process("${version;===;1.0.0}"));
-		assertEquals("1.0.1", macro.process("${version;==+;1.0.0}"));
-		assertEquals("1.1.1", macro.process("${version;=++;1.0.0}"));
-		assertEquals("2.1.1", macro.process("${version;+++;1.0.0}"));
-		assertEquals("0.1.1", macro.process("${version;-++;1.0.0}"));
-		assertEquals("0.1.1", macro.process("${version;-++;1.0.0}"));
-		assertEquals("0.0.0", macro.process("${version;---;1.1.1}"));
-		assertEquals("0.0", macro.process("${version;--;1.1.1}"));
-		assertEquals("1", macro.process("${version;=;1.1.1}"));
-		assertEquals("[1.1,1.2)", macro.process("[${version;==;1.1.1},${version;=+;1.1.1})"));
-		assertEquals("1.1", macro.process("${version;==;1.1.1}"));
-		assertEquals("0.1.0", macro.process("${version;=+0;0.0.1}"));
-		assertEquals("1.0.0", macro.process("${version;+00;0.1.1}"));
-
-		// Test implicit version
-		proc.setProperty("@", "1.2.3");
-		assertEquals("[1.2,1.3)", macro.process("[${version;==},${version;=+})"));
-		assertEquals("1.2", macro.process("${version;==}"));
-		assertEquals("1.3.0", macro.process("${version;=+0}"));
-		assertEquals("2.0.0", macro.process("${version;+00}"));
-
-		assertEquals(0, proc.getErrors().size());
-		assertEquals(0, proc.getWarnings().size());
-
-	}
-
-	public void testRange() throws Exception {
-		Processor proc = new Processor();
-		Macro macro = new Macro(proc);
-		assertEquals("[1.0,1.0]", macro.process("${range;[==,==];1.0.0}"));
-		assertEquals("[1.0.0,1.0.1]", macro.process("${range;[===,==+];1.0.0}"));
-		assertEquals("[0.1.0,0.1.2)", macro.process("${range;[=+0,=++);0.0.1}"));
-		assertEquals("[0.0.9,0.1.2)", macro.process("${range;[==9,=++);0.0.1}"));
-
-		assertEquals(0, proc.getErrors().size());
-		assertEquals(0, proc.getWarnings().size());
-
-		proc.setProperty("@", "1.2.3");
-		assertEquals("[1.0.0,2)", macro.process("${range;[=00,+)}"));
-
-		proc.clear();
-		macro.process("${range;=+0,=++;0.0.1}");
-		assertEquals(1, proc.getErrors().size());
-		assertEquals(1, proc.getWarnings().size());
-		
-		proc.clear();
-		macro.process("${range;[+,=)}");
-		assertEquals(1, proc.getErrors().size());
-		assertEquals(1, proc.getWarnings().size());
-	}
-
-	/**
-	 * Test the wc function
-	 */
-
-	public void testWc() {
-		Processor p = new Processor();
-		Macro macro = new Macro(p);
-		String a = macro.process("${lsr;" + new File("src/test").getAbsolutePath() + ";*.java}");
-		assertTrue(a.contains("MacroTest.java"));
-		assertTrue(a.contains("ManifestTest.java"));
-		assertFalse(a.contains(".classpath"));
-		assertFalse(a.contains("src/test/MacroTest.java"));
-		assertFalse(a.contains("src/test/ManifestTest.java"));
-
-		String b = macro.process("${lsa;" + new File("src/test").getAbsolutePath() + ";*.java}");
-		assertTrue(b.contains("src/test/MacroTest.java"));
-		assertTrue(b.contains("src/test/ManifestTest.java"));
-	}
-
-	/**
-	 * Check the uniq command
-	 */
-
-	public void testUniq() {
-		Builder builder = new Builder();
-		Properties p = new Properties();
-		p.setProperty("a", "${uniq;1}");
-		p.setProperty("b", "${uniq;1,2}");
-		p.setProperty("c", "${uniq;1;2}");
-		p.setProperty("d", "${uniq;1; 1,  2 , 3}");
-		p.setProperty("e", "${uniq;1; 1 , 2 ;      3;3,4,5,6}");
-		builder.setProperties(p);
-		assertEquals("1,2,3", builder.getProperty("d"));
-		assertEquals("1,2", builder.getProperty("b"));
-		assertEquals("1", builder.getProperty("a"));
-		assertEquals("1,2", builder.getProperty("c"));
-		assertEquals("1,2,3", builder.getProperty("d"));
-		assertEquals("1,2,3,4,5,6", builder.getProperty("e"));
-
-	}
-
-	/**
-	 * Test arguments with difficult characters like ;
-	 */
-
-	public void testEscapedArgs() {
-		Builder builder = new Builder();
-		Properties p = new Properties();
-		p.setProperty("x", "${replace;1,2,3;.+;$0\\;version=1}");
-		builder.setProperties(p);
-		assertEquals("1;version=1, 2;version=1, 3;version=1", builder.getProperty("x"));
-
-	}
-
-	/**
-	 * Check if variables that contain variables, ad nauseum, really wrk
-	 */
-	public void testNested() {
-		Builder builder = new Builder();
-		Properties p = new Properties();
-		p.setProperty("a", ".");
-		p.setProperty("b", "${a}");
-		p.setProperty("c", "${b}");
-
-		p.setProperty("d", "${tstamp;${format};${aug152008}}");
-		p.setProperty("format", "yyyy");
-		p.setProperty("aug152008", "1218810097322");
-
-		p.setProperty("f", "${d}");
-		p.setProperty("aug152008", "1218810097322");
-
-		builder.setProperties(p);
-		assertEquals(".", builder.getProperty("c"));
-		assertEquals("2008", builder.getProperty("d"));
-		assertEquals(builder.getProperty("f"), builder.getProperty("d"));
-	}
-
-	public void testLoop() {
-		Builder builder = new Builder();
-		Properties p = new Properties();
-		p.setProperty("a", "${b}");
-		p.setProperty("b", "${a}");
-
-		p.setProperty("d", "${e}");
-		p.setProperty("e", "${f}");
-		p.setProperty("f", "${g}");
-		p.setProperty("g", "${h}");
-		p.setProperty("h", "${d}");
-
-		builder.setProperties(p);
-		assertEquals("${infinite:[a,b,${b}]}", builder.getProperty("a"));
-		assertEquals("${infinite:[d,h,g,f,e,${e}]}", builder.getProperty("d"));
-	}
-
-	public void testTstamp() {
-		// TODO Timezones
-//		String aug152008 = "1218810097322";
-//		Processor p = new Processor();
-//		Macro m = new Macro(p);
-//		assertEquals("200808151521", m.process("${tstamp;yyyyMMddHHmm;" + aug152008 + "}"));
-//		// assertEquals( "2008", m.process("${tstamp;yyyy}"));
-	}
-
-	public void testIsfile() {
-		Processor p = new Processor();
-		Macro m = new Macro(p);
-		assertEquals("true", m.process("${isfile;.project}"));
-		assertEquals("false", m.process("${isfile;thisfiledoesnotexist}"));
-	}
-
-	public void testParentFile() {
-		Processor p = new Processor();
-		Macro m = new Macro(p);
-		assertTrue(m.process("${dir;.project}").endsWith("biz.aQute.bndlib"));
-	}
-
-	public void testBasename() {
-		Processor p = new Processor();
-		Macro m = new Macro(p);
-		assertEquals("biz.aQute.bndlib", m.process("${basename;${dir;.project}}"));
-	}
-
-	public void testMavenVersionMacro() throws Exception {
-		Builder builder = new Builder();
-		Properties p = new Properties();
-		p.setProperty("Export-Package", "org.objectweb.*;version=1.5-SNAPSHOT");
-		builder.setProperties(p);
-		builder.setClasspath(new File[] { new File("jar/asm.jar") });
-		Jar jar = builder.build();
-		Manifest manifest = jar.getManifest();
-		String export = manifest.getMainAttributes().getValue("Export-Package");
-		assertNotNull(export);
-		assertTrue("Test snapshot version", export.contains("1.5.0.SNAPSHOT"));
-	}
-
-	/**
-	 * Check if we can check for the defintion of a variable
-	 */
-
-	public void testDef() {
-		Processor p = new Processor();
-		p.setProperty("set.1", "1");
-		p.setProperty("set.2", "2");
-		Macro m = new Macro(p);
-		assertEquals("NO", m.process("${if;${def;set.3};YES;NO}"));
-		assertEquals("YES", m.process("${if;${def;set.1};YES;NO}"));
-		assertEquals("YES", m.process("${if;${def;set.2};YES;NO}"));
-	}
-
-	/**
-	 * NEW
-	 */
-	public void testReplace() {
-		Processor p = new Processor();
-		p.setProperty("specs", "a,b, c,    d");
-		Macro m = new Macro(p);
-		assertEquals("xay, xby, xcy, xdy", m.process("${replace;${specs};([^\\s]+);x$1y}"));
-	}
-
-	public void testToClassName() {
-		Processor p = new Processor();
-		Macro m = new Macro(p);
-		assertEquals("com.acme.test.Test", m.process("${toclassname;com/acme/test/Test.class}"));
-		assertEquals("Test", m.process("$<toclassname;Test.class>"));
-		assertEquals("Test,com.acme.test.Test", m
-				.process("${toclassname;Test.class, com/acme/test/Test.class}"));
-		assertEquals("", m.process("$(toclassname;Test)"));
-		assertEquals("com/acme/test/Test.class", m.process("$[toclasspath;com.acme.test.Test]"));
-		assertEquals("Test.class", m.process("${toclasspath;Test}"));
-		assertEquals("Test.class,com/acme/test/Test.class", m
-				.process("${toclasspath;Test,com.acme.test.Test}"));
-	}
-
-	public void testFindPath() throws IOException {
-		Analyzer analyzer = new Analyzer();
-		analyzer.setJar(new File("jar/asm.jar"));
-		Macro m = new Macro(analyzer);
-
-		assertTrue(m.process("${findname;(.*)\\.class;$1.xyz}").indexOf("FieldVisitor.xyz,") >= 0);
-		assertTrue(m.process("${findname;(.*)\\.class;$1.xyz}").indexOf("MethodVisitor.xyz,") >= 0);
-		assertTrue(m.process("${findpath;(.*)\\.class}").indexOf(
-				"org/objectweb/asm/AnnotationVisitor.class,") >= 0);
-		assertTrue(m.process("${findpath;(.*)\\.class}").indexOf(
-				"org/objectweb/asm/ByteVector.class, org/objectweb/asm/ClassAdapter.class,") >= 0);
-		assertEquals("META-INF/MANIFEST.MF", m.process("${findpath;META-INF/MANIFEST.MF}"));
-		assertEquals("Label.class", m.process("${findname;Label\\..*}"));
-		assertEquals("Adapter, Visitor, Writer", m.process("${findname;Method(.*)\\.class;$1}"));
-	}
-
-	public void testWarning() {
-		Processor p = new Processor();
-		p.setProperty("three", "333");
-		p.setProperty("empty", "");
-		p.setProperty("real", "true");
-		Macro m = new Macro(p);
-
-		m.process("    ${warning;xw;1;2;3 ${three}}");
-		m.process("    ${error;xe;1;2;3 ${three}}");
-		m.process("    ${if;1;$<a>}");
-		assertEquals("xw", p.getWarnings().get(0));
-		assertEquals("1", p.getWarnings().get(1));
-		assertEquals("2", p.getWarnings().get(2));
-		assertEquals("3 333", p.getWarnings().get(3));
-
-		assertEquals("xe", p.getErrors().get(0));
-		assertEquals("1", p.getErrors().get(1));
-		assertEquals("2", p.getErrors().get(2));
-		assertEquals("3 333", p.getErrors().get(3));
-	}
-
-	public void testNestedReplace() {
-		Processor p = new Processor();
-		Macro m = new Macro(p);
-		String value = m.process("xx$(replace;1.2.3-SNAPSHOT;(\\d(\\.\\d)+).*;$1)xx");
-		System.out.println(p.getWarnings());
-		assertEquals("xx1.2.3xx", value);
-
-		assertEquals("xx1.222.3xx", m
-				.process("xx$(replace;1.222.3-SNAPSHOT;(\\d+(\\.\\d+)+).*;$1)xx"));
-
-		p.setProperty("a", "aaaa");
-		assertEquals("[cac]", m.process("$[replace;acaca;a(.*)a;[$1]]"));
-		assertEquals("xxx", m.process("$(replace;yxxxy;[^x]*(x+)[^x]*;$1)"));
-		assertEquals("xxx", m.process("$(replace;yxxxy;([^x]*(x+)[^x]*);$2)"));
-
-	}
-
-	public void testParentheses() {
-		Processor p = new Processor();
-		Macro m = new Macro(p);
-		String value = m.process("$(replace;();(\\(\\));$1)");
-		assertEquals("()", value);
-	}
-
-	public void testSimple() {
-		Processor p = new Processor();
-		p.setProperty("a", "aaaa");
-		Macro m = new Macro(p);
-		assertEquals("aaaa", m.process("${a}"));
-		assertEquals("aaaa", m.process("$<a>"));
-		assertEquals("aaaa", m.process("$(a)"));
-		assertEquals("aaaa", m.process("$[a]"));
-
-		assertEquals("xaaaax", m.process("x${a}x"));
-		assertEquals("xaaaaxaaaax", m.process("x${a}x${a}x"));
-	}
-
-	public void testFilter() {
-		Processor p = new Processor();
-		p.setProperty("a", "aaaa");
-		Macro m = new Macro(p);
-		assertEquals("aa,cc,ee", m.process("${filter;aa,bb,cc,dd,ee,ff;[ace]+}"));
-		assertEquals("aaaa,cc,ee", m.process("${filter;${a},bb,cc,dd,ee,ff;[ace]+}"));
-		assertEquals("bb,dd,ff", m.process("${filter;${a},bb,cc,dd,ee,ff;[^ace]+}"));
-	}
-
-	public void testFilterOut() {
-		Processor p = new Processor();
-		p.setProperty("a", "aaaa");
-		Macro m = new Macro(p);
-		assertEquals("bb,dd,ff", m.process("${filterout;aa,bb,cc,dd,ee,ff;[ace]+}"));
-		assertEquals("bb,dd,ff", m.process("${filterout;${a},bb,cc,dd,ee,ff;[ace]+}"));
-		assertEquals("aaaa,cc,ee", m.process("${filterout;${a},bb,cc,dd,ee,ff;[^ace]+}"));
-	}
-
-	public void testSort() {
-		Processor p = new Processor();
-		p.setProperty("a", "aaaa");
-		Macro m = new Macro(p);
-		assertEquals("aa,bb,cc,dd,ee,ff", m.process("${sort;aa,bb,cc,dd,ee,ff}"));
-		assertEquals("aa,bb,cc,dd,ee,ff", m.process("${sort;ff,ee,cc,bb,dd,aa}"));
-		assertEquals("aaaa,bb,cc,dd,ee,ff", m.process("${sort;ff,ee,cc,bb,dd,$<a>}"));
-	}
-
-	public void testJoin() {
-		Processor p = new Processor();
-		p.setProperty("a", "aaaa");
-		Macro m = new Macro(p);
-		assertEquals("aa,bb,cc,dd,ee,ff", m.process("${join;aa,bb,cc,dd,ee,ff}"));
-		assertEquals("aa,bb,cc,dd,ee,ff", m.process("${join;aa,bb,cc;dd,ee,ff}"));
-		assertEquals("aa,bb,cc,dd,ee,ff", m.process("${join;aa;bb;cc;dd;ee,ff}"));
-	}
-
-	public void testIf() {
-		Processor p = new Processor();
-		p.setProperty("a", "aaaa");
-		Macro m = new Macro(p);
-		assertEquals("aaaa", m.process("${if;1;$<a>}"));
-		assertEquals("", m.process("${if;;$<a>}"));
-		assertEquals("yes", m.process("${if;;$<a>;yes}"));
-	}
-
-	public void testLiteral() {
-		Processor p = new Processor();
-		p.setProperty("a", "aaaa");
-		Macro m = new Macro(p);
-		assertEquals("${aaaa}", m.process("${literal;$<a>}"));
-	}
-}
diff --git a/biz.aQute.bndlib/src/test/MakeTest.java b/biz.aQute.bndlib/src/test/MakeTest.java
deleted file mode 100644
index 53013b5..0000000
--- a/biz.aQute.bndlib/src/test/MakeTest.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package test;
-
-import java.io.*;
-import java.util.*;
-
-import junit.framework.*;
-import aQute.lib.osgi.*;
-
-/**
- * Tests the make functionality.
- * 
- * @author aqute
- *
- */
-public class MakeTest extends TestCase {
-    
-    /**
-     * Test a make plugin
-     */
-    
-    public void testMakePlugin() throws Exception {
-        Builder b = new Builder();
-        b.setProperty("Export-Package", "*");
-        b.setProperty("Include-Resource", "jar/asm.jar.md5");
-        b.setProperty("-make", "(*).md5;type=md5;file=$1");        
-        b.setProperty("-plugin", "test.make.MD5");
-        b.addClasspath( new File("jar/osgi.jar"));
-        Jar jar = b.build();
-        System.out.println(b.getErrors());
-        System.out.println(b.getWarnings());
-        assertEquals(0, b.getErrors().size());
-        assertEquals(0, b.getWarnings().size());
-        assertNotNull( jar.getResource("asm.jar.md5"));
-    }
-    
-    /**
-     * Check if we can get a resource through the make copy facility.
-     * 
-     * @throws Exception
-     */
-    public void testCopy() throws Exception {
-        Builder bmaker = new Builder();
-        Properties p = new Properties();
-        p.setProperty("-resourceonly","true");
-        p.setProperty("-plugin", "aQute.bnd.make.MakeBnd, aQute.bnd.make.MakeCopy");
-        p.setProperty("-make", "(*).jar;type=bnd;recipe=bnd/$1.bnd, (*).jar;type=copy;from=jar/$1.jar");
-        p.setProperty("Include-Resource", "asm.jar,xyz=asm.jar");
-        bmaker.setProperties(p);
-        Jar jar = bmaker.build();
-        assertNotNull(jar.getResource("asm.jar"));
-        assertNotNull(jar.getResource("xyz"));
-        report(bmaker);
-        
-    }
-    
-    
- 
-    /**
-     * Check if we can create a JAR recursively
-     * 
-     * @throws Exception
-     */
-    public void testJarInJarInJar() throws Exception {
-        Builder bmaker = new Builder();
-        Properties p = new Properties();
-        p.setProperty("-plugin", "aQute.bnd.make.MakeBnd, aQute.bnd.make.MakeCopy");
-        p.setProperty("-resourceonly","true");
-        p.setProperty("-make", "(*).jar;type=bnd;recipe=bnd/$1.bnd");
-        p.setProperty("Include-Resource", "makesondemand.jar");
-        bmaker.setProperties(p);
-        bmaker.setClasspath( new String[] {"bin"});
-        Jar jar = bmaker.build();
-        JarResource resource = (JarResource) jar.getResource("makesondemand.jar");
-        assertNotNull(resource);
-        
-        jar = resource.getJar();
-        resource = (JarResource) jar.getResource("ondemand.jar");
-        assertNotNull(resource);
-        
-        report(bmaker);        
-    }
-    /**
-     * Check if we can create a jar on demand through the make
-     * facility with a new name.
-     * 
-     * @throws Exception
-     */
-    public void testComplexOnDemand() throws Exception {
-        Builder bmaker = new Builder();
-        Properties p = new Properties();
-        p.setProperty("-resourceonly","true");
-        p.setProperty("-plugin", "aQute.bnd.make.MakeBnd, aQute.bnd.make.MakeCopy");
-        p.setProperty("-make", "(*).jar;type=bnd;recipe=bnd/$1.bnd");
-        p.setProperty("Include-Resource", "www/xyz.jar=ondemand.jar");
-        bmaker.setProperties(p);
-        bmaker.setClasspath( new String[] {"bin"});
-        Jar jar = bmaker.build();
-        Resource resource =jar.getResource("www/xyz.jar");
-        assertNotNull(resource);
-        assertTrue( resource instanceof JarResource );
-        report(bmaker);
-        
-    }
-    void report(Processor processor) {
-        System.out.println();
-        for ( int i=0; i<processor.getErrors().size(); i++ )
-            System.out.println(processor.getErrors().get(i));
-        for ( int i=0; i<processor.getWarnings().size(); i++ )
-            System.out.println(processor.getWarnings().get(i));
-        assertEquals(0, processor.getErrors().size());
-        assertEquals(0, processor.getWarnings().size());
-    }
-
-}
diff --git a/biz.aQute.bndlib/src/test/ManifestTest.java b/biz.aQute.bndlib/src/test/ManifestTest.java
deleted file mode 100755
index 7e5fc01..0000000
--- a/biz.aQute.bndlib/src/test/ManifestTest.java
+++ /dev/null
@@ -1,196 +0,0 @@
-package test;
-
-import java.io.*;
-import java.util.*;
-import java.util.jar.*;
-import java.util.regex.*;
-import java.util.zip.*;
-
-import junit.framework.*;
-import aQute.lib.io.*;
-import aQute.lib.osgi.*;
-
-public class ManifestTest extends TestCase {
-
-	public void testNameSection() throws Exception {
-        Builder b = new Builder();
-        b.setProperty("Export-Package", "org.osgi.framework");        
-        b.addClasspath( new File("jar/osgi.jar"));
-        
-        Jar jar = b.build();
-        jar.calcChecksums(null);
-        File f = File.createTempFile("abc", ".jar");
-        f.deleteOnExit();
-        jar.write(f);
-        
-        jar = new Jar(f);
-        f.delete();
-        
-        assertEquals(0, b.getErrors().size());
-        assertEquals(0, b.getWarnings().size());
-        Resource r = jar.getResource("META-INF/MANIFEST.MF");        
-        assertNotNull( r );
-
-//        String ms = IO.collect( r.openInputStream());
-        
-        Manifest m = new Manifest( r.openInputStream());
-        
-        assertEquals( 31, m.getEntries().size());
-        
-        Attributes ba = m.getAttributes("org/osgi/framework/BundleActivator.class");
-        assertNotNull(ba);
-        assertEquals(  "RTRhr3kadnulINegRhpmog==", ba.getValue("MD5-Digest"));
-        
-        Attributes bundle = m.getAttributes("org/osgi/framework/Bundle.class");
-        assertNotNull(bundle);
-        assertEquals(  "fpQdL60w3CQK+7xlXtM6oA==", bundle.getValue("MD5-Digest"));
-        
-        Attributes sl = m.getAttributes("org/osgi/framework/ServiceListener.class");
-        assertNotNull(sl);
-        assertEquals(  "nzDRN19MrTJG+LP8ayKZITZ653g=", sl.getValue("SHA-Digest"));
-        
-	}
-
-	public void testUnicode() throws Exception {
-        Builder b = new Builder();
-        String longSentence = "\u1401\u1402\u1403\u1404\u1405\u1406\u1407\u1408\u1409\u140A\u140B\u140C\u140D\u140E\u140F\u1410\u1411\u1412\u1413\u1414\u1415\u1416\u1417\u1418\u1419\u141A\u141B\u141C\u141D\u141E\u141F\u1420\u1421\u1422\u1422\u1423\u1424\u1425\u1426\u1427\u1428\u1429\u1429\u142A\u142B\u142C\u142D\u142E\u142F\u1430\u1431\u1432\u1433\u1434\u1435\u1436\u1437\u1438\u1439\u143A\u143B\u143C\u143D\u143E\u143F\u1440\u1441\u1442\u1443\u1444\u1444\u1445\u1446\u1447\u1448\u1449\u144 [...]
-        String shortSentence = "\u1401\u1402\u1403\u1404\u1405\u1406\u1407\u1408\u1409\u140A\u140B\u140C\u140D\u140E\u140F\u1410\u1411\u1412\u1413\u1414\u1415\u1416";
-        assertEquals( 66, shortSentence.getBytes("UTF8").length);
-        assertEquals( 22, shortSentence.length());
-        
-        b.setProperty("A1", shortSentence);
-        b.setProperty("A11", shortSentence);
-        b.setProperty("A111", shortSentence);
-        b.setProperty("A1111", shortSentence);
-        b.setProperty("Long", longSentence);
-        
-        b.setProperty( "-resourceonly", "true");
-        b.setProperty( "Include-Resource", "jar/osgi.jar");
-        Jar jar = b.build();
-        File f = File.createTempFile("abc", ".jar");
-        f.deleteOnExit();
-        jar.write(f);
-        
-        jar = new Jar(f);
-        f.delete();
-        
-        assertEquals(0, b.getErrors().size());
-        assertEquals(0, b.getWarnings().size());
-        Resource r = jar.getResource("META-INF/MANIFEST.MF");        
-        assertNotNull( r );
-        
-        Manifest m = new Manifest( r.openInputStream());
-//        String ms = IO.collect(r.openInputStream());
-        
-        assertEquals( shortSentence, m.getMainAttributes().getValue("A1"));
-        assertEquals( shortSentence, m.getMainAttributes().getValue("A11"));
-        assertEquals( shortSentence, m.getMainAttributes().getValue("A111"));
-        assertEquals( shortSentence, m.getMainAttributes().getValue("A1111"));
-        assertEquals( longSentence, m.getMainAttributes().getValue("Long"));
-        
-	}
-	
-	
-	
-    public void test72() throws Exception {
-        Builder b = new Builder();
-        b.setProperty("H65","01234567890123456789012345678901234567890123456789012345678901234");
-        b.setProperty("H66","012345678901234567890123456789012345678901234567890123456789012345");
-        b.setProperty("H67","0123456789012345678901234567890123456789012345678901234567890123456");
-        b.setProperty("H68","01234567890123456789012345678901234567890123456789012345678901234567");
-        b.setProperty("H69","012345678901234567890123456789012345678901234567890123456789012345678");
-        b.setProperty( "-resourceonly", "true");
-        b.setProperty( "Include-Resource", "jar/osgi.jar");
-        Jar jar = b.build();
-        File f = File.createTempFile("abc", ".jar");
-        f.deleteOnExit();
-        jar.write(f);
-        
-        jar = new Jar(f);
-        f.delete();
-        
-        assertEquals(0, b.getErrors().size());
-        assertEquals(0, b.getWarnings().size());
-        Resource r = jar.getResource("META-INF/MANIFEST.MF");        
-        assertNotNull( r );
-        
-        Manifest m = new Manifest( r.openInputStream());
-        String ms = IO.collect( r.openInputStream());
-        
-        assertEquals( 65, m.getMainAttributes().getValue("H65").length());
-        assertEquals( 66, m.getMainAttributes().getValue("H66").length());
-        assertEquals( 67, m.getMainAttributes().getValue("H67").length());
-        assertEquals( 68, m.getMainAttributes().getValue("H68").length());
-        assertEquals( 69, m.getMainAttributes().getValue("H69").length());
-        
-        assertTrue( Pattern.compile("H65: \\d{65}\r\n").matcher(ms).find());
-        assertTrue( Pattern.compile("H66: \\d{66}\r\n").matcher(ms).find());
-        assertTrue( Pattern.compile("H67: \\d{67}\r\n").matcher(ms).find());
-        assertTrue( Pattern.compile("H68: \\d{67}\r\n 7\r\n").matcher(ms).find());
-        assertTrue( Pattern.compile("H69: \\d{67}\r\n 78\r\n").matcher(ms).find());
-    }
-    
-	
-    public void testNoManifest() throws Exception {
-        Builder b = new Builder();
-        b.setProperty("-nomanifest","true");
-        b.setProperty("Export-Package","org.osgi.service.event.*");
-        b.addClasspath(new File("jar/osgi.jar"));
-        Jar jar = b.build();
-        assertNull( jar.getResource("META-INF/MANIFEST.MF"));
-        ByteArrayOutputStream bout = new ByteArrayOutputStream();
-        jar.write(bout);
-        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
-        JarInputStream  in = new JarInputStream(bin);
-        ZipEntry entry = in.getNextEntry();
-        assertNotNull(entry);
-        assertNull( entry.getExtra());
-    }
-    
-    
-    public void testNames() throws Exception {
-        Manifest m = new Manifest();
-        m.getMainAttributes().putValue("Manifest-Version", "1.0");
-        m.getMainAttributes().putValue("x", "Loïc Cotonéa");
-        m.getMainAttributes().putValue("y", "Loïc Cotonéa");
-        m.getMainAttributes().putValue("z", "Loïc Cotonéa");
-        
-        ByteArrayOutputStream bout = new ByteArrayOutputStream();
-        Jar.writeManifest(m,bout);
-        byte [] result = bout.toByteArray();
-        
-        System.out.println( new String(result));
-    }
-    
-
-    public void testUTF8() throws Exception {
-        Manifest m = new Manifest();
-        m.getMainAttributes().putValue("Manifest-Version", "1.0");
-        m.getMainAttributes().putValue("x", "Loïc Cotonéa");
-        m.getMainAttributes().putValue("y", "Loïc Cotonéa");
-        m.getMainAttributes().putValue("z", "Loïc Cotonéa");
-        
-        ByteArrayOutputStream bout = new ByteArrayOutputStream();
-        Jar.writeManifest(m,bout);
-        byte [] result = bout.toByteArray();
-        
-        System.out.println( new String(result));
-    }
-    
-	public void testQuotes() {
-		Map<String,Map<String,String>> map = new HashMap<String,Map<String,String>>();
-		Map<String,String> clause = new HashMap<String,String>();
-		clause.put("version1", "0");
-		clause.put("version2", "0.0");
-		clause.put("version3", "\"0.0\"");
-		clause.put("version4", "   \"0.0\"    ");
-		clause.put("version5", "   0.0    ");
-		map.put("alpha", clause);
-		String s = Processor.printClauses(map);
-		assertTrue( s.indexOf("version1=0")>=0);
-		assertTrue( s.indexOf("version2=\"0.0\"")>=0);
-		assertTrue( s.indexOf("version3=\"0.0\"")>=0);
-		assertTrue( s.indexOf("version4=\"0.0\"")>=0);
-		assertTrue( s.indexOf("version5=\"0.0\"")>=0);
-	}
-}
diff --git a/biz.aQute.bndlib/src/test/MavenTest.java b/biz.aQute.bndlib/src/test/MavenTest.java
deleted file mode 100644
index f4cba81..0000000
--- a/biz.aQute.bndlib/src/test/MavenTest.java
+++ /dev/null
@@ -1,361 +0,0 @@
-package test;
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.regex.*;
-
-import junit.framework.*;
-import aQute.bnd.build.*;
-import aQute.bnd.maven.*;
-import aQute.bnd.maven.support.*;
-import aQute.bnd.maven.support.Pom.*;
-import aQute.bnd.service.RepositoryPlugin.Strategy;
-import aQute.lib.io.*;
-import aQute.lib.osgi.*;
-import aQute.libg.map.*;
-import aQute.libg.version.*;
-
-public class MavenTest extends TestCase {
-	Processor	processor	= new Processor();
-	final static File cwd = new File("").getAbsoluteFile();
-	static ExecutorService executor = Executors.newCachedThreadPool();
-	Maven maven = new Maven(executor);
-
-	/**
-	 * A test against maven 2
-	 * @throws Exception 
-	 * @throws URISyntaxException 
-	 */
-	public void testRemote() throws URISyntaxException, Exception {
-		URI repo = new URI("http://repo1.maven.org/maven2");
-		MavenEntry entry = maven.getEntry("org.springframework", "spring-aspects"	, "3.0.5.RELEASE");
-		entry.remove();
-		CachedPom pom = maven.getPom("org.springframework", "spring-aspects"	, "3.0.5.RELEASE", repo);
-		Set<Pom> dependencies = pom.getDependencies(Scope.compile, repo);
-		for ( Pom dep : dependencies ) {
-			System.out.printf( "%20s %-20s %10s\n", dep.getGroupId(), dep.getArtifactId(), dep.getVersion());
-		}
-		
-	}
-	
-	/**
-	 * Test reading a pom for the buildpath
-	 * @throws Exception 
-	 */
-	
-	public void testPom() throws Exception{
-		
-		Project project = getProject("maven2");
-		
-		Collection<Container> containers = project.getBuildpath();
-		List<String> files = new ArrayList<String>();
-		for ( Container c : containers ) {
-			files.add( c.getFile().getName());
-		}
-		assertTrue(files.remove("bin"));
-		System.out.println(files);
-		assertTrue( files.contains("com.springsource.org.apache.commons.beanutils-1.6.1.jar"));		
-		assertTrue( files.contains("com.springsource.org.apache.commons.collections-2.1.1.jar"));		
-		assertTrue( files.contains("com.springsource.org.apache.commons.logging-1.0.4.jar"));		
-		
-	}
-	
-	
-	/**
-	 * Check if we get the correct bundles for a project
-	 * 
-	 * @throws Exception 
-	 */
-	
-	public void testProjectBundles() throws Exception {
-//		Project project = getProject("maven1");
-//		
-//		Collection<Container> containers = project.getBuildpath();
-//		List<String> files = new ArrayList<String>();
-//		for ( Container c : containers ) {
-//			files.add( c.getFile().getName());
-//		}
-//		assertTrue(files.remove("bin"));
-//		System.out.println(files);
-//		assertTrue( files.contains("com.springsource.org.apache.commons.beanutils-1.6.1.jar"));
-	}
-
-	/**
-	 * @return
-	 * @throws Exception
-	 */
-	protected Project getProject(String name) throws Exception {
-		File wsf = IO.getFile(cwd, "test/ws");
-		Workspace ws =  Workspace.getWorkspace( wsf );
-	
-		assertNotNull(ws);
-
-		Project project = ws.getProject(name);
-		assertNotNull(project);
-		return project;
-	}
-	
-	
-	/**
-	 * See if we can create a maven repostory as a plugin
-	 * 
-	 * @throws Exception 
-	 */
-	
-	public void testMavenRepo() throws Exception {
-		Workspace ws =  Workspace.getWorkspace( cwd.getParentFile());
-		Maven maven = ws.getMaven();
-		
-		Processor processor = new Processor(ws);
-		processor.setProperty(Constants.PLUGIN, 
-				"aQute.bnd.maven.support.MavenRemoteRepository;repositories=test/ws/maven1/m2");
-
-		MavenRemoteRepository mr = processor.getPlugin(MavenRemoteRepository.class);
-		assertNotNull(mr);
-		assertEquals( maven, mr.getMaven());
-		
-		// Cleanup the maven cache so we do not get random results
-		MavenEntry me = maven.getEntry("org.apache.commons",
-				"com.springsource.org.apache.commons.beanutils", "1.6.1");
-		assertNotNull(me);
-		me.remove();
-
-		Map<String,String> map = MAP.$("groupId","org.apache.commons"); 
-		File file = mr.get("com.springsource.org.apache.commons.beanutils",
-				"1.6.1", Strategy.LOWEST, map);
-
-		assertNotNull(file);
-		assertEquals("com.springsource.org.apache.commons.beanutils-1.6.1.jar", file.getName());
-		assertTrue( file.isFile());
-
-		Map<String,String> map2 = MAP.$("groupId","org.apache.commons").$("scope","compile"); 
-
-		file = mr.get("com.springsource.org.apache.commons.beanutils",
-				"1.6.1", Strategy.LOWEST, map2);
-		assertNotNull(file);
-		assertTrue( file.isFile());
-		assertEquals("compile.lib", file.getName());
-		String lib = IO.collect(file);
-		System.out.println(lib);
-		lib = lib.replaceAll("org.apache.commons\\+com.springsource.org.apache.commons.beanutils;version=\"1.6.1\"","1");
-   		lib = lib.replaceAll("org.apache.commons\\+com.springsource.org.apache.commons.collections;version=\"2.1.1\"", "2");
-		lib = lib.replaceAll("org.apache.commons\\+com.springsource.org.apache.commons.logging;version=\"1.0.4\"", "3");
-		assertEquals( "1\n2\n3\n", lib);
-	}
-	
-	
-	
-	
-	/**
-	 * Test parsing a project pom
-	 * @throws Exception 
-	 */
-	
-	public void testProjectPom() throws Exception {
-		Maven maven = new Maven(null);
-		ProjectPom pom = maven.createProjectModel( IO.getFile( cwd, "test/ws/maven1/testpom.xml"));
-		assertEquals( "artifact", pom.getArtifactId());
-		assertEquals( "group-parent", pom.getGroupId());
-		assertEquals( "1.0.0", pom.getVersion());
-		assertEquals( "Artifact", pom.getName());
-		assertEquals( "Parent Description\n\nDescription artifact", pom.getDescription());
-		
-		List<Dependency> dependencies = pom.getDependencies();
-		boolean dep1=false; // dep1
-		boolean dep2=false; // artifact (after macro)
-		boolean dep3=false; // junit
-		boolean dep4=false; // easymock
-		
-		for ( Dependency dep : dependencies ) {
-			String artifactId = dep.getArtifactId();
-			if ( "dep1".equals(artifactId)) {
-				assertFalse( dep1);
-				dep1=true;
-				assertEquals( "xyz", dep.getGroupId());
-				assertEquals( "1.0.1", dep.getVersion());				
-				assertEquals( Pom.Scope.valueOf("compile"), dep.getScope());
-				
-			} else if ( "artifact".equals(artifactId)) {
-				assertFalse( dep2);
-				dep2=true;
-				assertEquals( "group-parent", dep.getGroupId());
-				assertEquals( "1.0.2", dep.getVersion());
-				assertEquals( Pom.Scope.valueOf("compile"), dep.getScope());				
-			} else if ( "junit".equals(artifactId)) {
-				assertFalse( dep3);
-				dep3=true;
-				assertEquals( "junit", dep.getGroupId());
-				assertEquals( "4.0", dep.getVersion());
-				assertEquals( Pom.Scope.valueOf("test"), dep.getScope());				
-			} else if ( "easymock".equals(artifactId)) {
-				assertFalse( dep4);
-				dep4=true;
-				assertEquals( "org.easymock", dep.getGroupId());
-				assertEquals( "2.4", dep.getVersion());
-				assertEquals( Pom.Scope.valueOf("compile"), dep.getScope());				
-			} else
-				fail("'"+artifactId+"'");
-		}
-		assertTrue(dep1 && dep2 && dep3 && dep4);
-		
-		assertEquals( "aa", pom.getProperty("a"));
-		assertEquals( "b from parent", pom.getProperty("b"));
-		assertEquals( "aab from parentartifact", pom.getProperty("c"));
-	}
-	
-	/**
-	 * Test the maven remote repository
-	 */
-
-	public void testMavenRepo1() throws Exception {
-		Maven maven = new Maven(null);
-		MavenRemoteRepository mr = new MavenRemoteRepository();
-		mr.setMaven(maven);
-
-		MavenEntry me = maven.getEntry("org.apache.commons",
-				"com.springsource.org.apache.commons.beanutils", "1.6.1");
-		me.remove();
-
-		me = maven.getEntry("org.apache.commons",
-				"com.springsource.org.apache.commons.collections", "2.1.1");
-		me.remove();
-
-		me = maven.getEntry("org.apache.commons",
-				"com.springsource.org.apache.commons.logging", "1.0.4");
-		me.remove();
-
-		mr.setRepositories(new URI[] { IO.getFile(new File("").getAbsoluteFile(), "test/ws/maven1/m2").toURI() });
-
-		Map<String, String> map = new HashMap<String, String>();
-		map.put("scope", "compile");
-		File file = mr.get("org.apache.commons+com.springsource.org.apache.commons.beanutils",
-				"1.6.1", Strategy.LOWEST, map);
-		
-		assertNotNull(file);
-		assertTrue( file.isFile());
-		
-		assertEquals(
-				"org.apache.commons+com.springsource.org.apache.commons.beanutils;version=\"1.6.1\"\n"
-						+ "org.apache.commons+com.springsource.org.apache.commons.collections;version=\"2.1.1\"\n"
-						+ "org.apache.commons+com.springsource.org.apache.commons.logging;version=\"1.0.4\"\n",
-				IO.collect(file));
-
-
-		file = mr.get("org.apache.commons+com.springsource.org.apache.commons.beanutils",
-				"1.6.1", Strategy.LOWEST, null);
-		assertEquals( "com.springsource.org.apache.commons.beanutils-1.6.1.jar", file.getName());
-	}
-
-	public void testMavenx() throws Exception {
-		Maven maven = new Maven(null);
-		CachedPom pom = maven.getPom("javax.xml.bind", "com.springsource.javax.xml.bind", "2.2.0",
-				new URI("http://repository.springsource.com/maven/bundles/release"), new URI(
-						"http://repository.springsource.com/maven/bundles/external"));
-		// Pom pom = maven.getPom("javax.xml.ws",
-		// "com.springsource.javax.xml.ws", "2.1.1", new
-		// URL("http://repository.springsource.com/maven/bundles/release"), new
-		// URL("http://repository.springsource.com/maven/bundles/external"));
-		System.out.println(pom.getGroupId() + " + " + pom.getArtifactId() + "-" + pom.getVersion());
-
-		System.out.println(pom.getDependencies(Pom.Scope.compile));
-
-		File artifact = pom.getArtifact();
-		System.out.println(artifact);
-	}
-
-
-	/**
-	 * Test the pom parser which will turn the pom into a set of properties,
-	 * which will make it actually readable according to some.
-	 * 
-	 * @throws Exception
-	 */
-
-	public void testPomParser() throws Exception {
-		PomParser parser = new PomParser();
-		Properties p = parser.getProperties(new File("test/ws/maven1/pom.xml"));
-		p.store(System.out, "testing");
-		assertEquals("Apache Felix Metatype Service", p.get("pom.name"));
-		assertEquals("org.apache.felix", p.get("pom.groupId")); // is from
-																// parent
-		assertEquals("org.apache.felix.metatype", p.get("pom.artifactId"));
-		assertEquals("bundle", p.get("pom.packaging"));
-
-		Map<String, Map<String, String>> map = parser.parseHeader(p.getProperty("pom.scope.test"));
-		Map<String, String> junit = map.get("junit.junit");
-		assertNotNull(junit);
-		assertEquals("4.0", junit.get("version"));
-		Map<String, String> easymock = map.get("org.easymock.easymock");
-		assertNotNull(easymock);
-		assertEquals("2.4", easymock.get("version"));
-	}
-
-	// public void testDependencies() throws Exception {
-	// MavenDependencyGraph graph;
-	//
-	// graph = new MavenDependencyGraph();
-	// File home = new File( System.getProperty("user.home"));
-	// File m2 = new File( home, ".m2");
-	// File m2Repo = new File( m2, "repository");
-	// if ( m2Repo.isDirectory())
-	// graph.addRepository( m2Repo.toURI().toURL());
-	//
-	// graph.addRepository( new URL("http://repo1.maven.org/maven2/"));
-	// graph.addRepository( new
-	// URL("http://repository.springsource.com/maven/bundles/external"));
-	// // graph.root.add( new File("test/poms/pom-1.xml").toURI().toURL());
-	//
-	// }
-
-//	public void testMaven() throws Exception {
-//		MavenRepository maven = new MavenRepository();
-//		maven.setReporter(processor);
-//		maven.setProperties(new HashMap<String, String>());
-//		maven.setRoot(processor.getFile("test/maven-repo"));
-//
-//		File files[] = maven.get("activation.activation", null);
-//		assertNotNull(files);
-//		assertEquals("activation-1.0.2.jar", files[0].getName());
-//
-//		files = maven.get("biz.aQute.bndlib", null);
-//		assertNotNull(files);
-//		assertEquals(5, files.length);
-//		assertEquals("bndlib-0.0.145.jar", files[0].getName());
-//		assertEquals("bndlib-0.0.255.jar", files[4].getName());
-//
-//		List<String> names = maven.list(null);
-//		System.out.println(names);
-//		assertEquals(13, names.size());
-//		assertTrue(names.contains("biz.aQute.bndlib"));
-//		assertTrue(names.contains("org.apache.felix.javax.servlet"));
-//		assertTrue(names.contains("org.apache.felix.org.osgi.core"));
-//
-//		List<Version> versions = maven.versions("org.apache.felix.javax.servlet");
-//		assertEquals(1, versions.size());
-//		versions.contains(new Version("1.0.0"));
-//
-//		versions = maven.versions("biz.aQute.bndlib");
-//		assertEquals(5, versions.size());
-//		versions.contains(new Version("0.0.148"));
-//		versions.contains(new Version("0.0.255"));
-//	}
-
-//	public void testMavenBsnMapping() throws Exception {
-//		Processor processor = new Processor();
-//		processor
-//				.setProperty("-plugin",
-//						"aQute.bnd.maven.MavenGroup; groupId=org.apache.felix, aQute.bnd.maven.MavenRepository");
-//		MavenRepository maven = new MavenRepository();
-//		maven.setReporter(processor);
-//		Map<String, String> map = new HashMap<String, String>();
-//		map.put("root", IO.getFile(cwd,"test/maven-repo").getAbsolutePath());
-//		maven.setProperties(map);
-//
-//		File files[] = maven.get("org.apache.felix.framework", null);
-//		assertNotNull(files);
-//		;
-//		assertEquals(1, files.length);
-//	}
-}
diff --git a/biz.aQute.bndlib/src/test/MergeTest.java b/biz.aQute.bndlib/src/test/MergeTest.java
deleted file mode 100644
index 0323a3b..0000000
--- a/biz.aQute.bndlib/src/test/MergeTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package test;
-
-import java.io.*;
-import java.util.*;
-
-import junit.framework.*;
-
-import aQute.lib.osgi.*;
-
-public class MergeTest extends TestCase {
-
-	public void testFirst() throws Exception {
-		testMerge("first", new String[] { "A", "C" }, new String[] { "B" },
-				"first", 0, 0);
-	}
-	
-	public void testMergeFirst() throws Exception {
-		testMerge("merge-first", new String[] { "A", "B", "C" },
-				new String[] { "" }, "first", 0, 0);
-	}
-	
-	public void testDefault() throws Exception {
-		testMerge(null, new String[] { "A", "B", "C" }, new String[] { },
-				"first", 0, 1);
-	}
-	
-	public void testMergeLast() throws Exception {
-		testMerge("merge-last", new String[] { "A", "B", "C" },
-				new String[] { "" }, "last", 0, 0);
-	}
-	
-	public void testError() throws Exception {
-		testMerge("error", null, null,null, 1, 0);
-	}
-
-	void testMerge(String type, String[] in, String[] out, String c,
-			int errors, int warnings) throws Exception {
-		Builder b = new Builder();
-		b.setClasspath(new File[] { new File("src/test/split/split-a.jar"),
-				new File("src/test/split/split-b.jar") });
-		Properties p = new Properties();
-		if (type != null)
-			p.put("Export-Package", "test.split;-split-package:=" + type);
-		else
-			p.put("Export-Package", "test.split");
-		p.put("Import-Package", "");
-		b.setProperties(p);
-		Jar jar = b.build();
-		System.out.println("Errors     :" + b.getErrors());
-		System.out.println("Warnings   :" + b.getWarnings());
-		assertEquals(errors, b.getErrors().size());
-		assertEquals(warnings, b.getWarnings().size());
-		if (errors != 0)
-			return;
-
-		for (int i = 0; in != null && i < in.length; i++)
-			assertNotNull("Contains " + in[i], jar.getResource("test/split/"
-					+ in[i]));
-		for (int i = 0; out != null && i < out.length; i++)
-			assertNull("Does not contain " + out[i], jar
-					.getResource("test/split/" + out[i]));
-
-		Resource r = jar.getResource("test/split/C");
-		InputStream is = r.openInputStream();
-		BufferedReader dis = new BufferedReader( new InputStreamReader(is));
-		String s = dis.readLine();
-		assertEquals(s, c);
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/test/MetatypeTest.java b/biz.aQute.bndlib/src/test/MetatypeTest.java
deleted file mode 100644
index b5ea5bb..0000000
--- a/biz.aQute.bndlib/src/test/MetatypeTest.java
+++ /dev/null
@@ -1,902 +0,0 @@
-package test;
-
-import java.io.*;
-import java.lang.reflect.*;
-import java.net.*;
-import java.util.*;
-import java.util.regex.*;
-
-import javax.xml.namespace.*;
-import javax.xml.parsers.*;
-import javax.xml.xpath.*;
-
-import junit.framework.*;
-
-import org.w3c.dom.*;
-
-import aQute.bnd.annotation.metatype.*;
-import aQute.lib.io.*;
-import aQute.lib.osgi.*;
-import aQute.libg.generics.*;
-
-public class MetatypeTest extends TestCase {
-	DocumentBuilderFactory	dbf		= DocumentBuilderFactory.newInstance();
-	XPathFactory			xpathf	= XPathFactory.newInstance();
-	XPath					xpath	= xpathf.newXPath();
-
-	DocumentBuilder			db;
-	{
-		try {
-			dbf.setNamespaceAware(true);
-			db = dbf.newDocumentBuilder();
-			xpath.setNamespaceContext(new NamespaceContext() {
-
-				public Iterator getPrefixes(String namespaceURI) {
-					return Arrays.asList("md").iterator();
-				}
-
-				public String getPrefix(String namespaceURI) {
-					return "md";
-				}
-
-				public String getNamespaceURI(String prefix) {
-					return "http://www.osgi.org/xmlns/metatype/v1.1.0";
-				}
-			});
-		} catch (ParserConfigurationException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		}
-	}
-	
-	
-	public void testOptions() {
-		
-	}
-	
-	
-	
-	
-	/**
-	 * Test method naming options with '.' and reserved names
-	 */
-	
-	@Meta.OCD
-	public static interface Naming {
-		String secret();
-		String _secret(); // .secret
-		String __secret(); // _secret
-		String $new(); // new
-		String $$new(); // $new
-		String a_b_c(); // a.b.c
-		String a__b__c(); // a_b_c
-		String _a__b(); // .a_b
-		String $$$$$$$$a__b(); // $$$$a_b
-		String $$$$$$$$a_b(); // $$$$a.b
-		String a$(); // a
-		String a$$(); // a$
-		String a$$$(); // a$
-		String a$$$$(); // a$$
-		String a$$_$$(); // a$.$
-		String a$$__$$(); // a$_$
-		String a_$_(); // a..
-		
-		@Meta.AD(id="secret")
-		String xsecret();
-		@Meta.AD(id=".secret")
-		String x_secret();
-		@Meta.AD(id="_secret")
-		String x__secret(); // _secret
-		@Meta.AD(id="new")
-		String x$new(); // new
-		@Meta.AD(id="$new")
-		String x$$new(); // $new
-		@Meta.AD(id="a.b.c")
-		String xa_b_c(); // a.b.c
-		@Meta.AD(id="a_b_c")
-		String xa__b__c(); // a_b_c
-		@Meta.AD(id=".a_b")
-		String x_a__b(); // .a_b
-		@Meta.AD(id="$$$$a_b")
-		String x$$$$$$$$a__b(); // $$$$a_b
-		@Meta.AD(id="$$$$a.b")
-		String x$$$$$$$$a_b(); // $$$$a.b
-		@Meta.AD(id="a")
-		String xa$(); // a
-		@Meta.AD(id="a$")
-		String xa$$(); // a$
-		@Meta.AD(id="a$")
-		String xa$$$(); // a$
-		@Meta.AD(id="a$$")
-		String xa$$$$(); // a$$
-		@Meta.AD(id="a$.$")
-		String xa$$_$$(); // a$.$
-		@Meta.AD(id="a$_$")
-		String xa$$__$$(); // a$_$
-		@Meta.AD(id="a..")
-		String xa_$_(); // a..
-		
-		String noid();
-		
-		@Meta.AD(id=Meta.NULL)
-		String nullid();
-	}
-	
-	public void testNaming() throws Exception {
-		Map<String,Object> map = Create.map();
-		
-		map.put("_secret", "_secret");
-		map.put("_secret", "_secret");
-		map.put(".secret", ".secret");
-		map.put("$new", "$new");
-		map.put("new", "new");
-		map.put("secret", "secret");
-		map.put("a_b_c", "a_b_c");
-		map.put("a.b.c", "a.b.c");
-		map.put(".a_b", ".a_b");
-		map.put("$$$$a_b", "$$$$a_b");
-		map.put("$$$$a.b", "$$$$a.b");
-		map.put("a", "a");
-		map.put("a$", "a$");
-		map.put("a$$", "a$$");
-		map.put("a$.$", "a$.$");
-		map.put("a$_$", "a$_$");
-		map.put("a..", "a..");
-		map.put("noid", "noid");
-		map.put("nullid", "nullid");
-		
-		Naming trt = Configurable.createConfigurable(Naming.class, map);
-		
-		// By name
-		assertEquals( "secret", trt.secret() );
-		assertEquals( "_secret", trt.__secret() );
-		assertEquals( ".secret", trt._secret() );
-		assertEquals( "new", trt.$new() );
-		assertEquals( "$new", trt.$$new() );
-		assertEquals( "a.b.c", trt.a_b_c() );
-		assertEquals( "a_b_c", trt.a__b__c() );
-		assertEquals( ".a_b", trt._a__b() );
-		assertEquals( "$$$$a.b", trt.$$$$$$$$a_b() );
-		assertEquals( "$$$$a_b", trt.$$$$$$$$a__b() );
-		assertEquals( "a", trt.a$() );
-		assertEquals( "a$", trt.a$$() );
-		assertEquals( "a$", trt.a$$$() );
-		assertEquals( "a$.$", trt.a$$_$$() );
-		assertEquals( "a$_$", trt.a$$__$$() );
-		assertEquals( "a..", trt.a_$_() );
-		assertEquals( "noid", trt.noid() );
-		assertEquals( "nullid", trt.nullid() );
-
-		// By AD
-		assertEquals( "secret", trt.xsecret() );
-		assertEquals( "_secret", trt.x__secret() );
-		assertEquals( ".secret", trt.x_secret() );
-		assertEquals( "new", trt.x$new() );
-		assertEquals( "$new", trt.x$$new() );
-		assertEquals( "a.b.c", trt.xa_b_c() );
-		assertEquals( "a_b_c", trt.xa__b__c() );
-		assertEquals( ".a_b", trt.x_a__b() );
-		assertEquals( "$$$$a.b", trt.x$$$$$$$$a_b() );
-		assertEquals( "$$$$a_b", trt.x$$$$$$$$a__b() );
-		assertEquals( "a", trt.xa$() );
-		assertEquals( "a$", trt.xa$$() );
-		assertEquals( "a$", trt.xa$$$() );
-		assertEquals( "a$.$", trt.xa$$_$$() );
-
-		Builder b = new Builder();
-		b.addClasspath(new File("bin"));
-		b.setProperty("Export-Package", "test");
-		b.setProperty("-metatype", "*");
-		b.build();
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		Resource r = b.getJar().getResource("OSGI-INF/metatype/test.MetatypeTest$Naming.xml");
-		IO.copy(r.openInputStream(), System.out);
-		Document d = db.parse(r.openInputStream(),"UTF-8");
-		assertEquals("http://www.osgi.org/xmlns/metatype/v1.1.0", d.getDocumentElement()
-				.getNamespaceURI());
-		
-	}
-
-	/**
-	 * Test the special conversions.
-	 */
-	
-	public static class MyList<T> extends ArrayList<T> {
-		private static final long	serialVersionUID	= 1L;
-		
-		public MyList() {
-			System.out.println("Constr");
-			
-		}
-	}
-	interface CollectionsTest {
-		Collection<String> collection();
-		List<String> list();
-		Set<String> set();
-		Queue<String> queue();
-//		Deque<String> deque();
-		Stack<String> stack();
-		ArrayList<String> arrayList();
-		LinkedList<String> linkedList();
-		LinkedHashSet<String> linkedHashSet();
-		MyList<String> myList();
-	}
-
-	public void testCollections() throws Exception {
-		CollectionsTest trt = set( CollectionsTest.class, new int[]{1,2,3});
-		List<String> source = Arrays.asList("1","2","3");
-		
-		assertTrue( trt.collection() instanceof Collection);		
-		assertEqualList( source, trt.collection());
-		
-		assertTrue( trt.list() instanceof List);
-		assertEqualList( source, trt.list());
-		assertTrue( trt.set() instanceof Set);
-		assertEqualList( source, trt.set());
-		assertTrue( trt.queue() instanceof Queue);
-		assertEqualList(source, trt.queue());
-//		assertTrue( trt.deque() instanceof Deque);
-//		assertEqualList( source, trt.deque());
-		assertTrue( trt.stack() instanceof Stack);
-		assertEqualList(source, trt.stack());
-		assertTrue( trt.arrayList() instanceof ArrayList);
-		assertEqualList( source, trt.arrayList());
-		assertTrue( trt.linkedList() instanceof LinkedList);
-		assertEqualList( source, trt.linkedList());
-		assertTrue( trt.linkedHashSet() instanceof LinkedHashSet);
-		assertEqualList( source, trt.linkedHashSet());
-		assertTrue( trt.myList() instanceof MyList);
-		assertEqualList( source, trt.myList());
-	}
-
-	private void assertEqualList(List<?> a, Collection<?> b) {
-		if ( a.size() == b.size()) {
-			for ( Object x : a ) {
-				if ( !b.contains(x))
-					throw new AssertionFailedError("expected:<" +a + "> but was: <"+ b +">");					
-			}
-			return;
-		}
-		throw new AssertionFailedError("expected:<" +a + "> but was: <"+ b +">");
-	}
-
-	/**
-	 * Test the special conversions.
-	 */
-	interface SpecialConversions {
-		enum X {
-			A, B, C
-		}
-
-		X enumv();
-
-		Pattern pattern();
-
-		Class<?> clazz();
-
-		URI constructor();
-	}
-
-	public void testSpecialConversions() throws URISyntaxException {
-		Properties p = new Properties();
-		p.put("enumv", "A");
-		p.put("pattern", ".*");
-		p.put("clazz", "java.lang.Object");
-		p.put("constructor", "http://www.aQute.biz");
-
-		SpecialConversions trt = Configurable.createConfigurable(SpecialConversions.class, (Map) p);
-		assertEquals(SpecialConversions.X.A, trt.enumv());
-		assertEquals(".*", trt.pattern().pattern());
-		assertEquals(Object.class, trt.clazz());
-		assertEquals(new URI("http://www.aQute.biz"), trt.constructor());
-	}
-
-	/**
-	 * Test the converter.
-	 * 
-	 * @throws URISyntaxException
-	 */
-
-	public void testConverter() throws URISyntaxException {
-		{
-			// Test collections as value
-			TestReturnTypes trt = set(TestReturnTypes.class,Arrays.asList(55));
-			assertTrue(Arrays.equals(new boolean[] { true }, trt.rpaBoolean()));
-			assertTrue(Arrays.equals(new byte[] { 55 }, trt.rpaByte()));
-			assertTrue(Arrays.equals(new short[] { 55 }, trt.rpaShort()));
-			assertTrue(Arrays.equals(new int[] { 55 }, trt.rpaInt()));
-			assertTrue(Arrays.equals(new long[] { 55 }, trt.rpaLong()));
-			assertTrue(Arrays.equals(new float[] { 55 }, trt.rpaFloat()));
-			assertTrue(Arrays.equals(new double[] { 55 }, trt.rpaDouble()));
-			assertEquals(Arrays.asList(true), trt.rBooleans());
-			assertEquals(Arrays.asList(new Byte((byte) 55)), trt.rBytes());
-			assertEquals(Arrays.asList(new Short((short) 55)), trt.rShorts());
-			assertEquals(Arrays.asList(new Integer(55)), trt.rInts());
-			assertEquals(Arrays.asList(new Long(55L)), trt.rLongs());
-			assertEquals(Arrays.asList(new Float(55F)), trt.rFloats());
-			assertEquals(Arrays.asList(new Double(55D)), trt.rDoubles());
-			assertEquals(Arrays.asList("55"), trt.rStrings());
-			assertEquals(Arrays.asList(new URI("55")), trt.rURIs());
-
-			assertTrue(Arrays.equals(new Boolean[] { true }, trt.raBoolean()));
-			assertTrue(Arrays.equals(new Byte[] { 55 }, trt.raByte()));
-			assertTrue(Arrays.equals(new Short[] { 55 }, trt.raShort()));
-			assertTrue(Arrays.equals(new Integer[] { 55 }, trt.raInt()));
-			assertTrue(Arrays.equals(new Long[] { 55L }, trt.raLong()));
-			assertTrue(Arrays.equals(new Float[] { 55F }, trt.raFloat()));
-			assertTrue(Arrays.equals(new Double[] { 55D }, trt.raDouble()));
-			assertTrue(Arrays.equals(new String[] { "55" }, trt.raString()));
-			assertTrue(Arrays.equals(new URI[] { new URI("55") }, trt.raURI()));
-
-		}
-		{
-			// Test primitive arrays as value
-			TestReturnTypes trt = set(TestReturnTypes.class,new int[] { 55 });
-			assertTrue(Arrays.equals(new boolean[] { true }, trt.rpaBoolean()));
-			assertTrue(Arrays.equals(new byte[] { 55 }, trt.rpaByte()));
-			assertTrue(Arrays.equals(new short[] { 55 }, trt.rpaShort()));
-			assertTrue(Arrays.equals(new int[] { 55 }, trt.rpaInt()));
-			assertTrue(Arrays.equals(new long[] { 55 }, trt.rpaLong()));
-			assertTrue(Arrays.equals(new float[] { 55 }, trt.rpaFloat()));
-			assertTrue(Arrays.equals(new double[] { 55 }, trt.rpaDouble()));
-			assertEquals(Arrays.asList(true), trt.rBooleans());
-			assertEquals(Arrays.asList(new Byte((byte) 55)), trt.rBytes());
-			assertEquals(Arrays.asList(new Short((short) 55)), trt.rShorts());
-			assertEquals(Arrays.asList(new Integer(55)), trt.rInts());
-			assertEquals(Arrays.asList(new Long(55L)), trt.rLongs());
-			assertEquals(Arrays.asList(new Float(55F)), trt.rFloats());
-			assertEquals(Arrays.asList(new Double(55D)), trt.rDoubles());
-			assertEquals(Arrays.asList("55"), trt.rStrings());
-			assertEquals(Arrays.asList(new URI("55")), trt.rURIs());
-
-			assertTrue(Arrays.equals(new Boolean[] { true }, trt.raBoolean()));
-			assertTrue(Arrays.equals(new Byte[] { 55 }, trt.raByte()));
-			assertTrue(Arrays.equals(new Short[] { 55 }, trt.raShort()));
-			assertTrue(Arrays.equals(new Integer[] { 55 }, trt.raInt()));
-			assertTrue(Arrays.equals(new Long[] { 55L }, trt.raLong()));
-			assertTrue(Arrays.equals(new Float[] { 55F }, trt.raFloat()));
-			assertTrue(Arrays.equals(new Double[] { 55D }, trt.raDouble()));
-			assertTrue(Arrays.equals(new String[] { "55" }, trt.raString()));
-			assertTrue(Arrays.equals(new URI[] { new URI("55") }, trt.raURI()));
-
-		}
-
-		{
-			// Test single value
-			TestReturnTypes trt = set(TestReturnTypes.class,55);
-			assertEquals(true, trt.rpBoolean());
-			assertEquals(55, trt.rpByte());
-			assertEquals(55, trt.rpShort());
-			assertEquals(55, trt.rpInt());
-			assertEquals(55L, trt.rpLong());
-			assertEquals(55.0D, trt.rpDouble());
-			assertEquals(55.0F, trt.rpFloat());
-			assertEquals((Boolean) true, trt.rBoolean());
-			assertEquals(new Byte((byte) 55), trt.rByte());
-			assertEquals(new Short((short) 55), trt.rShort());
-			assertEquals(new Integer(55), trt.rInt());
-			assertEquals(new Long(55L), trt.rLong());
-			assertEquals(new Float(55F), trt.rFloat());
-			assertEquals(new Double(55), trt.rDouble());
-			assertEquals("55", trt.rString());
-			assertEquals(new URI("55"), trt.rURI());
-			assertTrue(Arrays.equals(new boolean[] { true }, trt.rpaBoolean()));
-			assertTrue(Arrays.equals(new byte[] { 55 }, trt.rpaByte()));
-			assertTrue(Arrays.equals(new short[] { 55 }, trt.rpaShort()));
-			assertTrue(Arrays.equals(new int[] { 55 }, trt.rpaInt()));
-			assertTrue(Arrays.equals(new long[] { 55 }, trt.rpaLong()));
-			assertTrue(Arrays.equals(new float[] { 55 }, trt.rpaFloat()));
-			assertTrue(Arrays.equals(new double[] { 55 }, trt.rpaDouble()));
-			assertEquals(Arrays.asList(true), trt.rBooleans());
-			assertEquals(Arrays.asList(new Byte((byte) 55)), trt.rBytes());
-			assertEquals(Arrays.asList(new Short((short) 55)), trt.rShorts());
-			assertEquals(Arrays.asList(new Integer(55)), trt.rInts());
-			assertEquals(Arrays.asList(new Long(55L)), trt.rLongs());
-			assertEquals(Arrays.asList(new Float(55F)), trt.rFloats());
-			assertEquals(Arrays.asList(new Double(55D)), trt.rDoubles());
-			assertEquals(Arrays.asList("55"), trt.rStrings());
-			assertEquals(Arrays.asList(new URI("55")), trt.rURIs());
-
-			assertTrue(Arrays.equals(new Boolean[] { true }, trt.raBoolean()));
-			assertTrue(Arrays.equals(new Byte[] { 55 }, trt.raByte()));
-			assertTrue(Arrays.equals(new Short[] { 55 }, trt.raShort()));
-			assertTrue(Arrays.equals(new Integer[] { 55 }, trt.raInt()));
-			assertTrue(Arrays.equals(new Long[] { 55L }, trt.raLong()));
-			assertTrue(Arrays.equals(new Float[] { 55F }, trt.raFloat()));
-			assertTrue(Arrays.equals(new Double[] { 55D }, trt.raDouble()));
-			assertTrue(Arrays.equals(new String[] { "55" }, trt.raString()));
-			assertTrue(Arrays.equals(new URI[] { new URI("55") }, trt.raURI()));
-		}
-	}
-
-	<T> T set(Class<T> interf, Object value) {
-		Properties p = new Properties();
-		Method ms[] = interf.getMethods();
-		Set<String> failed = new HashSet<String>();
-
-		for (Method m : ms) {
-			p.put(m.getName(), value);
-		}
-		return Configurable.createConfigurable(interf, (Map) p);
-	}
-
-	/**
-	 * Test enum handling
-	 */
-
-	@Meta.OCD public static interface Enums {
-		enum X {
-			requireConfiguration, optionalConfiguration, ignoreConfiguration
-		};
-
-		X r();
-
-		X i();
-
-		X o();
-	}
-
-	public void testEnum() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("bin"));
-		b.setProperty("Export-Package", "test");
-		b.setProperty("-metatype", "*");
-		b.build();
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-
-		Resource r = b.getJar().getResource("OSGI-INF/metatype/test.MetatypeTest$Enums.xml");
-		IO.copy(r.openInputStream(), System.out);
-
-		Document d = db.parse(r.openInputStream());
-		assertEquals("http://www.osgi.org/xmlns/metatype/v1.1.0", d.getDocumentElement()
-				.getNamespaceURI());
-
-		Properties p = new Properties();
-		p.setProperty("r", "requireConfiguration");
-		p.setProperty("i", "ignoreConfiguration");
-		p.setProperty("o", "optionalConfiguration");
-		Enums enums = Configurable.createConfigurable(Enums.class, (Map) p);
-		assertEquals(Enums.X.requireConfiguration, enums.r());
-		assertEquals(Enums.X.ignoreConfiguration, enums.i());
-		assertEquals(Enums.X.optionalConfiguration, enums.o());
-	}
-
-	/**
-	 * Test the OCD settings
-	 */
-	@Meta.OCD() public static interface OCDEmpty {
-	}
-
-	@Meta.OCD(description = "description") public static interface OCDDescription {
-	}
-
-	@Meta.OCD() public static interface OCDDesignatePidOnly {
-	}
-
-	@Meta.OCD(factory = true) public static interface OCDDesignatePidFactory {
-	}
-
-	@Meta.OCD(id = "id") public static interface OCDId {
-	}
-
-	@Meta.OCD(id = "id") public static interface OCDIdWithPid {
-	}
-
-	@Meta.OCD(localization = "localization") public static interface OCDLocalization {
-	}
-
-	@Meta.OCD(name = "name") public static interface OCDName {
-	}
-
-	public void testOCD() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("bin"));
-		b.setProperty("Export-Package", "test");
-		b.setProperty("-metatype", "*");
-		b.build();
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-		System.out.println(b.getJar().getResources().keySet());
-
-		assertOCD(b, "test.MetatypeTest$OCDEmpty", "test.MetatypeTest$OCDEmpty",
-				"Metatype test OCDEmpty", null, "test.MetatypeTest$OCDEmpty", false, null);
-		assertOCD(b, "test.MetatypeTest$OCDName", "test.MetatypeTest$OCDName", "name", null,
-				"test.MetatypeTest$OCDName", false, null);
-		assertOCD(b, "test.MetatypeTest$OCDDescription", "test.MetatypeTest$OCDDescription",
-				"Metatype test OCDDescription", "description", "test.MetatypeTest$OCDDescription",
-				false, null);
-		assertOCD(b, "test.MetatypeTest$OCDDesignatePidOnly",
-				"test.MetatypeTest$OCDDesignatePidOnly", "Metatype test OCDDesignate pid only",
-				null, "test.MetatypeTest$OCDDesignatePidOnly", false, null);
-		assertOCD(b, "test.MetatypeTest$OCDDesignatePidFactory",
-				"test.MetatypeTest$OCDDesignatePidFactory",
-				"Metatype test OCDDesignate pid factory", null,
-				"test.MetatypeTest$OCDDesignatePidFactory", true, null);
-		assertOCD(b, "test.MetatypeTest$OCDId", "id", "Metatype test OCDId", null, "id", false,
-				null);
-		assertOCD(b, "test.MetatypeTest$OCDIdWithPid", "id", "Metatype test OCDId with pid", null,
-				"id", false, null);
-		assertOCD(b, "test.MetatypeTest$OCDLocalization", "test.MetatypeTest$OCDLocalization",
-				"Metatype test OCDLocalization", null, "test.MetatypeTest$OCDLocalization", false,
-				"localization");
-	}
-
-	void assertOCD(Builder b, String cname, String id, String name, String description,
-			String designate, boolean factory, String localization) throws Exception {
-		Resource r = b.getJar().getResource("OSGI-INF/metatype/" + cname + ".xml");
-		assertNotNull(r);
-		IO.copy(r.openInputStream(), System.out);
-		Document d = db.parse(r.openInputStream());
-		assertEquals(id, xpath.evaluate("//OCD/@id", d, XPathConstants.STRING));
-		assertEquals(name, xpath.evaluate("//OCD/@name", d, XPathConstants.STRING));
-		assertEquals(localization == null ? cname : localization,
-				xpath.evaluate("//OCD/@localization", d, XPathConstants.STRING));
-		assertEquals(description == null ? "" : description,
-				xpath.evaluate("//OCD/@description", d, XPathConstants.STRING));
-
-		if (designate == null) {
-			assertEquals(id, xpath.evaluate("//Designate/@pid", d, XPathConstants.STRING));
-			if (factory)
-				assertEquals(id,
-						xpath.evaluate("//Designate/@factoryPid", d, XPathConstants.STRING));
-		} else {
-			assertEquals(designate, xpath.evaluate("//Designate/@pid", d, XPathConstants.STRING));
-			if (factory)
-				assertEquals(designate,
-						xpath.evaluate("//Designate/@factoryPid", d, XPathConstants.STRING));
-		}
-
-		assertEquals(id, xpath.evaluate("//Object/@ocdref", d, XPathConstants.STRING));
-	}
-
-	/**
-	 * Test the AD settings.
-	 */
-
-	@Meta.OCD(description = "advariations") public static interface TestAD {
-		@Meta.AD String noSettings();
-
-		@Meta.AD(id = "id") String withId();
-
-		@Meta.AD(name = "name") String withName();
-
-		@Meta.AD(max = "1") String withMax();
-
-		@Meta.AD(min = "-1") String withMin();
-
-		@Meta.AD(deflt = "deflt") String withDefault();
-
-		@Meta.AD(cardinality = 0) String[] withC0();
-
-		@Meta.AD(cardinality = 1) String[] withC1();
-
-		@Meta.AD(cardinality = -1) Collection<String> withC_1();
-
-		@Meta.AD(cardinality = -1) String[] withC_1ButArray();
-
-		@Meta.AD(cardinality = 1) Collection<String> withC1ButCollection();
-
-		@Meta.AD(type = Meta.Type.String) int withInt();
-
-		@Meta.AD(type = Meta.Type.Integer) String withString();
-
-		@Meta.AD(description = "description") String a();
-
-		@Meta.AD(optionValues = { "a", "b" }) String valuesOnly();
-
-		@Meta.AD(optionValues = { "a", "b" }, optionLabels = { "A", "B" }) String labelsAndValues();
-
-		@Meta.AD(required = true) String required();
-
-		@Meta.AD(required = false) String notRequired();
-	}
-
-	public void testAD() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("bin"));
-		b.setProperty("Export-Package", "test");
-		b.setProperty("-metatype", "*");
-		b.build();
-		Resource r = b.getJar().getResource("OSGI-INF/metatype/test.MetatypeTest$TestAD.xml");
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-		System.out.println(b.getJar().getResources().keySet());
-		assertNotNull(r);
-		IO.copy(r.openInputStream(), System.out);
-
-		Document d = db.parse(r.openInputStream());
-
-		assertAD(d, "noSettings", "No settings", "noSettings", null, null, null, 0, "String", null,
-				null, null);
-		assertAD(d, "withId", "With id", "id", null, null, null, 0, "String", null, null, null);
-		assertAD(d, "name", "name", "withName", null, null, null, 0, "String", null, null, null);
-		assertAD(d, "withMax", "With max", "withMax", null, "1", null, 0, "String", null, null,
-				null);
-		assertAD(d, "withMin", "With min", "withMin", "-1", null, null, 0, "String", null, null,
-				null);
-		assertAD(d, "withC1", "With c1", "withC1", null, null, null, 1, "String", null, null, null);
-		assertAD(d, "withC0", "With c0", "withC0", null, null, null, 2147483647, "String", null,
-				null, null);
-		assertAD(d, "withC_1", "With c 1", "withC.1", null, null, null, -1, "String", null, null,
-				null);
-		assertAD(d, "withC_1ButArray", "With c 1 but array", "withC.1ButArray", null, null, null,
-				-1, "String", null, null, null);
-		assertAD(d, "withC1ButCollection", "With c1 but collection", "withC1ButCollection", null,
-				null, null, 1, "String", null, null, null);
-		assertAD(d, "withInt", "With int", "withInt", null, null, null, 0, "String", null, null,
-				null);
-		assertAD(d, "withString", "With string", "withString", null, null, null, 0, "Integer",
-				null, null, null);
-		assertAD(d, "a", "A", "a", null, null, null, 0, "String", "description", null, null);
-		assertAD(d, "valuesOnly", "Values only", "valuesOnly", null, null, null, 0, "String", null,
-				new String[] { "a", "b" }, new String[] { "a", "b" });
-		assertAD(d, "labelsAndValues", "Labels and values", "labelsAndValues", null, null, null, 0,
-				"String", null, new String[] { "a", "b" }, new String[] { "A", "A" });
-	}
-
-	void assertAD(Document d, String mname, String name, String id, String min, String max,
-			String deflt, int cardinality, String type, String description, String[] optionvalues,
-			String optionLabels[]) throws XPathExpressionException {
-		assertEquals(name,
-				xpath.evaluate("//OCD/AD[@id='" + id + "']/@name", d, XPathConstants.STRING));
-		assertEquals(id, xpath.evaluate("//OCD/AD[@id='" + id + "']/@id", d, XPathConstants.STRING));
-		assertEquals(min == null ? "" : min,
-				xpath.evaluate("//OCD/AD[@id='" + id + "']/@min", d, XPathConstants.STRING));
-		assertEquals(max == null ? "" : max,
-				xpath.evaluate("//OCD/AD[@id='" + id + "']/@max", d, XPathConstants.STRING));
-		assertEquals(deflt == null ? "" : deflt,
-				xpath.evaluate("//OCD/AD[@id='" + id + "']/@deflt", d, XPathConstants.STRING));
-		assertEquals(cardinality + "",
-				xpath.evaluate("//OCD/AD[@id='" + id + "']/@cardinality", d, XPathConstants.STRING));
-		assertEquals(type,
-				xpath.evaluate("//OCD/AD[@id='" + id + "']/@type", d, XPathConstants.STRING));
-		assertEquals(description == null ? "" : description,
-				xpath.evaluate("//OCD/AD[@id='" + id + "']/@description", d, XPathConstants.STRING));
-	}
-
-	/**
-	 * Test all the return types.
-	 */
-	@Meta.OCD(description = "simple", name = "TestSimple") public static interface TestReturnTypes {
-		boolean rpBoolean();
-
-		byte rpByte();
-
-		char rpCharacter();
-
-		short rpShort();
-
-		int rpInt();
-
-		long rpLong();
-
-		float rpFloat();
-
-		double rpDouble();
-
-		Boolean rBoolean();
-
-		Byte rByte();
-
-		Character rCharacter();
-
-		Short rShort();
-
-		Integer rInt();
-
-		Long rLong();
-
-		Float rFloat();
-
-		Double rDouble();
-
-		String rString();
-
-		URI rURI();
-
-		boolean[] rpaBoolean();
-
-		byte[] rpaByte();
-
-		char[] rpaCharacter();
-
-		short[] rpaShort();
-
-		int[] rpaInt();
-
-		long[] rpaLong();
-
-		float[] rpaFloat();
-
-		double[] rpaDouble();
-
-		Collection<Boolean> rBooleans();
-
-		Collection<Byte> rBytes();
-
-		Collection<Character> rCharacters();
-
-		Collection<Short> rShorts();
-
-		Collection<Integer> rInts();
-
-		Collection<Long> rLongs();
-
-		Collection<Float> rFloats();
-
-		Collection<Double> rDoubles();
-
-		Collection<String> rStrings();
-
-		Collection<URI> rURIs();
-
-		Boolean[] raBoolean();
-
-		Byte[] raByte();
-
-		Character[] raCharacter();
-
-		Short[] raShort();
-
-		Integer[] raInt();
-
-		Long[] raLong();
-
-		Float[] raFloat();
-
-		Double[] raDouble();
-
-		String[] raString();
-
-		URI[] raURI();
-	}
-
-	public void testReturnTypes() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("bin"));
-		b.setProperty("Export-Package", "test");
-		b.setProperty("-metatype", "*");
-		b.build();
-		Resource r = b.getJar().getResource(
-				"OSGI-INF/metatype/test.MetatypeTest$TestReturnTypes.xml");
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-		System.out.println(b.getJar().getResources().keySet());
-		assertNotNull(r);
-		IO.copy(r.openInputStream(), System.out);
-
-		Document d = db.parse(r.openInputStream());
-		assertEquals("http://www.osgi.org/xmlns/metatype/v1.1.0", d.getDocumentElement()
-				.getNamespaceURI());
-		// Primitives
-		assertEquals("Boolean", xpath.evaluate("//OCD/AD[@id='rpBoolean']/@type", d));
-		assertEquals("Byte", xpath.evaluate("//OCD/AD[@id='rpByte']/@type", d));
-		assertEquals("Character", xpath.evaluate("//OCD/AD[@id='rpCharacter']/@type", d));
-		assertEquals("Short", xpath.evaluate("//OCD/AD[@id='rpShort']/@type", d));
-		assertEquals("Integer", xpath.evaluate("//OCD/AD[@id='rpInt']/@type", d));
-		assertEquals("Long", xpath.evaluate("//OCD/AD[@id='rpLong']/@type", d));
-		assertEquals("Float", xpath.evaluate("//OCD/AD[@id='rpFloat']/@type", d));
-		assertEquals("Double", xpath.evaluate("//OCD/AD[@id='rpDouble']/@type", d));
-
-		// Primitive Wrappers
-		assertEquals("Boolean", xpath.evaluate("//OCD/AD[@id='rBoolean']/@type", d));
-		assertEquals("Byte", xpath.evaluate("//OCD/AD[@id='rByte']/@type", d));
-		assertEquals("Character", xpath.evaluate("//OCD/AD[@id='rCharacter']/@type", d));
-		assertEquals("Short", xpath.evaluate("//OCD/AD[@id='rShort']/@type", d));
-		assertEquals("Integer", xpath.evaluate("//OCD/AD[@id='rInt']/@type", d));
-		assertEquals("Long", xpath.evaluate("//OCD/AD[@id='rLong']/@type", d));
-		assertEquals("Float", xpath.evaluate("//OCD/AD[@id='rFloat']/@type", d));
-		assertEquals("Double", xpath.evaluate("//OCD/AD[@id='rDouble']/@type", d));
-
-		// Primitive Arrays
-		assertEquals("Boolean", xpath.evaluate("//OCD/AD[@id='rpaBoolean']/@type", d));
-		assertEquals("Byte", xpath.evaluate("//OCD/AD[@id='rpaByte']/@type", d));
-		assertEquals("Character", xpath.evaluate("//OCD/AD[@id='rpaCharacter']/@type", d));
-		assertEquals("Short", xpath.evaluate("//OCD/AD[@id='rpaShort']/@type", d));
-		assertEquals("Integer", xpath.evaluate("//OCD/AD[@id='rpaInt']/@type", d));
-		assertEquals("Long", xpath.evaluate("//OCD/AD[@id='rpaLong']/@type", d));
-		assertEquals("Float", xpath.evaluate("//OCD/AD[@id='rpaFloat']/@type", d));
-		assertEquals("Double", xpath.evaluate("//OCD/AD[@id='rpaDouble']/@type", d));
-
-		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='rpaBoolean']/@cardinality", d));
-		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='rpaByte']/@cardinality", d));
-		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='rpaCharacter']/@cardinality", d));
-		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='rpaShort']/@cardinality", d));
-		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='rpaInt']/@cardinality", d));
-		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='rpaLong']/@cardinality", d));
-		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='rpaFloat']/@cardinality", d));
-		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='rpaDouble']/@cardinality", d));
-
-		// Wrapper + Object arrays
-		assertEquals("Boolean", xpath.evaluate("//OCD/AD[@id='raBoolean']/@type", d));
-		assertEquals("Byte", xpath.evaluate("//OCD/AD[@id='raByte']/@type", d));
-		assertEquals("Character", xpath.evaluate("//OCD/AD[@id='raCharacter']/@type", d));
-		assertEquals("Short", xpath.evaluate("//OCD/AD[@id='raShort']/@type", d));
-		assertEquals("Integer", xpath.evaluate("//OCD/AD[@id='raInt']/@type", d));
-		assertEquals("Long", xpath.evaluate("//OCD/AD[@id='raLong']/@type", d));
-		assertEquals("Float", xpath.evaluate("//OCD/AD[@id='raFloat']/@type", d));
-		assertEquals("Double", xpath.evaluate("//OCD/AD[@id='raDouble']/@type", d));
-		assertEquals("String", xpath.evaluate("//OCD/AD[@id='raString']/@type", d));
-		assertEquals("String", xpath.evaluate("//OCD/AD[@id='raURI']/@type", d));
-
-		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='raBoolean']/@cardinality", d));
-		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='raByte']/@cardinality", d));
-		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='raCharacter']/@cardinality", d));
-		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='raShort']/@cardinality", d));
-		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='raInt']/@cardinality", d));
-		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='raLong']/@cardinality", d));
-		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='raFloat']/@cardinality", d));
-		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='raDouble']/@cardinality", d));
-		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='raString']/@cardinality", d));
-		assertEquals("2147483647", xpath.evaluate("//OCD/AD[@id='raURI']/@cardinality", d));
-
-		// Wrapper + Object collections
-		assertEquals("Boolean", xpath.evaluate("//OCD/AD[@id='rBooleans']/@type", d));
-		assertEquals("Byte", xpath.evaluate("//OCD/AD[@id='rBytes']/@type", d));
-		assertEquals("Character", xpath.evaluate("//OCD/AD[@id='rCharacter']/@type", d));
-		assertEquals("Short", xpath.evaluate("//OCD/AD[@id='rShorts']/@type", d));
-		assertEquals("Integer", xpath.evaluate("//OCD/AD[@id='rInts']/@type", d));
-		assertEquals("Long", xpath.evaluate("//OCD/AD[@id='rLongs']/@type", d));
-		assertEquals("Float", xpath.evaluate("//OCD/AD[@id='rFloats']/@type", d));
-		assertEquals("Double", xpath.evaluate("//OCD/AD[@id='rDoubles']/@type", d));
-		assertEquals("String", xpath.evaluate("//OCD/AD[@id='rStrings']/@type", d));
-		assertEquals("String", xpath.evaluate("//OCD/AD[@id='rURIs']/@type", d));
-
-		assertEquals("-2147483648", xpath.evaluate("//OCD/AD[@id='rBooleans']/@cardinality", d));
-		assertEquals("-2147483648", xpath.evaluate("//OCD/AD[@id='rBytes']/@cardinality", d));
-		assertEquals("-2147483648", xpath.evaluate("//OCD/AD[@id='rCharacters']/@cardinality", d));
-		assertEquals("-2147483648", xpath.evaluate("//OCD/AD[@id='rShorts']/@cardinality", d));
-		assertEquals("-2147483648", xpath.evaluate("//OCD/AD[@id='rInts']/@cardinality", d));
-		assertEquals("-2147483648", xpath.evaluate("//OCD/AD[@id='rLongs']/@cardinality", d));
-		assertEquals("-2147483648", xpath.evaluate("//OCD/AD[@id='rFloats']/@cardinality", d));
-		assertEquals("-2147483648", xpath.evaluate("//OCD/AD[@id='rDoubles']/@cardinality", d));
-		assertEquals("-2147483648", xpath.evaluate("//OCD/AD[@id='rStrings']/@cardinality", d));
-		assertEquals("-2147483648", xpath.evaluate("//OCD/AD[@id='rURIs']/@cardinality", d));
-	}
-
-	/**
-	 * Test simple
-	 * 
-	 * @author aqute
-	 * 
-	 */
-	@Meta.OCD(description = "simple", name = "TestSimple") public static interface TestSimple {
-		@Meta.AD String simple();
-
-		String[] notSoSimple();
-
-		Collection<String> stringCollection();
-	}
-
-	public void testSimple() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath(new File("bin"));
-		b.setProperty("Export-Package", "test");
-		b.setProperty("-metatype", "*");
-		b.build();
-		Resource r = b.getJar().getResource("OSGI-INF/metatype/test.MetatypeTest$TestSimple.xml");
-		assertEquals(0, b.getErrors().size());
-		assertEquals(0, b.getWarnings().size());
-		System.out.println(b.getJar().getResources().keySet());
-		assertNotNull(r);
-		IO.copy(r.openInputStream(), System.out);
-
-		Document d = db.parse(r.openInputStream());
-
-		assertEquals("TestSimple", xpath.evaluate("//OCD/@name", d));
-		assertEquals("simple", xpath.evaluate("//OCD/@description", d));
-		assertEquals("test.MetatypeTest$TestSimple", xpath.evaluate("//OCD/@id", d));
-		assertEquals("test.MetatypeTest$TestSimple", xpath.evaluate("//Designate/@pid", d));
-		assertEquals("test.MetatypeTest$TestSimple", xpath.evaluate("//Object/@ocdref", d));
-		assertEquals("simple", xpath.evaluate("//OCD/AD[@id='simple']/@id", d));
-		assertEquals("Simple", xpath.evaluate("//OCD/AD[@id='simple']/@name", d));
-		assertEquals("String", xpath.evaluate("//OCD/AD[@id='simple']/@type", d));
-		assertEquals(Integer.MAX_VALUE + "",
-				xpath.evaluate("//OCD/AD[@id='notSoSimple']/@cardinality", d));
-
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/test/NativeHeader.java b/biz.aQute.bndlib/src/test/NativeHeader.java
deleted file mode 100755
index 6a60ba8..0000000
--- a/biz.aQute.bndlib/src/test/NativeHeader.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package test;
-
-import java.util.*;
-
-import junit.framework.*;
-import aQute.lib.osgi.*;
-
-public class NativeHeader extends TestCase {
-    
-        public void testFunnyHeader() throws Exception {
-            Verifier v = new Verifier();
-            v.doNative("org/osgi/test/cases/framework/fragments/tb8/linux_x86/libNative.so; osname=Linux; processor=x86; osversion=\"(1000,10000]\",");
-            assertBad(v, "name");
-        }
-        
-        public void testWildcardNotAtEnd() throws Exception {
-            Verifier v = new Verifier();
-            v.doNative("x.so;osname=win32,*,x.dll");
-            assertBad(v, "may only END in wildcard");
-        }
-        
-
-    public void testWildcard() throws Exception {
-        Verifier v = new Verifier();
-        v.doNative("x.so ;y.so;osname=Linux;processor=amd64,*");
-        assertOk(v);
-    }
-    
-	public void testSimple() throws Exception {
-		Verifier v = new Verifier();
-		v.doNative("\rnative/libclib_jiio.so ;\r"
-				+ "native/libmlib_jai.so;\r" + "osname=Linux ;\r"
-				+ "processor=amd64\r");
-        assertOk(v);
-	}
-
-
-    void assertOk(Processor v) {
-        System.err.println(v.getWarnings());
-        System.err.println(v.getErrors());
-        assertEquals(0, v.getErrors().size());
-        assertEquals(0, v.getWarnings().size());        
-    }
-    
-    void assertBad(Processor v, String ok) {
-        assertEmptyAfterRemove(v.getErrors(), ok);
-        assertEmptyAfterRemove(v.getWarnings(), ok);
-    }
-
-
-    private void assertEmptyAfterRemove(List<String> errors, String ok) {
-        for ( String s: errors ) {
-            if ( s.indexOf(ok)<0)
-                fail("Found error/warning that can not be removed: " + s + " : " + ok);
-        }        
-    }
-    
-   
-}
diff --git a/biz.aQute.bndlib/src/test/NoUsesTest.java b/biz.aQute.bndlib/src/test/NoUsesTest.java
deleted file mode 100644
index 4d16571..0000000
--- a/biz.aQute.bndlib/src/test/NoUsesTest.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package test;
-
-import java.io.*;
-import java.util.*;
-
-import junit.framework.*;
-import aQute.lib.osgi.*;
-
-public class NoUsesTest extends TestCase {
-
-	/*
-	 * Check if we explicitly set a uses directive, prepend the calculated
-	 * but the calculated is empty. This should remove the extraneuous comma
-	 */
-	public void testExplicitUsesWithPrependZeroUses() throws Exception {
-		Builder bmaker = new Builder();
-		bmaker.setProperty("Private-Package", "org.osgi.framework");
-		bmaker.setProperty("Export-Package", "org.osgi.util.tracker;uses:=\"<<USES>>,not.used\"");
-		String uses = findUses(bmaker, "org.osgi.util.tracker");
-		assertEquals("not.used", uses);
-	}
-	
-	/*
-	 * Check if we explicitly set a uses directive, but append it
-	 * with the calculated directive
-	 */
-	public void testExplicitUsesWithAppend() throws Exception {
-		Builder bmaker = new Builder();
-		bmaker.setProperty("Export-Package", "org.osgi.util.tracker;uses:=\"not.used,<<USES>>\"");
-		String uses = findUses(bmaker, "org.osgi.util.tracker");
-		assertTrue("not.used", uses.indexOf("not.used")>=0);
-		assertTrue("org.osgi.framework", uses.indexOf("org.osgi.framework")>=0);
-	}
-
-	/*
-	 * Check if we explicitly set a uses directive, append the calculated
-	 * but the calculated is empty. This should remove the extraneuous comma
-	 */
-	public void testExplicitUsesWithAppendZeroUses() throws Exception {
-		Builder bmaker = new Builder();
-		bmaker.setProperty("Private-Package", "org.osgi.framework");
-		bmaker.setProperty("Export-Package", "org.osgi.util.tracker;uses:=\"not.used,<<USES>>\"");
-		String uses = findUses(bmaker, "org.osgi.util.tracker");
-		assertEquals("not.used", uses);
-	}
-	
-	/*
-	 * Check if we explicitly set a uses directive, but append it
-	 * with the calculated directive
-	 */
-	public void testExplicitUsesWithPrepend() throws Exception {
-		Builder bmaker = new Builder();
-		bmaker.setProperty("Export-Package", "org.osgi.util.tracker;uses:=\"<<USES>>,not.used\"");
-		String uses = findUses(bmaker, "org.osgi.util.tracker");
-		assertTrue("not.used", uses.indexOf("not.used")>=0);
-		assertTrue("org.osgi.framework", uses.indexOf("org.osgi.framework")>=0);
-	}
-	/*
-	 * Check if we explicitly set a uses directive
-	 */
-	public void testExplicitUses() throws Exception {
-		Builder bmaker = new Builder();
-		bmaker.setProperty("Export-Package", "org.osgi.util.tracker;uses:=\"not.used\"");
-		String uses = findUses(bmaker, "org.osgi.util.tracker");
-		assertEquals("not.used", uses);
-	}
-	
-	public void testExportedUses() throws Exception {
-		Builder bmaker = new Builder();
-		bmaker.setProperty("Export-Package", "org.osgi.util.tracker, org.osgi.framework");
-		String uses = findUses(bmaker, "org.osgi.util.tracker");
-		assertEquals("org.osgi.framework", uses);
-	}
-	
-
-	public void testPrivateUses() throws Exception {
-		Builder bmaker = new Builder();
-		bmaker.setProperty("Private-Package", "org.osgi.framework");
-		bmaker.setProperty("Export-Package", "org.osgi.util.tracker");
-		String uses = findUses(bmaker, "org.osgi.util.tracker");
-		assertNull("org.osgi.framework", uses);
-	}
-	
-	public void testHasUses() throws Exception {
-		Builder bmaker = new Builder();
-		bmaker.setProperty("Export-Package", "test.activator");
-		String uses = findUses(bmaker, "test.activator");
-		assertEquals("org.osgi.framework", uses);
-	}
-
-	public void testNoUses() throws Exception {
-		Builder bmaker = new Builder();
-		bmaker.setProperty("Export-Package", "test.activator");
-		bmaker.setProperty("-nouses", "true");
-		String uses = findUses(bmaker, "test.activator");
-		assertNull("org.osgi.framework", uses);
-	}
-
-
-	
-	String findUses(Builder bmaker, String pack ) throws Exception {
-			File cp[] = { new File("bin"), new File("jar/osgi.jar") };
-			bmaker.setClasspath(cp);
-			Jar jar = bmaker.build();
-			assertOk(bmaker);
-			String exports = jar.getManifest().getMainAttributes().getValue("Export-Package");
-			assertNotNull("exports", exports );
-			Map<String,Map<String,String>> map = Processor.parseHeader(exports, null);
-			if ( map == null )
-				return null;
-			
-			Map<String,String> clause = map.get(pack);
-			if ( clause == null )
-				return null;
-			
-			return (String) clause.get("uses:");			
-	}
-	
-	void assertOk(Analyzer bmaker) throws Exception {
-		System.out.println(bmaker.getErrors());
-		System.out.println(bmaker.getWarnings());
-		bmaker.getJar().getManifest().write(System.out);
-		assertEquals(0,bmaker.getErrors().size());
-		assertEquals(0,bmaker.getWarnings().size());
-		
-	}
-}
diff --git a/biz.aQute.bndlib/src/test/PackTest.java b/biz.aQute.bndlib/src/test/PackTest.java
deleted file mode 100644
index dae4d8c..0000000
--- a/biz.aQute.bndlib/src/test/PackTest.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package test;
-
-import junit.framework.*;
-
-public class PackTest extends TestCase {
-
-	public void testNot() {}
-	
-//	public void testSimple() throws Exception {
-//		Workspace ws= Workspace.getWorkspace("/Ws/aQute");
-//		Project p = ws.getProject("aQute.metatype");
-//		ProjectLauncher pl = p.getProjectLauncher();
-//		
-//		Jar jar = pl.executable();
-//		
-//	}
-	
-	
-}
diff --git a/biz.aQute.bndlib/src/test/ParseHeaderTest.java b/biz.aQute.bndlib/src/test/ParseHeaderTest.java
deleted file mode 100755
index 712232a..0000000
--- a/biz.aQute.bndlib/src/test/ParseHeaderTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package test;
-
-import java.util.*;
-
-import aQute.lib.osgi.*;
-import aQute.libg.header.*;
-import junit.framework.*;
-
-public class ParseHeaderTest extends TestCase {
-
-    public void testPropertiesSimple() {
-        Map<String,String> p = OSGiHeader.parseProperties("a=1, b=\"3   3\", c=c");
-        assertEquals("1", p.get("a"));
-        assertEquals("3   3", p.get("b"));
-        assertEquals("c", p.get("c"));
-    }
-    
-	public void testClauseName() {
-		assertNames("a,b,c;", new String[] {"a","b","c"});		
-		assertNames("a,b,c", new String[] {"a","b","c"});		
-		assertNames("a;x=0,b;x=0,c;x=0", new String[] {"a","b","c"});		
-		assertNames("a;b;c;x=0", new String[] {"a","b","c"});		
-		assertNames(",", new String[] {}, null, "Empty clause, usually caused" );
-		assertNames("a;a,b", new String[] { "a", "a~", "b"}, null, "Duplicate name a used in header");
-		assertNames("a;x=0;b", new String[] { "a", "b"}, "Header contains name field after attribute or directive", null);
-		assertNames("a;x=0;x=0,b", new String[] { "a", "b"}, null, "Duplicate attribute/directive name");
-		assertNames("a;;;,b", new String[] { "a", "b"});
-		assertNames(",,a,,", new String[] { "a"}, null, "Empty clause, usually caused by repeating");
-		assertNames(",a", new String[] { "a"}, null, "Empty clause, usually caused");
-		assertNames(",a,b,c,", new String[] { "a", "b", "c" },null, "Empty clause, usually caused");
-		assertNames("a,b,c,", new String[] { "a", "b", "c" }, null, "Empty clause, usually caused");
-		assertNames("a,b,,c", new String[] { "a", "b", "c" }, null, "Empty clause, usually caused");
-	}
-
-	
-	
-	void assertNames(String header, String[] keys) {
-		assertNames(header,keys, null, null);
-	}
-	void assertNames(String header, String[] keys, String expectedError, String expectedWarning) {
-		Processor p = new Processor();
-		p.setPedantic(true);
-		Map<String,Map<String,String>> map = Processor.parseHeader(header, p);
-		for (String key : keys )
-			assertTrue(map.containsKey(key));
-		
-		assertEquals(keys.length, map.size());
-		if (expectedError != null) {
-			System.out.println(p.getErrors());
-			assertTrue(p.getErrors().size()>0);
-			assertTrue(((String) p.getErrors().get(0)).indexOf(expectedError) >= 0);
-		} else
-			assertEquals(0, p.getErrors().size());
-		if (expectedWarning != null) {
-			System.out.println(p.getWarnings());
-			assertTrue(p.getWarnings().size()>0);
-			String w = (String) p.getWarnings().get(0);
-			assertTrue(w.startsWith(expectedWarning));
-		} else
-			assertEquals(0, p.getWarnings().size());
-	}
-
-	public void testSimple() {
-		String s = "a;a=a1;b=a2;c=a3, b;a=b1;b=b2;c=b3, c;d;e;a=x1";
-		Map<String,Map<String,String>> map = Processor.parseHeader(s, null);
-		assertEquals(5, map.size());
-
-		Map<String,String> a = map.get("a");
-		assertEquals("a1", a.get("a"));
-		assertEquals("a2", a.get("b"));
-		assertEquals("a3", a.get("c"));
-
-		Map<String,String> d = map.get("d");
-		assertEquals("x1", d.get("a"));
-
-		Map<String,String> e = map.get("e");
-		assertEquals(e, d);
-
-		System.out.println(map);
-	}
-}
diff --git a/biz.aQute.bndlib/src/test/PluginTest.java b/biz.aQute.bndlib/src/test/PluginTest.java
deleted file mode 100644
index 1f42024..0000000
--- a/biz.aQute.bndlib/src/test/PluginTest.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package test;
-
-import java.applet.*;
-import java.util.*;
-
-import junit.framework.*;
-import aQute.bnd.service.*;
-import aQute.lib.osgi.*;
-import aQute.libg.reporter.*;
-
-public class PluginTest extends TestCase {
-    static Processor main = new Processor();
-    
-    public void testMissingPluginNotUsed() throws Exception {
-        Builder p = new Builder();
-        p.setProperty("-plugin", "missing;command:=\"-abc,-def\"");
-        /*List<?> plugins =*/ p.getPlugins(Object.class);
-        assertEquals(0, p.getErrors().size());
-        
-        p.setProperty("-abc", "whatever");
-        p.setProperty("-resourceonly", "true");
-        p.setProperty("Include-Resource", "jar/osgi.jar");
-        p.build();
-        assertEquals(1, p.getErrors().size());
-        assertTrue(p.getErrors().get(0).contains("Missing plugin"));
-    }
-
-    static class TPlugin implements Plugin {
-        Map<String,String> properties;
-        
-        public void setProperties(Map<String, String> map) {
-            properties = map;
-        }
-
-        public void setReporter(Reporter processor) {
-            assertEquals(main, processor );
-        }
-    }
-    public void testPlugin() {
-        main.setProperty(Constants.PLUGIN, "test.PluginTest.TPlugin;a=1;b=2");
-        
-        for ( TPlugin plugin : main.getPlugins(TPlugin.class)) {
-            assertEquals( test.PluginTest.TPlugin.class, plugin.getClass());
-            assertEquals( "1", plugin.properties.get("a"));
-            assertEquals( "2", plugin.properties.get("b"));
-        }
-    }
-
-    public void testLoadPlugin() {
-        main.setProperty(Constants.PLUGIN, "thinlet.Thinlet;path:=jar/thinlet.jar");
-        for ( Applet applet : main.getPlugins(Applet.class)) {
-            assertEquals( "thinlet.Thinlet", applet.getClass().getName());
-        }        
-    }
-}
diff --git a/biz.aQute.bndlib/src/test/ProcessorTest.java b/biz.aQute.bndlib/src/test/ProcessorTest.java
deleted file mode 100644
index aa9d93b..0000000
--- a/biz.aQute.bndlib/src/test/ProcessorTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package test;
-
-import junit.framework.*;
-import aQute.lib.osgi.*;
-
-public class ProcessorTest extends TestCase{
-
-	
-	public void testPlugins() {
-		
-	}
-	
-	
-    public void testDuplicates() {
-        assertEquals("", Processor.removeDuplicateMarker("~") );
-        
-        assertTrue( Processor.isDuplicate("abc~"));
-        assertTrue( Processor.isDuplicate("abc~~~~~~~~~"));
-        assertTrue( Processor.isDuplicate("~"));
-        assertFalse( Processor.isDuplicate(""));
-        assertFalse( Processor.isDuplicate("abc"));
-        assertFalse( Processor.isDuplicate("ab~c"));
-        assertFalse( Processor.isDuplicate("~abc"));
-        
-        assertEquals("abc", Processor.removeDuplicateMarker("abc~") );
-        assertEquals("abc", Processor.removeDuplicateMarker("abc~~~~~~~") );
-        assertEquals("abc", Processor.removeDuplicateMarker("abc") );
-        assertEquals("ab~c", Processor.removeDuplicateMarker("ab~c") );
-        assertEquals("~abc", Processor.removeDuplicateMarker("~abc") );
-        assertEquals("", Processor.removeDuplicateMarker("") );
-        assertEquals("", Processor.removeDuplicateMarker("~~~~~~~~~~~~~~") );
-    }
-    
-    
-    public void appendPathTest() throws Exception {
-        assertEquals("a/b/c", Processor.appendPath("","a/b/c/"));
-        assertEquals("a/b/c", Processor.appendPath("","/a/b/c"));
-        assertEquals("a/b/c", Processor.appendPath("/","/a/b/c/"));
-        assertEquals("a/b/c", Processor.appendPath("a","b/c/"));
-        assertEquals("a/b/c", Processor.appendPath("a","b","c"));
-        assertEquals("a/b/c", Processor.appendPath("a","b","/c/"));
-        assertEquals("a/b/c", Processor.appendPath("/","a","b","/c/"));
-        assertEquals("a/b/c", Processor.appendPath("////////","////a////b///c//"));
-        
-    }
-}
diff --git a/biz.aQute.bndlib/src/test/ProjectTest.java b/biz.aQute.bndlib/src/test/ProjectTest.java
deleted file mode 100755
index 77d4aef..0000000
--- a/biz.aQute.bndlib/src/test/ProjectTest.java
+++ /dev/null
@@ -1,211 +0,0 @@
-package test;
-
-import java.io.File;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.jar.Manifest;
-
-import junit.framework.TestCase;
-import aQute.bnd.build.Project;
-import aQute.bnd.build.Workspace;
-import aQute.bnd.service.RepositoryPlugin.*;
-import aQute.lib.deployer.FileRepo;
-import aQute.lib.io.*;
-import aQute.lib.osgi.Builder;
-import aQute.lib.osgi.Jar;
-import aQute.lib.osgi.Processor;
-import aQute.lib.osgi.eclipse.EclipseClasspath;
-import aQute.libg.version.Version;
-
-public class ProjectTest extends TestCase {
-
-	/**
-	 * Check multiple repos
-	 * 
-	 * @throws Exception
-	 */
-	public void testMultipleRepos() throws Exception {
-		Workspace ws = Workspace.getWorkspace(new File("test/ws"));
-		Project project = ws.getProject("p1");
-		System.out.println(project.getBundle("org.apache.felix.configadmin", "1.1.0",
-				Strategy.EXACT, null));
-		System.out.println(project.getBundle("org.apache.felix.configadmin", "1.1.0",
-				Strategy.HIGHEST, null));
-		System.out.println(project.getBundle("org.apache.felix.configadmin", "1.1.0",
-				Strategy.LOWEST, null));
-	}
-
-	/**
-	 * Check if the getSubBuilders properly predicts the output.
-	 */
-
-	public void testSubBuilders() throws Exception {
-		Workspace ws = Workspace.getWorkspace(new File("test/ws"));
-		Project project = ws.getProject("p4-sub");
-
-		Collection<? extends Builder> bs = project.getSubBuilders();
-		assertNotNull(bs);
-		assertEquals(3, bs.size());
-		Set<String> names = new HashSet<String>();
-		for (Builder b : bs) {
-			names.add(b.getBsn());
-		}
-		assertTrue(names.contains("p4-sub.a"));
-		assertTrue(names.contains("p4-sub.b"));
-		assertTrue(names.contains("p4-sub.c"));
-
-		File[] files = project.build();
-		System.out.println(Processor.join(project.getErrors(), "\n"));
-		System.out.println(Processor.join(project.getWarnings(), "\n"));
-		assertEquals(0, project.getErrors().size());
-		assertEquals(0, project.getWarnings().size());
-		assertNotNull(files);
-		assertEquals(3, files.length);
-		for (File file : files) {
-			Jar jar = new Jar(file);
-			Manifest m = jar.getManifest();
-			assertTrue(names.contains(m.getMainAttributes().getValue("Bundle-SymbolicName")));
-		}
-	}
-
-	/**
-	 * Tests the handling of the -sub facility
-	 * 
-	 * @throws Exception
-	 */
-
-	public void testSub() throws Exception {
-		Workspace ws = Workspace.getWorkspace(new File("test/ws"));
-		Project project = ws.getProject("p4-sub");
-		File[] files = project.build();
-		System.out.println(Processor.join(project.getErrors(), "\n"));
-		System.out.println(Processor.join(project.getWarnings(), "\n"));
-
-		assertEquals(0, project.getErrors().size());
-		assertEquals(0, project.getWarnings().size());
-		assertNotNull(files);
-		assertEquals(3, files.length);
-
-		Jar a = new Jar(files[0]);
-		Jar b = new Jar(files[1]);
-		Manifest ma = a.getManifest();
-		Manifest mb = b.getManifest();
-
-		assertEquals("base", ma.getMainAttributes().getValue("Base-Header"));
-		assertEquals("base", mb.getMainAttributes().getValue("Base-Header"));
-		assertEquals("a", ma.getMainAttributes().getValue("Sub-Header"));
-		assertEquals("b", mb.getMainAttributes().getValue("Sub-Header"));
-	}
-
-	public void testOutofDate() throws Exception {
-		Workspace ws = Workspace.getWorkspace(new File("test/ws"));
-		Project project = ws.getProject("p3");
-		File bnd = new File("test/ws/p3/bnd.bnd");
-		assertTrue(bnd.exists());
-
-		project.clean();
-		project.getTarget().mkdirs();
-		try {
-			// Now we build it.
-			File[] files = project.build();
-			System.out.println(project.getErrors());
-			System.out.println(project.getWarnings());
-			assertTrue(project.isOk());
-			assertNotNull(files);
-			assertEquals(1, files.length);
-
-			// Now we should not rebuild it
-			long lastTime = files[0].lastModified();
-			files = project.build();
-			assertEquals(1, files.length);
-			assertTrue(files[0].lastModified() == lastTime);
-
-			Thread.sleep(2000);
-
-			project.updateModified(System.currentTimeMillis(), "Testing");
-			files = project.build();
-			assertEquals(1, files.length);
-			assertTrue("Must have newer files now", files[0].lastModified() > lastTime);
-		} finally {
-			project.clean();
-		}
-	}
-
-	public void testRepoMacro() throws Exception {
-		Workspace ws = Workspace.getWorkspace(new File("test/ws"));
-		Project project = ws.getProject("p2");
-		System.out.println(project.getPlugins(FileRepo.class));
-		String s = project.getReplacer().process(("${repo;libtest}"));
-		System.out.println(s);
-		assertTrue(s.contains("org.apache.felix.configadmin/org.apache.felix.configadmin-1.2.0"));
-		assertTrue(s.contains("org.apache.felix.ipojo/org.apache.felix.ipojo-1.0.0.jar"));
-
-		s = project.getReplacer().process(("${repo;libtestxyz}"));
-		assertTrue(s.matches("<<[^>]+>>"));
-
-		s = project.getReplacer().process("${repo;org.apache.felix.configadmin;1.0.0;highest}");
-		s.endsWith("org.apache.felix.configadmin-1.1.0.jar");
-		s = project.getReplacer().process("${repo;org.apache.felix.configadmin;1.0.0;lowest}");
-		s.endsWith("org.apache.felix.configadmin-1.0.1.jar");
-	}
-
-	public void testClasspath() throws Exception {
-		File project = new File("").getAbsoluteFile();
-		File workspace = project.getParentFile();
-		Processor processor = new Processor();
-		EclipseClasspath p = new EclipseClasspath(processor, workspace, project);
-		System.out.println(p.getDependents());
-		System.out.println(p.getClasspath());
-		System.out.println(p.getSourcepath());
-		System.out.println(p.getOutput());
-	}
-
-	public void testBump() throws Exception {
-		File tmp = new File("tmp-ws");
-		if (tmp.exists())
-			IO.delete(tmp);
-		tmp.mkdir();
-		assertTrue(tmp.isDirectory());
-
-		try {
-			IO.copy(new File("test/ws"), tmp);
-			Workspace ws = Workspace.getWorkspace(tmp);
-			Project project = ws.getProject("p1");
-			int size = project.getProperties().size();
-			Version old = new Version(project.getProperty("Bundle-Version"));
-			System.out.println("Old version " + old);
-			project.bump("=+0");
-			Version newv = new Version(project.getProperty("Bundle-Version"));
-			System.out.println("New version " + newv);
-			assertEquals(old.getMajor(), newv.getMajor());
-			assertEquals(old.getMinor() + 1, newv.getMinor());
-			assertEquals(0, newv.getMicro());
-			assertEquals(size, project.getProperties().size());
-			assertEquals("sometime", newv.getQualifier());
-		} finally {
-			IO.delete(tmp);
-		}
-	}
-
-	public void testRunBuilds() throws Exception {
-		Workspace ws = Workspace.getWorkspace(new File("test/ws"));
-
-		// Running a .bnd includes built bundles by default
-		Project p1 = ws.getProject("p1");
-		assertTrue(p1.getRunBuilds());
-
-		// Can override the default by specifying -runbuilds: false
-		Project p2 = ws.getProject("p2");
-		assertFalse(p2.getRunBuilds());
-
-		// Running a .bndrun DOES NOT include built bundles by default
-		Project p1a = new Project(ws, new File("test/ws/p1"), new File("test/ws/p1/p1a.bndrun"));
-		assertFalse(p1a.getRunBuilds());
-
-		// ... unless we override the default by specifying -runbuilds: true
-		Project p1b = new Project(ws, new File("test/ws/p1"), new File("test/ws/p1/p1b.bndrun"));
-		assertTrue(p1b.getRunBuilds());
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/test/PropertiesTest.java b/biz.aQute.bndlib/src/test/PropertiesTest.java
deleted file mode 100755
index 2283f4c..0000000
--- a/biz.aQute.bndlib/src/test/PropertiesTest.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package test;
-
-import java.io.*;
-import java.util.*;
-import java.util.jar.*;
-
-import junit.framework.*;
-import aQute.lib.osgi.*;
-
-public class PropertiesTest extends TestCase {
-    static <T> T notNull(T t) { assertNotNull(t); return t; }
-    
-    public void testFlattening() throws Exception {
-        Processor p = new Processor();
-        p.setProperty("-versionpolicy", "${version;===;${@}}");
-        p.setProperty("x", "x");
-        p.setProperty("_x", "_x");
-               
-        Properties flattened = notNull(p.getFlattenedProperties());
-        String x = notNull(flattened.getProperty("-versionpolicy"));
-        assertTrue( x.contains("@"));
-        notNull( flattened.getProperty("x"));
-        assertNull( flattened.getProperty("_x"));
-        assertEquals( 2,flattened.size());
-    }
-    
-    public void testFilter() {
-        Processor p1 = new Processor();
-        p1.setProperty("dan", "bandera");
-        p1.setProperty("susan", "sarandon");
-        p1.setProperty("jon", "bostrom");
-        
-        Processor p2 = new Processor(p1);
-        p2.setForceLocal( Arrays.asList("dan"));
-        p2.setProperty("susan", "schwarze");
-        
-        assertNull( p2.getProperty("dan"));
-        assertEquals("schwarze", p2.getProperty("susan"));
-        assertEquals("bostrom", p2.getProperty("jon"));
-    }
-    
-    public void testUnicode() {
-        StringBuffer sb = new StringBuffer();
-        String s = "Loïc Cotonéa";
-        for ( int i=0; i<s.length(); i++ ) {
-            char c = s.charAt(i);
-            if ( c < 0x20 || c > 0x7F ) { 
-                sb.append("\\u");
-                sb.append(String.format("%04x",(int)c));
-            } else {
-                sb.append(c);
-            }
-        }
-        System.out.println(sb);
-    }
-
-    public  void testSpacesAround() throws Exception {
-        String test="#comment\n"
-            + "   abc    =   abc\r\n"
-            + "def = def\n\r"
-            + " ghi =               ghi\r"
-            + " jkl =               jkl"
-            ;
-        
-        byte [] bytes = test.getBytes("ISO8859-1");
-        ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
-        Properties p = new Properties();
-        p.load(bin);
-        
-        assertEquals("abc", p.get("abc"));
-        assertEquals("def", p.get("def"));
-        assertEquals("ghi", p.get("ghi"));
-        assertEquals("jkl", p.get("jkl"));
-    }
-    
-    public void testInternationalCharacters() throws Exception {
-        String test="#comment\n"
-            + "Namex=Lo\u00EFc Coton\u00E9a\n"
-            + "Export-Package: *\n"
-            + "Unicode=\\u0040\n"
-            + "NameAgain=Loïc Cotonéa";
-        
-
-        byte [] bytes = test.getBytes("ISO8859-1");
-        ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
-        Properties p = new Properties();
-        p.load(bin);
-        assertEquals("@", p.get("Unicode"));
-        assertEquals("Lo\u00EFc Coton\u00E9a", p.get("Namex"));
-        
-        // Now test if we can make the round trip
-        Builder b  = new Builder();
-        b.setProperties(p);
-        b.addClasspath( new File("jar/asm.jar"));
-        Jar jar = b.build();
-        
-        ByteArrayOutputStream bout = new ByteArrayOutputStream();
-        jar.getManifest().write(bout);
-        
-        bin = new ByteArrayInputStream(bout.toByteArray());
-        Manifest m = new Manifest( bin );
-        
-        assertEquals("Lo\u00EFc Coton\u00E9a", m.getMainAttributes().getValue("Namex"));
-    }
-	public void testBadProperties() throws Exception {
-		Analyzer	analyzer = new Analyzer();
-		analyzer.setPedantic(true);
-		analyzer.setProperties(new File("src/test/badproperties.prop"));
-		String  s = analyzer.getProperty(Analyzer.IMPORT_PACKAGE);
-		Map<String,Map<String,String>> map = analyzer.parseHeader(s);
-		assertEquals(2,map.size());
-		assertTrue(map.containsKey("org.osgi.service.cm"));
-		assertTrue(map.containsKey("org.osgi.util.tracker"));
-        assertEquals(1,analyzer.getWarnings().size());
-        System.out.println(analyzer.getWarnings());
-        assertTrue(analyzer.getWarnings().get(0).indexOf("Empty clause, usually caused by repeating a comma without")>=0);
-		System.out.println(analyzer.getWarnings());
-	}
-	
-	public void testProperties() throws Exception {
-		Analyzer	analyzer = new Analyzer();
-		analyzer.setProperties(new File("src/test/variables.mf"));
-		
-		assertEquals("aQute.test", analyzer.getProperty("Header"));
-		System.out.println("property " + analyzer.getProperty("Header"));
-	}
-}
diff --git a/biz.aQute.bndlib/src/test/RepoBuilderTest.java b/biz.aQute.bndlib/src/test/RepoBuilderTest.java
deleted file mode 100644
index 1ec77ab..0000000
--- a/biz.aQute.bndlib/src/test/RepoBuilderTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package test;
-
-import junit.framework.*;
-
-public class RepoBuilderTest extends TestCase {
-
-    public void testA() {}
-    
-//    public void testSimple() {
-//        assertBundles("osgi", RepoBuilder.STRATEGY_LOWEST, new String[]{"osgi-3.0.0.jar"});
-//        assertBundles("osgi", RepoBuilder.STRATEGY_HIGHEST, new String[]{"osgi-4.2.0.jar"});
-//        assertBundles("osgi;version=4.1", RepoBuilder.STRATEGY_HIGHEST, new String[]{"osgi-4.2.0.jar"});
-//        assertBundles("osgi;version=4.1", RepoBuilder.STRATEGY_LOWEST, new String[]{"osgi-4.1.0.jar"});
-//        assertBundles("osgi;version=4.1.1", RepoBuilder.STRATEGY_LOWEST, new String[]{"osgi-4.2.0.jar"});
-//        assertBundles("osgi;version=\"(4.1,5)\"", RepoBuilder.STRATEGY_LOWEST, new String[]{"osgi-4.2.0.jar"});
-//        assertBundles("osgi;version=\"[4.1,5)\"", RepoBuilder.STRATEGY_LOWEST, new String[]{"osgi-4.1.0.jar"});
-//        assertBundles("osgi;version=\"[4.1,5)\"", RepoBuilder.STRATEGY_HIGHEST, new String[]{"osgi-4.2.0.jar"});
-//        assertBundles("osgi;version=\"[3,4)\"", RepoBuilder.STRATEGY_HIGHEST, new String[]{"osgi-3.0.0.jar"});
-//        //assertBundles("osgi,org.osgi.impl.service.log,org.osgi.impl.service.cm", RepoBuilder.STRATEGY_LOWEST, new String[]{"osgi-3.0.0.jar", "org.osgi.impl.service.cm-2.1.1.jar"});
-//    }
-//    
-//    
-//    void assertBundles(String bundles, int strategy, String endsWith[]) {        
-//        RepoBuilder r = new RepoBuilder();
-//        Properties p = new Properties();
-//        p.setProperty("-plugin", "aQute.lib.deployer.FileRepo;location=src/test/repo");
-//        p.setProperty("-bundles", bundles );
-//        r.setProperties(p);
-//        List<Container> b = r.getBundles(strategy, r.getProperty("-bundles"));
-//        List<File> l = new ArrayList<File>();
-//        for ( Container c : b ) 
-//            l.add(c.getFile());
-//        check(r);
-//        assertEquals( endsWith.length, b.size());
-//        for ( int i =0; i<endsWith.length; i++ ) {
-//            assertTrue(endsWith[i] + " : " + l.get(i), l.get(i).toString().endsWith(endsWith[i]));
-//        }
-//        System.out.println(b);        
-//    }
-//    
-//    void check(Analyzer r) {
-//        System.out.println(r.getErrors());
-//        System.out.println(r.getWarnings());
-//        assertEquals(0, r.getWarnings().size());
-//        assertEquals(0, r.getErrors().size());
-//    }
-}
diff --git a/biz.aQute.bndlib/src/test/ResourcesTest.java b/biz.aQute.bndlib/src/test/ResourcesTest.java
deleted file mode 100644
index 9864dcf..0000000
--- a/biz.aQute.bndlib/src/test/ResourcesTest.java
+++ /dev/null
@@ -1,220 +0,0 @@
-package test;
-
-import java.util.*;
-
-import junit.framework.*;
-import aQute.lib.osgi.*;
-
-public class ResourcesTest extends TestCase {
-
-    
-    public void testNegativeFilter() throws Exception {
-        Builder b = new Builder();
-        b.setProperty("Include-Resource", "TargetFolder=test/ws/p2/Resources;filter:=!*.txt");
-        b.setProperty("-resourceonly", "true");
-        Jar jar = b.build();
-        Resource r = jar.getResource("TargetFolder/resource1.res");
-        assertNotNull(r);
-        r = jar.getResource("TargetFolder/resource2.res");
-        assertNotNull(r);
-        r = jar.getResource("TargetFolder/resource5.asc");
-        assertNotNull(r);
-    }
-
-    public void testCopyToRoot() throws Exception {
-        Builder bmaker = new Builder();
-        Properties p = new Properties();
-        p.setProperty("-resourceonly", "true");
-        p.setProperty("Include-Resource", "/=src/test/activator");
-        bmaker.setProperties(p);
-        Jar jar = bmaker.build();
-        for ( String s : jar.getResources().keySet() )
-            System.out.println( s);
-        assertNotNull(jar.getResource("Activator.java"));
-        assertEquals( 0, bmaker.getErrors().size() );
-        assertEquals( 0, bmaker.getWarnings().size() );
-    }
-    
-    public void testIncludeResourceDirectivesDefault() throws Exception {
-        Builder b = new Builder();
-        b.setProperty("Include-Resource", "TargetFolder=test/ws/p2/Resources");
-        b.setProperty("-resourceonly", "true");
-        Jar jar = b.build();
-        Resource r = jar.getResource("TargetFolder/resource3.txt");
-        assertNotNull(r);
-        r = jar.getResource("TargetFolder/resource4.txt");
-        assertNotNull(r);
-        r = jar.getResource("TargetFolder/more/resource6.txt");
-        assertNotNull(r);
-        r = jar.getResource("TargetFolder/more/resource7.txt");
-        assertNotNull(r);
-        r = jar.getResource("TargetFolder/stuff/resource9.res");
-        assertNotNull(r);
-        r = jar.getResource("TargetFolder/text.txt");
-        assertNotNull(r);
-
-    }
-    public void testIncludeResourceDoNotCopy() throws Exception {
-        Builder b = new Builder();
-        
-        // Use Properties file otherwise -donotcopy is not picked up
-        Properties p = new Properties();
-        p.put("-donotcopy", "CVS|.svn|stuff");
-        p.put("Include-Resource", "TargetFolder=test/ws/p2/Resources");
-        p.put("-resourceonly", "true");
-        b.setProperties(p);
-        
-        Jar jar = b.build();
-        Resource r = jar.getResource("TargetFolder/resource3.txt");
-        assertNotNull(r);
-        r = jar.getResource("TargetFolder/resource4.txt");
-        assertNotNull(r);
-        r = jar.getResource("TargetFolder/more/resource6.txt");
-        assertNotNull(r);
-        r = jar.getResource("TargetFolder/more/resource7.txt");
-        assertNotNull(r);
-        r = jar.getResource("TargetFolder/stuff/resource9.res");
-        assertNull(r);
-        r = jar.getResource("TargetFolder/text.txt");
-        assertNotNull(r);
-
-    }
-
-    public void testIncludeResourceDirectivesFilterRecursive() throws Exception {
-        Builder b = new Builder();
-        b.setProperty("Include-Resource", "TargetFolder=test/ws/p2/Resources;filter:=re*.txt");
-        b.setProperty("-resourceonly", "true");
-        Jar jar = b.build();
-        Resource r = jar.getResource("TargetFolder/resource3.txt");
-        assertNotNull(r);
-        r = jar.getResource("TargetFolder/resource4.txt");
-        assertNotNull(r);
-        r = jar.getResource("TargetFolder/more/resource6.txt");
-        assertNotNull(r);
-        r = jar.getResource("TargetFolder/more/resource7.txt");
-        assertNotNull(r);
-        r = jar.getResource("TargetFolder/text.txt");
-        assertNull(r);
-
-    }
-
-    public void testIncludeResourceDirectivesFilterRecursive2() throws Exception {
-        Builder b = new Builder();
-        b.setProperty("Include-Resource", "test/ws/p2/Resources;filter:=re*.txt");
-        b.setProperty("-resourceonly", "true");
-        Jar jar = b.build();
-        Resource r = jar.getResource("resource3.txt");
-        assertNotNull(r);
-        r = jar.getResource("resource4.txt");
-        assertNotNull(r);
-        r = jar.getResource("more/resource6.txt");
-        assertNotNull(r);
-        r = jar.getResource("more/resource7.txt");
-        assertNotNull(r);
-        r = jar.getResource("text.txt");
-        assertNull(r);
-
-    }
-
-    public void testIncludeResourceDirectivesFilterNonRecursive() throws Exception {
-        Builder b = new Builder();
-        b.setProperty("Include-Resource", "TargetFolder=test/ws/p2/Resources;filter:=re*.txt;recursive:=false");
-        b.setProperty("-resourceonly", "true");
-        Jar jar = b.build();
-        Resource r = jar.getResource("TargetFolder/resource3.txt");
-        assertNotNull(r);
-        r = jar.getResource("TargetFolder/resource4.txt");
-        assertNotNull(r);
-        r = jar.getResource("TargetFolder/more/resource6.txt");
-        assertNull(r);
-        r = jar.getResource("TargetFolder/more/resource7.txt");
-        assertNull(r);
-    }
-
-    public void testIncludeResourceDirectivesFilterRecursiveFlatten() throws Exception {
-    	Builder b = new Builder();
-    	b.setProperty("Include-Resource", "TargetFolder=test/ws/p2/Resources;filter:=re*.txt;flatten:=true");
-        b.setProperty("-resourceonly", "true");
-        Jar jar = b.build();
-        
-        Resource r = jar.getResource("TargetFolder/resource3.txt");
-        assertNotNull(r);
-        r = jar.getResource("TargetFolder/resource4.txt");
-        assertNotNull(r);
-        r = jar.getResource("TargetFolder/resource6.txt");
-        assertNotNull(r);
-        r = jar.getResource("TargetFolder/resource7.txt");
-        assertNotNull(r);
-        r = jar.getResource("TargetFolder/resource1.res");
-        assertNull(r);
-
-    }
- 
-    public void testEmpty() throws Exception {
-        Builder bmaker = new Builder();
-        Properties p = new Properties();
-        p.setProperty("-resourceonly", "true");
-        p.setProperty("Include-Resource", "  ");
-        bmaker.setProperties(p);
-        Jar jar = bmaker.build();
-        assertEquals( 0, jar.getResources().size());
-        assertEquals( 1, bmaker.getErrors().size() );
-        System.out.println(bmaker.getErrors());
-        assertTrue( bmaker.getErrors().get(0).indexOf("The JAR is empty") >= 0);
-        assertEquals( 0, bmaker.getWarnings().size() );
-    }
-    
-    
-    public void testLiteral() throws Exception {
-        Builder bmaker = new Builder();
-        Properties p = new Properties();
-        p.setProperty("-resourceonly","true");
-        p.setProperty("Include-Resource", "text;literal=TEXT;extra='hello/world;charset=UTF-8'");
-        bmaker.setProperties(p);
-        bmaker.setClasspath( new String[] {"src"});
-        Jar jar = bmaker.build();
-        Resource resource =jar.getResource("text");
-        assertNotNull(resource);
-        byte buffer[] = new byte[1000];
-        int size = resource.openInputStream().read(buffer);
-        String s= new String(buffer,0,size);
-        assertEquals("TEXT",s);
-        assertEquals("hello/world;charset=UTF-8", resource.getExtra());
-        report(bmaker);
-        
-    }
-    
-    
-    /**
-     * Check if we can create a jar on demand through the make
-     * facility.
-     * 
-     * @throws Exception
-     */
-    public void testOnDemandResource() throws Exception {
-        Builder bmaker = new Builder();
-        Properties p = new Properties();
-        p.setProperty("-resourceonly","true");
-        p.setProperty("-plugin", "aQute.bnd.make.MakeBnd, aQute.bnd.make.MakeCopy");
-        p.setProperty("-make", "(*).jar;type=bnd;recipe=bnd/$1.bnd");
-        p.setProperty("Include-Resource", "ondemand.jar");
-        bmaker.setProperties(p);
-        bmaker.setClasspath( new String[] {"bin"});
-        Jar jar = bmaker.build();
-        Resource resource =jar.getResource("ondemand.jar");
-        assertNotNull(resource);
-        assertTrue( resource instanceof JarResource );
-        report(bmaker);
-        
-    }
-    
-    void report(Processor processor) {
-        System.out.println();
-        for ( int i=0; i<processor.getErrors().size(); i++ )
-            System.out.println(processor.getErrors().get(i));
-        for ( int i=0; i<processor.getWarnings().size(); i++ )
-            System.out.println(processor.getWarnings().get(i));
-        assertEquals(0, processor.getErrors().size());
-        assertEquals(0, processor.getWarnings().size());
-    }
-}
diff --git a/biz.aQute.bndlib/src/test/SpringTest.java b/biz.aQute.bndlib/src/test/SpringTest.java
deleted file mode 100644
index 61ba7ff..0000000
--- a/biz.aQute.bndlib/src/test/SpringTest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package test;
-
-import junit.framework.*;
-import aQute.lib.osgi.*;
-
-public class SpringTest extends TestCase {
-
-	/**
-	 * Basic test to see if the analzyer works. We read the sprint-test1.xml and
-	 * see if we can detect all the different packages.
-	 * 
-	 * @throws Exception
-	 */
-	public void testSimple() throws Exception {
-	    
-//		InputStream in = getClass().getResourceAsStream("spring-test1.xml");
-//		Set set = SpringComponent.analyze(in);
-//		System.out.println(set);
-//		assertTrue(set.contains("com.foo.one"));
-//		assertTrue(set.contains("com.foo.one.one"));
-//		assertTrue(set.contains("com.foo.one.two"));
-//		assertTrue(set.contains("value_type"));
-//		assertTrue(set.contains("a.b"));
-//		assertTrue(set.contains("c.d"));
-//		assertTrue(set.contains("e.f"));
-//		assertTrue(set.contains("interfaces_1"));
-//		assertTrue(set.contains("interfaces_2"));
-//		assertFalse(set.contains("interfaces_3"));
-//		assertFalse(set.contains("I-am-not-here"));
-	}
-
-	/**
-	 * Now check if the plugin works, we create a dummy bundle and put the
-	 * spring-test1.xml in the appropriate place. This means that the
-	 * import-header contains all the the packages.
-	 * 
-	 * @throws Exception
-	public void testPlugin() throws Exception {
-		Builder b = new Builder();
-		b.setProperty(Analyzer.INCLUDE_RESOURCE,
-				"META-INF/spring/one.xml=src/test/spring-test1.xml");
-		b.setProperty(Analyzer.IMPORT_PACKAGE, "*");
-		b.setProperty(Analyzer.EXPORT_PACKAGE, "*");
-		b.setClasspath(new File[] { new File("jar/asm.jar") });
-		Jar jar = b.build();
-		checkMessages(b,0,0);
-		test(jar);
-	}
-	 */
-
-	/**
-	 * See what happens if we put the spring file in the wrong place.
-	 * We should have no import packages.
-	 * 
-	 * @throws Exception
-	 */
-//	public void testPluginWrongPlace() throws Exception {
-//		Builder b = new Builder();
-//		b.setProperty(Analyzer.INCLUDE_RESOURCE,
-//				"META-INF/not-spring/one.xml=src/test/spring-test1.xml");
-//		Jar jar = b.build();
-//		checkMessages(b,0,2);
-//		Manifest m = jar.getManifest();
-//		assertNull(m.getMainAttributes().getValue(Analyzer.IMPORT_PACKAGE));
-//	}
-//
-//	void test(Jar jar) throws Exception {
-//		Manifest m = jar.getManifest();
-//		String header = m.getMainAttributes().getValue("Import-Package");
-//		assertTrue(header.indexOf("com.foo.one") >= 0);
-//		assertTrue(header.indexOf("com.foo.one.one") >= 0);
-//		assertTrue(header.indexOf("com.foo.one.two") >= 0);
-//		assertTrue(header.indexOf("value_type") >= 0);
-//		assertTrue(header.indexOf("a.b") >= 0);
-//		assertTrue(header.indexOf("c.d") >= 0);
-//		assertTrue(header.indexOf("e.f") >= 0);
-//		assertTrue(header.indexOf("interfaces_1") >= 0);
-//		assertTrue(header.indexOf("interfaces_2") >= 0);
-//		assertFalse(header.indexOf("interfaces_3") >= 0);
-//		assertFalse(header.indexOf("I-am-not-here") >= 0);
-//
-//	}
-
-	public void checkMessages(Processor processor, int errors, int warnings) {
-		System.out.println("Errors:    " + processor.getErrors());
-		System.out.println("Warnings:  " + processor.getWarnings());
-		assertEquals(errors, processor.getErrors().size());
-		assertEquals(warnings, processor.getWarnings().size());
-
-	}
-}
diff --git a/biz.aQute.bndlib/src/test/TestBndBook.java b/biz.aQute.bndlib/src/test/TestBndBook.java
deleted file mode 100644
index e7bc935..0000000
--- a/biz.aQute.bndlib/src/test/TestBndBook.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package test;
-
-import java.io.*;
-
-import junit.framework.*;
-import aQute.lib.osgi.*;
-
-public class TestBndBook extends TestCase {
-
-    public void testFilterout() throws Exception {
-        Builder b = new Builder();
-        b.addClasspath( new File("jar/osgi.jar"));
-        b.addClasspath( new File("jar/ds.jar"));
-        b.setProperty("Export-Package", "org.eclipse.*, org.osgi.*");
-        b.setProperty("fwusers", "${classes;importing;org.osgi.framework}");
-        b.setProperty("foo", "${filterout;${fwusers};org\\.osgi\\..*}");
-        b.build();
-        String fwusers = b.getProperty("fwusers");
-        String foo = b.getProperty("foo");
-        assertTrue( fwusers.length() > foo.length() );
-        assertTrue( fwusers.indexOf("org.osgi.framework.ServicePermission")>=0 );
-        assertTrue( fwusers.indexOf("org.eclipse.equinox.ds.instance.BuildDispose")>=0 );
-        assertFalse( foo.indexOf("org.osgi.framework.ServicePermission")>=0 );
-        assertTrue( foo.indexOf("org.eclipse.equinox.ds.instance.BuildDispose")>=0 );
-        System.out.println(b.getProperty("fwusers"));
-        System.out.println(b.getProperty("foo"));
-        
-    }
-}
diff --git a/biz.aQute.bndlib/src/test/TestEclipseRepo.java b/biz.aQute.bndlib/src/test/TestEclipseRepo.java
deleted file mode 100644
index 88d5465..0000000
--- a/biz.aQute.bndlib/src/test/TestEclipseRepo.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package test;
-
-import java.util.*;
-
-import junit.framework.*;
-import aQute.bnd.repo.eclipse.*;
-import aQute.libg.generics.*;
-
-public class TestEclipseRepo extends TestCase {
-
-    
-    public void testSimple() {
-        EclipseRepo er = new EclipseRepo();
-        Map<String, String> map = Create.map();
-        map.put("location", "test/eclipse");
-        map.put("name", "eclipse-test");
-        er.setProperties(map);
-        
-        System.out.println(er.list("*"));
-    }
-}
diff --git a/biz.aQute.bndlib/src/test/TestQuotedTokenizer.java b/biz.aQute.bndlib/src/test/TestQuotedTokenizer.java
deleted file mode 100755
index f8c6fef..0000000
--- a/biz.aQute.bndlib/src/test/TestQuotedTokenizer.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package test;
-
-import junit.framework.*;
-import aQute.libg.qtokens.*;
-
-public class TestQuotedTokenizer extends TestCase {
-
-	public void testNativeSeps() {
-		String s[] = new QuotedTokenizer("x;c;d=4", ";,=", true).getTokens();
-		assertEquals("Length", 7, s.length);
-		assertEquals("x", s[0]);
-		assertEquals(";", s[1]);
-		assertEquals("c", s[2]);
-		assertEquals(";", s[3]);
-		assertEquals("d", s[4]);
-		assertEquals("=", s[5]);
-		assertEquals("4", s[6]);
-	}
-	
-	public void testSimple() {
-		String s[] = new QuotedTokenizer("1.jar, 2.jar,    \t   3.jar", ",").getTokens();
-		assertEquals("Length", 3, s.length);
-		assertEquals("1.jar", s[0]);
-		assertEquals("2.jar", s[1]);
-		assertEquals("3.jar", s[2]);
-	}
-	
-	public void testQuoted() {
-		String s[] = new QuotedTokenizer("'1 ,\t.jar'", ",").getTokens();
-		assertEquals("Length", 1, s.length);
-		assertEquals("1 ,\t.jar", s[0]);
-	}
-	
-	public void testWhiteSpace() {
-		String s[] = new QuotedTokenizer("               1.jar,               2.jar         ", ",").getTokens();
-		assertEquals("Length", 2, s.length);
-		assertEquals("1.jar", s[0]);
-		assertEquals("2.jar", s[1]);
-	}
-	
-	public void testMultipleSeps() {
-		String s[] = new QuotedTokenizer("1.jar,,,,,,,,,,,    , ,2.jar", ",").getTokens();
-		assertEquals("Length", 14, s.length);
-		assertEquals("1.jar", s[0]);
-		assertEquals("2.jar", s[13]);
-	}
-	
-	public void testNative() {
-		String s[] = new QuotedTokenizer("x.dll;y.dll;abc=3;def=5;version=\"1.2.34,123\"", ";,=").getTokens();
-		assertEquals("Length", 8, s.length);
-		assertEquals("x.dll", s[0]);
-		assertEquals("y.dll", s[1]);
-		assertEquals("abc", s[2]);
-		assertEquals("3", s[3]);
-		assertEquals("def", s[4]);
-		assertEquals("5", s[5]);
-		assertEquals("version", s[6]);
-		assertEquals("1.2.34,123", s[7]);
-	}
-	
-}
diff --git a/biz.aQute.bndlib/src/test/TestSelfBuild.java b/biz.aQute.bndlib/src/test/TestSelfBuild.java
deleted file mode 100644
index bfee36e..0000000
--- a/biz.aQute.bndlib/src/test/TestSelfBuild.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package test;
-
-import java.io.File;
-
-import junit.framework.TestCase;
-import aQute.bnd.build.Project;
-import aQute.bnd.build.Workspace;
-import aQute.lib.osgi.*;
-
-public class TestSelfBuild extends TestCase {
-
-	public void testSelfBuild() throws Throwable {
-		Project project = Workspace.getWorkspace( new File("").getAbsoluteFile().getParentFile() ).getProject("biz.aQute.bndlib");
-		project.setPedantic(true);
-		project.action("build");
-		
-		File files[] = project.build();
-		System.out.println(Processor.join(project.getErrors(),"\n"));
-		System.out.println(Processor.join(project.getWarnings(),"\n"));
-		assertEquals(0, project.getErrors().size());
-		assertEquals(0, project.getWarnings().size());
-		assertNotNull(files);
-		assertEquals(1,files.length);
-	}
-}
diff --git a/biz.aQute.bndlib/src/test/TestSignatures.java b/biz.aQute.bndlib/src/test/TestSignatures.java
deleted file mode 100644
index 0e33adf..0000000
--- a/biz.aQute.bndlib/src/test/TestSignatures.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package test;
-
-import java.io.*;
-import java.lang.reflect.*;
-
-import test.signatures.*;
-
-import junit.framework.*;
-import aQute.bnd.compatibility.*;
-
-public class TestSignatures extends TestCase {
-	Signatures s = new Signatures();
-	
-	
-	public void testScopes() throws Exception {
-		assertEquals( "<E:Ljava/lang/Object;>(TE;TC;TD;)V", s.getSignature( Z.V.class.getMethod("fooLCO", Object.class, Object.class, Object.class)));
-	}
-	
-	public void testClass() throws Exception {
-		assertEquals( "<C:Ljava/lang/Object;>Ltest/signatures/X<Ljava/lang/String;>;Ltest/signatures/Y<Ljava/lang/Integer;>;", s.getSignature(Z.class));
-		assertEquals( "<D:Ljava/lang/Object;>Ljava/lang/Object;", s.getSignature(Z.V.class));
-	}
-	
-	public void testMethodDeclarations() throws Exception {	
-		assertEquals( "<E:Ljava/lang/Object;>(TE;)V", s.getSignature( Z.class.getMethod("foo", Object.class)));
-		assertEquals( "<E:Ljava/io/InputStream;>(TE;)V", s.getSignature( Z.class.getMethod("fooC", InputStream.class)));
-		assertEquals( "<E:Ljava/io/InputStream;:Ljava/lang/Cloneable;>(TE;)V", s.getSignature( Z.class.getMethod("fooCI", InputStream.class)));
-		assertEquals( "<E:Ljava/io/InputStream;:Ljava/lang/Cloneable;:Ljava/io/Serializable;>(TE;)V", s.getSignature( Z.class.getMethod("fooCII", InputStream.class)));
-		assertEquals( "<E::Ljava/io/Serializable;:Ljava/lang/Cloneable;>(TE;)V", s.getSignature( Z.class.getMethod("fooII", Serializable.class)));
-		assertEquals( "<E::Ljava/lang/Cloneable;>(TE;)V", s.getSignature( Z.class.getMethod("fooI", Cloneable.class)));
-		assertEquals( "<E:TC;>(TE;)V", s.getSignature( Z.class.getMethod("fooP", Object.class)));		
-		assertEquals( "<E:Ljava/lang/Object;F:Ljava/lang/Object;>(TE;TF;)V", s.getSignature( Z.class.getMethod("foo", Object.class, Object.class)));		
-	}
-	
-	public void testFields() throws Exception {
-		// Z<Long>.V<Integer>
-		assertEquals( "Ltest/signatures/Z<Ljava/lang/Long;>.V<Ljava/lang/Integer;>;", s.getSignature(Z.class.getField("referenceToNestedClass")));
-		
-		// 
-		assertEquals( "Ltest/signatures/Z<TC;>.V<TC;>;", s.getSignature(Z.class.getField("vc")));
-		assertEquals( "<C:Ljava/lang/Object;>Ltest/signatures/X<Ljava/lang/String;>;Ltest/signatures/Y<Ljava/lang/Integer;>;", s.getSignature(Z.class));
-		assertEquals( "<D:Ljava/lang/Object;>Ljava/lang/Object;", s.getSignature(Z.V.class));
-		assertEquals( "Ltest/signatures/X<Ltest/signatures/Y<TC;>;>;", s.getSignature( Z.class.getField("field")));
-	}
-	
-	
-	public void testWildcards() throws Exception {
-		assertEquals( "Ljava/util/Collection<*>;", s.getSignature( Z.class.getField("wildcard_001")));
-		assertEquals( "Ljava/util/Collection<+Ljava/lang/Cloneable;>;", s.getSignature( Z.class.getField("wildcard_002")));
-		assertEquals( "Ljava/util/Collection<-Ljava/lang/Cloneable;>;", s.getSignature( Z.class.getField("wildcard_003")));
-		assertEquals( "Ljava/util/Collection<+TC;>;", s.getSignature( Z.class.getField("wildcard_004")));
-		assertEquals( "Ljava/util/Collection<-TC;>;", s.getSignature( Z.class.getField("wildcard_005")));
-		assertEquals( "Ljava/util/Collection<+Ltest/signatures/Z<TC;>.V<Ljava/lang/Integer;>;>;", s.getSignature( Z.class.getField("wildcard_006")));
-		assertEquals( "Ljava/util/Collection<-Ltest/signatures/Z<TC;>.V<Ljava/lang/Integer;>;>;", s.getSignature( Z.class.getField("wildcard_007")));
-	}
-	
-	public void testNormalize() {
-		assertEquals( "Ltest/signatures/Z<Ljava/lang/Long;>.V<Ljava/lang/Integer;>;", s.normalize("Ltest/signatures/Z<Ljava/lang/Long;>.V<Ljava/lang/Integer;>;"));
-		assertEquals( s.normalize("<A:Ljava/lang/Object;>(TA;)V"), s.normalize("<E:Ljava/lang/Object;>(TE;)V"));		
-		assertEquals( s.normalize("<A:Ljava/lang/Object;>(TA;TB;)V"), s.normalize("<E:Ljava/lang/Object;>(TE;TC;)V"));
-		
-		// we use (A,A) and test against (A,B)
-		assertFalse( s.normalize("<A:Ljava/lang/Object;>(TA;TA;)V").equals(s.normalize("<E:Ljava/lang/Object;>(TE;TC;)V")));		
-		assertEquals( "<_0:Ljava/lang/Object;>(T_0;)V", s.normalize("<E:Ljava/lang/Object;>(TE;)V"));		
-		assertEquals( "<_0:Ljava/lang/Object;>(T_0;T_1;T_2;)V", s.normalize("<E:Ljava/lang/Object;>(TE;TC;TD;)V"));
-		assertEquals( "<_0:Ljava/lang/Object;>Ljava/lang/Object;", s.normalize("<_0:Ljava/lang/Object;>Ljava/lang/Object;"));
-	}
-	
-	public void testCompatibility() throws Exception {
-		String _001 =ns(Z.class.getMethod("compatibility_001"));
-		String _002 =ns(Z.class.getMethod("compatibility_002"));
-		String _003 =ns(Z.class.getMethod("compatibility_003"));
-		assertEquals( _001, _002);
-		assertTrue( _001.equals(_002));
-		assertFalse( _001.equals(_003));
-	}
-
-	private String ns(Method method) throws Exception {
-		String sig = s.getSignature(method);
-		return s.normalize(sig);
-	}
-}
diff --git a/biz.aQute.bndlib/src/test/VerifierTest.java b/biz.aQute.bndlib/src/test/VerifierTest.java
deleted file mode 100755
index 9e0636b..0000000
--- a/biz.aQute.bndlib/src/test/VerifierTest.java
+++ /dev/null
@@ -1,240 +0,0 @@
-package test;
-
-import java.io.File;
-import java.util.Properties;
-import java.util.jar.Manifest;
-
-import junit.framework.TestCase;
-import aQute.lib.osgi.*;
-
-public class VerifierTest extends TestCase {
-	
-	
-	public void testnativeCode() throws Exception {
-		Builder b = new Builder();
-		b.addClasspath( new File("bin"));
-		b.setProperty("-resourceonly", "true");
-		b.setProperty("Include-Resource", "native/win32/NTEventLogAppender-1.2.dll;literal='abc'");
-		b.setProperty("Bundle-NativeCode", "native/win32/NTEventLogAppender-1.2.dll; osname=Win32; processor=x86");
-		Jar jar = b.build();
-		Verifier v = new Verifier(jar);
-		v.setJar(jar);
-		
-		v.verifyNative();
-		System.out.println( v.getErrors());
-		assertEquals(0, v.getErrors().size());
-		v.close();
-		b.close();
-	}
-	
-	
-
-    public void testFilter() {
-
-        testFilter("(&(a=b)(c=1))");
-        testFilter("(&(a=b)(!(c=1))(&(c=1))(c=1)(c=1)(c=1)(c=1)(c=1)(c=1)(c=1)(c=1))");
-        testFilter("(!(a=b))");
-        testInvalidFilter("(!(a=b)(c=2))");
-        testInvalidFilter("(axb)");
-        testInvalidFilter("(a=3 ");
-        testFilter("(room=*)");
-        testFilter("(room=bedroom)");
-        testFilter("(room~= B E D R O O M )");
-        testFilter("(room=abc)");
-        testFilter(" ( room >=aaaa)");
-        testFilter("(room <=aaaa)");
-        testFilter("  ( room =b*) ");
-        testFilter("  ( room =*m) ");
-        testFilter("(room=bed*room)");
-        testFilter("  ( room =b*oo*m) ");
-        testFilter("  ( room =*b*oo*m*) ");
-        testFilter("  ( room =b*b*  *m*) ");
-        testFilter("  (& (room =bedroom) (channel ~=34))");
-        testFilter("  (&  (room =b*)  (room =*x) (channel=34))");
-        testFilter("(| (room =bed*)(channel=222)) ");
-        testFilter("(| (room =boom*)(channel=101)) ");
-        testFilter("  (! (room =ab*b*oo*m*) ) ");
-        testFilter("  (status =\\(o*\\\\\\)\\*) ");
-        testFilter("  (canRecord =true\\(x\\)) ");
-        testFilter("(max Record Time <=140) ");
-        testFilter("(shortValue >=100) ");
-        testFilter("(intValue <=100001) ");
-        testFilter("(longValue >=10000000000) ");
-        testFilter("  (  &  (  byteValue <=100)  (  byteValue >=10)  )  ");
-        testFilter("(weirdValue =100) ");
-        testFilter("(bigIntValue =4123456) ");
-        testFilter("(bigDecValue =4.123456) ");
-        testFilter("(floatValue >=1.0) ");
-        testFilter("(doubleValue <=2.011) ");
-        testFilter("(charValue ~=a) ");
-        testFilter("(booleanValue =true) ");
-        testFilter("(primIntArrayValue =1) ");
-        testFilter("(primLongArrayValue =2) ");
-        testFilter("(primByteArrayValue =3) ");
-        testFilter("(primShortArrayValue =1) ");
-        testFilter("(primFloatArrayValue =1.1) ");
-        testFilter("(primDoubleArrayValue =2.2) ");
-        testFilter("(primCharArrayValue ~=D) ");
-        testFilter("(primBooleanArrayValue =false) ");
-        testFilter("(& (| (room =d*m) (room =bed*) (room=abc)) (! (channel=999)))");
-        testFilter("(room=bedroom)");
-        testFilter("(*=foo)");
-        testInvalidFilter("(!  ab=b)");
-        testInvalidFilter("(|   ab=b)");
-        testInvalidFilter("(&=c)");
-        testInvalidFilter("(!=c)");
-        testInvalidFilter("(|=c)");
-        testInvalidFilter("(&    ab=b)");
-        testInvalidFilter("(!ab=*)");
-        testInvalidFilter("(|ab=*)");
-        testInvalidFilter("(&ab=*)");
-        testFilter("(empty=)");
-        testFilter("(empty=*)");
-        testFilter("(space= )");
-        testFilter("(space=*)");
-        testFilter("(intvalue=*)");
-        testFilter("(intvalue=b)");
-        testFilter("(intvalue=)");
-        testFilter("(longvalue=*)");
-        testFilter("(longvalue=b)");
-        testFilter("(longvalue=)");
-        testFilter("(shortvalue=*)");
-        testFilter("(shortvalue=b)");
-        testFilter("(shortvalue=)");
-        testFilter("(bytevalue=*)");
-        testFilter("(bytevalue=b)");
-        testFilter("(bytevalue=)");
-        testFilter("(charvalue=*)");
-        testFilter("(charvalue=)");
-        testFilter("(floatvalue=*)");
-        testFilter("(floatvalue=b)");
-        testFilter("(floatvalue=)");
-        testFilter("(doublevalue=*)");
-        testFilter("(doublevalue=b)");
-        testFilter("(doublevalue=)");
-        testFilter("(booleanvalue=*)");
-        testFilter("(booleanvalue=b)");
-        testFilter("(booleanvalue=)");
-
-        testInvalidFilter("");
-        testInvalidFilter("()");
-        testInvalidFilter("(=foo)");
-        testInvalidFilter("(");
-        testInvalidFilter("(abc = ))");
-        testInvalidFilter("(& (abc = xyz) (& (345))");
-        testInvalidFilter("  (room = b**oo!*m*) ) ");
-        testInvalidFilter("  (room = b**oo)*m*) ) ");
-        testInvalidFilter("  (room = *=b**oo*m*) ) ");
-        testInvalidFilter("  (room = =b**oo*m*) ) ");
-        testFilter("(shortValue =100*) ");
-        testFilter("(intValue =100*) ");
-        testFilter("(longValue =100*) ");
-        testFilter("(  byteValue =1*00  )");
-        testFilter("(bigIntValue =4*23456) ");
-        testFilter("(bigDecValue =4*123456) ");
-        testFilter("(floatValue =1*0) ");
-        testFilter("(doubleValue =2*011) ");
-        testFilter("(charValue =a*) ");
-        testFilter("(booleanValue =t*ue) ");
-    }
-
-    private void testFilter(String string) {
-        int index = Verifier.verifyFilter(string, 0);
-        while (index < string.length() && Character.isWhitespace(string.charAt(index)))
-                index++;
-
-        if ( index != string.length())
-            throw new IllegalArgumentException("Characters after filter");
-    }
-
-    private void testInvalidFilter(String string) {
-        try {
-            testFilter(string);
-            fail("Invalid filter");
-        } catch (Exception e) {
-        }
-    }
-
-    public void testBundleActivationPolicyNone() throws Exception {
-        Builder v = new Builder();
-        v.setProperty("Private-Package", "aQute.bnd.make");
-        v.addClasspath( new File("bin"));
-        v.build();
-        assertEquals(0, v.getWarnings().size());
-        System.out.println(v.getErrors());
-        assertEquals(0, v.getErrors().size());
-    }
-
-    public void testBundleActivationPolicyBad() throws Exception {
-        Builder v = new Builder();
-        v.setProperty("Private-Package", "aQute.bnd.make");
-        v.addClasspath( new File("bin"));
-        v.setProperty(Constants.BUNDLE_ACTIVATIONPOLICY, "eager");
-        v.build();
-
-        System.out.println("Errors: " + Processor.join(v.getErrors(), "\n"));
-        System.out.println("Warnings: " + Processor.join(v.getWarnings(), "\n"));
-        assertEquals(1, v.getWarnings().size());
-        assertEquals(0, v.getErrors().size());
-    }
-
-    public void testBundleActivationPolicyGood() throws Exception {
-        Builder v = new Builder();
-        v.setProperty("Private-Package", "aQute.bnd.make");
-        v.addClasspath( new File("bin"));
-        v.setProperty(Constants.BUNDLE_ACTIVATIONPOLICY, "lazy   ;   hello:=1");
-        v.build();
-
-        System.out.println("Errors: " + Processor.join(v.getErrors(), "\n"));
-        System.out.println("Warnings: " + Processor.join(v.getWarnings(), "\n"));
-        assertEquals(0, v.getWarnings().size());
-        assertEquals(0, v.getErrors().size());
-    }
-
-    public void testBundleActivationPolicyMultiple() throws Exception {
-        Builder v = new Builder();
-        v.setProperty("Private-Package", "aQute.bnd.make");
-        v.addClasspath( new File("bin"));
-        v.setProperty(Constants.BUNDLE_ACTIVATIONPOLICY, "lazy;hello:=1,2");
-        v.build();
-
-        assertEquals(1, v.getWarnings().size());
-        assertEquals(0, v.getErrors().size());
-    }
-
-    public void testInvalidCaseForHeader() throws Exception {
-        Properties p = new Properties();
-        p.put("Export-package", "org.apache.mina.*");
-        p.put("Bundle-Classpath", ".");
-        Analyzer analyzer = new Analyzer();
-        analyzer.setProperties(p);
-        analyzer.getProperties();
-        System.out.println("Errors   " + analyzer.getErrors());
-        System.out.println("Warnings " + analyzer.getWarnings());
-        assertEquals(0, analyzer.getErrors().size());
-        assertEquals(2, analyzer.getWarnings().size());
-    }
-
-    public void testSimple() throws Exception {
-        File cp[] = { new File("jar/mina.jar") };
-        Properties p = new Properties();
-        p.put("Export-Package", "org.apache.mina.*;version=1");
-        p.put("Import-Package", "*");
-        p.put("DynamicImport-Package", "org.slf4j");
-        Builder bmaker = new Builder();
-        bmaker.setProperties(p);
-        bmaker.setClasspath(cp);
-
-        Jar jar = bmaker.build();
-        Manifest m = jar.getManifest();
-        assertFalse(m.getMainAttributes().getValue("Import-Package").indexOf(
-                "org.slf4j") >= 0);
-        assertTrue(m.getMainAttributes().getValue("DynamicImport-Package")
-                .indexOf("org.slf4j") >= 0);
-        System.out.println(Processor.join( bmaker.getErrors(),"\n"));
-        System.out.println(Processor.join( bmaker.getWarnings(),"\n"));
-        assertTrue(bmaker.getErrors().size() == 0);
-        assertTrue(bmaker.getWarnings().size() == 0);
-    }
-
-}
diff --git a/biz.aQute.bndlib/src/test/VersionPolicyTest.java b/biz.aQute.bndlib/src/test/VersionPolicyTest.java
deleted file mode 100644
index 448254e..0000000
--- a/biz.aQute.bndlib/src/test/VersionPolicyTest.java
+++ /dev/null
@@ -1,274 +0,0 @@
-package test;
-
-import java.io.*;
-import java.util.*;
-import java.util.jar.*;
-
-import junit.framework.*;
-import aQute.lib.osgi.*;
-
-public class VersionPolicyTest extends TestCase {
-	
-	/**
-	 * Test disable default package versions.
-	 */
-    public void testDisableDefaultPackageVersion() throws Exception {
-        Builder a = new Builder();
-        a.addClasspath(new File("bin"));
-        a.setProperty("Bundle-Version", "1.2.3");
-        a.setProperty("Export-Package", "test.refer");
-        a.setProperty("-nodefaultversion", "true");
-        Jar jar = a.build();
-        
-        Manifest m = jar.getManifest();
-        Map<String, Map<String, String>> exports = Processor.parseHeader(m.getMainAttributes().getValue(Constants.EXPORT_PACKAGE), null);
-        Map<String,String> attrs = exports.get("test.refer");
-        assertNotNull(attrs);
-        assertNull( attrs.get("version"));
-    }
-	
-	/**
-	 * Test default package versions.
-	 */
-    public void testDefaultPackageVersion() throws Exception {
-        Builder a = new Builder();
-        a.addClasspath(new File("bin"));
-        a.setProperty("Bundle-Version", "1.2.3");
-        a.setProperty("Export-Package", "test.refer");
-        Jar jar = a.build();
-        
-        Manifest m = jar.getManifest();
-        Map<String, Map<String, String>> exports = Processor.parseHeader(m.getMainAttributes().getValue(Constants.EXPORT_PACKAGE), null);
-        Map<String,String> attrs = exports.get("test.refer");
-        assertNotNull(attrs);
-        assertEquals( "1.2.3", attrs.get("version"));
-    }
-	
-	
-
-    /**
-     * Test import provide:.
-     */
-    public void testImportProvided() throws Exception {
-        Builder a = new Builder();
-        a.addClasspath(new File("jar/osgi.jar"));
-        a.addClasspath(new File("bin"));
-        a.setProperty("Private-Package", "test.refer");
-        a.setProperty("Import-Package", "org.osgi.service.event;provide:=true,*");
-        Jar jar = a.build();
-        Map<String,String> event = a.getImports().get("org.osgi.service.event");
-        assertEquals("[1.0,1.1)", event.get("version"));
-        Map<String,String> http = a.getImports().get("org.osgi.service.http");
-        assertEquals("[1.2,2)", http.get("version"));
-        
-        Manifest m = jar.getManifest();
-        String imports = m.getMainAttributes().getValue(Constants.IMPORT_PACKAGE);
-        assertFalse( imports.contains(Constants.PROVIDE_DIRECTIVE));
-    }
-    
-    /**
-     * Test import provide:.
-     */
-    public void testExportProvided() throws Exception {
-        Builder a = new Builder();
-        a.addClasspath(new File("jar/osgi.jar"));
-        a.addClasspath(new File("bin"));
-        a.setProperty("Private-Package", "test.refer");
-        a.setProperty("Export-Package", "org.osgi.service.http;provide:=true");
-        Jar jar = a.build();
-        Map<String,String> event = a.getImports().get("org.osgi.service.event");
-        assertEquals("[1.0,2)", event.get("version"));
-        Map<String,String> http = a.getImports().get("org.osgi.service.http");
-        assertEquals("[1.2,1.3)", http.get("version"));
-        
-        Manifest m = jar.getManifest();
-        String imports = m.getMainAttributes().getValue(Constants.IMPORT_PACKAGE);
-        assertFalse( imports.contains(Constants.PROVIDE_DIRECTIVE));
-    }
-    
-    /**
-     * Test export annotation.
-     */
-    public void testExportAnnotation() throws Exception {
-        Builder a = new Builder();
-        a.addClasspath(new File("bin"));
-        a.setProperty("build", "xyz");
-        a.setProperty("Export-Package", "test.versionpolicy.api");
-        a.build();
-        Map<String,String> attrs = a.getExports().get("test.versionpolicy.api");
-        assertEquals("1.2.0.xyz", attrs.get("version"));
-        assertEquals("PrivateImpl", attrs.get("exclude:"));
-        assertEquals("a", attrs.get("mandatory:"));
-    }
-
-    /**
-     * Check implementation version policy.
-     * 
-     * Uses the package test.versionpolicy.(uses|implemented)
-     * 
-     * TODO currently commented out because it is too restrictive unless
-     * supported by package
-     */
-    public void testImplementationVersionPolicies() throws Exception {
-//        assertPolicy("test.versionpolicy.implemented", "IMPL");
-//        assertPolicy("test.versionpolicy.implmajor", "USES");
-//        assertPolicy("test.versionpolicy.uses", "USES");
-    }
-
-    void assertPolicy(String pack, String type) throws Exception {
-        Builder a = new Builder();
-        a.addClasspath(new File("bin"));
-        a.setProperty("Export-Package", "test.versionpolicy.api");
-        Jar jar = a.build();
-
-        Builder b = new Builder();
-        b.addClasspath(jar);
-        b.addClasspath(new File("bin"));
-
-        b.setProperty("-versionpolicy-impl", "IMPL");
-        b.setProperty("-versionpolicy-uses", "USES");
-        b.setProperty("Private-Package", pack);
-        b.build();
-        Manifest m = b.getJar().getManifest();
-        m.write(System.out);
-        Map<String, String> map = b.getImports().get("test.versionpolicy.api");
-        assertNotNull(map);
-//        String s = map.get(Constants.IMPLEMENTED_DIRECTIVE);
-//        assertEquals("true", s);
-        Map<String, Map<String, String>> mp = Processor.parseHeader(m
-                .getMainAttributes().getValue("Import-Package"), null);
-        assertEquals(type, mp.get("test.versionpolicy.api").get("version"));
-    }
-
-    /**
-     * hardcoded imports
-     */
-    public void testHardcodedImports() throws Exception {
-        Builder b = new Builder();
-        b.addClasspath(new File("jar/osgi.jar"));
-        b.setProperty("-versionpolicy",
-                "${range;[==,+)}");
-        b.setProperty("Private-Package", "org.objectweb.asm");
-        b.setProperty("Import-Package",
-                "org.osgi.framework,org.objectweb.asm,abc;version=2.0.0,*");
-        b.build();
-        Manifest m = b.getJar().getManifest();
-        m.write(System.out);
-        String s = b.getImports().get("org.objectweb.asm").get("version");
-        assertNull(s);
-        s = b.getImports().get("abc").get("version");
-        assertEquals("2.0.0", s);
-
-        s = b.getImports().get("org.osgi.framework").get("version");
-        assertEquals("[1.3,2)", s);
-
-    }
-
-    /**
-     * Specify the version on the export and verify that the policy is applied
-     * on the matching import.
-     */
-    public void testExportsSpecifiesVersion() throws Exception {
-        Builder b = new Builder();
-        b.addClasspath(new File("jar/osgi.jar"));
-        b.addClasspath(new File("bin"));
-        b.setProperty("Export-Package", "org.osgi.service.event");
-        b.setProperty("Private-Package", "test.refer");
-        b.build();
-        String s = b.getImports().get("org.osgi.service.event").get("version");
-        assertEquals("[1.0,2)", s);
-
-    }
-
-    /**
-     * See if we a can override the version from the export statement and the
-     * version from the source.
-     */
-    public void testImportOverridesDiscoveredVersion() throws Exception {
-        Builder b = new Builder();
-        b.addClasspath(new File("jar/osgi.jar"));
-        b.addClasspath(new File("bin"));
-        b.setProperty("Export-Package", "org.osgi.service.event");
-        b.setProperty("Private-Package", "test.refer");
-        b.setProperty("Import-Package",
-                "org.osgi.service.event;version=2.1.3.q");
-        b.build();
-        String s = b.getImports().get("org.osgi.service.event").get("version");
-        assertEquals("2.1.3.q", s);
-    }
-
-    /**
-     * Test if we can get the version from the source and apply the default
-     * policy.
-     */
-    public void testVersionPolicyImportedExportsDefaultPolicy()
-            throws Exception {
-        Builder b = new Builder();
-        b.addClasspath(new File("jar/osgi.jar"));
-        b.addClasspath(new File("bin"));
-        b.setProperty("Export-Package", "org.osgi.service.event");
-        b.setProperty("Private-Package", "test.refer");
-        b.build();
-        String s = b.getImports().get("org.osgi.service.event").get("version");
-        assertEquals("[1.0,2)", s);
-    }
-
-    /**
-     * Test if we can get the version from the source and apply a specific
-     * policy.
-     */
-    public void testVersionPolicyImportedExportsWithPolicy() throws Exception {
-        Builder b = new Builder();
-        b.addClasspath(new File("jar/osgi.jar"));
-        b.addClasspath(new File("bin"));
-        b.setProperty("-versionpolicy",
-                "${range;[==,=+)}");
-        b.setProperty("Export-Package", "org.osgi.service.event");
-        b.setProperty("Private-Package", "test.refer");
-        b.build();
-        String s = b.getImports().get("org.osgi.service.event").get("version");
-        assertEquals("[1.0,1.1)", s);
-    }
-
-    /**
-     * The default policy is truncate micro. Check if this is applied to the
-     * import.
-     */
-    public void testImportMicroTruncated() throws Exception {
-        Builder b = new Builder();
-        b.addClasspath(new File("jar/osgi.jar"));
-        b.setProperty("Import-Package", "org.osgi.service.event");
-        b.build();
-        String s = b.getImports().get("org.osgi.service.event").get("version");
-        assertEquals("[1.0,2)", s);
-    }
-
-    /**
-     * See if we can apply a policy to an import where we get the version from
-     * the source.
-     */
-    public void testVersionPolicy() throws Exception {
-        Builder b = new Builder();
-        b.addClasspath(new File("jar/osgi.jar"));
-        b.setProperty("-versionpolicy",
-                "${range;[==,=+)}");
-        b.setProperty("Import-Package", "org.osgi.service.event");
-        b.build();
-        String s = b.getImports().get("org.osgi.service.event").get("version");
-        assertEquals("[1.0,1.1)", s);
-    }
-
-    /**
-     * Check if we can set a specific version on the import that does not use a
-     * version policy.
-     */
-    public void testImportMicroNotTruncated() throws Exception {
-        Builder b = new Builder();
-        b.addClasspath(new File("jar/osgi.jar"));
-        b.setProperty("Import-Package", "org.osgi.service.event;version=${@}");
-        b.build();
-        String s = b.getImports().get("org.osgi.service.event").get("version");
-        assertEquals("1.0.1", s);
-    }
-
-}
diff --git a/biz.aQute.bndlib/src/test/WorkspaceTest.java b/biz.aQute.bndlib/src/test/WorkspaceTest.java
deleted file mode 100644
index 1c12456..0000000
--- a/biz.aQute.bndlib/src/test/WorkspaceTest.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package test;
-
-import java.io.*;
-
-import junit.framework.*;
-import aQute.bnd.build.*;
-
-public class WorkspaceTest extends TestCase {
-    
-    public void testWorkspace() throws Exception {
-        Workspace ws = Workspace.getWorkspace( new File("test/w o r k s p a c e"));
-        
-        assertEquals( "parent", ws.getProperty("override"));
-        assertEquals( "true", ws.getProperty("ext"));
-        assertEquals( "abcdef", ws.getProperty("test"));
-    }
-
-    
-    public void testNestedWorkspace() throws Exception {
-        Workspace ws = Workspace.getWorkspace( new File("test/redirectws/wss/ws"));
-        
-        assertEquals( "true", ws.getProperty("testcnf"));
-        assertEquals( "true", ws.getProperty("ext"));
-    }
-
-    
-}
diff --git a/biz.aQute.bndlib/src/test/activator/Activator.java b/biz.aQute.bndlib/src/test/activator/Activator.java
deleted file mode 100755
index f7d5cdb..0000000
--- a/biz.aQute.bndlib/src/test/activator/Activator.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package test.activator;
-
-import org.osgi.framework.*;
-
-public class Activator implements BundleActivator {
-
-	public void start(BundleContext context) throws Exception {
-	}
-
-	public void stop(BundleContext context) throws Exception {
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/test/activator/inherits/InheritedActivator.java b/biz.aQute.bndlib/src/test/activator/inherits/InheritedActivator.java
deleted file mode 100644
index 15b70fa..0000000
--- a/biz.aQute.bndlib/src/test/activator/inherits/InheritedActivator.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package test.activator.inherits;
-
-import org.osgi.framework.*;
-
-import test.activator.*;
-import aQute.bnd.annotation.component.*;
-
- at Component(name="inheritedactivator",provide=BundleActivator.class)
-public class InheritedActivator extends Activator {
-
-}
diff --git a/biz.aQute.bndlib/src/test/classreference/ClassReference.java b/biz.aQute.bndlib/src/test/classreference/ClassReference.java
deleted file mode 100755
index 279d86f..0000000
--- a/biz.aQute.bndlib/src/test/classreference/ClassReference.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package test.classreference;
-
-
-public class ClassReference {
-
-	public void testClassReference() {
-		System.out.println(javax.swing.Box.class);
-	}
-}
diff --git a/biz.aQute.bndlib/src/test/lib/deployer/obr/NanoHTTPD.java b/biz.aQute.bndlib/src/test/lib/deployer/obr/NanoHTTPD.java
deleted file mode 100644
index 214ccce..0000000
--- a/biz.aQute.bndlib/src/test/lib/deployer/obr/NanoHTTPD.java
+++ /dev/null
@@ -1,1004 +0,0 @@
-package test.lib.deployer.obr;
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.URLEncoder;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Locale;
-import java.util.Properties;
-import java.util.StringTokenizer;
-import java.util.TimeZone;
-import java.util.Vector;
-
-/**
- * A simple, tiny, nicely embeddable HTTP 1.0 server in Java
- * 
- * <p><b>Modified from the original as follows: removed main method; added base directory parameter
- * for use when serving files.</b></p>
- *
- * <p> NanoHTTPD version 1.21,
- * Copyright © 2001,2005-2011 Jarno Elonen (elonen at iki.fi, http://iki.fi/elonen/)
- * and Copyright © 2010 Konstantinos Togias (info at ktogias.gr, http://ktogias.gr)
- *
- * <p><b>Features + limitations: </b><ul>
- *
- *    <li> Only one Java file </li>
- *    <li> Java 1.1 compatible </li>
- *    <li> Released as open source, Modified BSD licence </li>
- *    <li> No fixed config files, logging, authorization etc. (Implement yourself if you need them.) </li>
- *    <li> Supports parameter parsing of GET and POST methods </li>
- *    <li> Supports both dynamic content and file serving </li>
- *    <li> Supports file upload (since version 1.2, 2010) </li>
- *    <li> Never caches anything </li>
- *    <li> Doesn't limit bandwidth, request time or simultaneous connections </li>
- *    <li> Default code serves files and shows all HTTP parameters and headers</li>
- *    <li> File server supports directory listing, index.html and index.htm </li>
- *    <li> File server does the 301 redirection trick for directories without '/'</li>
- *    <li> File server supports simple skipping for files (continue download) </li>
- *    <li> File server uses current directory as a web root </li>
- *    <li> File server serves also very long files without memory overhead </li>
- *    <li> Contains a built-in list of most common mime types </li>
- *    <li> All header names are converted lowercase so they don't vary between browsers/clients </li>
- *
- * </ul>
- *
- * <p><b>Ways to use: </b><ul>
- *
- *    <li> Run as a standalone app, serves files from current directory and shows requests</li>
- *    <li> Subclass serve() and embed to your own program </li>
- *    <li> Call serveFile() from serve() with your own base directory </li>
- *
- * </ul>
- *
- * See the end of the source file for distribution license
- * (Modified BSD licence)
- */
-public class NanoHTTPD
-{
-	// ==================================================
-	// API parts
-	// ==================================================
-
-	/**
-	 * Override this to customize the server.<p>
-	 *
-	 * (By default, this delegates to serveFile() and allows directory listing.)
-	 *
-	 * @param uri	Percent-decoded URI without parameters, for example "/index.cgi"
-	 * @param method	"GET", "POST" etc.
-	 * @param parms	Parsed, percent decoded parameters from URI and, in case of POST, data.
-	 * @param header	Header entries, percent decoded
-	 * @return HTTP response, see class Response for details
-	 */
-	public Response serve( String uri, String method, Properties header, Properties parms, Properties files )
-	{
-		System.out.println( method + " '" + uri + "' " );
-
-		Enumeration e = header.propertyNames();
-		while ( e.hasMoreElements())
-		{
-			String value = (String)e.nextElement();
-			System.out.println( "  HDR: '" + value + "' = '" +
-								header.getProperty( value ) + "'" );
-		}
-		e = parms.propertyNames();
-		while ( e.hasMoreElements())
-		{
-			String value = (String)e.nextElement();
-			System.out.println( "  PRM: '" + value + "' = '" +
-								parms.getProperty( value ) + "'" );
-		}
-		e = files.propertyNames();
-		while ( e.hasMoreElements())
-		{
-			String value = (String)e.nextElement();
-			System.out.println( "  UPLOADED: '" + value + "' = '" +
-								files.getProperty( value ) + "'" );
-		}
-
-		return serveFile( uri, header, baseDir, true );
-	}
-
-	/**
-	 * HTTP response.
-	 * Return one of these from serve().
-	 */
-	public class Response
-	{
-		/**
-		 * Default constructor: response = HTTP_OK, data = mime = 'null'
-		 */
-		public Response()
-		{
-			this.status = HTTP_OK;
-		}
-
-		/**
-		 * Basic constructor.
-		 */
-		public Response( String status, String mimeType, InputStream data )
-		{
-			this.status = status;
-			this.mimeType = mimeType;
-			this.data = data;
-		}
-
-		/**
-		 * Convenience method that makes an InputStream out of
-		 * given text.
-		 */
-		public Response( String status, String mimeType, String txt )
-		{
-			this.status = status;
-			this.mimeType = mimeType;
-			try
-			{
-				this.data = new ByteArrayInputStream( txt.getBytes("UTF-8"));
-			}
-			catch ( java.io.UnsupportedEncodingException uee )
-			{
-				uee.printStackTrace();
-			}
-		}
-
-		/**
-		 * Adds given line to the header.
-		 */
-		public void addHeader( String name, String value )
-		{
-			header.put( name, value );
-		}
-
-		/**
-		 * HTTP status code after processing, e.g. "200 OK", HTTP_OK
-		 */
-		public String status;
-
-		/**
-		 * MIME type of content, e.g. "text/html"
-		 */
-		public String mimeType;
-
-		/**
-		 * Data of the response, may be null.
-		 */
-		public InputStream data;
-
-		/**
-		 * Headers for the HTTP response. Use addHeader()
-		 * to add lines.
-		 */
-		public Properties header = new Properties();
-	}
-
-	/**
-	 * Some HTTP response status codes
-	 */
-	public static final String
-		HTTP_OK = "200 OK",
-		HTTP_REDIRECT = "301 Moved Permanently",
-		HTTP_FORBIDDEN = "403 Forbidden",
-		HTTP_NOTFOUND = "404 Not Found",
-		HTTP_BADREQUEST = "400 Bad Request",
-		HTTP_INTERNALERROR = "500 Internal Server Error",
-		HTTP_NOTIMPLEMENTED = "501 Not Implemented";
-
-	/**
-	 * Common mime types for dynamic content
-	 */
-	public static final String
-		MIME_PLAINTEXT = "text/plain",
-		MIME_HTML = "text/html",
-		MIME_DEFAULT_BINARY = "application/octet-stream",
-		MIME_XML = "text/xml";
-
-	// ==================================================
-	// Socket & server code
-	// ==================================================
-
-	/**
-	 * Starts a HTTP server to given port.<p>
-	 * Throws an IOException if the socket is already in use
-	 */
-	public NanoHTTPD( File baseDir, int port ) throws IOException
-	{
-		this.baseDir = baseDir;
-		myTcpPort = port;
-		myServerSocket = new ServerSocket( myTcpPort );
-		myThread = new Thread( new Runnable()
-			{
-				public void run()
-				{
-					try
-					{
-						while( true )
-							new HTTPSession( myServerSocket.accept());
-					}
-					catch ( IOException ioe )
-					{}
-				}
-			});
-		myThread.setDaemon( true );
-		myThread.start();
-	}
-
-	/**
-	 * Stops the server.
-	 */
-	public void stop()
-	{
-		try
-		{
-			myServerSocket.close();
-			myThread.join();
-		}
-		catch ( IOException ioe ) {}
-		catch ( InterruptedException e ) {}
-	}
-
-
-	/**
-	 * Handles one session, i.e. parses the HTTP request
-	 * and returns the response.
-	 */
-	private class HTTPSession implements Runnable
-	{
-		public HTTPSession( Socket s )
-		{
-			mySocket = s;
-			Thread t = new Thread( this );
-			t.setDaemon( true );
-			t.start();
-		}
-
-		public void run()
-		{
-			try
-			{
-				InputStream is = mySocket.getInputStream();
-				if ( is == null) return;
-
-				// Read the first 8192 bytes.
-				// The full header should fit in here.
-				// Apache's default header limit is 8KB.
-				int bufsize = 8192;
-				byte[] buf = new byte[bufsize];
-				int rlen = is.read(buf, 0, bufsize);
-				if (rlen <= 0) return;
-
-				// Create a BufferedReader for parsing the header.
-				ByteArrayInputStream hbis = new ByteArrayInputStream(buf, 0, rlen);
-				BufferedReader hin = new BufferedReader( new InputStreamReader( hbis ));
-				Properties pre = new Properties();
-				Properties parms = new Properties();
-				Properties header = new Properties();
-				Properties files = new Properties();
-
-				// Decode the header into parms and header java properties
-				decodeHeader(hin, pre, parms, header);
-				String method = pre.getProperty("method");
-				String uri = pre.getProperty("uri");
-
-				long size = 0x7FFFFFFFFFFFFFFFl;
-				String contentLength = header.getProperty("content-length");
-				if (contentLength != null)
-				{
-					try { size = Integer.parseInt(contentLength); }
-					catch (NumberFormatException ex) {}
-				}
-
-				// We are looking for the byte separating header from body.
-				// It must be the last byte of the first two sequential new lines.
-				int splitbyte = 0;
-				boolean sbfound = false;
-				while (splitbyte < rlen)
-				{
-					if (buf[splitbyte] == '\r' && buf[++splitbyte] == '\n' && buf[++splitbyte] == '\r' && buf[++splitbyte] == '\n') {
-						sbfound = true;
-						break;
-					}
-					splitbyte++;
-				}
-				splitbyte++;
-
-				// Write the part of body already read to ByteArrayOutputStream f
-				ByteArrayOutputStream f = new ByteArrayOutputStream();
-				if (splitbyte < rlen) f.write(buf, splitbyte, rlen-splitbyte);
-
-				// While Firefox sends on the first read all the data fitting
-				// our buffer, Chrome and Opera sends only the headers even if
-				// there is data for the body. So we do some magic here to find
-				// out whether we have already consumed part of body, if we
-				// have reached the end of the data to be sent or we should
-				// expect the first byte of the body at the next read.
-				if (splitbyte < rlen)
-					size -= rlen - splitbyte +1;
-				else if (!sbfound || size == 0x7FFFFFFFFFFFFFFFl)
-					size = 0;
-
-				// Now read all the body and write it to f
-				buf = new byte[512];
-				while ( rlen >= 0 && size > 0 )
-				{
-					rlen = is.read(buf, 0, 512);
-					size -= rlen;
-					if (rlen > 0)
-						f.write(buf, 0, rlen);
-				}
-
-				// Get the raw body as a byte []
-				byte [] fbuf = f.toByteArray();
-
-				// Create a BufferedReader for easily reading it as string.
-				ByteArrayInputStream bin = new ByteArrayInputStream(fbuf);
-				BufferedReader in = new BufferedReader( new InputStreamReader(bin));
-
-				// If the method is POST, there may be parameters
-				// in data section, too, read it:
-				if ( method.equalsIgnoreCase( "POST" ))
-				{
-					String contentType = "";
-					String contentTypeHeader = header.getProperty("content-type");
-					StringTokenizer st = new StringTokenizer( contentTypeHeader , "; " );
-					if ( st.hasMoreTokens()) {
-						contentType = st.nextToken();
-					}
-
-					if (contentType.equalsIgnoreCase("multipart/form-data"))
-					{
-						// Handle multipart/form-data
-						if ( !st.hasMoreTokens())
-							sendError( HTTP_BADREQUEST, "BAD REQUEST: Content type is multipart/form-data but boundary missing. Usage: GET /example/file.html" );
-						String boundaryExp = st.nextToken();
-						st = new StringTokenizer( boundaryExp , "=" );
-						if (st.countTokens() != 2)
-							sendError( HTTP_BADREQUEST, "BAD REQUEST: Content type is multipart/form-data but boundary syntax error. Usage: GET /example/file.html" );
-						st.nextToken();
-						String boundary = st.nextToken();
-
-						decodeMultipartData(boundary, fbuf, in, parms, files);
-					}
-					else
-					{
-						// Handle application/x-www-form-urlencoded
-						String postLine = "";
-						char pbuf[] = new char[512];
-						int read = in.read(pbuf);
-						while ( read >= 0 && !postLine.endsWith("\r\n") )
-						{
-							postLine += String.valueOf(pbuf, 0, read);
-							read = in.read(pbuf);
-						}
-						postLine = postLine.trim();
-						decodeParms( postLine, parms );
-					}
-				}
-
-				// Ok, now do the serve()
-				Response r = serve( uri, method, header, parms, files );
-				if ( r == null )
-					sendError( HTTP_INTERNALERROR, "SERVER INTERNAL ERROR: Serve() returned a null response." );
-				else
-					sendResponse( r.status, r.mimeType, r.header, r.data );
-
-				in.close();
-				is.close();
-			}
-			catch ( IOException ioe )
-			{
-				try
-				{
-					sendError( HTTP_INTERNALERROR, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage());
-				}
-				catch ( Throwable t ) {}
-			}
-			catch ( InterruptedException ie )
-			{
-				// Thrown by sendError, ignore and exit the thread.
-			}
-		}
-
-		/**
-		 * Decodes the sent headers and loads the data into
-		 * java Properties' key - value pairs
-		**/
-		private  void decodeHeader(BufferedReader in, Properties pre, Properties parms, Properties header)
-			throws InterruptedException
-		{
-			try {
-				// Read the request line
-				String inLine = in.readLine();
-				if (inLine == null) return;
-				StringTokenizer st = new StringTokenizer( inLine );
-				if ( !st.hasMoreTokens())
-					sendError( HTTP_BADREQUEST, "BAD REQUEST: Syntax error. Usage: GET /example/file.html" );
-
-				String method = st.nextToken();
-				pre.put("method", method);
-
-				if ( !st.hasMoreTokens())
-					sendError( HTTP_BADREQUEST, "BAD REQUEST: Missing URI. Usage: GET /example/file.html" );
-
-				String uri = st.nextToken();
-
-				// Decode parameters from the URI
-				int qmi = uri.indexOf( '?' );
-				if ( qmi >= 0 )
-				{
-					decodeParms( uri.substring( qmi+1 ), parms );
-					uri = decodePercent( uri.substring( 0, qmi ));
-				}
-				else uri = decodePercent(uri);
-
-				// If there's another token, it's protocol version,
-				// followed by HTTP headers. Ignore version but parse headers.
-				// NOTE: this now forces header names lowercase since they are
-				// case insensitive and vary by client.
-				if ( st.hasMoreTokens())
-				{
-					String line = in.readLine();
-					while ( line != null && line.trim().length() > 0 )
-					{
-						int p = line.indexOf( ':' );
-						if ( p >= 0 )
-							header.put( line.substring(0,p).trim().toLowerCase(), line.substring(p+1).trim());
-						line = in.readLine();
-					}
-				}
-
-				pre.put("uri", uri);
-			}
-			catch ( IOException ioe )
-			{
-				sendError( HTTP_INTERNALERROR, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage());
-			}
-		}
-
-		/**
-		 * Decodes the Multipart Body data and put it
-		 * into java Properties' key - value pairs.
-		**/
-		private void decodeMultipartData(String boundary, byte[] fbuf, BufferedReader in, Properties parms, Properties files)
-			throws InterruptedException
-		{
-			try
-			{
-				int[] bpositions = getBoundaryPositions(fbuf,boundary.getBytes());
-				int boundarycount = 1;
-				String mpline = in.readLine();
-				while ( mpline != null )
-				{
-					if (mpline.indexOf(boundary) == -1)
-						sendError( HTTP_BADREQUEST, "BAD REQUEST: Content type is multipart/form-data but next chunk does not start with boundary. Usage: GET /example/file.html" );
-					boundarycount++;
-					Properties item = new Properties();
-					mpline = in.readLine();
-					while (mpline != null && mpline.trim().length() > 0)
-					{
-						int p = mpline.indexOf( ':' );
-						if (p != -1)
-							item.put( mpline.substring(0,p).trim().toLowerCase(), mpline.substring(p+1).trim());
-						mpline = in.readLine();
-					}
-					if (mpline != null)
-					{
-						String contentDisposition = item.getProperty("content-disposition");
-						if (contentDisposition == null)
-						{
-							sendError( HTTP_BADREQUEST, "BAD REQUEST: Content type is multipart/form-data but no content-disposition info found. Usage: GET /example/file.html" );
-						}
-						StringTokenizer st = new StringTokenizer( contentDisposition , "; " );
-						Properties disposition = new Properties();
-						while ( st.hasMoreTokens())
-						{
-							String token = st.nextToken();
-							int p = token.indexOf( '=' );
-							if (p!=-1)
-								disposition.put( token.substring(0,p).trim().toLowerCase(), token.substring(p+1).trim());
-						}
-						String pname = disposition.getProperty("name");
-						pname = pname.substring(1,pname.length()-1);
-
-						String value = "";
-						if (item.getProperty("content-type") == null) {
-							while (mpline != null && mpline.indexOf(boundary) == -1)
-							{
-								mpline = in.readLine();
-								if ( mpline != null)
-								{
-									int d = mpline.indexOf(boundary);
-									if (d == -1)
-										value+=mpline;
-									else
-										value+=mpline.substring(0,d-2);
-								}
-							}
-						}
-						else
-						{
-							if (boundarycount> bpositions.length)
-								sendError( HTTP_INTERNALERROR, "Error processing request" );
-							int offset = stripMultipartHeaders(fbuf, bpositions[boundarycount-2]);
-							String path = saveTmpFile(fbuf, offset, bpositions[boundarycount-1]-offset-4);
-							files.put(pname, path);
-							value = disposition.getProperty("filename");
-							value = value.substring(1,value.length()-1);
-							do {
-								mpline = in.readLine();
-							} while (mpline != null && mpline.indexOf(boundary) == -1);
-						}
-						parms.put(pname, value);
-					}
-				}
-			}
-			catch ( IOException ioe )
-			{
-				sendError( HTTP_INTERNALERROR, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage());
-			}
-		}
-
-		/**
-		 * Find the byte positions where multipart boundaries start.
-		**/
-		public int[] getBoundaryPositions(byte[] b, byte[] boundary)
-		{
-			int matchcount = 0;
-			int matchbyte = -1;
-			Vector matchbytes = new Vector();
-			for (int i=0; i<b.length; i++)
-			{
-				if (b[i] == boundary[matchcount])
-				{
-					if (matchcount == 0)
-						matchbyte = i;
-					matchcount++;
-					if (matchcount==boundary.length)
-					{
-						matchbytes.addElement(new Integer(matchbyte));
-						matchcount = 0;
-						matchbyte = -1;
-					}
-				}
-				else
-				{
-					i -= matchcount;
-					matchcount = 0;
-					matchbyte = -1;
-				}
-			}
-			int[] ret = new int[matchbytes.size()];
-			for (int i=0; i < ret.length; i++)
-			{
-				ret[i] = ((Integer)matchbytes.elementAt(i)).intValue();
-			}
-			return ret;
-		}
-
-		/**
-		 * Retrieves the content of a sent file and saves it
-		 * to a temporary file.
-		 * The full path to the saved file is returned.
-		**/
-		private String saveTmpFile(byte[] b, int offset, int len)
-		{
-			String path = "";
-			if (len > 0)
-			{
-				String tmpdir = System.getProperty("java.io.tmpdir");
-				try {
-					File temp = File.createTempFile("NanoHTTPD", "", new File(tmpdir));
-					OutputStream fstream = new FileOutputStream(temp);
-					fstream.write(b, offset, len);
-					fstream.close();
-					path = temp.getAbsolutePath();
-				} catch (Exception e) { // Catch exception if any
-					System.err.println("Error: " + e.getMessage());
-				}
-			}
-			return path;
-		}
-
-
-		/**
-		 * It returns the offset separating multipart file headers
-		 * from the file's data.
-		**/
-		private int stripMultipartHeaders(byte[] b, int offset)
-		{
-			int i = 0;
-			for (i=offset; i<b.length; i++)
-			{
-				if (b[i] == '\r' && b[++i] == '\n' && b[++i] == '\r' && b[++i] == '\n')
-					break;
-			}
-			return i+1;
-		}
-
-		/**
-		 * Decodes the percent encoding scheme. <br/>
-		 * For example: "an+example%20string" -> "an example string"
-		 */
-		private String decodePercent( String str ) throws InterruptedException
-		{
-			try
-			{
-				StringBuffer sb = new StringBuffer();
-				for( int i=0; i<str.length(); i++ )
-				{
-					char c = str.charAt( i );
-					switch ( c )
-					{
-						case '+':
-							sb.append( ' ' );
-							break;
-						case '%':
-							sb.append((char)Integer.parseInt( str.substring(i+1,i+3), 16 ));
-							i += 2;
-							break;
-						default:
-							sb.append( c );
-							break;
-					}
-				}
-				return sb.toString();
-			}
-			catch( Exception e )
-			{
-				sendError( HTTP_BADREQUEST, "BAD REQUEST: Bad percent-encoding." );
-				return null;
-			}
-		}
-
-		/**
-		 * Decodes parameters in percent-encoded URI-format
-		 * ( e.g. "name=Jack%20Daniels&pass=Single%20Malt" ) and
-		 * adds them to given Properties. NOTE: this doesn't support multiple
-		 * identical keys due to the simplicity of Properties -- if you need multiples,
-		 * you might want to replace the Properties with a Hashtable of Vectors or such.
-		 */
-		private void decodeParms( String parms, Properties p )
-			throws InterruptedException
-		{
-			if ( parms == null )
-				return;
-
-			StringTokenizer st = new StringTokenizer( parms, "&" );
-			while ( st.hasMoreTokens())
-			{
-				String e = st.nextToken();
-				int sep = e.indexOf( '=' );
-				if ( sep >= 0 )
-					p.put( decodePercent( e.substring( 0, sep )).trim(),
-						   decodePercent( e.substring( sep+1 )));
-			}
-		}
-
-		/**
-		 * Returns an error message as a HTTP response and
-		 * throws InterruptedException to stop further request processing.
-		 */
-		private void sendError( String status, String msg ) throws InterruptedException
-		{
-			sendResponse( status, MIME_PLAINTEXT, null, new ByteArrayInputStream( msg.getBytes()));
-			throw new InterruptedException();
-		}
-
-		/**
-		 * Sends given response to the socket.
-		 */
-		private void sendResponse( String status, String mime, Properties header, InputStream data )
-		{
-			try
-			{
-				if ( status == null )
-					throw new Error( "sendResponse(): Status can't be null." );
-
-				OutputStream out = mySocket.getOutputStream();
-				PrintWriter pw = new PrintWriter( out );
-				pw.print("HTTP/1.0 " + status + " \r\n");
-
-				if ( mime != null )
-					pw.print("Content-Type: " + mime + "\r\n");
-
-				if ( header == null || header.getProperty( "Date" ) == null )
-					pw.print( "Date: " + gmtFrmt.format( new Date()) + "\r\n");
-
-				if ( header != null )
-				{
-					Enumeration e = header.keys();
-					while ( e.hasMoreElements())
-					{
-						String key = (String)e.nextElement();
-						String value = header.getProperty( key );
-						pw.print( key + ": " + value + "\r\n");
-					}
-				}
-
-				pw.print("\r\n");
-				pw.flush();
-
-				if ( data != null )
-				{
-					byte[] buff = new byte[2048];
-					while (true)
-					{
-						int read = data.read( buff, 0, 2048 );
-						if (read <= 0)
-							break;
-						out.write( buff, 0, read );
-					}
-				}
-				out.flush();
-				out.close();
-				if ( data != null )
-					data.close();
-			}
-			catch( IOException ioe )
-			{
-				// Couldn't write? No can do.
-				try { mySocket.close(); } catch( Throwable t ) {}
-			}
-		}
-
-		private Socket mySocket;
-	}
-
-	/**
-	 * URL-encodes everything between "/"-characters.
-	 * Encodes spaces as '%20' instead of '+'.
-	 */
-	private String encodeUri( String uri )
-	{
-		String newUri = "";
-		StringTokenizer st = new StringTokenizer( uri, "/ ", true );
-		while ( st.hasMoreTokens())
-		{
-			String tok = st.nextToken();
-			if ( tok.equals( "/" ))
-				newUri += "/";
-			else if ( tok.equals( " " ))
-				newUri += "%20";
-			else
-			{
-				newUri += URLEncoder.encode( tok );
-				// For Java 1.4 you'll want to use this instead:
-				// try { newUri += URLEncoder.encode( tok, "UTF-8" ); } catch ( java.io.UnsupportedEncodingException uee ) {}
-			}
-		}
-		return newUri;
-	}
-
-	private final File baseDir;
-	private int myTcpPort;
-	private final ServerSocket myServerSocket;
-	private Thread myThread;
-
-	// ==================================================
-	// File server code
-	// ==================================================
-
-	/**
-	 * Serves file from homeDir and its' subdirectories (only).
-	 * Uses only URI, ignores all headers and HTTP parameters.
-	 */
-	public Response serveFile( String uri, Properties header, File homeDir,
-							   boolean allowDirectoryListing )
-	{
-		// Make sure we won't die of an exception later
-		if ( !homeDir.isDirectory())
-			return new Response( HTTP_INTERNALERROR, MIME_PLAINTEXT,
-								 "INTERNAL ERRROR: serveFile(): given homeDir is not a directory." );
-
-		// Remove URL arguments
-		uri = uri.trim().replace( File.separatorChar, '/' );
-		if ( uri.indexOf( '?' ) >= 0 )
-			uri = uri.substring(0, uri.indexOf( '?' ));
-
-		// Prohibit getting out of current directory
-		if ( uri.startsWith( ".." ) || uri.endsWith( ".." ) || uri.indexOf( "../" ) >= 0 )
-			return new Response( HTTP_FORBIDDEN, MIME_PLAINTEXT,
-								 "FORBIDDEN: Won't serve ../ for security reasons." );
-
-		File f = new File( homeDir, uri );
-		if ( !f.exists())
-			return new Response( HTTP_NOTFOUND, MIME_PLAINTEXT,
-								 "Error 404, file not found." );
-
-		// List the directory, if necessary
-		if ( f.isDirectory())
-		{
-			// Browsers get confused without '/' after the
-			// directory, send a redirect.
-			if ( !uri.endsWith( "/" ))
-			{
-				uri += "/";
-				Response r = new Response( HTTP_REDIRECT, MIME_HTML,
-										   "<html><body>Redirected: <a href=\"" + uri + "\">" +
-										   uri + "</a></body></html>");
-				r.addHeader( "Location", uri );
-				return r;
-			}
-
-			// First try index.html and index.htm
-			if ( new File( f, "index.html" ).exists())
-				f = new File( homeDir, uri + "/index.html" );
-			else if ( new File( f, "index.htm" ).exists())
-				f = new File( homeDir, uri + "/index.htm" );
-
-			// No index file, list the directory
-			else if ( allowDirectoryListing )
-			{
-				String[] files = f.list();
-				String msg = "<html><body><h1>Directory " + uri + "</h1><br/>";
-
-				if ( uri.length() > 1 )
-				{
-					String u = uri.substring( 0, uri.length()-1 );
-					int slash = u.lastIndexOf( '/' );
-					if ( slash >= 0 && slash  < u.length())
-						msg += "<b><a href=\"" + uri.substring(0, slash+1) + "\">..</a></b><br/>";
-				}
-
-				for ( int i=0; i<files.length; ++i )
-				{
-					File curFile = new File( f, files[i] );
-					boolean dir = curFile.isDirectory();
-					if ( dir )
-					{
-						msg += "<b>";
-						files[i] += "/";
-					}
-
-					msg += "<a href=\"" + encodeUri( uri + files[i] ) + "\">" +
-						   files[i] + "</a>";
-
-					// Show file size
-					if ( curFile.isFile())
-					{
-						long len = curFile.length();
-						msg += "  <font size=2>(";
-						if ( len < 1024 )
-							msg += len + " bytes";
-						else if ( len < 1024 * 1024 )
-							msg += len/1024 + "." + (len%1024/10%100) + " KB";
-						else
-							msg += len/(1024*1024) + "." + len%(1024*1024)/10%100 + " MB";
-
-						msg += ")</font>";
-					}
-					msg += "<br/>";
-					if ( dir ) msg += "</b>";
-				}
-				msg += "</body></html>";
-				return new Response( HTTP_OK, MIME_HTML, msg );
-			}
-			else
-			{
-				return new Response( HTTP_FORBIDDEN, MIME_PLAINTEXT,
-								 "FORBIDDEN: No directory listing." );
-			}
-		}
-
-		try
-		{
-			// Get MIME type from file name extension, if possible
-			String mime = null;
-			int dot = f.getCanonicalPath().lastIndexOf( '.' );
-			if ( dot >= 0 )
-				mime = (String)theMimeTypes.get( f.getCanonicalPath().substring( dot + 1 ).toLowerCase());
-			if ( mime == null )
-				mime = MIME_DEFAULT_BINARY;
-
-			// Support (simple) skipping:
-			long startFrom = 0;
-			String range = header.getProperty( "range" );
-			if ( range != null )
-			{
-				if ( range.startsWith( "bytes=" ))
-				{
-					range = range.substring( "bytes=".length());
-					int minus = range.indexOf( '-' );
-					if ( minus > 0 )
-						range = range.substring( 0, minus );
-					try	{
-						startFrom = Long.parseLong( range );
-					}
-					catch ( NumberFormatException nfe ) {}
-				}
-			}
-
-			FileInputStream fis = new FileInputStream( f );
-			fis.skip( startFrom );
-			Response r = new Response( HTTP_OK, mime, fis );
-			r.addHeader( "Content-length", "" + (f.length() - startFrom));
-			r.addHeader( "Content-range", "" + startFrom + "-" +
-						(f.length()-1) + "/" + f.length());
-			return r;
-		}
-		catch( IOException ioe )
-		{
-			return new Response( HTTP_FORBIDDEN, MIME_PLAINTEXT, "FORBIDDEN: Reading file failed." );
-		}
-	}
-
-	/**
-	 * Hashtable mapping (String)FILENAME_EXTENSION -> (String)MIME_TYPE
-	 */
-	private static Hashtable theMimeTypes = new Hashtable();
-	static
-	{
-		StringTokenizer st = new StringTokenizer(
-			"css		text/css "+
-			"js			text/javascript "+
-			"htm		text/html "+
-			"html		text/html "+
-			"txt		text/plain "+
-			"asc		text/plain "+
-			"gif		image/gif "+
-			"jpg		image/jpeg "+
-			"jpeg		image/jpeg "+
-			"png		image/png "+
-			"mp3		audio/mpeg "+
-			"m3u		audio/mpeg-url " +
-			"pdf		application/pdf "+
-			"doc		application/msword "+
-			"ogg		application/x-ogg "+
-			"zip		application/octet-stream "+
-			"exe		application/octet-stream "+
-			"class		application/octet-stream " );
-		while ( st.hasMoreTokens())
-			theMimeTypes.put( st.nextToken(), st.nextToken());
-	}
-
-	/**
-	 * GMT date formatter
-	 */
-	private static java.text.SimpleDateFormat gmtFrmt;
-	static
-	{
-		gmtFrmt = new java.text.SimpleDateFormat( "E, d MMM yyyy HH:mm:ss 'GMT'", Locale.US);
-		gmtFrmt.setTimeZone(TimeZone.getTimeZone("GMT"));
-	}
-
-	/**
-	 * The distribution licence
-	 */
-	private static final String LICENCE =
-		"Copyright (C) 2001,2005-2011 by Jarno Elonen <elonen at iki.fi>\n"+
-		"and Copyright (C) 2010 by Konstantinos Togias <info at ktogias.gr>\n"+
-		"\n"+
-		"Redistribution and use in source and binary forms, with or without\n"+
-		"modification, are permitted provided that the following conditions\n"+
-		"are met:\n"+
-		"\n"+
-		"Redistributions of source code must retain the above copyright notice,\n"+
-		"this list of conditions and the following disclaimer. Redistributions in\n"+
-		"binary form must reproduce the above copyright notice, this list of\n"+
-		"conditions and the following disclaimer in the documentation and/or other\n"+
-		"materials provided with the distribution. The name of the author may not\n"+
-		"be used to endorse or promote products derived from this software without\n"+
-		"specific prior written permission. \n"+
-		" \n"+
-		"THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n"+
-		"IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n"+
-		"OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n"+
-		"IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n"+
-		"INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n"+
-		"NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"+
-		"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"+
-		"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"+
-		"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"+
-		"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.";
-}
diff --git a/biz.aQute.bndlib/src/test/lib/deployer/obr/OBRAllTests.java b/biz.aQute.bndlib/src/test/lib/deployer/obr/OBRAllTests.java
deleted file mode 100644
index 6a8f769..0000000
--- a/biz.aQute.bndlib/src/test/lib/deployer/obr/OBRAllTests.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package test.lib.deployer.obr;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-public class OBRAllTests {
-
-	public static Test suite() {
-		TestSuite suite = new TestSuite(OBRAllTests.class.getName());
-		//$JUnit-BEGIN$
-		suite.addTestSuite(OBRTest.class);
-		suite.addTestSuite(OBRParseTest.class);
-		//$JUnit-END$
-		return suite;
-	}
-
-}
diff --git a/biz.aQute.bndlib/src/test/lib/deployer/obr/OBRParseTest.java b/biz.aQute.bndlib/src/test/lib/deployer/obr/OBRParseTest.java
deleted file mode 100644
index e6f5756..0000000
--- a/biz.aQute.bndlib/src/test/lib/deployer/obr/OBRParseTest.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package test.lib.deployer.obr;
-
-import java.util.*;
-import java.util.concurrent.atomic.*;
-
-import javax.xml.parsers.*;
-
-import junit.framework.*;
-import aQute.lib.deployer.obr.*;
-
-public class OBRParseTest extends TestCase {
-	
-	
-	public void testParseOBR() throws Exception {
-		final List<Resource> resources = new ArrayList<Resource>();
-		IRepositoryListener listener = new IRepositoryListener() {
-			public boolean processResource(Resource resource) {
-				resources.add(resource);
-				return true;
-			}
-
-			public boolean processReferral(String fromUrl, Referral referral, int maxDepth, int currentDepth) {
-				fail("Method processReferral should not be called from this test!");
-				return true;
-			}
-		};
-		
-		SAXParserFactory parserFactory = SAXParserFactory.newInstance();
-		SAXParser parser = parserFactory.newSAXParser();
-
-		parser.parse(OBRParseTest.class.getResourceAsStream("testobr.xml"),
-				new OBRSAXHandler("file:sample/testobr.xml", listener));
-
-		assertEquals(2, resources.size());
-		
-		Resource firstResource = resources.get(0);
-		assertEquals("org.apache.felix.shell", firstResource.getSymbolicName());
-		assertEquals("file:sample/testobr.xml", firstResource.getBaseUrl());
-		assertEquals(6, firstResource.getCapabilities().size());
-		
-		Capability lastCapability = firstResource.getCapabilities().get(5);
-		assertEquals("package", lastCapability.getName());
-		assertEquals(3, lastCapability.getProperties().size());
-		assertEquals(new Property("package", null, "org.apache.felix.shell"), lastCapability.getProperties().get(0));
-		assertEquals(new Property("uses", null, "org.osgi.framework"), lastCapability.getProperties().get(1));
-		assertEquals(new Property("version", "version", "1.0.0"), lastCapability.getProperties().get(2));
-	}
-	
-	public void testParseOBRReferral() throws Exception {
-
-		final SAXParserFactory parserFactory = SAXParserFactory.newInstance();
-
-		final List<Resource> resources = new ArrayList<Resource>();
-		IRepositoryListener listener = new IRepositoryListener() {
-			public boolean processResource(Resource resource) {
-				resources.add(resource);
-				return true;
-			}
-
-			public boolean processReferral(String fromUrl, Referral referral, int maxDepth, int currentDepth) {
-				if ("file:sample/testobr.xml".equals(referral.getUrl())) {
-					try {
-						SAXParser parser = parserFactory.newSAXParser();
-						parser.parse(OBRParseTest.class.getResourceAsStream("testobr.xml"),
-								new OBRSAXHandler("file:sample/testobr.xml", this, maxDepth, currentDepth));
-					} catch (Exception e) {
-						throw new RuntimeException(e);
-					}
-				}
-				return true;
-			}
-		};
-		
-		SAXParser parser = parserFactory.newSAXParser();
-
-		parser.parse(OBRParseTest.class.getResourceAsStream("referralobr.xml"),
-				new OBRSAXHandler("file:sample/referral.xml", listener));
-
-		assertEquals(2, resources.size());
-		
-		Resource firstResource = resources.get(0);
-		assertEquals("org.apache.felix.shell", firstResource.getSymbolicName());
-		assertEquals("file:sample/testobr.xml", firstResource.getBaseUrl());
-		assertEquals(6, firstResource.getCapabilities().size());
-		
-		Capability lastCapability = firstResource.getCapabilities().get(5);
-		assertEquals("package", lastCapability.getName());
-		assertEquals(3, lastCapability.getProperties().size());
-		assertEquals(new Property("package", null, "org.apache.felix.shell"), lastCapability.getProperties().get(0));
-		assertEquals(new Property("uses", null, "org.osgi.framework"), lastCapability.getProperties().get(1));
-		assertEquals(new Property("version", "version", "1.0.0"), lastCapability.getProperties().get(2));
-	}
-
-	public void testEarlyTermination() throws Exception {
-		SAXParserFactory parserFactory = SAXParserFactory.newInstance();
-		SAXParser parser = parserFactory.newSAXParser();
-		
-		final AtomicInteger counter = new AtomicInteger(0);
-		IRepositoryListener listener = new IRepositoryListener() {
-			public boolean processResource(Resource resource) {
-				counter.incrementAndGet();
-				return false;
-			}
-
-			public boolean processReferral(String fromUrl, Referral referral, int maxDepth, int currentDepth) {
-				fail("Method processReferral should not be called from this test!");
-				return false;
-			}
-		};
-		
-		boolean parseStopped = false;
-		try {
-			parser.parse(OBRParseTest.class.getResourceAsStream("unparseable.xml"), new OBRSAXHandler("", listener));
-			fail("Parser not stopped");
-		} catch (StopParseException e) {
-			// Expected
-			parseStopped = true;
-		}
-		
-		assertEquals(1, counter.get());
-		assertTrue(parseStopped);
-	}
-	
-	
-}
diff --git a/biz.aQute.bndlib/src/test/lib/deployer/obr/OBRTest.java b/biz.aQute.bndlib/src/test/lib/deployer/obr/OBRTest.java
deleted file mode 100644
index 37eadb3..0000000
--- a/biz.aQute.bndlib/src/test/lib/deployer/obr/OBRTest.java
+++ /dev/null
@@ -1,189 +0,0 @@
-package test.lib.deployer.obr;
-
-import java.io.File;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import junit.framework.TestCase;
-import aQute.bnd.service.RepositoryPlugin.Strategy;
-import aQute.lib.deployer.obr.OBR;
-import aQute.libg.version.Version;
-
-public class OBRTest extends TestCase {
-	
-	private OBR obr;
-	private NanoHTTPD httpd;
-
-	@Override
-	protected void setUp() throws Exception {
-		obr = new OBR();
-		obr.setLocations(new URL[] { OBRTest.class.getResource("fullobr.xml") });
-		
-		File tmpFile = File.createTempFile("cache", ".tmp");
-		tmpFile.deleteOnExit();
-		
-		obr.setCacheDirectory(new File(tmpFile.getAbsolutePath() + ".dir"));
-		
-		httpd = new NanoHTTPD(new File("test/http"), 18080);
-	}
-	
-	@Override
-	protected void tearDown() throws Exception {
-		httpd.stop();
-		
-		File[] cachedFiles = obr.getCacheDirectory().listFiles();
-		if (cachedFiles != null) {
-			for (File file : cachedFiles) {
-				file.delete();
-			}
-		}
-		obr.getCacheDirectory().delete();
-	}
-	
-	public void testSetProperties() {
-		OBR obr2 = new OBR();
-		
-		Map<String,String> props = new HashMap<String, String>();
-		props.put("location", OBRTest.class.getResource("fullobr.xml").toString());
-		props.put("cache", this.obr.getCacheDirectory().getAbsolutePath());
-		obr2.setProperties(props);
-		
-		assertEquals(1, obr2.getOBRIndexes().size());
-		assertEquals(OBRTest.class.getResource("fullobr.xml").toString(), obr2.getOBRIndexes().get(0).toString());
-		
-		assertEquals(this.obr.getCacheDirectory(), obr2.getCacheDirectory());
-	}
-	
-	public void testInvalidProperties() {
-		OBR obr2 = new OBR();
-		try {
-			obr2.setProperties(new HashMap<String, String>());
-			fail("Should throw IllegalArgumentException");
-		} catch (IllegalArgumentException e) {
-			// Expected
-		}
-	}
-	
-	public void testCacheDirectoryNotSpecified() {
-		OBR obr2 = new OBR();
-		
-		Map<String,String> props = new HashMap<String, String>();
-		props.put("location", OBRTest.class.getResource("fullobr.xml").toString());
-		obr2.setProperties(props);
-	}
-	
-	public void testGetLatest() throws Exception {
-		File[] files = obr.get("name.njbartlett.osgi.emf.minimal", "latest");
-		
-		assertNotNull(files);
-		assertEquals(1, files.length);
-		
-		assertEquals("name.njbartlett.osgi.emf.minimal-2.7.0.jar", files[0].getName());
-	}
-	
-	public void testGetAll() throws Exception {
-		File[] files = obr.get("name.njbartlett.osgi.emf.xmi", null);
-		
-		assertNotNull(files);
-		assertEquals(2, files.length);
-		
-		assertEquals("name.njbartlett.osgi.emf.xmi-2.5.0.jar", files[0].getName());
-		assertEquals("name.njbartlett.osgi.emf.xmi-2.7.0.jar", files[1].getName());
-	}
-	
-	public void testGetHttp() throws Exception {
-		File[] files = obr.get("org.example.dummy", "latest");
-
-		assertNotNull(files);
-		assertEquals(1, files.length);
-
-		assertNotNull(files[0]);
-		assertEquals("bundles_dummybundle.jar", files[0].getName());
-	}
-	
-	public void testGetBsnLowest() throws Exception {
-		File result = obr.get("name.njbartlett.osgi.emf.xmi", null, Strategy.LOWEST, null);
-		assertNotNull(result);
-		assertEquals("name.njbartlett.osgi.emf.xmi-2.5.0.jar", result.getName());
-	}
-
-	public void testGetBsnHighest() throws Exception {
-		File result = obr.get("name.njbartlett.osgi.emf.xmi", null, Strategy.HIGHEST, null);
-		assertNotNull(result);
-		assertEquals("name.njbartlett.osgi.emf.xmi-2.7.0.jar", result.getName());
-	}
-	
-	public void testGetBsnLowestWithRange() throws Exception {
-		File result = obr.get("name.njbartlett.osgi.emf.xmi", "2.5.1", Strategy.LOWEST, null);
-		assertNotNull(result);
-		assertEquals("name.njbartlett.osgi.emf.xmi-2.7.0.jar", result.getName());
-	}
-	
-	public void testGetBsnHighestWithRange() throws Exception {
-		File result = obr.get("name.njbartlett.osgi.emf.xmi", "[2.5,2.7)", Strategy.HIGHEST, null);
-		assertNotNull(result);
-		assertEquals("name.njbartlett.osgi.emf.xmi-2.5.0.jar", result.getName());
-	}
-	
-	public void testGetPackageLowest() throws Exception {
-		Map<String, String> props = new HashMap<String, String>();
-		props.put("package", "org.eclipse.emf.common");
-		
-		File result = obr.get(null, null, Strategy.LOWEST, props);
-		assertNotNull(result);
-		assertEquals("name.njbartlett.osgi.emf.minimal-2.6.1.jar", result.getName());
-	}
-
-	public void testGetPackageLowestWithRange() throws Exception {
-		Map<String, String> props = new HashMap<String, String>();
-		props.put("package", "org.eclipse.emf.common");
-		
-		File result = obr.get(null, "2.6.2", Strategy.LOWEST, props);
-		assertNotNull(result);
-		assertEquals("name.njbartlett.osgi.emf.minimal-2.7.0.jar", result.getName());
-	}
-
-	public void testGetPackageHighest() throws Exception {
-		Map<String, String> props = new HashMap<String, String>();
-		props.put("package", "org.eclipse.emf.common");
-		
-		File result = obr.get(null, null, Strategy.HIGHEST, props);
-		assertNotNull(result);
-		assertEquals("name.njbartlett.osgi.emf.minimal-2.7.0.jar", result.getName());
-	}
-
-	public void testGetPackageHighestWithRange() throws Exception {
-		Map<String, String> props = new HashMap<String, String>();
-		props.put("package", "org.eclipse.emf.common");
-		
-		File result = obr.get(null, "[2.6,2.7)", Strategy.HIGHEST, props);
-		assertNotNull(result);
-		assertEquals("name.njbartlett.osgi.emf.minimal-2.6.1.jar", result.getName());
-	}
-	
-	public void testList() throws Exception {
-		List<String> result = obr.list("name\\.njbartlett\\..*");
-		assertNotNull(result);
-		assertEquals(2, result.size());
-	}
-	
-	public void testVersions() throws Exception {
-		List<Version> result = obr.versions("name.njbartlett.osgi.emf.minimal");
-		assertEquals(2, result.size());
-		
-		assertEquals(new Version("2.6.1.v20100914-1218"), result.get(0));
-		assertEquals(new Version("2.7.0.201104130744"), result.get(1));
-	}
-	
-	public void testName() throws MalformedURLException {
-		assertEquals(OBRTest.class.getResource("fullobr.xml").toString(), obr.getName());
-		
-		OBR obr2 = new OBR();
-		obr2.setLocations(new URL[] { new URL("http://www.example.com/bundles/dummybundle.jar"), new URL("file:/Users/neil/bundles/dummy.jar") });
-		
-		assertEquals("http://www.example.com/bundles/dummybundle.jar,file:/Users/neil/bundles/dummy.jar", obr2.getName());
-	}
-}
diff --git a/biz.aQute.bndlib/src/test/lib/deployer/obr/fullobr.xml b/biz.aQute.bndlib/src/test/lib/deployer/obr/fullobr.xml
deleted file mode 100644
index 9a62b81..0000000
--- a/biz.aQute.bndlib/src/test/lib/deployer/obr/fullobr.xml
+++ /dev/null
@@ -1,553 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<?xml-stylesheet type='text/xsl' href='http://www2.osgi.org/www/obr2html.xsl'?>
-
-<repository lastmodified='20110425120125.066' name='Untitled'>
-  <resource id='name.njbartlett.osgi.emf.minimal/2.7.0.201104130744' presentationname='name.njbartlett.osgi.emf.minimal' symbolicname='name.njbartlett.osgi.emf.minimal' uri='file:bundles/name.njbartlett.osgi.emf.minimal-2.7.0.jar' version='2.7.0.201104130744'>
-    <size>
-      2005961
-    </size>
-    <capability name='bundle'>
-      <p n='manifestversion' v='2'/>
-      <p n='presentationname' v='name.njbartlett.osgi.emf.minimal'/>
-      <p n='symbolicname' v='name.njbartlett.osgi.emf.minimal'/>
-      <p n='version' t='version' v='2.7.0.201104130744'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.common'/>
-      <p n='uses' v='org.eclipse.core.runtime,org.eclipse.emf.common.util,org.osgi.framework'/>
-      <p n='version' t='version' v='2.7.0.201104130744'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.common.notify'/>
-      <p n='uses' v='org.eclipse.emf.common.util'/>
-      <p n='version' t='version' v='2.7.0.201104130744'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.common.notify.impl'/>
-      <p n='uses' v='org.eclipse.emf.common.util,org.eclipse.emf.common.notify'/>
-      <p n='version' t='version' v='2.7.0.201104130744'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.common.util'/>
-      <p n='uses' v='org.eclipse.core.runtime,org.eclipse.emf.common'/>
-      <p n='version' t='version' v='2.7.0.201104130744'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore'/>
-      <p n='uses' v='org.eclipse.emf.common.util,org.eclipse.emf.ecore.resource,org.eclipse.emf.common.notify,org.eclipse.emf.ecore.impl,org.eclipse.emf.ecore.util'/>
-      <p n='version' t='version' v='2.7.0.201104130744'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.impl'/>
-      <p n='uses' v='org.eclipse.emf.ecore.util,org.eclipse.emf.ecore,org.eclipse.emf.common.util,org.eclipse.emf.ecore.resource,org.eclipse.emf.common.notify.impl,org.eclipse.emf.common.notify,org.eclipse.emf.ecore.xml.type.util,org.eclipse.emf.common,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.ecore.plugin,org.eclipse.emf.ecore.xml.type'/>
-      <p n='version' t='version' v='2.7.0.201104130744'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.plugin'/>
-      <p n='uses' v='org.eclipse.emf.ecore.resource,org.eclipse.core.runtime,org.osgi.framework,org.eclipse.emf.ecore,org.xml.sax.helpers,org.xml.sax,org.eclipse.emf.ecore.impl,org.eclipse.core.resources,org.eclipse.emf.common,org.eclipse.emf.common.util,javax.xml.parsers,org.eclipse.emf.ecore.util,org.eclipse.emf.ecore.resource.impl'/>
-      <p n='version' t='version' v='2.7.0.201104130744'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.resource'/>
-      <p n='uses' v='org.eclipse.core.runtime.content,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.common.util,org.eclipse.emf.ecore,org.eclipse.emf.common.notify'/>
-      <p n='version' t='version' v='2.7.0.201104130744'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.resource.impl'/>
-      <p n='uses' v='org.eclipse.emf.ecore.resource,javax.crypto.spec,javax.crypto,org.eclipse.emf.common.util,org.eclipse.emf.ecore,org.eclipse.emf.ecore.util,org.eclipse.core.runtime,org.eclipse.core.runtime.content,org.eclipse.emf.common,org.eclipse.emf.ecore.plugin,org.eclipse.core.resources,org.eclipse.emf.common.notify.impl,org.eclipse.emf.common.notify,org.eclipse.emf.ecore.impl'/>
-      <p n='version' t='version' v='2.7.0.201104130744'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.xml.namespace'/>
-      <p n='uses' v='org.eclipse.emf.common.util,org.eclipse.emf.ecore.util,org.eclipse.emf.ecore'/>
-      <p n='version' t='version' v='2.7.0.201104130744'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.xml.type'/>
-      <p n='uses' v='org.eclipse.emf.ecore.util,org.eclipse.emf.ecore,org.eclipse.emf.common.util,javax.xml.datatype,javax.xml.namespace'/>
-      <p n='version' t='version' v='2.7.0.201104130744'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.xml.type.internal'/>
-      <p n='uses' v='org.eclipse.emf.ecore.xml.type,javax.xml.namespace,org.eclipse.emf.ecore.plugin,org.eclipse.emf.common.util,org.eclipse.emf.ecore.xml.type.util,javax.xml.datatype'/>
-      <p n='version' t='version' v='2.7.0.201104130744'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.xml.type.util'/>
-      <p n='uses' v='org.xml.sax,org.eclipse.emf.ecore.xml.type,javax.xml.namespace,javax.xml.datatype,org.xml.sax.helpers,org.eclipse.emf.common.util,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.ecore,org.eclipse.emf.ecore.xml.type.internal,org.eclipse.emf.ecore.plugin,org.eclipse.emf.ecore.util'/>
-      <p n='version' t='version' v='2.7.0.201104130744'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.util'/>
-      <p n='uses' v='org.eclipse.emf.common.notify,org.eclipse.emf.ecore,org.eclipse.emf.common.util,org.eclipse.emf.ecore.xml.type,org.eclipse.emf.ecore.xml.type.util,org.eclipse.emf.ecore.impl,org.eclipse.emf.common.notify.impl,org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.plugin,org.eclipse.emf.ecore.xml.namespace'/>
-      <p n='version' t='version' v='2.7.0.201104130744'/>
-    </capability>
-    <require extend='false' filter='(&(package=javax.crypto)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package javax.crypto
-    </require>
-    <require extend='false' filter='(&(package=javax.crypto.spec)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package javax.crypto.spec
-    </require>
-    <require extend='false' filter='(&(package=javax.xml.datatype)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package javax.xml.datatype
-    </require>
-    <require extend='false' filter='(&(package=javax.xml.namespace)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package javax.xml.namespace
-    </require>
-    <require extend='false' filter='(&(package=javax.xml.parsers)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package javax.xml.parsers
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.core.resources)(version>=0.0.0))' multiple='false' name='package' optional='true'>
-      Import package org.eclipse.core.resources
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.core.runtime)(version>=0.0.0))' multiple='false' name='package' optional='true'>
-      Import package org.eclipse.core.runtime
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.core.runtime.content)(version>=0.0.0))' multiple='false' name='package' optional='true'>
-      Import package org.eclipse.core.runtime.content
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.common.notify)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.common.notify
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.common.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.common.util
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.impl)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.impl
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.plugin)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.plugin
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.resource)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.resource
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.util
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.type.internal)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.xml.type.internal
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.type.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.xml.type.util
-    </require>
-    <require extend='false' filter='(&(package=org.osgi.framework)(version>=1.6.0)(!(version>=2.0.0)))' multiple='false' name='package' optional='false'>
-      Import package org.osgi.framework ;version=[1.6.0,2.0.0)
-    </require>
-    <require extend='false' filter='(&(package=org.xml.sax)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.xml.sax
-    </require>
-    <require extend='false' filter='(&(package=org.xml.sax.helpers)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.xml.sax.helpers
-    </require>
-  </resource>
-  <resource id='name.njbartlett.osgi.emf.minimal/2.6.1.v20100914-1218' presentationname='name.njbartlett.osgi.emf.minimal' symbolicname='name.njbartlett.osgi.emf.minimal' uri='file:bundles/name.njbartlett.osgi.emf.minimal-2.6.1.jar' version='2.6.1.v20100914-1218'>
-    <size>
-      2029922
-    </size>
-    <capability name='bundle'>
-      <p n='manifestversion' v='2'/>
-      <p n='presentationname' v='name.njbartlett.osgi.emf.minimal'/>
-      <p n='symbolicname' v='name.njbartlett.osgi.emf.minimal'/>
-      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.common'/>
-      <p n='uses' v='org.eclipse.core.runtime,org.eclipse.emf.common.util,org.osgi.framework'/>
-      <p n='version' t='version' v='2.6.0.v20100914-1218'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.common.notify'/>
-      <p n='uses' v='org.eclipse.emf.common.util'/>
-      <p n='version' t='version' v='2.6.0.v20100914-1218'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.common.notify.impl'/>
-      <p n='uses' v='org.eclipse.emf.common.util,org.eclipse.emf.common.notify'/>
-      <p n='version' t='version' v='2.6.0.v20100914-1218'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.common.util'/>
-      <p n='uses' v='org.eclipse.core.runtime,org.eclipse.emf.common'/>
-      <p n='version' t='version' v='2.6.0.v20100914-1218'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore'/>
-      <p n='uses' v='org.eclipse.emf.common.util,org.eclipse.emf.ecore.resource,org.eclipse.emf.common.notify,org.eclipse.emf.ecore.impl,org.eclipse.emf.ecore.util'/>
-      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.impl'/>
-      <p n='uses' v='org.eclipse.emf.ecore.util,org.eclipse.emf.ecore,org.eclipse.emf.common.util,org.eclipse.emf.ecore.resource,org.eclipse.emf.common.notify.impl,org.eclipse.emf.common.notify,org.eclipse.emf.ecore.xml.type.util,org.eclipse.emf.common,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.ecore.plugin,org.eclipse.emf.ecore.xml.type'/>
-      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.plugin'/>
-      <p n='uses' v='org.eclipse.emf.ecore.resource,org.eclipse.core.runtime,org.osgi.framework,org.eclipse.emf.ecore,org.xml.sax.helpers,org.xml.sax,org.eclipse.emf.ecore.impl,org.eclipse.core.resources,org.eclipse.emf.common,org.eclipse.emf.common.util,javax.xml.parsers,org.eclipse.emf.ecore.resource.impl'/>
-      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.resource'/>
-      <p n='uses' v='org.eclipse.core.runtime.content,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.common.util,org.eclipse.emf.ecore,org.eclipse.emf.common.notify'/>
-      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.resource.impl'/>
-      <p n='uses' v='org.eclipse.emf.ecore.resource,javax.crypto.spec,javax.crypto,org.eclipse.emf.common.util,org.eclipse.emf.ecore,org.eclipse.emf.ecore.util,org.eclipse.core.runtime,org.eclipse.core.runtime.content,org.eclipse.emf.common,org.eclipse.emf.ecore.plugin,org.eclipse.core.resources,org.eclipse.emf.common.notify.impl,org.eclipse.emf.common.notify,org.eclipse.emf.ecore.impl'/>
-      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.xml.namespace'/>
-      <p n='uses' v='org.eclipse.emf.common.util,org.eclipse.emf.ecore.util,org.eclipse.emf.ecore'/>
-      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.xml.type'/>
-      <p n='uses' v='org.eclipse.emf.ecore.util,org.eclipse.emf.ecore,org.eclipse.emf.common.util,javax.xml.datatype,javax.xml.namespace'/>
-      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.xml.type.internal'/>
-      <p n='uses' v='org.eclipse.emf.ecore.xml.type,javax.xml.namespace,org.eclipse.emf.ecore.plugin,org.eclipse.emf.common.util,org.eclipse.emf.ecore.xml.type.util,javax.xml.datatype'/>
-      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.xml.type.util'/>
-      <p n='uses' v='org.xml.sax,org.eclipse.emf.ecore.xml.type,javax.xml.datatype,javax.xml.namespace,org.xml.sax.helpers,org.eclipse.emf.common.util,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.ecore,org.eclipse.emf.ecore.xml.type.internal,org.eclipse.emf.ecore.plugin,org.eclipse.emf.ecore.util'/>
-      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.util'/>
-      <p n='uses' v='org.eclipse.emf.common.notify,org.eclipse.emf.ecore,org.eclipse.emf.common.util,org.eclipse.emf.ecore.xml.type,org.eclipse.emf.ecore.xml.type.util,org.eclipse.emf.ecore.impl,org.eclipse.emf.common.notify.impl,org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.plugin,org.eclipse.emf.ecore.xml.namespace'/>
-      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
-    </capability>
-    <require extend='false' filter='(&(package=javax.crypto)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package javax.crypto
-    </require>
-    <require extend='false' filter='(&(package=javax.crypto.spec)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package javax.crypto.spec
-    </require>
-    <require extend='false' filter='(&(package=javax.xml.datatype)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package javax.xml.datatype
-    </require>
-    <require extend='false' filter='(&(package=javax.xml.namespace)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package javax.xml.namespace
-    </require>
-    <require extend='false' filter='(&(package=javax.xml.parsers)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package javax.xml.parsers
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.core.resources)(version>=0.0.0))' multiple='false' name='package' optional='true'>
-      Import package org.eclipse.core.resources
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.core.runtime)(version>=0.0.0))' multiple='false' name='package' optional='true'>
-      Import package org.eclipse.core.runtime
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.core.runtime.content)(version>=0.0.0))' multiple='false' name='package' optional='true'>
-      Import package org.eclipse.core.runtime.content
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.common.notify)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.common.notify
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.common.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.common.util
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.impl)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.impl
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.plugin)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.plugin
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.resource)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.resource
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.util
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.type.internal)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.xml.type.internal
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.type.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.xml.type.util
-    </require>
-    <require extend='false' filter='(&(package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))' multiple='false' name='package' optional='false'>
-      Import package org.osgi.framework ;version=[1.5.0,2.0.0)
-    </require>
-    <require extend='false' filter='(&(package=org.xml.sax)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.xml.sax
-    </require>
-    <require extend='false' filter='(&(package=org.xml.sax.helpers)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.xml.sax.helpers
-    </require>
-  </resource>
-  <resource id='name.njbartlett.osgi.emf.xmi/2.5.0.v20100521-1846' presentationname='name.njbartlett.osgi.emf.xmi' symbolicname='name.njbartlett.osgi.emf.xmi' uri='file:bundles/name.njbartlett.osgi.emf.xmi-2.5.0.jar' version='2.5.0.v20100521-1846'>
-    <size>
-      357938
-    </size>
-    <capability name='bundle'>
-      <p n='manifestversion' v='2'/>
-      <p n='presentationname' v='name.njbartlett.osgi.emf.xmi'/>
-      <p n='symbolicname' v='name.njbartlett.osgi.emf.xmi'/>
-      <p n='version' t='version' v='2.5.0.v20100521-1846'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.xmi'/>
-      <p n='uses' v='org.eclipse.emf.ecore,org.w3c.dom,org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.util,org.eclipse.emf.common.util,org.eclipse.emf.common,org.xml.sax.ext,org.xml.sax,javax.xml.parsers,org.eclipse.emf.ecore.xml.type'/>
-      <p n='version' t='version' v='2.5.0.v20100521-1846'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.xmi.impl'/>
-      <p n='uses' v='org.eclipse.emf.ecore.xmi,org.eclipse.emf.ecore,org.eclipse.emf.ecore.util,org.w3c.dom,org.eclipse.emf.common.util,org.xml.sax,org.xml.sax.helpers,org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.ecore.xml.type,org.eclipse.emf.common,org.eclipse.emf.ecore.impl,org.eclipse.emf.ecore.xml.type.util,org.eclipse.emf.ecore.xmi.util,org.eclipse.emf.ecore.xml.type.internal,javax.xml.namespace,org.xml.sax.ext,javax.xml.parsers,org.eclipse.emf [...]
-      <p n='version' t='version' v='2.5.0.v20100521-1846'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.xmi.util'/>
-      <p n='uses' v='org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.util,org.eclipse.emf.ecore.xmi,org.eclipse.emf.common.util,org.eclipse.emf.common,org.eclipse.emf.ecore.xmi.impl,org.eclipse.emf.ecore.resource.impl,org.w3c.dom,org.xml.sax,org.eclipse.emf.ecore,org.eclipse.emf.ecore.impl'/>
-      <p n='version' t='version' v='2.5.0.v20100521-1846'/>
-    </capability>
-    <require extend='false' filter='(&(package=javax.xml.namespace)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package javax.xml.namespace
-    </require>
-    <require extend='false' filter='(&(package=javax.xml.parsers)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package javax.xml.parsers
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.common)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.common
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.common.notify)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.common.notify
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.common.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.common.util
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.impl)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.impl
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.resource)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.resource
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.resource.impl)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.resource.impl
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.util
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.namespace)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.xml.namespace
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.type)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.xml.type
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.type.internal)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.xml.type.internal
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.type.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.xml.type.util
-    </require>
-    <require extend='false' filter='(&(package=org.w3c.dom)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.w3c.dom
-    </require>
-    <require extend='false' filter='(&(package=org.xml.sax)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.xml.sax
-    </require>
-    <require extend='false' filter='(&(package=org.xml.sax.ext)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.xml.sax.ext
-    </require>
-    <require extend='false' filter='(&(package=org.xml.sax.helpers)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.xml.sax.helpers
-    </require>
-  </resource>
-  <resource id='name.njbartlett.osgi.emf.xmi/2.7.0.201104130744' presentationname='name.njbartlett.osgi.emf.xmi' symbolicname='name.njbartlett.osgi.emf.xmi' uri='file:bundles/name.njbartlett.osgi.emf.xmi-2.7.0.jar' version='2.7.0.201104130744'>
-    <size>
-      362154
-    </size>
-    <capability name='bundle'>
-      <p n='manifestversion' v='2'/>
-      <p n='presentationname' v='name.njbartlett.osgi.emf.xmi'/>
-      <p n='symbolicname' v='name.njbartlett.osgi.emf.xmi'/>
-      <p n='version' t='version' v='2.7.0.201104130744'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.xmi'/>
-      <p n='uses' v='org.eclipse.emf.ecore,org.w3c.dom,org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.util,org.eclipse.emf.common.util,org.eclipse.emf.common,org.xml.sax.ext,org.xml.sax,javax.xml.parsers,org.eclipse.emf.ecore.xml.type'/>
-      <p n='version' t='version' v='2.7.0.201104130744'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.xmi.impl'/>
-      <p n='uses' v='org.eclipse.emf.ecore.xmi,org.eclipse.emf.ecore,org.eclipse.emf.ecore.util,org.w3c.dom,org.eclipse.emf.common.util,org.xml.sax,org.xml.sax.helpers,org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.ecore.xml.type,org.eclipse.emf.common,org.eclipse.emf.ecore.impl,org.eclipse.emf.ecore.xml.type.util,org.eclipse.emf.ecore.xmi.util,org.eclipse.emf.ecore.xml.type.internal,javax.xml.namespace,org.xml.sax.ext,javax.xml.parsers,org.eclipse.emf [...]
-      <p n='version' t='version' v='2.7.0.201104130744'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.eclipse.emf.ecore.xmi.util'/>
-      <p n='uses' v='org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.util,org.eclipse.emf.ecore.xmi,org.eclipse.emf.common.util,org.eclipse.emf.common,org.eclipse.emf.ecore.xmi.impl,org.eclipse.emf.ecore.resource.impl,org.w3c.dom,org.xml.sax,org.eclipse.emf.ecore,org.eclipse.emf.ecore.impl'/>
-      <p n='version' t='version' v='2.7.0.201104130744'/>
-    </capability>
-    <require extend='false' filter='(&(package=javax.xml.namespace)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package javax.xml.namespace
-    </require>
-    <require extend='false' filter='(&(package=javax.xml.parsers)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package javax.xml.parsers
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.common)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.common
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.common.notify)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.common.notify
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.common.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.common.util
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.impl)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.impl
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.resource)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.resource
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.resource.impl)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.resource.impl
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.util
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.namespace)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.xml.namespace
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.type)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.xml.type
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.type.internal)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.xml.type.internal
-    </require>
-    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.type.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.eclipse.emf.ecore.xml.type.util
-    </require>
-    <require extend='false' filter='(&(package=org.w3c.dom)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.w3c.dom
-    </require>
-    <require extend='false' filter='(&(package=org.xml.sax)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.xml.sax
-    </require>
-    <require extend='false' filter='(&(package=org.xml.sax.ext)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.xml.sax.ext
-    </require>
-    <require extend='false' filter='(&(package=org.xml.sax.helpers)(version>=0.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.xml.sax.helpers
-    </require>
-  </resource>
-  <resource id='org.apache.felix.shell/1.4.2' presentationname='Apache Felix Shell Service' symbolicname='org.apache.felix.shell' uri='file:bundles/org.apache.felix.shell-1.4.2.jar' version='1.4.2'>
-    <description>
-      A simple OSGi command shell service.
-    </description>
-    <size>
-      62719
-    </size>
-    <license>
-      http://www.apache.org/licenses/LICENSE-2.0.txt
-    </license>
-    <documentation>
-      http://www.apache.org/
-    </documentation>
-    <capability name='service'>
-      <p n='service' v='org.apache.felix.shell.ShellService'/>
-    </capability>
-    <capability name='service'>
-      <p n='service' v='org.ungoverned.osgi.service.shell.ShellService'/>
-    </capability>
-    <capability name='bundle'>
-      <p n='manifestversion' v='2'/>
-      <p n='presentationname' v='Apache Felix Shell Service'/>
-      <p n='symbolicname' v='org.apache.felix.shell'/>
-      <p n='version' t='version' v='1.4.2'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.ungoverned.osgi.service.shell'/>
-      <p n='uses' v='org.osgi.framework'/>
-      <p n='version' t='version' v='1.0.0'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.osgi.service.log'/>
-      <p n='uses' v='org.osgi.framework'/>
-      <p n='version' t='version' v='1.3.0'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.apache.felix.shell'/>
-      <p n='uses' v='org.osgi.framework'/>
-      <p n='version' t='version' v='1.0.0'/>
-    </capability>
-    <require extend='false' filter='(service=org.osgi.service.startlevel.StartLevel)' multiple='true' name='service' optional='false'>
-      Import Service org.osgi.service.startlevel.StartLevel
-    </require>
-    <require extend='false' filter='(service=org.osgi.service.packageadmin.PackageAdmin)' multiple='true' name='service' optional='false'>
-      Import Service org.osgi.service.packageadmin.PackageAdmin
-    </require>
-    <require extend='false' filter='(&(package=org.apache.felix.shell)(version>=1.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.apache.felix.shell ;version=1.0.0
-    </require>
-    <require extend='false' filter='(&(package=org.osgi.framework)(version>=1.4.0))' multiple='false' name='package' optional='false'>
-      Import package org.osgi.framework ;version=1.4.0
-    </require>
-    <require extend='false' filter='(&(package=org.osgi.service.log)(version>=1.3.0))' multiple='false' name='package' optional='false'>
-      Import package org.osgi.service.log ;version=1.3.0
-    </require>
-    <require extend='false' filter='(&(package=org.osgi.service.packageadmin)(version>=1.2.0))' multiple='false' name='package' optional='false'>
-      Import package org.osgi.service.packageadmin ;version=1.2.0
-    </require>
-    <require extend='false' filter='(&(package=org.osgi.service.startlevel)(version>=1.1.0))' multiple='false' name='package' optional='false'>
-      Import package org.osgi.service.startlevel ;version=1.1.0
-    </require>
-    <require extend='false' filter='(&(package=org.ungoverned.osgi.service.shell)(version>=1.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.ungoverned.osgi.service.shell ;version=1.0.0
-    </require>
-  </resource>
-  <resource id='org.apache.felix.shell.tui/1.4.1' presentationname='Apache Felix Shell TUI' symbolicname='org.apache.felix.shell.tui' uri='file:bundles/org.apache.felix.shell.tui-1.4.1.jar' version='1.4.1'>
-    <description>
-      A simple textual user interface for Felix' shell service.
-    </description>
-    <size>
-      12740
-    </size>
-    <license>
-      http://www.apache.org/licenses/LICENSE-2.0.txt
-    </license>
-    <documentation>
-      http://felix.apache.org/site/apache-felix-shell-tui.html
-    </documentation>
-    <capability name='bundle'>
-      <p n='manifestversion' v='2'/>
-      <p n='presentationname' v='Apache Felix Shell TUI'/>
-      <p n='symbolicname' v='org.apache.felix.shell.tui'/>
-      <p n='version' t='version' v='1.4.1'/>
-    </capability>
-    <require extend='false' filter='(service=org.apache.felix.shell.ShellService)' multiple='true' name='service' optional='false'>
-      Import Service org.apache.felix.shell.ShellService
-    </require>
-    <require extend='false' filter='(&(package=org.apache.felix.shell)(version>=1.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.apache.felix.shell ;version=1.0.0
-    </require>
-    <require extend='false' filter='(&(package=org.osgi.framework)(version>=1.3.0))' multiple='false' name='package' optional='false'>
-      Import package org.osgi.framework ;version=1.3.0
-    </require>
-  </resource>
-  <resource id='org.example.dummy/1.0.0' presentationname='Dummy' symbolicname='org.example.dummy' uri='http://127.0.0.1:18080/bundles/dummybundle.jar' version='1.0.0'>
-    <capability name='bundle'>
-      <p n='manifestversion' v='2'/>
-      <p n='presentationname' v='Dummy'/>
-      <p n='symbolicname' v='org.example.dummy'/>
-      <p n='version' t='version' v='1.0.0'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.example.dummy'/>
-      <p n='version' t='version' v='1.0.0'/>
-    </capability>
-  </resource>
-</repository>
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/test/lib/deployer/obr/referralobr.xml b/biz.aQute.bndlib/src/test/lib/deployer/obr/referralobr.xml
deleted file mode 100644
index 3ab87cf..0000000
--- a/biz.aQute.bndlib/src/test/lib/deployer/obr/referralobr.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<?xml-stylesheet type='text/xsl' href='http://www2.osgi.org/www/obr2html.xsl'?>
-
-<repository lastmodified='20110525120125.066' name='Untitled'>
-  <referral url="file:sample/testobr.xml" depth="2"/>
-</repository>
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/test/lib/deployer/obr/testobr.xml b/biz.aQute.bndlib/src/test/lib/deployer/obr/testobr.xml
deleted file mode 100644
index fbd8c33..0000000
--- a/biz.aQute.bndlib/src/test/lib/deployer/obr/testobr.xml
+++ /dev/null
@@ -1,99 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<?xml-stylesheet type='text/xsl' href='http://www2.osgi.org/www/obr2html.xsl'?>
-
-<repository lastmodified='20110425120125.066' name='Untitled'>
-<resource id='org.apache.felix.shell/1.4.2' presentationname='Apache Felix Shell Service' symbolicname='org.apache.felix.shell' uri='file:bundles/org.apache.felix.shell-1.4.2.jar' version='1.4.2'>
-    <description>
-      A simple OSGi command shell service.
-    </description>
-    <size>
-      62719
-    </size>
-    <license>
-      http://www.apache.org/licenses/LICENSE-2.0.txt
-    </license>
-    <documentation>
-      http://www.apache.org/
-    </documentation>
-    <capability name='service'>
-      <p n='service' v='org.apache.felix.shell.ShellService'/>
-    </capability>
-    <capability name='service'>
-      <p n='service' v='org.ungoverned.osgi.service.shell.ShellService'/>
-    </capability>
-    <capability name='bundle'>
-      <p n='manifestversion' v='2'/>
-      <p n='presentationname' v='Apache Felix Shell Service'/>
-      <p n='symbolicname' v='org.apache.felix.shell'/>
-      <p n='version' t='version' v='1.4.2'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.ungoverned.osgi.service.shell'/>
-      <p n='uses' v='org.osgi.framework'/>
-      <p n='version' t='version' v='1.0.0'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.osgi.service.log'/>
-      <p n='uses' v='org.osgi.framework'/>
-      <p n='version' t='version' v='1.3.0'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.apache.felix.shell'/>
-      <p n='uses' v='org.osgi.framework'/>
-      <p n='version' t='version' v='1.0.0'/>
-    </capability>
-    <require extend='false' filter='(service=org.osgi.service.startlevel.StartLevel)' multiple='true' name='service' optional='false'>
-      Import Service org.osgi.service.startlevel.StartLevel
-    </require>
-    <require extend='false' filter='(service=org.osgi.service.packageadmin.PackageAdmin)' multiple='true' name='service' optional='false'>
-      Import Service org.osgi.service.packageadmin.PackageAdmin
-    </require>
-    <require extend='false' filter='(&(package=org.apache.felix.shell)(version>=1.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.apache.felix.shell ;version=1.0.0
-    </require>
-    <require extend='false' filter='(&(package=org.osgi.framework)(version>=1.4.0))' multiple='false' name='package' optional='false'>
-      Import package org.osgi.framework ;version=1.4.0
-    </require>
-    <require extend='false' filter='(&(package=org.osgi.service.log)(version>=1.3.0))' multiple='false' name='package' optional='false'>
-      Import package org.osgi.service.log ;version=1.3.0
-    </require>
-    <require extend='false' filter='(&(package=org.osgi.service.packageadmin)(version>=1.2.0))' multiple='false' name='package' optional='false'>
-      Import package org.osgi.service.packageadmin ;version=1.2.0
-    </require>
-    <require extend='false' filter='(&(package=org.osgi.service.startlevel)(version>=1.1.0))' multiple='false' name='package' optional='false'>
-      Import package org.osgi.service.startlevel ;version=1.1.0
-    </require>
-    <require extend='false' filter='(&(package=org.ungoverned.osgi.service.shell)(version>=1.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.ungoverned.osgi.service.shell ;version=1.0.0
-    </require>
-  </resource>
-  <resource id='org.apache.felix.shell.tui/1.4.1' presentationname='Apache Felix Shell TUI' symbolicname='org.apache.felix.shell.tui' uri='file:bundles/org.apache.felix.shell.tui-1.4.1.jar' version='1.4.1'>
-    <description>
-      A simple textual user interface for Felix' shell service.
-    </description>
-    <size>
-      12740
-    </size>
-    <license>
-      http://www.apache.org/licenses/LICENSE-2.0.txt
-    </license>
-    <documentation>
-      http://felix.apache.org/site/apache-felix-shell-tui.html
-    </documentation>
-    <capability name='bundle'>
-      <p n='manifestversion' v='2'/>
-      <p n='presentationname' v='Apache Felix Shell TUI'/>
-      <p n='symbolicname' v='org.apache.felix.shell.tui'/>
-      <p n='version' t='version' v='1.4.1'/>
-    </capability>
-    <require extend='false' filter='(service=org.apache.felix.shell.ShellService)' multiple='true' name='service' optional='false'>
-      Import Service org.apache.felix.shell.ShellService
-    </require>
-    <require extend='false' filter='(&(package=org.apache.felix.shell)(version>=1.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.apache.felix.shell ;version=1.0.0
-    </require>
-    <require extend='false' filter='(&(package=org.osgi.framework)(version>=1.3.0))' multiple='false' name='package' optional='false'>
-      Import package org.osgi.framework ;version=1.3.0
-    </require>
-  </resource>
- </repository>
\ No newline at end of file
diff --git a/biz.aQute.bndlib/src/test/lib/deployer/obr/unparseable.xml b/biz.aQute.bndlib/src/test/lib/deployer/obr/unparseable.xml
deleted file mode 100644
index 18862b2..0000000
--- a/biz.aQute.bndlib/src/test/lib/deployer/obr/unparseable.xml
+++ /dev/null
@@ -1,70 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<?xml-stylesheet type='text/xsl' href='http://www2.osgi.org/www/obr2html.xsl'?>
-
-<repository lastmodified='20110425120125.066' name='Untitled'>
-<resource id='org.apache.felix.shell/1.4.2' presentationname='Apache Felix Shell Service' symbolicname='org.apache.felix.shell' uri='file:bundles/org.apache.felix.shell-1.4.2.jar' version='1.4.2'>
-    <description>
-      A simple OSGi command shell service.
-    </description>
-    <size>
-      62719
-    </size>
-    <license>
-      http://www.apache.org/licenses/LICENSE-2.0.txt
-    </license>
-    <documentation>
-      http://www.apache.org/
-    </documentation>
-    <capability name='service'>
-      <p n='service' v='org.apache.felix.shell.ShellService'/>
-    </capability>
-    <capability name='service'>
-      <p n='service' v='org.ungoverned.osgi.service.shell.ShellService'/>
-    </capability>
-    <capability name='bundle'>
-      <p n='manifestversion' v='2'/>
-      <p n='presentationname' v='Apache Felix Shell Service'/>
-      <p n='symbolicname' v='org.apache.felix.shell'/>
-      <p n='version' t='version' v='1.4.2'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.ungoverned.osgi.service.shell'/>
-      <p n='uses' v='org.osgi.framework'/>
-      <p n='version' t='version' v='1.0.0'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.osgi.service.log'/>
-      <p n='uses' v='org.osgi.framework'/>
-      <p n='version' t='version' v='1.3.0'/>
-    </capability>
-    <capability name='package'>
-      <p n='package' v='org.apache.felix.shell'/>
-      <p n='uses' v='org.osgi.framework'/>
-      <p n='version' t='version' v='1.0.0'/>
-    </capability>
-    <require extend='false' filter='(service=org.osgi.service.startlevel.StartLevel)' multiple='true' name='service' optional='false'>
-      Import Service org.osgi.service.startlevel.StartLevel
-    </require>
-    <require extend='false' filter='(service=org.osgi.service.packageadmin.PackageAdmin)' multiple='true' name='service' optional='false'>
-      Import Service org.osgi.service.packageadmin.PackageAdmin
-    </require>
-    <require extend='false' filter='(&(package=org.apache.felix.shell)(version>=1.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.apache.felix.shell ;version=1.0.0
-    </require>
-    <require extend='false' filter='(&(package=org.osgi.framework)(version>=1.4.0))' multiple='false' name='package' optional='false'>
-      Import package org.osgi.framework ;version=1.4.0
-    </require>
-    <require extend='false' filter='(&(package=org.osgi.service.log)(version>=1.3.0))' multiple='false' name='package' optional='false'>
-      Import package org.osgi.service.log ;version=1.3.0
-    </require>
-    <require extend='false' filter='(&(package=org.osgi.service.packageadmin)(version>=1.2.0))' multiple='false' name='package' optional='false'>
-      Import package org.osgi.service.packageadmin ;version=1.2.0
-    </require>
-    <require extend='false' filter='(&(package=org.osgi.service.startlevel)(version>=1.1.0))' multiple='false' name='package' optional='false'>
-      Import package org.osgi.service.startlevel ;version=1.1.0
-    </require>
-    <require extend='false' filter='(&(package=org.ungoverned.osgi.service.shell)(version>=1.0.0))' multiple='false' name='package' optional='false'>
-      Import package org.ungoverned.osgi.service.shell ;version=1.0.0
-    </require>
-  </resource>
-</boom!!!>
diff --git a/biz.aQute.bndlib/src/test/make/MD5.java b/biz.aQute.bndlib/src/test/make/MD5.java
deleted file mode 100644
index e407f93..0000000
--- a/biz.aQute.bndlib/src/test/make/MD5.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package test.make;
-
-import java.io.*;
-import java.security.*;
-import java.util.*;
-
-import aQute.bnd.service.*;
-import aQute.lib.osgi.*;
-
-public class MD5 implements MakePlugin {
-
-    public Resource make(Builder builder, String source,
-            Map<String, String> arguments) throws Exception {
-        if (!arguments.get("type").equals("md5"))
-            return null;
-        source = source.substring(0,source.length()-4);
-        final File f = builder.getFile(source);
-        if (f.isFile()) {
-            return new AbstractResource(f.lastModified()) {
-                public byte[] getBytes() throws Exception {
-                    return md5(f);
-                }
-            };
-        } else
-            throw new FileNotFoundException("No such file: " + source);
-    }
-
-    private byte [] md5(File f) throws Exception {
-        MessageDigest md5 = MessageDigest.getInstance("MD5");
-        InputStream in = new FileInputStream(f);
-        try {
-            byte[] b = new byte[1000];
-            int size;
-            while ((size = in.read()) > 0) {
-                md5.update(b, 0, size);
-            }
-            return md5.digest();
-        } finally {
-            in.close();
-        }        
-    }
-}
diff --git a/biz.aQute.bndlib/src/test/packageinfo/Dummy.java b/biz.aQute.bndlib/src/test/packageinfo/Dummy.java
deleted file mode 100644
index cafef98..0000000
--- a/biz.aQute.bndlib/src/test/packageinfo/Dummy.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package test.packageinfo;
-
-
-public class Dummy {
-}
diff --git a/biz.aQute.bndlib/src/test/packageinfo/ref/DummyRef.java b/biz.aQute.bndlib/src/test/packageinfo/ref/DummyRef.java
deleted file mode 100644
index 2aceb7a..0000000
--- a/biz.aQute.bndlib/src/test/packageinfo/ref/DummyRef.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package test.packageinfo.ref;
-
-import test.packageinfo.*;
-
-public class DummyRef {
-    Dummy dummy = new Dummy();
-}
diff --git a/biz.aQute.bndlib/src/test/privateimport/PrivateImport.java b/biz.aQute.bndlib/src/test/privateimport/PrivateImport.java
deleted file mode 100644
index 478ece9..0000000
--- a/biz.aQute.bndlib/src/test/privateimport/PrivateImport.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package test.privateimport;
-
-import java.io.*;
-
-import org.osgi.framework.*;
-import org.osgi.service.cm.*;
-
-public class PrivateImport implements ConfigurationAdmin {
-
-    public Configuration createFactoryConfiguration(String factoryPid)
-            throws IOException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    public Configuration createFactoryConfiguration(String factoryPid,
-            String location) throws IOException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    public Configuration getConfiguration(String pid) throws IOException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    public Configuration getConfiguration(String pid, String location)
-            throws IOException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    public Configuration[] listConfigurations(String filter)
-            throws IOException, InvalidSyntaxException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-}
diff --git a/biz.aQute.bndlib/src/test/refer/RefersToEventAdmin.java b/biz.aQute.bndlib/src/test/refer/RefersToEventAdmin.java
deleted file mode 100644
index 9dbb4f9..0000000
--- a/biz.aQute.bndlib/src/test/refer/RefersToEventAdmin.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package test.refer;
-
-import org.osgi.service.event.*;
-
-public class RefersToEventAdmin {
-	EventAdmin acmin;
-}
diff --git a/biz.aQute.bndlib/src/test/refer/RefersToHttp.java b/biz.aQute.bndlib/src/test/refer/RefersToHttp.java
deleted file mode 100644
index 1992160..0000000
--- a/biz.aQute.bndlib/src/test/refer/RefersToHttp.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package test.refer;
-
-import org.osgi.service.http.*;
-
-public class RefersToHttp {
-	HttpService acmin;
-}
diff --git a/biz.aQute.bndlib/src/test/refer/RefersToMeasurement.java b/biz.aQute.bndlib/src/test/refer/RefersToMeasurement.java
deleted file mode 100644
index 7398ea8..0000000
--- a/biz.aQute.bndlib/src/test/refer/RefersToMeasurement.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package test.refer;
-
-import org.osgi.util.measurement.*;
-
-public class RefersToMeasurement {
-	Measurement acmin;
-}
diff --git a/biz.aQute.bndlib/src/test/signatures/Z.java b/biz.aQute.bndlib/src/test/signatures/Z.java
deleted file mode 100644
index e78bc5d..0000000
--- a/biz.aQute.bndlib/src/test/signatures/Z.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package test.signatures;
-
-import java.io.*;
-import java.util.*;
-
-class X<A> {
-}
-
-interface Y<B> {
-}
-
-public class Z<C> extends X<String> implements Y<Integer> {
-
-	public class V<D> {
-		public <E> void fooLCO(E e, C c, D d) {
-		}
-	}
-
-	public abstract class U extends Z<String> implements Cloneable, Serializable {}
-	
-	// Constructors
-	public Z() {
-	}
-
-	public Z(C c) {
-	}
-
-	// Fields
-	public X<Y<C>>				field;
-	public Z<Long>.V<Integer>	referenceToNestedClass;
-	public V<C>					vc	= new V<C>();
-
-	// Methods
-	public <T> void method() {
-	}
-
-	// Test all possible declarations
-	public <E> void foo(E e) {
-	}
-
-	public <E extends InputStream & Cloneable> void fooCI(E e) {
-	}
-
-	public <E extends InputStream & Cloneable & Serializable> void fooCII(E e) {
-	}
-
-	public <E extends Serializable & Cloneable> void fooII(E e) {
-	}
-
-	public <E extends Cloneable> void fooI(E e) {
-	}
-
-	public <E extends InputStream> void fooC(E e) {
-	}
-
-	public <E extends C> void fooP(E e) {
-	}
-
-	public <E, F> void foo(E e, F f) {
-	}
-
-	// test with variable in signature
-	public <E> void fooLC(E e, C f) {
-	}
-
-	// test wildcards
-	public Collection< ? >							wildcard_001;
-	public Collection< ? extends Cloneable>		wildcard_002;
-	public Collection< ? super Cloneable>			wildcard_003;
-	public Collection< ? extends C>					wildcard_004;
-	public Collection< ? super C>					wildcard_005;
-	public Collection< ? extends Z<C>.V<Integer>>	wildcard_006;
-	public Collection< ? super Z<C>.V<Integer>>		wildcard_007;
-	
-	
-	// test compatibility
-	public <E extends Cloneable> Collection<E> compatibility_001() {return null; }
-	public <F extends Cloneable> Collection<F> compatibility_002() {return null; }
-	public <F extends InputStream> Collection<F> compatibility_003() {return null; }
-	
-	public C[] typevarArray;
-
-}
diff --git a/biz.aQute.bndlib/src/test/top/Top.java b/biz.aQute.bndlib/src/test/top/Top.java
deleted file mode 100644
index 7356f9b..0000000
--- a/biz.aQute.bndlib/src/test/top/Top.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package test.top;
-
-public class Top {
-}
diff --git a/biz.aQute.bndlib/src/test/versionpolicy/api/EventAdmin.java b/biz.aQute.bndlib/src/test/versionpolicy/api/EventAdmin.java
deleted file mode 100644
index 4e6f455..0000000
--- a/biz.aQute.bndlib/src/test/versionpolicy/api/EventAdmin.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package test.versionpolicy.api;
-
-import aQute.bnd.annotation.*;
-
- at ProviderType
-public interface EventAdmin {
-    void post(Object o);
-}
diff --git a/biz.aQute.bndlib/src/test/versionpolicy/api/EventHandler.java b/biz.aQute.bndlib/src/test/versionpolicy/api/EventHandler.java
deleted file mode 100644
index b9d49c4..0000000
--- a/biz.aQute.bndlib/src/test/versionpolicy/api/EventHandler.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package test.versionpolicy.api;
-
-import aQute.bnd.annotation.*;
-
- at SuppressWarnings("deprecation") @UsePolicy
- at ConsumerType
-public interface EventHandler {
-    void listen(Object o);
-}
diff --git a/biz.aQute.bndlib/src/test/versionpolicy/api/package-info.java b/biz.aQute.bndlib/src/test/versionpolicy/api/package-info.java
deleted file mode 100644
index 2bdc19a..0000000
--- a/biz.aQute.bndlib/src/test/versionpolicy/api/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
- at Version("1.2.0.${build}")
- at Export(exclude=PrivateImpl.class, mandatory="a=b")
-package test.versionpolicy.api;
-
-import aQute.bnd.annotation.*;
-
diff --git a/biz.aQute.bndlib/src/test/versionpolicy/implemented/Implemented.java b/biz.aQute.bndlib/src/test/versionpolicy/implemented/Implemented.java
deleted file mode 100644
index 007f023..0000000
--- a/biz.aQute.bndlib/src/test/versionpolicy/implemented/Implemented.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package test.versionpolicy.implemented;
-
-import test.versionpolicy.api.*;
-
-public class Implemented implements EventAdmin {
-    public void post(Object o) {
-    }
-}
diff --git a/biz.aQute.bndlib/src/test/versionpolicy/implmajor/MajorImplemented.java b/biz.aQute.bndlib/src/test/versionpolicy/implmajor/MajorImplemented.java
deleted file mode 100644
index 6a08cae..0000000
--- a/biz.aQute.bndlib/src/test/versionpolicy/implmajor/MajorImplemented.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package test.versionpolicy.implmajor;
-
-import test.versionpolicy.api.EventHandler;
-
-public class MajorImplemented implements EventHandler {
-
-    public void listen(Object o) {
-    }
-
-}
diff --git a/biz.aQute.bndlib/src/test/versionpolicy/uses/Uses.java b/biz.aQute.bndlib/src/test/versionpolicy/uses/Uses.java
deleted file mode 100644
index 919479e..0000000
--- a/biz.aQute.bndlib/src/test/versionpolicy/uses/Uses.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package test.versionpolicy.uses;
-
-import test.versionpolicy.api.*;
-
-public class Uses {
-    EventAdmin admin;
-}
diff --git a/biz.aQute.bndlib/test.out b/biz.aQute.bndlib/test.out
deleted file mode 100644
index be6f94e..0000000
--- a/biz.aQute.bndlib/test.out
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version='1.0'?>
-
-<metatype:MetaData xmlns:metatype='http://www.osgi.org/xmlns/metatype/v1.1.0'>
-  <OCD name='Metatype test naming' id='test.MetatypeTest$Naming' localization='test.MetatypeTest$Naming'>
-    <AD name='Secret' id='secret' cardinality='0' required='true' type='String'/>
-    <AD name='Secret *' id='.secret' cardinality='0' required='true' type='String'/>
-    <AD name='Secret' id='_secret' cardinality='0' required='true' type='String'/>
-    <AD name='New' id='new' cardinality='0' required='true' type='String'/>
-    <AD name='New' id='$new' cardinality='0' required='true' type='String'/>
-    <AD name='A b c' id='a.b.c' cardinality='0' required='true' type='String'/>
-    <AD name='A b c' id='a_b_c' cardinality='0' required='true' type='String'/>
-    <AD name='A b *' id='.a_b' cardinality='0' required='true' type='String'/>
-    <AD name='A b' id='$$$$a_b' cardinality='0' required='true' type='String'/>
-    <AD name='A b' id='$$$$a.b' cardinality='0' required='true' type='String'/>
-    <AD name='A' id='a' cardinality='0' required='true' type='String'/>
-    <AD name='A ' id='a$' cardinality='0' required='true' type='String'/>
-    <AD name='A ' id='a$' cardinality='0' required='true' type='String'/>
-    <AD name='A ' id='a$$' cardinality='0' required='true' type='String'/>
-    <AD name='A ' id='a$.$' cardinality='0' required='true' type='String'/>
-    <AD name='A ' id='a$_$' cardinality='0' required='true' type='String'/>
-    <AD name='A ' id='a..' cardinality='0' required='true' type='String'/>
-    <AD name='Xsecret' id='secret' cardinality='0' required='true' type='String'/>
-    <AD name='X secret' id='.secret' cardinality='0' required='true' type='String'/>
-    <AD name='X secret' id='_secret' cardinality='0' required='true' type='String'/>
-    <AD name='Xnew' id='new' cardinality='0' required='true' type='String'/>
-    <AD name='X new' id='$new' cardinality='0' required='true' type='String'/>
-    <AD name='Xa b c' id='a.b.c' cardinality='0' required='true' type='String'/>
-    <AD name='Xa b c' id='a_b_c' cardinality='0' required='true' type='String'/>
-    <AD name='X a b' id='.a_b' cardinality='0' required='true' type='String'/>
-    <AD name='X a b' id='$$$$a_b' cardinality='0' required='true' type='String'/>
-    <AD name='X a b' id='$$$$a.b' cardinality='0' required='true' type='String'/>
-    <AD name='Xa' id='a' cardinality='0' required='true' type='String'/>
-    <AD name='Xa ' id='a$' cardinality='0' required='true' type='String'/>
-    <AD name='Xa ' id='a$' cardinality='0' required='true' type='String'/>
-    <AD name='Xa ' id='a$$' cardinality='0' required='true' type='String'/>
-    <AD name='Xa ' id='a$.$' cardinality='0' required='true' type='String'/>
-    <AD name='Xa ' id='a$_$' cardinality='0' required='true' type='String'/>
-    <AD name='Xa ' id='a..' cardinality='0' required='true' type='String'/>
-    <AD name='Noid' id='noid' cardinality='0' required='true' type='String'/>
-    <AD name='Nullid' id='<<NULL>>' cardinality='0' required='true' type='String'/>
-  </OCD>
-  <Designate pid='test.MetatypeTest$Naming'>
-    <Object ocdref='test.MetatypeTest$Naming'/>
-  </Designate>
-</metatype:MetaData>
\ No newline at end of file
diff --git a/biz.aQute.bndlib/test/w o r k s p a c e/cnf/build.bnd b/biz.aQute.bndlib/test/w o r k s p a c e/cnf/build.bnd
deleted file mode 100644
index 8431c94..0000000
--- a/biz.aQute.bndlib/test/w o r k s p a c e/cnf/build.bnd	
+++ /dev/null
@@ -1,2 +0,0 @@
-test=abcdef
-override=parent
diff --git a/biz.aQute.bndlib/test/w o r k s p a c e/cnf/ext/extension.bnd b/biz.aQute.bndlib/test/w o r k s p a c e/cnf/ext/extension.bnd
deleted file mode 100644
index af4f12f..0000000
--- a/biz.aQute.bndlib/test/w o r k s p a c e/cnf/ext/extension.bnd	
+++ /dev/null
@@ -1,2 +0,0 @@
-ext = true
-override = extension
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/_maven.repositories b/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/_maven.repositories
deleted file mode 100644
index d83f635..0000000
--- a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/_maven.repositories
+++ /dev/null
@@ -1,4 +0,0 @@
-#NOTE: This is an internal implementation file, its format can be changed without prior notice.
-#Wed Apr 13 12:42:00 CEST 2011
-com.springsource.org.apache.commons.logging-1.0.4.pom>com.springsource.repository.bundles.external=
-com.springsource.org.apache.commons.logging-1.0.4.jar>com.springsource.repository.bundles.external=
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.jar.lastUpdated b/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.jar.lastUpdated
deleted file mode 100644
index 0b59902..0000000
--- a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.jar.lastUpdated
+++ /dev/null
@@ -1,5 +0,0 @@
-#NOTE: This is an internal implementation file, its format can be changed without prior notice.
-#Wed Apr 13 12:42:00 CEST 2011
-http\://repository.springsource.com/maven/bundles/external/.lastUpdated=1302691320835
-http\://repository.springsource.com/maven/bundles/release/.lastUpdated=1302691318506
-http\://repository.springsource.com/maven/bundles/release/.error=
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.jar.sha1 b/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.jar.sha1
deleted file mode 100644
index 8bd9b69..0000000
--- a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-b34d071ef5281fb76a9f8c4a2543943485578861
\ No newline at end of file
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.pom b/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.pom
deleted file mode 100644
index 1fcf3ce..0000000
--- a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.pom
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-   Apache Maven 2 POM generated by Apache Ivy
-   http://ant.apache.org/ivy/
-   Apache Ivy version: 2.0.0-rc1-local-20080411224353 20080411224353
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>org.apache.commons</groupId>
-  <artifactId>com.springsource.org.apache.commons.logging</artifactId>
-  <packaging>jar</packaging>
-  <version>1.0.4</version>
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.log4j</groupId>
-      <artifactId>com.springsource.org.apache.log4j</artifactId>
-      <version>1.2.15</version>
-      <optional>true</optional>
-    </dependency>
-  </dependencies>
-</project>
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.pom.lastUpdated b/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.pom.lastUpdated
deleted file mode 100644
index b4ebc6e..0000000
--- a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.pom.lastUpdated
+++ /dev/null
@@ -1,5 +0,0 @@
-#NOTE: This is an internal implementation file, its format can be changed without prior notice.
-#Wed Apr 13 12:41:57 CEST 2011
-http\://repository.springsource.com/maven/bundles/external/.lastUpdated=1302691317770
-http\://repository.springsource.com/maven/bundles/release/.lastUpdated=1302691317425
-http\://repository.springsource.com/maven/bundles/release/.error=
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.pom.sha1 b/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.pom.sha1
deleted file mode 100644
index acf49a8..0000000
--- a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.0.4/com.springsource.org.apache.commons.logging-1.0.4.pom.sha1
+++ /dev/null
@@ -1 +0,0 @@
-2041f5ba898e62d37ea8ecb3b5a334ef1c93c5b7
\ No newline at end of file
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar.sha1 b/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar.sha1
deleted file mode 100644
index 8482d33..0000000
--- a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-7657caf2c78e1d79c74d36f2ae128a115f7cc180
\ No newline at end of file
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.pom b/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.pom
deleted file mode 100644
index 776ef02..0000000
--- a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.pom
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-   Apache Maven 2 POM generated by Apache Ivy
-   http://ant.apache.org/ivy/
-   Apache Ivy version: 2.0.0-rc1-local-20080411224353 20080411224353
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>org.apache.commons</groupId>
-  <artifactId>com.springsource.org.apache.commons.logging</artifactId>
-  <packaging>jar</packaging>
-  <version>1.1.1</version>
-  <dependencies>
-    <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>com.springsource.javax.servlet</artifactId>
-      <version>2.4.0</version>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.log4j</groupId>
-      <artifactId>com.springsource.org.apache.log4j</artifactId>
-      <version>1.2.15</version>
-      <optional>true</optional>
-    </dependency>
-  </dependencies>
-</project>
diff --git a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.pom.sha1 b/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.pom.sha1
deleted file mode 100644
index 2a03cc4..0000000
--- a/biz.aQute.bndlib/test/ws/maven1/m2/org/apache/commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.pom.sha1
+++ /dev/null
@@ -1 +0,0 @@
-30493963029f45cdd6fc0f2dd7aa4cc78e8f3329
\ No newline at end of file
diff --git a/biz.aQute.jpm/.classpath b/biz.aQute.jpm/.classpath
new file mode 100644
index 0000000..0d9c1f7
--- /dev/null
+++ b/biz.aQute.jpm/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" output="bin_test" path="test"/>
+	<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/biz.aQute.jpm/.project b/biz.aQute.jpm/.project
new file mode 100644
index 0000000..e07e354
--- /dev/null
+++ b/biz.aQute.jpm/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>biz.aQute.jpm</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>bndtools.core.bndbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>bndtools.core.bndnature</nature>
+	</natures>
+</projectDescription>
diff --git a/biz.aQute.jpm/.settings/org.eclipse.core.resources.prefs b/biz.aQute.jpm/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..f6822ac
--- /dev/null
+++ b/biz.aQute.jpm/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Mon Sep 19 11:00:09 EDT 2005
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/biz.aQute.jpm/.settings/org.eclipse.core.runtime.prefs b/biz.aQute.jpm/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..d7b5655
--- /dev/null
+++ b/biz.aQute.jpm/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Tue Dec 14 12:22:25 EST 2010
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/biz.aQute.jpm/.settings/org.eclipse.jdt.core.prefs b/biz.aQute.jpm/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..615ad9c
--- /dev/null
+++ b/biz.aQute.jpm/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,361 @@
+#Wed Nov 14 10:48:07 CET 2012
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=ignore
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=true
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/biz.aQute.jpm/.settings/org.eclipse.jdt.ui.prefs b/biz.aQute.jpm/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..f5e8897
--- /dev/null
+++ b/biz.aQute.jpm/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,61 @@
+#Fri Aug 10 13:48:46 CEST 2012
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=false
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=false
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=false
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
+cleanup_settings_version=2
+eclipse.preferences.version=1
+formatter_profile=_bnd(tools)
+formatter_settings_version=12
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=1
+org.eclipse.jdt.ui.staticondemandthreshold=1
diff --git a/biz.aQute.jpm/bnd.bnd b/biz.aQute.jpm/bnd.bnd
new file mode 100644
index 0000000..8dfaf24
--- /dev/null
+++ b/biz.aQute.jpm/bnd.bnd
@@ -0,0 +1,46 @@
+-include: .settings/org.eclipse.jdt.core.prefs
+
+javac.source 			= ${org.eclipse.jdt.core.compiler.compliance}
+javac.target 			= ${org.eclipse.jdt.core.compiler.codegen.targetPlatform}
+
+-sources: false
+
+Bundle-Description: JPM, Just another Package Manager for Java, is a package management
+  system making true the promise of Java. It allows applications to be easily installed
+  or deployed on a myriad of platforms. JPM is associated with the http://www.jpm4j.org web
+  site that hosts a well organized index to zillions of jars. Any jar that has a main
+  method can easily be installed through this program from the command line. Further, 
+  jpm supports a service model that allows programs to be started when the system boots
+  and stopped before the system exits. The command provide extensive diagnostices. To get
+  started, visit the website or type jpm help.
+ 
+Bundle-License: 				http://www.opensource.org/licenses/apache2.0.php; \
+									description="${Bundle-Copyright}"; \
+									link=LICENSE
+Bundle-Vendor: 					jpm4j.org
+Bundle-Icon: 					images/icon.png;size=64
+						
+Conditional-Package: 			aQute.libg.*, aQute.lib.*
+Bundle-Version: 				1.0.2
+
+-buildpath: aQute.libg;version=project,\
+	biz.aQute.bndlib;version=project,\
+	ee.j2se;version=${javac.ee},\
+	com.springsource.junit,\
+	org.mockito.mockito-all;version=1.9.0,\
+	aQute.library.client;version=1.0.1
+	
+
+-digests: MD5, SHA1
+
+-sub: *.bnd
+
+Bundle-Developers: \
+	pkriens; \
+		email=Peter.Kriens at aQute.biz;
+		name="Peter Kriens"; \
+		organization=aQute; \
+		organizationUrl=http://www.jpm4j.org; \
+		roles="architect,developer"; \
+      	timezone=1
+
diff --git a/biz.aQute.jpm/bnd/service.bnd b/biz.aQute.jpm/bnd/service.bnd
new file mode 100644
index 0000000..97f1365
--- /dev/null
+++ b/biz.aQute.jpm/bnd/service.bnd
@@ -0,0 +1,8 @@
+Bundle-Description: Provides the ServiceMain class that handles a command written with a \
+ static main as a service.
+Bundle-Version: 0.0.2
+Private-Package: aQute.jpm.service
+
+JPM-Service:
+JPM-Command: 
+JPM-Embedded: 
diff --git a/biz.aQute.jpm/build.xml b/biz.aQute.jpm/build.xml
new file mode 100644
index 0000000..23063e2
--- /dev/null
+++ b/biz.aQute.jpm/build.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="project" default="build"> 
+	<import file="../cnf/build.xml"/>
+</project>
diff --git a/biz.aQute.jpm/daemon.bnd b/biz.aQute.jpm/daemon.bnd
new file mode 100644
index 0000000..33f9d7a
--- /dev/null
+++ b/biz.aQute.jpm/daemon.bnd
@@ -0,0 +1,8 @@
+Bundle-Description: A test daemon, just prints out a number every 3 seconds
+Private-Package: aQute.daemon
+Main-Class: aQute.daemon.Daemon
+JPM-Service: testd
+JPM-Command: 
+JPM-Embedded: 
+
+Bundle-Version: 0.0.6
\ No newline at end of file
diff --git a/biz.aQute.jpm/images/icon.png b/biz.aQute.jpm/images/icon.png
new file mode 100644
index 0000000..7badfab
Binary files /dev/null and b/biz.aQute.jpm/images/icon.png differ
diff --git a/biz.aQute.jpm/release b/biz.aQute.jpm/release
new file mode 100644
index 0000000..57aac2e
--- /dev/null
+++ b/biz.aQute.jpm/release
@@ -0,0 +1 @@
+${system;git log -50 --oneline}
diff --git a/biz.aQute.jpm/restart.sh b/biz.aQute.jpm/restart.sh
new file mode 100755
index 0000000..e663802
--- /dev/null
+++ b/biz.aQute.jpm/restart.sh
@@ -0,0 +1,6 @@
+#!/bin/sh -e
+java -jar generated/biz.aQute.jpm.run.jar -et deinit -f
+java -jar generated/biz.aQute.jpm.run.jar -et init
+jpm -et install -f generated/biz.aQute.jpm.daemon.jar 
+jpm -et start testd
+
diff --git a/biz.aQute.jpm/run.bnd b/biz.aQute.jpm/run.bnd
new file mode 100644
index 0000000..996a652
--- /dev/null
+++ b/biz.aQute.jpm/run.bnd
@@ -0,0 +1,18 @@
+Private-Package: aQute.jpm.*
+Conditional-Package: aQute.*, org.osgi.service.*
+Include-Resource: images=images, service.jar, {release}
+
+Main-Class: 					aQute.jpm.main.Main
+JPM-Command:					jpm
+
+Bundle-Version: 1.0.0.${tstamp}
+Bundle-Icon: images/icon.png
+
+Bundle-Description: jpm4j is Just another Package Manager for Java. It stills the envy of all
+  Java developers of Ruby with their Gems, Perl with its cpan, and Python with its pips. jpm makes
+  it very easy to deploy Java applications on a myriad of platforms. This program is the
+  command line application that performs the front end of the https://www.jpm4j.org website. It
+  provides full access to the repository index (i.e. jpm find osgi), it can be used
+  to install, etc. Use jpm help to see all the commands.
+  
+Bundle-DocURL: https://www.jpm4j.org/#/md/jpm
diff --git a/biz.aQute.jpm/src/aQute/daemon/Daemon.java b/biz.aQute.jpm/src/aQute/daemon/Daemon.java
new file mode 100644
index 0000000..dee6455
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/daemon/Daemon.java
@@ -0,0 +1,19 @@
+package aQute.daemon;
+
+public class Daemon {
+
+	public static void main(String args[]) throws Exception {
+		int n = 1;
+		int inc = 1;
+		if (args.length > 0)
+			inc = Integer.parseInt(args[0]);
+		if (args.length > 1)
+			n = Integer.parseInt(args[1]);
+
+		while (true) {
+			System.out.println("count " + n);
+			n += inc;
+			Thread.sleep(3000);
+		}
+	}
+}
diff --git a/biz.aQute.jpm/src/aQute/jpm/lib/ArtifactData.java b/biz.aQute.jpm/src/aQute/jpm/lib/ArtifactData.java
new file mode 100644
index 0000000..3dfa04b
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/lib/ArtifactData.java
@@ -0,0 +1,33 @@
+package aQute.jpm.lib;
+
+import java.util.*;
+
+import aQute.struct.*;
+
+public class ArtifactData extends struct {
+	public byte[]		sha;
+	public long			time			= System.currentTimeMillis();
+	public CommandData	command;
+	public ServiceData	service;
+	public String		error;
+
+	public String		name;
+	public String		mainClass;
+	public String		description;
+	public List<String>	dependencies	= new ArrayList<String>();		// shas
+	public String		title;
+	boolean				busy			= false;
+	public String		file;
+	public String		coordinates;
+
+	synchronized void done() {
+		busy = false;
+		notifyAll();
+	}
+
+	public synchronized void sync() throws InterruptedException {
+		while (busy)
+			wait();
+	}
+
+}
diff --git a/biz.aQute.jpm/src/aQute/jpm/lib/CommandData.java b/biz.aQute.jpm/src/aQute/jpm/lib/CommandData.java
new file mode 100644
index 0000000..1c48171
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/lib/CommandData.java
@@ -0,0 +1,28 @@
+package aQute.jpm.lib;
+
+import java.util.*;
+
+import aQute.lib.data.*;
+import aQute.struct.*;
+
+public class CommandData extends struct {
+	public long			time			= System.currentTimeMillis();
+	public String		name;
+	public String		title;
+	@AllowNull
+	public String		description;
+	public boolean		force;
+	@AllowNull
+	public String		jvmArgs			= "";
+
+	public String		main;
+
+	public List<String>	dependencies	= new ArrayList<String>();
+	public boolean		installed;
+	public byte[]		sha;
+	public String		bin;
+	public String		java;
+	public String		coordinates;
+	public boolean		trace;
+
+}
diff --git a/biz.aQute.jpm/src/aQute/jpm/lib/JustAnotherPackageManager.java b/biz.aQute.jpm/src/aQute/jpm/lib/JustAnotherPackageManager.java
new file mode 100644
index 0000000..afa6810
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/lib/JustAnotherPackageManager.java
@@ -0,0 +1,963 @@
+package aQute.jpm.lib;
+
+import static aQute.lib.io.IO.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.net.*;
+import java.security.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.jar.*;
+import java.util.regex.*;
+
+import aQute.bnd.build.*;
+import aQute.bnd.header.*;
+import aQute.bnd.version.*;
+import aQute.jpm.platform.*;
+import aQute.lib.base64.*;
+import aQute.lib.converter.*;
+import aQute.lib.hex.*;
+import aQute.lib.io.*;
+import aQute.lib.json.*;
+import aQute.libg.cryptography.*;
+import aQute.library.remote.*;
+import aQute.service.library.*;
+import aQute.service.library.Library.Phase;
+import aQute.service.library.Library.Program;
+import aQute.service.library.Library.Revision;
+import aQute.service.library.Library.RevisionRef;
+import aQute.service.reporter.*;
+import aQute.struct.*;
+
+/**
+ * JPM is the Java package manager. It manages a local repository in the user
+ * global directory and/or a global directory. This class is the main entry point
+ * for the command line. This program maintains a repository, a list of
+ * installed commands, and a list of installed service. It provides the commands
+ * to changes these resources. All information is kept in a platform specific
+ * area. However, the layout of this area is standardized.
+ * 
+ * <pre>
+ * 	platform/
+ *      check									check for write access
+ *      repo/                              		repository
+ *        <bsn>/                     		bsn directory
+ *          <bsn>-<version>.jar		jar file
+ *      service/                               All service
+ *        <service>/                      A service
+ *        	data								Service data (JSON)
+ *          wdir/								Working dir
+ *          lock								Lock file (if running, contains port)
+ *      commands/
+ *        <command>						Command data (JSON)
+ * </pre>
+ * 
+ * For each service, the platform must also have a user writable directory used
+ * for working dir, lock, and logging.
+ * 
+ * <pre>
+ *   platform var/
+ *       wdir/									Working dir
+ *       lock									Lock file (exists only when running, contains UDP port)
+ * </pre>
+ */
+
+public class JustAnotherPackageManager {
+	static JSONCodec	codec			= new JSONCodec();
+	static Pattern		BSN_P			= Pattern
+												.compile(
+														"([-a-z0-9_]+(?:\\.[-a-z0-9_]+)+)(?:@([0-9]+(?:\\.[0-9]+(?:\\.[0-9]+(?:\\.[-_a-z0-9]+)?)?)?))?",
+														Pattern.CASE_INSENSITIVE);
+	static Pattern		COORD_P			= Pattern
+												.compile(
+														"([-a-z0-9_.]+):([-a-z0-9_.]+)(?::([-a-z0-9_.]+))?(?:@([-a-z0-9._]+))?",
+														Pattern.CASE_INSENSITIVE);
+	static Pattern		URL_P			= Pattern.compile("([a-z]{3,6}:/.*)", Pattern.CASE_INSENSITIVE);
+	static Pattern		CMD_P			= Pattern.compile("([a-z_][a-z\\d_]*)", Pattern.CASE_INSENSITIVE);
+	static Pattern		SHA_P			= Pattern.compile("(?:sha:)?([a-f0-9]{40,40})", Pattern.CASE_INSENSITIVE);
+	static Executor		executor;
+
+	File				homeDir;
+	File				binDir;
+	File				repoDir;
+	File				commandDir;
+	File				serviceDir;
+	File				service;
+	Platform			platform;
+	RemoteLibrary		library			= new RemoteLibrary(null);
+	Reporter			reporter;
+	final List<Service>	startedByDaemon	= new ArrayList<Service>();
+
+	/**
+	 * Constructor
+	 * 
+	 * @throws IOException
+	 */
+	public JustAnotherPackageManager(Reporter reporter) throws IOException {
+		this.reporter = reporter;
+		setPlatform(Platform.getPlatform(reporter));
+	}
+
+	public boolean hasAccess() {
+		File file = new File(homeDir, "check");
+		try {
+			store("", file);
+			return true;
+		}
+		catch (Exception e) {
+			return false;
+		}
+	}
+
+	public List<ServiceData> getServices() throws Exception {
+		List<ServiceData> result = new ArrayList<ServiceData>();
+		for (File sdir : serviceDir.listFiles()) {
+			File dataFile = new File(sdir, "data");
+			ServiceData data = getData(ServiceData.class, dataFile);
+			result.add(data);
+		}
+		return result;
+	}
+
+	public List<CommandData> getCommands() throws Exception {
+		List<CommandData> result = new ArrayList<CommandData>();
+		for (File f : commandDir.listFiles()) {
+			CommandData data = getData(CommandData.class, f);
+			if (data != null)
+				result.add(data);
+		}
+		return result;
+	}
+
+	public CommandData getCommand(String name) throws Exception {
+		File f = new File(commandDir, name);
+		if (!f.isFile())
+			return null;
+
+		return getData(CommandData.class, f);
+	}
+
+	/**
+	 * Garbage collect any service and commands.
+	 * 
+	 * @throws Exception
+	 */
+	public void gc() throws Exception {
+		for (File cmd : commandDir.listFiles()) {
+			CommandData data = getData(CommandData.class, cmd);
+			// File repoFile = new File(data.repoFile);
+			// if (!repoFile.isFile()) {
+			// platform.remove(data);
+			// cmd.delete();
+			// }
+		}
+
+		for (File service : serviceDir.listFiles()) {
+			File dataFile = new File(service, "data");
+
+			ServiceData data = getData(ServiceData.class, dataFile);
+
+			// if (!repoFile.isFile()) {
+			// Service s = getService(service.getName());
+			// s.stop();
+			// if (data.work != null)
+			// IO.delete(new File(data.work));
+			// if (data.sdir != null)
+			// IO.delete(new File(data.sdir));
+			// if (data.log != null)
+			// IO.delete(new File(data.log));
+			// platform.remove(data);
+			// IO.delete(service);
+			// }
+		}
+	}
+
+	/**
+	 * Remove the JPM area.
+	 * 
+	 * @return
+	 * @throws Exception
+	 */
+
+	public String deinit(boolean force) throws Exception {
+		for ( CommandData d : getCommands())  {
+			reporter.trace("delete cmd %s", d.name);
+			deleteCommand(d.name);
+		}
+		
+		for ( ServiceData sd : getServices()) {
+			reporter.trace("delete service %s", sd.name);
+			Service s = getService(sd.name);
+			if ( s != null)
+				s.remove();
+		}
+		
+		
+		reporter.trace("delete repo");
+		IO.delete(repoDir);
+		gc(); 
+		reporter.trace("delete repo, command, and service dir");
+		IO.delete(repoDir);
+		IO.delete(commandDir);
+		IO.delete(serviceDir);
+		return null;
+	}
+
+	/**
+	 * @param data
+	 * @param target
+	 * @throws Exception
+	 * @throws IOException
+	 */
+	public String createService(ServiceData data) throws Exception, IOException {
+
+		File sdir = new File(serviceDir, data.name);
+		if (!sdir.exists() && !sdir.mkdirs()) {
+			throw new IOException("Could not create directory " + data.sdir);
+		}
+		data.sdir = sdir.getAbsolutePath();
+
+		File lock = new File(data.sdir, "lock");
+		data.lock = lock.getAbsolutePath();
+
+		if (data.work == null)
+			data.work = new File(data.sdir, "work").getAbsolutePath();
+		if (data.user == null)
+			data.user = platform.user();
+
+		if (data.user == null)
+			data.user = "root";
+
+		new File(data.work).mkdir();
+
+		if (data.log == null)
+			data.log = new File(data.sdir, "log").getAbsolutePath();
+
+		// TODO
+		// if (Data.validate(data) != null)
+		// return "Invalid service data: " + Data.validate(data);
+
+		if (service == null)
+			throw new RuntimeException(
+					"Missing biz.aQute.jpm.service in repo, should have been installed by init, try reiniting");
+
+		data.serviceLib = service.getAbsolutePath();
+
+		platform.chown(data.user, true, new File(data.sdir));
+
+		String s = platform.createService(data, null);
+		if (s == null)
+			storeData(new File(data.sdir, "data"), data);
+		return s;
+	}
+
+	/**
+	 * @param data
+	 * @param target
+	 * @throws Exception
+	 * @throws IOException
+	 */
+	public String createCommand(CommandData data) throws Exception, IOException {
+
+		// TODO
+		// if (Data.validate(data) != null)
+		// return "Invalid command data: " + Data.validate(data);
+
+		if (binDir != null)
+			data.bin = new File(binDir, data.name).getAbsolutePath();
+
+		Map<String,String> map = null;
+		if ( data.trace ) {
+			map = new HashMap<String,String>();
+			map.put("java.security.manager", "aQute.jpm.service.TraceSecurityManager");
+			reporter.trace("tracing");
+		}
+		String s = platform.createCommand(data, map, service.getAbsolutePath());
+		if (s == null)
+			storeData(new File(commandDir, data.name), data);
+		return s;
+	}
+
+	public void deleteCommand(String name) throws Exception {
+		CommandData cmd = getCommand(name);
+		if (cmd == null)
+			throw new IllegalArgumentException("No such command " + name);
+
+		platform.deleteCommand(cmd);
+		File tobedel = new File(commandDir, name);
+		IO.deleteWithException(tobedel);
+	}
+
+	public Service getService(String service) throws Exception {
+		File base = new File(serviceDir, service);
+		File dataFile = new File(base, "data");
+		if (!dataFile.isFile())
+			return null;
+
+		ServiceData data = getData(ServiceData.class, dataFile);
+		return new Service(this, data);
+	}
+
+	/**
+	 * Verify that the jar file is correct. This also verifies ok when there are
+	 * no checksums or.
+	 * 
+	 * @throws IOException
+	 */
+	static Pattern	MANIFEST_ENTRY	= Pattern.compile("(META-INF/[^/]+)|(.*/)");
+
+	public String verify(JarFile jar, String... algorithms) throws IOException {
+		if (algorithms == null || algorithms.length == 0)
+			algorithms = new String[] {
+					"MD5", "SHA"
+			};
+		else if (algorithms.length == 1 && algorithms[0].equals("-"))
+			return null;
+
+		try {
+			Manifest m = jar.getManifest();
+			if (m.getEntries().isEmpty())
+				return "No name sections";
+
+			for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements();) {
+				JarEntry je = e.nextElement();
+				if (MANIFEST_ENTRY.matcher(je.getName()).matches())
+					continue;
+
+				Attributes nameSection = m.getAttributes(je.getName());
+				if (nameSection == null)
+					return "No name section for " + je.getName();
+
+				for (String algorithm : algorithms) {
+					try {
+						MessageDigest md = MessageDigest.getInstance(algorithm);
+						String expected = nameSection.getValue(algorithm + "-Digest");
+						if (expected != null) {
+							byte digest[] = Base64.decodeBase64(expected);
+							copy(jar.getInputStream(je), md);
+							if (!Arrays.equals(digest, md.digest()))
+								return "Invalid digest for " + je.getName() + ", " + expected + " != "
+										+ Base64.encodeBase64(md.digest());
+						} else
+							System.out.println("could not find digest for " + algorithm + "-Digest");
+					}
+					catch (NoSuchAlgorithmException nsae) {
+						return "Missing digest algorithm " + algorithm;
+					}
+				}
+			}
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+			return "Failed to verify due to exception: " + e.getMessage();
+		}
+		return null;
+	}
+
+	/**
+	 * @param clazz
+	 * @param dataFile
+	 * @return
+	 * @throws Exception
+	 */
+
+	private <T> T getData(Class<T> clazz, File dataFile) throws Exception {
+		try {
+			return codec.dec().from(dataFile).get(clazz);
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+			System.out.println("Cannot read data file "+dataFile+": " + IO.collect(dataFile));
+			return null;
+		}
+	}
+
+	private void storeData(File dataFile, Object o) throws Exception {
+		codec.enc().to(dataFile).put(o);
+	}
+
+	public void setPlatform(Platform plf) throws IOException {
+		this.platform = plf;
+		if (homeDir == null)
+			homeDir = platform.getGlobal();
+
+		initDirs();
+	}
+
+	void initDirs() throws IOException {
+		if (!homeDir.exists() && !homeDir.mkdirs()) {
+			throw new ExceptionInInitializerError("Could not create directory " + homeDir);
+		}
+
+		repoDir = IO.getFile(homeDir, "repo");
+		if (!repoDir.exists() && !repoDir.mkdirs()) {
+			throw new ExceptionInInitializerError("Could not create directory " + repoDir);
+		}
+
+		commandDir = new File(homeDir, "commands");
+		serviceDir = new File(homeDir, "service");
+		commandDir.mkdir();
+		serviceDir.mkdir();
+		service = new File(repoDir, "service.jar");
+		if (!service.isFile()) {
+			init();
+		}
+	}
+
+	public ArtifactData parse(File source) throws Exception {
+		assert source.isFile();
+
+		JarFile jar = new JarFile(source);
+		try {
+			ArtifactData artifact = new ArtifactData();
+			artifact.sha = SHA1.digest(source).digest();
+
+			Manifest m = jar.getManifest();
+			Attributes main = m.getMainAttributes();
+			String name = main.getValue("Bundle-SymbolicName");
+			String version = main.getValue("Bundle-Version");
+			if (version != null)
+				name += "-" + version;
+
+			artifact.name = name;
+
+			artifact.mainClass = main.getValue("Main-Class");
+			artifact.description = main.getValue("Bundle-Description");
+			artifact.title = main.getValue("JPM-Name");
+
+			List<ArtifactData> dependencies = new ArrayList<ArtifactData>();
+			{
+				Parameters requires = OSGiHeader.parseHeader(main.getValue("JPM-Classpath"));
+				List<DownloadBlocker> blockers = new ArrayList<DownloadBlocker>();
+
+				for (Map.Entry<String,Attrs> e : requires.entrySet()) {
+					String key = e.getKey();
+					String v = e.getValue().get("version");
+					if (aQute.bnd.osgi.Verifier.isBsn(e.getKey()) && aQute.bnd.osgi.Verifier.isVersion(v)) {
+						key = Library.OSGI_GROUP + ":" + key + ":" + v;
+					}
+					reporter.trace("searching %s", key);
+					ArtifactData candidate = getCandidate(key, false);
+
+					if (candidate == null) {
+						reporter.error("Missing dependency: %s", key);
+					} else {
+						reporter.trace("found %s", candidate);
+						dependencies.add(candidate);
+					}
+				}
+
+				for (ArtifactData data : dependencies) {
+					data.sync();
+					if (data.error != null) {
+						reporter.error("Download of %s failed: %s", data.name, data.error);
+					} else {
+						reporter.trace("adding dependency %s", data.file);
+						artifact.dependencies.add(data.file);
+					}
+				}
+			}
+
+			{
+				Parameters service = OSGiHeader.parseHeader(main.getValue("JPM-Service"));
+				if (service.size() > 1)
+					reporter.error("Only one service can be specified");
+				for (Map.Entry<String,Attrs> e : service.entrySet()) {
+					Attrs attrs = e.getValue();
+					ServiceData data = new ServiceData();
+					data.name = e.getKey();
+					doService(attrs, data, artifact);
+					data.name = e.getKey();
+					artifact.service = data;
+				}
+				reporter.trace("service %s", artifact.service);
+			}
+			{
+				Parameters command = OSGiHeader.parseHeader(main.getValue("JPM-Command"));
+				if (command.size() > 1)
+					reporter.error("Only one command can be specified");
+				for (Map.Entry<String,Attrs> e : command.entrySet()) {
+					Attrs attrs = e.getValue();
+					CommandData data = new CommandData();
+					doCommand(attrs, data, artifact);
+					data.name = e.getKey();
+					artifact.command = data;
+				}
+				reporter.trace("commands %s", artifact.command);
+			}
+
+			reporter.trace("returning " + artifact);
+			return artifact;
+		}
+		finally {
+			jar.close();
+		}
+
+	}
+
+	private void doCommand(Attrs attrs, CommandData data, ArtifactData artifact) {
+		data.sha = artifact.sha;
+		data.description = artifact.description;
+		if (attrs.containsKey("jvmargs"))
+			data.jvmArgs = attrs.get("jvmargs");
+		data.main = artifact.mainClass;
+		data.title = attrs.get("title");
+
+		if (data.title != null)
+			data.title = artifact.title;
+
+		if (data.title != null)
+			data.title = data.name;
+
+		data.dependencies = artifact.dependencies;
+	}
+
+	private void doService(Attrs attrs, ServiceData data, ArtifactData artifact) throws Exception {
+		doCommand(attrs, data, artifact);
+		data.user = platform.user();
+		if (attrs.containsKey("args"))
+			data.args = attrs.get("args");
+	}
+
+	/**
+	 * This is called when JPM runs in the background to start jobs
+	 * 
+	 * @throws Exception
+	 */
+	public void daemon() throws Exception {
+		Runtime.getRuntime().addShutdownHook(new Thread("Daemon shutdown") {
+			public void run() {
+
+				for (Service service : startedByDaemon) {
+					try {
+						System.err.println("Stopping " + service);
+						service.stop();
+						System.err.println("Stopped " + service);
+					}
+					catch (Exception e) {
+						// Ignore
+					}
+				}
+			}
+		});
+		List<ServiceData> services = getServices();
+		Map<String,ServiceData> map = new HashMap<String,ServiceData>();
+		for (ServiceData d : services) {
+			map.put(d.name, d);
+		}
+		List<ServiceData> start = new ArrayList<ServiceData>();
+		Set<ServiceData> set = new HashSet<ServiceData>();
+		for (ServiceData sd : services) {
+			checkStartup(map, start, sd, set);
+		}
+
+		if (start.isEmpty())
+			System.out.println("No services to start");
+
+		for (ServiceData sd : start) {
+			try {
+				Service service = getService(sd.name);
+				System.err.println("Starting " + service);
+				String result = service.start();
+				if (result != null)
+					System.err.println("Started error " + result);
+				else
+					startedByDaemon.add(service);
+				System.err.println("Started " + service);
+			}
+			catch (Exception e) {
+				System.err.println("Cannot start daemon " + sd.name);
+			}
+		}
+
+		while (true) {
+			for (Service sd : startedByDaemon) {
+				try {
+					if (!sd.isRunning()) {
+						System.err.println("Starting due to failure " + sd);
+						String result = sd.start();
+						if (result != null)
+							System.err.println("Started error " + result);
+					}
+				}
+				catch (Exception e) {
+					System.err.println("Cannot start daemon " + sd);
+				}
+			}
+			Thread.sleep(10000);
+		}
+
+	}
+
+	private void checkStartup(Map<String,ServiceData> map, List<ServiceData> start, ServiceData sd,
+			Set<ServiceData> cyclic) {
+		if (sd.after.isEmpty() || start.contains(sd))
+			return;
+
+		if (cyclic.contains(sd)) {
+			System.err.println("Cyclic dependency for " + sd.name);
+			return;
+		}
+
+		cyclic.add(sd);
+
+		for (String dependsOn : sd.after) {
+			if (dependsOn.equals("boot"))
+				continue;
+
+			ServiceData deps = map.get(dependsOn);
+			if (deps == null) {
+				System.err.println("No such service " + dependsOn + " but " + sd.name + " depends on it");
+			} else {
+				checkStartup(map, start, deps, cyclic);
+			}
+		}
+		start.add(sd);
+	}
+
+	public void register(boolean user) throws Exception {
+		platform.installDaemon(user);
+	}
+
+	public ArtifactData putAsync(final URI uri) {
+		final ArtifactData data = new ArtifactData();
+		data.busy = true;
+		Runnable r = new Runnable() {
+
+			public void run() {
+				try {
+					put(uri, data);
+				}
+				catch (Throwable e) {
+					data.error = e.toString();
+				}
+				finally {
+					data.done();
+				}
+			}
+
+		};
+		getExecutor().execute(r);
+		return data;
+	}
+
+	public ArtifactData put(final URI uri) throws Exception {
+		final ArtifactData data = new ArtifactData();
+		put(uri, data);
+		return data;
+	}
+
+	void put(final URI uri, ArtifactData data) throws Exception {
+		File tmp = createTempFile(repoDir, "mtp", ".whatever");
+		tmp.deleteOnExit();
+		try {
+			copy(uri.toURL(), tmp);
+			byte[] sha = SHA1.digest(tmp).digest();
+			reporter.trace("SHA %s %s", uri, Hex.toHexString(sha));
+			ArtifactData existing = get(sha);
+			if (existing == null) {
+				File meta = new File(repoDir, Hex.toHexString(sha) + ".json");
+				File file = new File(repoDir, Hex.toHexString(sha));
+				rename(tmp, file);
+				existing = parse(file);
+				existing.file = file.getAbsolutePath();
+				existing.sha = sha;
+				codec.enc().to(meta).put(existing);
+			}
+			xcopy(existing, data);
+			reporter.trace("TD = " + data);
+		}
+		finally {
+			tmp.delete();
+		}
+	}
+
+	public ArtifactData get(byte[] sha) throws Exception {
+		String name = Hex.toHexString(sha);
+		File data = new File(repoDir, name + ".json");
+		if (data.isFile()) {
+			ArtifactData artifact = codec.dec().from(data).get(ArtifactData.class);
+			artifact.file = new File(repoDir, name).getAbsolutePath();
+			return artifact;
+		} else
+			return null;
+	}
+
+	public List<Revision> filter(Collection<Revision> list, EnumSet<Library.Phase> phases) {
+		List<Revision> filtered = new ArrayList<Library.Revision>();
+		for (Revision r : list)
+			if (phases.contains(r.phase))
+				filtered.add(r);
+
+		return filtered;
+	}
+
+	public Map<String,Revision> latest(Collection<Revision> list) {
+		Map<String,Revision> programs = new HashMap<String,Library.Revision>();
+
+		for (Revision r : list) {
+			String coordinates = r.groupId + ":" + r.artifactId;
+			if (r.classifier != null)
+				coordinates += ":" + r.classifier;
+
+			if (r.groupId.equals(Library.SHA_GROUP))
+				continue;
+
+			Revision current = programs.get(coordinates);
+			if (current == null)
+				programs.put(coordinates, r);
+			else {
+				// who is better?
+				if (compare(r, current) >= 0)
+					programs.put(coordinates, r);
+			}
+		}
+		return programs;
+	}
+
+	private int compare(Revision a, Revision b) {
+		if (Arrays.equals(a._id, b._id))
+			return 0;
+
+		Version va = getVersion(a);
+		Version vb = getVersion(b);
+		int n = va.compareTo(vb);
+		if (n != 0)
+			return n;
+
+		if (a.created != b.created)
+			return a.created > b.created ? 1 : -1;
+
+		for (int i = 0; i < a._id.length; i++)
+			if (a._id[i] != b._id[i])
+				return a._id[i] > b._id[i] ? 1 : -1;
+
+		return 0;
+	}
+
+	private Version getVersion(Revision a) {
+		if (a.qualifier != null)
+			return new Version(a.baseline + "." + a.qualifier);
+		return new Version(a.baseline);
+	}
+
+	public String getCoordinates(Revision r) {
+		StringBuilder sb = new StringBuilder(r.groupId).append(":").append(r.artifactId).append(":");
+		if (r.classifier != null)
+			sb.append(r.classifier).append("@");
+		sb.append(r.version);
+
+		return sb.toString();
+	}
+
+	public ArtifactData getCandidate(String key, boolean staged) throws Exception {
+		reporter.trace("getCandidate " + key);
+		// Short cut, see if we alread have it
+		Matcher m = SHA_P.matcher(key);
+		if (m.matches()) {
+			byte[] sha = Hex.toByteArray(m.group(1));
+			reporter.trace("sha " + key);
+			ArtifactData art = get(sha);
+			if (art != null)
+				return art;
+
+			reporter.trace("sha not in cache");
+			Revision r = library.getRevision(sha);
+			if (r != null) {
+				reporter.trace("downloading sha");
+				ArtifactData target = put(r.url);
+				target.coordinates = key;
+				return target;
+			}
+			reporter.trace("no sha found");
+			// fall through
+		}
+
+		File f = new File(key);
+		if (f.isFile()) {
+			reporter.trace("is file");
+			ArtifactData target = put(f.toURI());
+			target.coordinates = f.getAbsolutePath();
+			return target;
+		}
+
+		m = URL_P.matcher(key);
+		if (m.matches()) {
+			reporter.trace("looks like a url");
+			try {
+				ArtifactData target = put(new URI(key));
+				target.coordinates = key;
+				return target;
+			}
+			catch (Exception e) {
+				// Ignore
+				reporter.trace("hmm, not a valid url");
+			}
+			// fall through
+		}
+
+		reporter.trace("get the programs for %s", key);
+		Iterable< ? extends Program> ps = library.getPrograms(key);
+		if (ps == null)
+			return null;
+
+		Matcher matcher = COORD_P.matcher(key);
+		String classifier = matcher.matches() ? matcher.group(3) : null;
+		reporter.trace("filter for valid versions, classifier %s", classifier);
+		List<RevisionRef> refs = new ArrayList<RevisionRef>();
+		for (Program p : ps) {
+			RevisionRef selected = selectBest(p.revisions, staged, classifier);
+			if (selected != null)
+				refs.add(selected);
+		}
+		if (refs.isEmpty()) {
+			reporter.trace("no valid versions found");
+			return null;
+		}
+
+		if (refs.size() == 1) {
+			reporter.trace("found 1 program %s:%s", refs.get(0).groupId, refs.get(0).artifactId);
+			RevisionRef r = refs.get(0);
+
+			ArtifactData target = get(r.revision);
+			if (target == null)
+				target = put(r.url);
+
+			target.coordinates = key;
+			return target;
+		}
+
+		System.out.printf("Multiple candidates for this name, select with its sha\n");
+		for (Program p : ps) {
+			RevisionRef selected = selectBest(p.revisions, staged, classifier);
+			if (selected != null) {
+				String desc = selected.description;
+				if (desc == null) {
+					desc = p.wiki.text;
+					if (desc == null)
+						desc = "-";
+				}
+
+				System.out.printf("%-20s:%20s %-10s %s %s\n", selected.groupId, selected.artifactId, selected.version,
+						Hex.toHexString(selected.revision), desc);
+			}
+		}
+		return null;
+	}
+
+	private RevisionRef selectBest(List<RevisionRef> revisions, boolean staged, String classifier) {
+		long date = 0;
+		RevisionRef selected = null;
+		for (RevisionRef r : revisions) {
+			reporter.trace("%s:%s:%s@%s %s", r.groupId, r.artifactId, r.classifier, r.version, classifier);
+			if (r.classifier == null && classifier != null || r.classifier != null && classifier == null) {
+				continue;
+			}
+
+			if (r.classifier == null || classifier == null || classifier.equals(r.classifier)) {
+				if (r.phase == Phase.MASTER || (r.phase == Phase.STAGING && staged)) {
+					if (selected == null || r.created > selected.created)
+						selected = r;
+				}
+			}
+		}
+		if (selected == null) {
+			reporter.trace("no candidate found");
+		} else {
+			reporter.trace("selected %s:%s:%s@%s", selected.groupId, selected.artifactId, selected.classifier,
+					selected.version);
+		}
+		return selected;
+	}
+
+	public static Executor getExecutor() {
+		if (executor == null)
+			executor = Executors.newFixedThreadPool(4);
+		return executor;
+	}
+
+	public static void setExecutor(Executor executor) {
+		JustAnotherPackageManager.executor = executor;
+	}
+
+	public void setLibrary(URI url) {
+		library = new RemoteLibrary(url.toString());
+	}
+
+	public void close() {
+		if (executor != null && executor instanceof ExecutorService)
+			((ExecutorService) executor).shutdown();
+	}
+
+	public void init() throws IOException {
+		URL s = getClass().getClassLoader().getResource("service.jar");
+		IO.copy(s, service);
+	}
+
+	public List<Revision> getCandidates(String key) throws Exception {
+		Iterable<Revision> revisions = library.getRevisions(key);
+		List<Revision> revs = new ArrayList<Revision>();
+		for (Revision r : revisions) {
+			revs.add(r);
+		}
+		return revs;
+	}
+
+	public Iterable< ? extends Program> find(String q) throws Exception {
+		return library.findProgram().query(q);
+	}
+
+	public void setHomeDir(File homeDir) throws IOException {
+		this.homeDir = homeDir;
+		initDirs();
+	}
+
+	public void setBinDir(File binDir) throws IOException {
+		this.binDir = binDir;
+		this.binDir.mkdirs();
+	}
+
+	public Platform getPlatform() {
+		return platform;
+	}
+
+	/**
+	 * Copy from the copy method in StructUtil. Did not want to drag that code
+	 * in. maybe this actually should go to struct.
+	 * 
+	 * @param from
+	 * @param to
+	 * @param excludes
+	 * @return
+	 * @throws Exception
+	 */
+	static public <T extends struct> T xcopy(struct from, T to, String... excludes) throws Exception {
+		Arrays.sort(excludes);
+		for (Field f : from.fields()) {
+			if (Arrays.binarySearch(excludes, f.getName()) >= 0)
+				continue;
+
+			Object o = f.get(from);
+			if (o == null)
+				continue;
+
+			Field tof = to.getField(f.getName());
+			if (tof != null)
+				try {
+					tof.set(to, Converter.cnv(tof.getGenericType(), o));
+				}
+				catch (Exception e) {
+					System.out.println("Failed to convert " + f.getName() + " from " + from.getClass() + " to "
+							+ to.getClass() + " value " + o + " exception " + e);
+				}
+		}
+
+		return to;
+	}
+
+	public RemoteLibrary getLibrary() {
+		return library;
+	}
+	
+}
\ No newline at end of file
diff --git a/biz.aQute.jpm/src/aQute/jpm/lib/Service.java b/biz.aQute.jpm/src/aQute/jpm/lib/Service.java
new file mode 100644
index 0000000..2c13cc1
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/lib/Service.java
@@ -0,0 +1,169 @@
+package aQute.jpm.lib;
+
+import static aQute.lib.io.IO.*;
+
+import java.io.*;
+import java.net.*;
+
+import aQute.lib.io.*;
+
+public class Service {
+	final ServiceData				data;
+	final JustAnotherPackageManager	jpm;
+	final File						lock;
+
+	Service(JustAnotherPackageManager jpm, ServiceData data) throws Exception {
+		this.jpm = jpm;
+		this.data = data;
+		this.lock = new File(data.lock);
+	}
+
+	public String start() throws Exception {
+		if (lock.exists())
+			return "Already running";
+
+		if (lock.createNewFile()) {
+			jpm.platform.chown(data.user, false, lock);
+			try {
+				int result = jpm.platform.launchService(data);
+				if (result != 0)
+					return "Could not launch service " + data.name + " return value " + result;
+
+				long start = System.currentTimeMillis();
+				while (System.currentTimeMillis() - start < 10000) {
+					Thread.sleep(100);
+					if (getPort() != -1)
+						return null;
+				}
+				lock.delete();
+				return "Could not establish a link to the service, likely failed to start";
+			}
+			catch (Throwable t) {
+				IO.delete(lock);
+				return String.format("Failed to start %s for %s", data.name, t.getMessage());
+			}
+		}
+		return "Already running";
+	}
+
+	public String stop() throws Exception {
+		if (lock.exists()) {
+			if (!lock.canWrite()) {
+				return String.format("Cannot write lock %s", data.lock);
+			}
+			try {
+				send(getPort(), "STOP");
+				for (int i = 0; i < 20; i++) {
+					if (!lock.exists())
+						return null;
+
+					Thread.sleep(500);
+				}
+				return "Lock was not deleted by service in time (waited 10 secs)";
+			}
+			finally {
+				lock.delete();
+			}
+		}
+		return "Not running";
+	}
+
+	public String status() throws Exception {
+		if (lock.canWrite() && lock.exists())
+			return send(getPort(), "STATUS");
+
+		return null;
+	}
+
+	private String send(int port, String m) throws Exception {
+		if (port == -1)
+			return "Invalid port";
+
+		byte data[] = m.getBytes("UTF-8");
+		DatagramPacket p = new DatagramPacket(data, 0, data.length, InetAddress.getByAddress(new byte[] {
+				127, 0, 0, 1
+		}), port);
+		DatagramSocket dsocket = new DatagramSocket();
+		dsocket.setReceiveBufferSize(5000);
+		dsocket.setSoTimeout(5000);
+		try {
+			dsocket.send(p);
+			byte[] buffer = new byte[1000];
+			DatagramPacket dp = new DatagramPacket(buffer, 1000);
+			dsocket.receive(dp);
+			return new String(dp.getData(), dp.getOffset(), dp.getLength(), "UTF-8");
+		}
+		catch (SocketTimeoutException stoe) {
+			return "Timed out";
+		}
+		finally {
+			dsocket.close();
+		}
+	}
+
+	int getPort() {
+		try {
+			String l = collect(data.lock);
+			String parts[] = l.split(":");
+			return Integer.parseInt(parts[0]);
+		}
+		catch (Exception e) {
+			return -1;
+		}
+	}
+
+	int getPid() throws IOException {
+		try {
+			String l = collect(data.lock);
+			String parts[] = l.split(":");
+			return Integer.parseInt(parts[1]);
+		}
+		catch (Exception e) {
+			return -1;
+		}
+	}
+
+	public boolean isRunning() {
+		return lock.exists();
+	}
+
+	@Override
+	public String toString() {
+		return data.name;
+	}
+
+	public ServiceData getServiceData() {
+		return data;
+	}
+
+	public String update(ServiceData data) throws Exception {
+		return jpm.createService(data);
+	}
+
+	public String trace(boolean b) throws Exception {
+		if (!isRunning())
+			return "Not running";
+
+		if (b)
+			send(getPort(), "TRACE-ON");
+		else
+			send(getPort(), "TRACE-OFF");
+		return null;
+	}
+
+	public void remove() throws Exception {
+		try {
+			stop();
+		}
+		catch (Exception e) {}
+
+		IO.deleteWithException(new File(data.sdir));
+		jpm.platform.remove(data);
+	}
+
+	public void clear() {
+		IO.delete(new File(data.log));
+		IO.delete(new File(data.work));
+		new File(data.work).mkdir();
+	}
+}
diff --git a/biz.aQute.jpm/src/aQute/jpm/lib/ServiceData.java b/biz.aQute.jpm/src/aQute/jpm/lib/ServiceData.java
new file mode 100644
index 0000000..5100d07
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/lib/ServiceData.java
@@ -0,0 +1,20 @@
+package aQute.jpm.lib;
+
+import java.util.*;
+
+import aQute.lib.data.*;
+
+public class ServiceData extends CommandData {
+	public String		args	= "";
+	public String		user;
+	public String		sdir;
+	public String		work;
+	public String		lock;
+	public String		log;
+	public String		epilog	= "";
+	public String		prolog	= "";
+	public List<String>	after	= new ArrayList<String>();
+	@AllowNull
+	public String		serviceLib;
+	public byte[]		artifact;
+}
diff --git a/biz.aQute.jpm/src/aQute/jpm/main/InstallCert.java b/biz.aQute.jpm/src/aQute/jpm/main/InstallCert.java
new file mode 100644
index 0000000..2560c7e
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/main/InstallCert.java
@@ -0,0 +1,159 @@
+package aQute.jpm.main;
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Sun Microsystems nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/**
+ * http://blogs.sun.com/andreas/resource/InstallCert.java
+ * Use:
+ * java InstallCert hostname
+ * Example:
+ *% java InstallCert ecc.fedora.redhat.com
+ */
+
+import java.io.*;
+import java.security.*;
+import java.security.cert.*;
+
+import javax.net.ssl.*;
+
+import aQute.lib.hex.*;
+import aQute.lib.io.*;
+import aQute.service.reporter.*;
+
+/**
+ * Class used to add the server's certificate to the KeyStore with your trusted
+ * certificates.
+ */
+public class InstallCert {
+
+	public static void installCert(Reporter reporter, String host, int port, String passphrase, File file, boolean install)
+			throws Exception {
+		if (file == null) {
+			File java = new File(System.getProperty("java.home"));
+			file = IO.getFile(java, "lib/security/jssecacerts");
+			if (!file.isFile())
+				file = IO.getFile(java, "lib/security/cacerts");
+			if (!file.isFile())
+				throw new IllegalArgumentException(
+						"Cannot find certifcate file in $JAVA_HOME/lib/security/(jsse)?cacerts");
+		}
+		KeyStore ks;
+		InputStream in = new FileInputStream(file);
+		try {
+			ks = KeyStore.getInstance(KeyStore.getDefaultType());
+			ks.load(in, passphrase.toCharArray());
+		}
+		finally {
+			in.close();
+		}
+
+		SSLContext context = SSLContext.getInstance("TLS");
+		TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+		tmf.init(ks);
+		X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];
+		SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
+		context.init(null, new TrustManager[] {
+			tm
+		}, null);
+		SSLSocketFactory factory = context.getSocketFactory();
+
+		reporter.trace("Opening connection to %s:%s", host, port);
+		SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
+		socket.setSoTimeout(10000);
+		try {
+			reporter.trace("Starting SSL handshake...");
+			socket.startHandshake();
+			socket.close();
+			reporter.trace("No errors, certificate is already trusted");
+		}
+		catch (SSLException e) {
+			reporter.trace("expected exception");
+		}
+
+		X509Certificate[] chain = tm.chain;
+		if (chain == null) {
+			reporter.trace("Could not obtain server certificate chain");
+			return;
+		}
+
+		reporter.trace("Server sent " + chain.length + " certificate(s):");
+		MessageDigest sha1 = MessageDigest.getInstance("SHA1");
+		MessageDigest md5 = MessageDigest.getInstance("MD5");
+
+		for (int i = 0; i < chain.length; i++) {
+			X509Certificate cert = chain[i];
+			System.out.printf("%3s Subject %s Issuer %s sha1=%s md5=%s\n" ,i, cert.getSubjectDN(), cert.getIssuerDN(), Hex.toHexString(sha1.digest()),
+					Hex.toHexString(md5.digest()));
+			sha1.update(cert.getEncoded());
+			md5.update(cert.getEncoded());
+		}
+		if (!install)
+			return;
+
+		X509Certificate cert = chain[0];
+		String alias = host;
+		ks.setCertificateEntry(alias, cert);
+
+		OutputStream out = new FileOutputStream(file);
+		try {
+			ks.store(out, passphrase.toCharArray());
+		}
+		finally {
+			out.close();
+		}
+
+		reporter.trace("Added certificate to keystore '%s' using alias '%s'", file, alias);
+	}
+
+	private static class SavingTrustManager implements X509TrustManager {
+
+		private final X509TrustManager	tm;
+		X509Certificate[]		chain;
+
+		SavingTrustManager(X509TrustManager tm) {
+			this.tm = tm;
+		}
+
+		public X509Certificate[] getAcceptedIssuers() {
+			throw new UnsupportedOperationException();
+		}
+
+		public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+			throw new UnsupportedOperationException();
+		}
+
+		public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+			this.chain = chain;
+			tm.checkServerTrusted(chain, authType);
+		}
+	}
+
+}
diff --git a/biz.aQute.jpm/src/aQute/jpm/main/Main.java b/biz.aQute.jpm/src/aQute/jpm/main/Main.java
new file mode 100644
index 0000000..a09e6e6
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/main/Main.java
@@ -0,0 +1,1475 @@
+package aQute.jpm.main;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.net.*;
+import java.nio.charset.*;
+import java.security.*;
+import java.security.spec.*;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.jar.*;
+import java.util.regex.*;
+
+import aQute.bnd.osgi.*;
+import aQute.bnd.version.*;
+import aQute.jpm.lib.*;
+import aQute.jpm.lib.Service;
+import aQute.jpm.platform.*;
+import aQute.jpm.platform.windows.*;
+import aQute.lib.base64.*;
+import aQute.lib.collections.*;
+import aQute.lib.data.*;
+import aQute.lib.getopt.*;
+import aQute.lib.hex.*;
+import aQute.lib.io.*;
+import aQute.lib.justif.*;
+import aQute.lib.settings.*;
+import aQute.libg.reporter.*;
+import aQute.library.remote.*;
+import aQute.service.library.*;
+import aQute.service.library.Library.Program;
+import aQute.service.library.Library.Revision;
+
+/**
+ * The command line interface to JPM
+ */
+ at Description("Just Another Package Manager (for Java)\nMaintains a local repository of Java jars (apps or libs). Can automatically link these jars to an OS command or OS service. For more information see https://www.jpm4j.org/#/md/jpm")
+public class Main extends ReporterAdapter {
+	static Pattern				ASSIGNMENT		= Pattern.compile("\\s*([-\\w\\d_.]+)\\s*(?:=\\s*([^\\s]+)\\s*)?");
+	public final static Pattern	URL_PATTERN		= Pattern.compile("[a-zA-Z][0-9A-Za-z]{1,8}:.+");
+	public final static Pattern	BSNID_PATTERN	= Pattern.compile("([-A-Z0-9_.]+?)(-\\d+\\.\\d+.\\d+)?",
+														Pattern.CASE_INSENSITIVE);
+	File						base			= new File(System.getProperty("user.dir"));
+	Settings					settings		= new Settings();
+
+	/**
+	 * Show installed binaries
+	 */
+
+	public interface ModifyService extends ModifyCommand {
+		@Description("Provide arguments to the service when started")
+		String args();
+
+		@Description("Set the log path. Log output will go to this file, otherwise in a reserved directory")
+		String log();
+
+		@Description("Set the log path")
+		String work();
+
+		@Description("Set the user id for the service when running")
+		String user();
+
+		@Description("If set, will be started at boot time after the given services have been started. Specify boot if there are no other dependencies.")
+		List<String> after();
+
+		@Description("Commands executed after the service exits, will run under root.")
+		String epilog();
+
+		@Description("Commands executed just before the service starts while still root.")
+		String prolog();
+	}
+
+	public interface ModifyCommand {
+		@Description("Provide or override the JVM arguments")
+		String jvmargs();
+
+		@Description("Provide the name of the main class used to launch this command or service in fully qualified form, e.g. aQute.main.Main")
+		String main();
+
+		@Description("Provide the name of the command or service")
+		String name();
+
+		@Description("Provide the title of the command or service")
+		String title();
+
+		@Description("Collect permission requests and print them at the end of a run. This can provide detailed information about what resources the command is using.")
+		boolean trace();
+
+	}
+
+	/**
+	 * Services
+	 */
+	@Arguments(arg = {
+		"[name]"
+	})
+	@Description("Manage the JPM ervices. Without arguments and options, this wil show all the current services. Careful, if --remove is used all services are removed without any parameters.")
+	public interface ServiceOptions extends Options, ModifyService {
+
+		@Description("Create a new service on an existing artifact")
+		String create();
+
+		@Description("Remove the given service")
+		boolean remove();
+
+		@Description("Consider staged versions. Normally only masters are considered.")
+		boolean staged();
+
+		@Description("Update the service with the latest master/staged version (see --staged)")
+		boolean update();
+
+		@Description("Specify the coordinates of the service, identifies the main binary")
+		String coordinates();
+	}
+
+	/**
+	 * Commands
+	 */
+	@Arguments(arg = "command")
+	@Description("Manage the commands that have been installed so far")
+	public interface CommandOptions extends Options, ModifyCommand {
+		String create();
+
+		boolean remove();
+
+	}
+
+	/**
+	 * Uninstall a binary.
+	 */
+	@Description("Uninstall a jar by bsn.")
+	@Arguments(arg = {
+			"bsn", "..."
+	})
+	public interface uninstallOptions extends Options {
+		@Description("Version range that must be matched, if not specified all versions are removed.")
+		Version version();
+	}
+
+	/**
+	 * Uninstall a binary.
+	 */
+	public interface deinitOptions extends Options {
+		boolean force();
+	}
+
+	/**
+	 * garbage collect commands and service
+	 */
+	@Description("Garbage collect any orphan service and commands")
+	@Arguments(arg = {})
+	public interface GCOptions extends Options {}
+
+	JustAnotherPackageManager	jpm;
+	final PrintStream			err;
+	final PrintStream			out;
+	File						sm;
+	private String				url;
+	static String				encoding	= System.getProperty("file.encoding");
+
+	static {
+		if (encoding == null)
+			encoding = Charset.defaultCharset().name();
+	}
+
+	/**
+	 * Default constructor
+	 * 
+	 * @throws UnsupportedEncodingException
+	 */
+
+	public Main() throws UnsupportedEncodingException {
+		super(new PrintStream(System.err, true, encoding));
+		err = new PrintStream(System.err, true, encoding);
+		out = new PrintStream(System.out, true, encoding);
+	}
+
+	/**
+	 * Main entry
+	 * 
+	 * @throws Exception
+	 */
+	public static void main(String args[]) throws Exception {
+		Main jpm = new Main();
+		try {
+			jpm.run(args);
+		}
+		finally {
+			jpm.err.flush();
+			jpm.out.flush();
+		}
+	}
+
+	/**
+	 * Main options
+	 */
+
+	@Arguments(arg = "cmd ...")
+	@Description("Options valid for all commands. Must be given before sub command")
+	interface JpmOptions extends Options {
+
+		@Description("Print exception stack traces when they occur.")
+		boolean exceptions();
+
+		@Description("Trace on.")
+		boolean trace();
+
+		@Description("Be pedantic about all details.")
+		boolean pedantic();
+
+		@Description("Specify a new base directory (default working directory).")
+		String Base();
+
+		@Description("Do not return error status for error that match this given regular expression.")
+		String[] failok();
+
+		@Description("Remote library url (can also be permanently set with 'jpm settings library.url=...'")
+		String library();
+
+		@Description("Cache directory, can als be permanently set with 'jpm settings library.cache=...'")
+		String cache();
+
+		@Description("The directory where to store executables. Can also be set 'jpm settings library.bin=...'")
+		String bin();
+
+		@Description("Wait for a key press, might be useful when you want to see the result before it is overwritten by a next command")
+		boolean key();
+
+		@Description("Show the release notes")
+		boolean release();
+	}
+
+	/**
+	 * Initialize the repository and other global vars.
+	 * 
+	 * @param opts
+	 *            the options
+	 * @throws InterruptedException
+	 * @throws IOException
+	 */
+	@Description("Just Another Package Manager for Java")
+	public void _jpm(JpmOptions opts) throws IOException {
+		try {
+			setExceptions(opts.exceptions());
+			setTrace(opts.trace());
+			setPedantic(opts.pedantic());
+			trace("set the options");
+
+			if (opts.Base() != null)
+				base = IO.getFile(base, opts.Base());
+
+			url = opts.library();
+			if (url == null)
+				url = settings.get("library.url");
+
+			if (url != null)
+				jpm.setLibrary(new URI(url));
+
+			File homeDir;
+			if (opts.cache() != null) {
+				homeDir = IO.getFile(base, opts.cache());
+			} else if (settings.containsKey("library.cache")) {
+				homeDir = IO.getFile(base, settings.get("library.cache"));
+			} else
+				homeDir = null;
+
+			if (homeDir != null)
+				jpm.setHomeDir(homeDir);
+
+			File binDir;
+			if (opts.bin() != null) {
+				binDir = IO.getFile(base, opts.bin());
+			} else if (settings.containsKey("library.bin")) {
+				binDir = IO.getFile(base, settings.get("library.bin"));
+			} else
+				homeDir = null;
+
+			CommandLine handler = opts._command();
+			List<String> arguments = opts._();
+
+			if (arguments.isEmpty()) {
+				Justif j = new Justif();
+				Formatter f = j.formatter();
+				handler.help(f, this);
+				err.println(j.wrap());
+			} else {
+				String cmd = arguments.remove(0);
+				String help = handler.execute(this, cmd, arguments);
+				if (help != null) {
+					err.println(help);
+				}
+			}
+		}
+
+		catch (InvocationTargetException t) {
+			Throwable tt = t;
+			while (tt instanceof InvocationTargetException)
+				tt = ((InvocationTargetException) tt).getTargetException();
+
+			exception(tt, "%s", tt.getMessage());
+		}
+		catch (Throwable t) {
+			exception(t, "Failed %s", t);
+		}
+		finally {
+			// Check if we need to wait for it to finish
+			if (opts.key()) {
+				System.out.println("Hit a key to continue ...");
+				System.in.read();
+			}
+		}
+
+		if (!check(opts.failok())) {
+			System.exit(getErrors().size());
+		}
+	}
+
+	/**
+	 * Install a jar options
+	 */
+	@Arguments(arg = {
+		"command|service"
+	})
+	@Description("Install a jar into the repository. If the jar defines a number of headers it can also be installed as a command and/or a service. ")
+	public interface installOptions extends ModifyCommand, Options {
+		@Description("Ignore command and service information")
+		boolean ignore();
+
+		@Description("Force overwrite of existing command")
+		boolean force();
+
+		@Description("Require a master version even when version is specified")
+		boolean master();
+
+		@Description("Include staged revisions in the search")
+		boolean staged();
+
+		@Description("Ignore digest")
+		boolean xdigest();
+
+		@Description("Run service (if present) under the given user name, default is the name of the service")
+		String user();
+
+		/**
+		 * If specified, will install a revision with the given name and version
+		 * and then add any command/service to the system.
+		 */
+		String bsn();
+
+		/**
+		 * Specify a version range for the artifact.
+		 * 
+		 * @return
+		 */
+		Version version();
+
+		/**
+		 * Install a file and extra commands
+		 */
+
+		String local();
+
+		@Description("The path to the log file")
+		String path();
+
+		@Description("Specify a command name, overrides the JPM-Command header")
+		String command();
+
+	}
+
+	/**
+	 * The command line command for install.
+	 * 
+	 * @param opts
+	 *            The options for installing
+	 */
+	@Description("Install an artifact from a url, file, or www.jpm4j.org")
+	public void _install(installOptions opts) throws Exception {
+		if (!jpm.hasAccess()) {
+			error("No write acces, might require administrator or root privileges (sudo in *nix)");
+			return;
+		}
+
+		ArtifactData target = null;
+		boolean staged = false;
+
+		if (opts.local() != null) {
+
+			File f = IO.getFile(base, opts.local());
+			if (f.isFile()) {
+				trace("Found file %s", f);
+				target = jpm.put(f.toURI());
+				target.coordinates = f.toURI().toString();
+			} else {
+				try {
+					trace("Found url %s", f);
+					target = jpm.put(new URI(opts.local()));
+					target.coordinates = opts.local();
+				}
+				catch (Exception e) {
+					e.printStackTrace();
+					// ignore
+				}
+			}
+			if (target == null) {
+				error("Could not install from file/url: %s", opts.local());
+				return;
+			}
+		} else {
+			if (opts._().isEmpty()) {
+				error("You need to specify a command name or artifact id");
+				return;
+			}
+			String key = opts._().get(0);
+			if (isSha(key) && (target = jpm.get(Hex.toByteArray(key))) != null) {
+
+				// we've got to check for locally installed files
+				trace("locally installed file found");
+				target.coordinates = "sha:" + key.trim();
+			} else {
+				staged = isSha(key) || opts.staged() || key.indexOf('@') > 0;
+				target = jpm.getCandidate(key, staged);
+				if (target == null) {
+					if (!staged) {
+						target = jpm.getCandidate(key, true);
+						if (target != null) {
+							error("No candidate %s found, but found staged version(s): %s", key, target);
+							return;
+						}
+					}
+					error("No such candidate %s", key);
+					return;
+				}
+
+				target.sync();
+				if (target.error != null) {
+					error("Error in getting target %s", target.error);
+					return;
+				}
+				target.coordinates = key;
+			}
+		}
+		trace("Target from %s", Hex.toHexString(target.sha));
+
+		if (target.command != null) {
+			target.command.force = opts.force();
+			target.command.coordinates = target.coordinates;
+			update(target.command, opts);
+			target.command.dependencies.add(0, target.file);
+			if (opts.force() && jpm.getCommand(target.command.name) != null)
+				jpm.deleteCommand(target.command.name);
+
+			String result = jpm.createCommand(target.command);
+			if (result != null)
+				error("Command creation failed: %s", result);
+		} else if (opts.name() != null) {
+			CommandData data = new CommandData();
+			data.description = "Installed from command line";
+			data.coordinates = target.coordinates;
+			data.force = opts.force();
+			data.main = target.mainClass;
+			data.name = opts.name();
+			data.sha = target.sha;
+			data.time = System.currentTimeMillis();
+			data.dependencies.add(target.file);
+			update(data, opts);
+			if (data.main == null) {
+				error("No main class set");
+				return;
+			}
+
+			if (opts.force() && jpm.getCommand(data.name) != null)
+				jpm.deleteCommand(data.name);
+			String result = jpm.createCommand(data);
+			if (result != null)
+				error("Command creation failed: %s", result);
+		} else {
+			if (staged)
+				warning("No command found in %s", target.coordinates);
+			else
+				warning("No command found in %s. You could try with --staged to find a staged version?",
+						target.coordinates);
+		}
+
+		if (target.service != null) {
+			target.service.force = opts.force();
+			target.service.coordinates = target.coordinates;
+			target.service.dependencies.add(0, target.file);
+			Service s = jpm.getService(target.service.name);
+			trace("existing service %s", s);
+			if (opts.force() && s != null) {
+				trace("will remove %s", s.getServiceData().bin);
+				s.remove();
+			}
+			String result = jpm.createService(target.service);
+			if (result != null)
+				error("Service creation failed: %s", result);
+		}
+	}
+
+	/**
+	 * Check if a key is a sha
+	 * 
+	 * @param key
+	 * @return
+	 */
+	private boolean isSha(String key) {
+		return key != null && key.length() == 40 && key.matches("[\\da-fA-F]{40,40}");
+	}
+
+	@Description("Manage the jpm4j services")
+	public void _service(ServiceOptions opts) throws Exception {
+		if (opts._().isEmpty()) {
+			for (ServiceData sd : jpm.getServices())
+				print(sd);
+			return;
+		}
+
+		List<String> cmdline = opts._();
+		String name = cmdline.remove(0);
+
+		Service s = jpm.getService(name);
+
+		if (opts.remove()) {
+			if (!jpm.hasAccess()) {
+				error("No write access to create service %s", name);
+				return;
+			}
+			if (s == null) {
+				error("No such service %s to remove", name);
+				return;
+			}
+			s.stop();
+			s.remove();
+			return;
+		}
+
+		if (opts.create() != null) {
+			if (s != null) {
+				error("Service already exists, cannot be created: %s. Update or remove it first", name);
+				return;
+			}
+
+			ArtifactData target = jpm.getCandidate(opts.create(), opts.staged());
+			if (target == null)
+				return;
+
+			ServiceData data = target.service;
+			data.coordinates = opts.create();
+			update(data, opts);
+			String result = jpm.createService(data);
+			if (result != null)
+				error("Create service failed: %s", result);
+			return;
+		}
+
+		if (s == null) {
+			error("No such service: %s", name);
+			return;
+		}
+
+		ServiceData data = s.getServiceData();
+		if (update(data, opts) || opts.coordinates() != null || opts.update()) {
+			if (!jpm.hasAccess()) {
+				error("No write access to update service %s", name);
+				return;
+			}
+
+			//
+			// Check if we have to update the underlying artifact
+			// This is triggered by --coordinates, which provides
+			// the new coordinates or just --update which reuses the
+			// old coordinates without version
+			//
+
+			if (opts.coordinates() != null || opts.update()) {
+				String coordinates = opts.coordinates();
+				if (coordinates == null || coordinates.equals(".")) {
+					coordinates = data.coordinates;
+				}
+				if (coordinates == null) {
+					error("No coordinates found in old service record");
+					return;
+				}
+
+				int n = coordinates.indexOf('@');
+				if (n > 0)
+					coordinates = coordinates.substring(0, n);
+
+				trace("Updating from coordinates: %s", coordinates);
+				ArtifactData target = jpm.getCandidate(coordinates, opts.staged());
+				if (target == null) {
+					error("No candidates found for %s (%s)", coordinates, opts.staged() ? "staged" : "only masters");
+					return;
+				}
+
+				data.dependencies.clear();
+				data.dependencies.add(target.file);
+				data.dependencies.addAll(target.dependencies);
+				data.coordinates = coordinates;
+			}
+			data.force = true;
+			String result = jpm.createService(data);
+			if (result != null)
+				error("Update service failed: %s", result);
+			else if (s.isRunning())
+				warning("Changes will not affect the currently running process");
+		}
+		Data.details(data, out);
+	}
+
+	private boolean update(ServiceData data, ModifyService opts) {
+		boolean update = false;
+		if (opts.args() != null) {
+			data.args = opts.args();
+			update = true;
+		}
+		if (opts.prolog() != null) {
+			data.prolog = opts.prolog();
+			update = true;
+		}
+		if (opts.epilog() != null) {
+			data.epilog = opts.epilog();
+			update = true;
+		}
+		if (opts.log() != null) {
+			data.log = IO.getFile(base, opts.log()).getAbsolutePath();
+			update = true;
+		}
+		if (opts.work() != null) {
+			data.work = IO.getFile(base, opts.work()).getAbsolutePath();
+			update = true;
+		}
+
+		if (opts.after() != null) {
+			data.after = opts.after();
+			update = true;
+		}
+		if (opts.user() != null) {
+			data.user = opts.user();
+			update = true;
+		}
+
+		return update((CommandData) data, opts) || update;
+	}
+
+	private boolean update(CommandData data, ModifyCommand opts) {
+		boolean update = false;
+		if (opts.main() != null) {
+			data.main = opts.main();
+			update = true;
+		}
+		if (opts.jvmargs() != null) {
+			data.jvmArgs = opts.jvmargs();
+			update = true;
+		}
+		if (opts.name() != null) {
+			data.name = opts.name();
+			update = true;
+		}
+		if (opts.title() != null) {
+			data.title = opts.title();
+			update = true;
+		}
+		if (opts.trace() != data.trace) {
+			data.trace = opts.trace();
+			update = true;
+		}
+		return update;
+	}
+
+	private void print(ServiceData sd) throws Exception {
+		Service s = jpm.getService(sd.name);
+		out.printf("%-40s (%s) %s%n", sd.name, s.isRunning() ? "runs   " : "stopped", sd.args);
+	}
+
+	@Description("Manage the jpm4j commands")
+	public void _command(CommandOptions opts) throws Exception {
+
+		if (opts.remove()) {
+			Instructions instrs = new Instructions(opts._());
+			for (CommandData cmd : jpm.getCommands()) {
+				if (instrs.matches(cmd.name)) {
+					jpm.deleteCommand(cmd.name);
+				}
+			}
+			return;
+		}
+
+		if (opts._().isEmpty()) {
+			for (CommandData sd : jpm.getCommands())
+				out.printf("%-40s %s%n", sd.name, sd.description == null ? "" : sd.description);
+			return;
+		}
+
+		String cmd = opts._().get(0);
+
+		CommandData data = jpm.getCommand(cmd);
+		if (data == null) {
+			error("Not found: %s", cmd);
+		} else {
+			if (update(data, opts)) {
+				jpm.deleteCommand(data.name);
+				String result = jpm.createCommand(data);
+				if (result != null)
+					error("Failed to update command %s: %s", cmd, result);
+			}
+
+			out.printf("%-40s %s%n", data.name, data.description == null ? "" : data.description);
+			out.printf("  %-38s %s%n", "Classpath", data.dependencies);
+			out.printf("  %-38s %s%n", "JVM Args", data.jvmArgs);
+			out.printf("  %-38s %s%n", "Main class", data.main);
+			out.printf("  %-38s %s%n", "Time", new Date(data.time));
+		}
+	}
+
+	@Description("Clean up any stale data, including any downloaded files not used in any commands")
+	public void _gc(GCOptions opts) throws Exception {
+		jpm.gc();
+	}
+
+	/**
+	 * Remove all traces.
+	 * 
+	 * @param opts
+	 * @throws Exception
+	 */
+	@Description("Remove jpm from the system by deleting all artifacts and metadata")
+	public void _deinit(deinitOptions opts) throws Exception {
+
+		if (opts._().size() != 0)
+			error("Deinit requires no other parameters: %s", opts._());
+		if (!jpm.hasAccess())
+			error("Requires write access to jmp area (sudo?)");
+
+		if (!isOk())
+			return;
+
+		String result = jpm.deinit(opts.force());
+		if (result == null)
+			return;
+
+		error("Cannot doinit due to %s", result);
+	}
+
+	/**
+	 * Main entry for the command line
+	 * 
+	 * @param args
+	 * @throws Exception
+	 */
+	private void run(String[] args) throws Exception {
+		jpm = new JustAnotherPackageManager(this);
+		try {
+			if (args.length > 0 && args[0].equals("daemon"))
+				jpm.daemon();
+			else {
+				CommandLine cl = new CommandLine(this);
+				ExtList<String> list = new ExtList<String>(args);
+				String help = cl.execute(this, "jpm", list);
+				check();
+				if (help != null)
+					err.println(help);
+			}
+		}
+		finally {
+			jpm.close();
+		}
+	}
+
+	/**
+	 * Setup jpm to run on this system.
+	 * 
+	 * @throws Exception
+	 */
+	interface InitOptions extends Options {}
+
+	@Description("Install jpm on the current system")
+	public void _init(InitOptions opts) throws Exception {
+		try {
+			String s = System.getProperty("java.class.path");
+			if (s == null || s.indexOf(File.pathSeparator) > 0) {
+				error("Cannot initialize because not clear what the command jar is from java.class.path: %s", s);
+				return;
+			}
+			try {
+				File f = new File(s).getAbsoluteFile();
+				if (f.exists()) {
+					jpm.init();
+					CommandLine cl = new CommandLine(this);
+					String help = cl.execute(this, "install", Arrays.asList("-fl", f.getAbsolutePath()));
+					if (help != null)
+						error(help);
+
+				} else
+					error("Cannot find the jpm jar from %s", f);
+			}
+			catch (InvocationTargetException e) {
+				exception(e.getTargetException(), "Could not install jpm, %s", e.getTargetException().getMessage());
+			}
+		}
+		catch (Throwable e) {
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * Show platform
+	 */
+	@Arguments(arg = {})
+	@Description("Show the name of the platform, or more specific information")
+	public interface PlatformOptions extends Options {
+		@Description("Show detailed information")
+		boolean verbose();
+	}
+
+	/**
+	 * Show the platform info.
+	 * 
+	 * @param opts
+	 * @throws IOException
+	 * @throws Exception
+	 */
+	@Description("Show platform information")
+	public void _platform(PlatformOptions opts) throws IOException, Exception {
+		if (opts.verbose()) {
+			Justif j = new Justif(80, 30, 40, 50, 60);
+			jpm.getPlatform().report(j.formatter());
+			out.append(j.wrap());
+		} else
+			out.println(jpm.getPlatform().getName());
+	}
+
+	/**
+	 * Start a service.
+	 * 
+	 * @param options
+	 * @throws Exception
+	 */
+	interface startOptions extends Options {
+		boolean clean();
+	}
+
+	@Description("Start a service")
+	public void _start(startOptions options) throws Exception {
+		if (!jpm.hasAccess()) {
+			error("No write acces, might require administrator or root privileges (sudo in *nix)");
+			return;
+		}
+		for (String s : options._()) {
+			Service service = jpm.getService(s);
+			if (service == null)
+				error("Non existent service %s", s);
+			else {
+				if (!service.isRunning()) {
+					try {
+						ServiceData d = service.getServiceData();
+						trace("starting %s as user %s, lock=%s, log=%s", d.name, d.user, d.lock, d.log);
+						if (options.clean())
+							service.clear();
+						String result = service.start();
+						if (result != null)
+							error("Failed to start: %s", result);
+					}
+					catch (Exception e) {
+						exception(e, "Could not start service %s due to %s", s, e.getMessage());
+					}
+				} else
+					warning("Service %s already running", s);
+			}
+		}
+	}
+
+	/**
+	 * Restart a service.
+	 * 
+	 * @param options
+	 * @throws Exception
+	 */
+	@Description("Restart a service")
+	public void _restart(Options options) throws Exception {
+		for (String s : options._()) {
+			Service service = jpm.getService(s);
+			if (service == null)
+				error("Non existent service %s", s);
+			else {
+				try {
+					if (service.isRunning())
+						service.stop();
+					String result = service.start();
+					if (result != null)
+						error("Failed to start: %s", result);
+				}
+				catch (Exception e) {
+					exception(e, "Could not start service %s due to %s", s, e.getMessage());
+				}
+			}
+		}
+	}
+
+	/**
+	 * Trace a service.
+	 * 
+	 * @param options
+	 * @throws Exception
+	 */
+	@Arguments(arg = {
+			"service", "[on|off]"
+	})
+	public interface traceOptions extends Options {
+		boolean continuous();
+	}
+
+	@Description("Trace a service")
+	public void _trace(traceOptions options) throws Exception {
+		List<String> args = options._();
+		String s = args.remove(0);
+		boolean on = args.isEmpty() || !"off".equalsIgnoreCase(args.remove(0));
+
+		Service service = jpm.getService(s);
+		if (service == null)
+			error("Non existent service %s", s);
+		else {
+			try {
+				if (!service.isRunning())
+					error("First start the service to trace it");
+				else {
+					String result = service.trace(on);
+					if (result != null)
+						error("Failed to trace: %s", result);
+				}
+			}
+			catch (Exception e) {
+				exception(e, "Could not trace service %s due to %s", s, e.getMessage());
+			}
+		}
+	}
+
+	/**
+	 * Stop a service.
+	 * 
+	 * @param options
+	 * @throws Exception
+	 */
+	@Description("Stop a service")
+	public void _stop(Options options) throws Exception {
+		for (String s : options._()) {
+			Service service = jpm.getService(s);
+			if (service == null)
+				error("Non existent service %s", s);
+			else {
+				if (service.isRunning()) {
+					try {
+						String result = service.stop();
+						if (result != null)
+							error("Failed to stop: %s", result);
+					}
+					catch (Exception e) {
+						exception(e, "Could not stop service %s due to %s", s, e.getMessage());
+					}
+				} else
+					warning("Service %s not running", s);
+			}
+		}
+	}
+
+	/**
+	 * Status a service.
+	 * 
+	 * @param options
+	 * @throws Exception
+	 */
+	interface statusOptions extends Options {
+		boolean continuous();
+	}
+
+	@Description("Status of a service")
+	public void _status(statusOptions options) throws InterruptedException {
+		while (true) {
+			for (String s : options._()) {
+				String runs = "false";
+				String status = "no service";
+				try {
+					Service service = jpm.getService(s);
+					if (service != null) {
+						runs = service.isRunning() + "";
+						status = service.status();
+					}
+				}
+				catch (Exception e) {
+					status = e.getMessage();
+					exception(e, "could not fetch status information from service %s, due to %s", s, e.getMessage());
+				}
+				out.printf("%-40s %8s %s\r", s, runs, status);
+			}
+			if (!options.continuous()) {
+				out.println();
+				return;
+			}
+			Thread.sleep(1000);
+		}
+	}
+
+	/**
+	 * Show the current version
+	 * 
+	 * @throws IOException
+	 */
+
+	@Arguments(arg = {})
+	@Description("Show the current version. The qualifier represents the build date.")
+	interface VersionOptions extends Options {
+
+	}
+
+	@Description("Show the current version of jpm")
+	public void _version(VersionOptions options) throws IOException {
+		Enumeration<URL> urls = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF");
+		while (urls.hasMoreElements()) {
+			URL url = urls.nextElement();
+			trace("found manifest %s", url);
+			Manifest m = new Manifest(url.openStream());
+			String name = m.getMainAttributes().getValue("Bundle-SymbolicName");
+			if (name != null && name.trim().equals("biz.aQute.jpm.run")) {
+				out.println(m.getMainAttributes().getValue("Bundle-Version"));
+				return;
+			}
+		}
+		error("No version found in jar");
+	}
+
+	// /**
+	// * Manage the interface to the library
+	// *
+	// * @throws Exception
+	// */
+	//
+	// public void _lib(LibraryCommandOptions options) throws Exception {
+	// LibraryCommand library = new LibraryCommand(options, base, out,
+	// settings);
+	//
+	// CommandLine cline = options._command();
+	// List<String> _ = options._();
+	// if (_.isEmpty())
+	// cline.execute(library, "info", _);
+	// else
+	// cline.execute(library, _.remove(0), _);
+	//
+	// }
+
+	/**
+	 * @throws Exception
+	 */
+
+	interface KeysOptions extends Options {
+		boolean secret();
+
+		boolean pem();
+
+		boolean hex();
+
+		boolean extended();
+	}
+
+	@Description("Show the jpm machine keys")
+	public void _keys(KeysOptions opts) throws Exception {
+		boolean any = opts.pem() || opts.extended() || opts.hex();
+
+		if (opts.extended()) {
+			PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(settings.getPrivateKey());
+			X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(settings.getPublicKey());
+			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+			PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
+			PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
+			privateKey.getAlgorithm();
+			if (opts.secret())
+				out.format("private %s", privateKey);
+			out.format("public  %s", publicKey);
+		}
+		if (opts.hex()) {
+			if (opts.secret())
+				out.format("private %s", Hex.toHexString(settings.getPrivateKey()));
+			out.format("public  %s", Hex.toHexString(settings.getPublicKey()));
+		}
+		if (opts.pem() || !any) {
+			formatKey(settings.getPublicKey(), "PUBLIC");
+			if (opts.secret())
+				formatKey(settings.getPrivateKey(), "PRIVATE");
+		}
+	}
+
+	private void formatKey(byte[] data, String type) throws UnknownHostException {
+		String email = settings.getEmail();
+		if (email == null)
+			email = "<no email set>";
+		email += " " + InetAddress.getLocalHost().getHostName();
+
+		StringBuilder sb = new StringBuilder(Base64.encodeBase64(data));
+		int r = 60;
+		while (r < sb.length()) {
+			sb.insert(r, "\n");
+			r += 60;
+		}
+		out.format("-----BEGIN %s %s KEY-----%n", email, type);
+		out.append(sb.toString()).append("\n");
+		out.format("-----END %s %s KEY-----%n", email, type);
+	}
+
+	/**
+	 * Show the tail of the log output.
+	 */
+
+	@Arguments(arg = "service")
+	interface logOptions extends Options {
+
+		boolean tail();
+
+		boolean clear();
+
+	}
+
+	@Description("Show the service log")
+	public void _log(logOptions opts) throws Exception {
+
+		String s = opts._().isEmpty() ? null : opts._().get(0);
+		if (s == null) {
+			error("No such service %s", s);
+			return;
+		}
+		Service service = jpm.getService(s);
+		if (service == null) {
+			error("No such service %s", s);
+			return;
+		}
+
+		ServiceData data = service.getServiceData();
+		File logFile = new File(data.log);
+		if (!logFile.isFile()) {
+			error("Log file %s for service %s is not a file", logFile, s);
+			return;
+		}
+
+		if (opts.clear()) {
+			logFile.delete();
+			logFile.createNewFile();
+		}
+
+		RandomAccessFile raf = new RandomAccessFile(logFile, "r");
+		try {
+			long start = Math.max(logFile.length() - 2000, 0);
+			while (true) {
+				long l = raf.length();
+				byte[] buffer = new byte[(int) (l - start)];
+				raf.seek(start);
+				raf.read(buffer);
+				out.write(buffer);
+				start = l;
+				if (!service.isRunning() || !opts.tail())
+					return;
+
+				if (l == raf.length())
+					Thread.sleep(100);
+			}
+		}
+		finally {
+			raf.close();
+		}
+	}
+
+	/**
+	 * Install JPM as a platform daemon that will start the services marked with
+	 * after xxx (where boot is the canonical start).
+	 */
+
+	@Arguments(arg = {})
+	interface registerOptions extends Options {
+		@Description("Register for user login only")
+		boolean user();
+	}
+
+	@Description("Install JPM as a platform daemon")
+	public void _register(registerOptions opts) throws Exception {
+		jpm.register(opts.user());
+	}
+
+	/**
+	 * Handle the global settings
+	 */
+	interface settingOptions extends Options {
+		boolean clear();
+
+		boolean publicKey();
+
+		boolean secretKey();
+
+		boolean id();
+
+		boolean mac();
+
+		boolean hex();
+	}
+
+	@Description("Manage user settings of jpm (in ~/.jpm)")
+	public void _settings(settingOptions opts) throws Exception {
+		try {
+			trace("settings %s", opts.clear());
+			List<String> rest = opts._();
+
+			if (opts.clear()) {
+				settings.clear();
+				trace("clear %s", settings.entrySet());
+			}
+
+			if (opts.publicKey()) {
+				out.println(tos(opts.hex(), settings.getPublicKey()));
+				return;
+			}
+			if (opts.secretKey()) {
+				out.println(tos(opts.hex(), settings.getPrivateKey()));
+				return;
+			}
+			if (opts.id()) {
+				out.printf("%s\n", tos(opts.hex(), settings.getPublicKey()));
+			}
+
+			if (opts.mac()) {
+				for (String s : rest) {
+					byte[] data = s.getBytes("UTF-8");
+					byte[] signature = settings.sign(data);
+					out.printf("%s\n", tos(opts.hex(), signature));
+				}
+				return;
+			}
+
+			if (rest.isEmpty()) {
+				list(null, settings);
+			} else {
+				boolean set = false;
+				for (String s : rest) {
+					Matcher m = ASSIGNMENT.matcher(s);
+					trace("try %s", s);
+					if (m.matches()) {
+						trace("matches %s %s %s", s, m.group(1), m.group(2));
+						String key = m.group(1);
+						Instructions instr = new Instructions(key);
+						Collection<String> select = instr.select(settings.keySet(), true);
+
+						String value = m.group(2);
+						if (value == null) {
+							trace("list wildcard " + instr + " " + select + " " + settings.keySet());
+							list(select, settings);
+						} else {
+							trace("assignment 	");
+							settings.put(key, value);
+							set = true;
+						}
+					} else {
+						err.printf("Cannot assign %s\n", s);
+
+					}
+				}
+				if (set) {
+					trace("saving");
+					settings.save();
+				}
+			}
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	private String tos(boolean hex, byte[] data) {
+		return hex ? Hex.toHexString(data) : Base64.encodeBase64(data);
+	}
+
+	private void list(Collection<String> keys, Map<String,String> map) {
+		for (Entry<String,String> e : map.entrySet()) {
+			if (keys == null || keys.contains(e.getKey()))
+				out.printf("%-40s = %s\n", e.getKey(), e.getValue());
+		}
+	}
+
+	/**
+	 * Turned out that StartSSL HTTPS certifcates are not recognized by the Java
+	 * certificate store. So we have a command to get the certificate chain
+	 */
+
+	@Arguments(arg = "host")
+	@Description("Provides a way to let Java trust a host for HTTPS access. "
+			+ "The certificate command makes it possible to import an HTTPS certificate from a "
+			+ "remote host that runs HTTPS. It will contact the host over the given host and port and "
+			+ "then add the certificate chain's top certificate to the local keystore of the running VM. This command"
+			+ "requires running as an administrator/root. By default this command will only show what it"
+			+ "will do, specify -i/--install to really install it. Note that running this command is global for the Java VM and is persistent.")
+	interface CertificateOptions extends Options {
+		@Description("Only install the certificate when this option is specified")
+		boolean install();
+
+		@Description("Override the default HTTPS port 443")
+		int port();
+
+		@Description("Password for the keystore. Only necessary when the password has been changed before (the default is 'changeit' for MacOS and 'changeme' for others)")
+		String secret();
+
+		@Description("Override the default $JAVA_HOME/lib/security/(jsse)cacerts file location.")
+		File cacerts();
+	}
+
+	@Description("Install a certificate that is trusted by this VM (persistent for the JVM!)")
+	public void _certificate(CertificateOptions opts) throws Exception {
+		if (!this.jpm.hasAccess())
+			error("Must be administrator");
+
+		InstallCert.installCert(this, opts._().get(0), opts.port() == 0 ? 443 : opts.port(),
+				opts.secret() == null ? Platform.getPlatform(this).defaultCacertsPassword() : opts.secret(),
+				opts.cacerts(), opts.install());
+	}
+
+	/**
+	 * List candidates
+	 * 
+	 * @throws Exception
+	 */
+
+	@Description("Show the candidate revisions for a given program coordinate")
+	public void _candidates(Options opts) throws Exception {
+		for (String key : opts._()) {
+			List<Revision> candidates = jpm.getCandidates(key);
+			if (candidates == null) {
+				error("No candidates found for %s", key);
+			} else
+				print(candidates);
+		}
+	}
+
+	void print(Iterable<Revision> revisions) {
+		for (Revision r : revisions) {
+			out.printf("%-40s %s %s\n", jpm.getCoordinates(r), Hex.toHexString(r._id), (r.description == null ? ""
+					: r.description));
+		}
+	}
+
+	void printPrograms(Iterable< ? extends Program> programs) {
+		Justif j = new Justif(120, 40, 42, 100);
+		StringBuilder sb = new StringBuilder();
+		Formatter f = new Formatter(sb);
+		try {
+			for (Program p : programs) {
+				if (p.groupId.equals(Library.OSGI_GROUP) || p.groupId.equals(Library.SHA_GROUP))
+					f.format("%s", p.artifactId);
+				else
+					f.format("%s:%s", p.groupId, p.artifactId);
+
+				f.format("\t0-\t1");
+
+				if (p.wiki != null && p.wiki.text != null)
+					sb.append(p.wiki.text.replace('\n', '\f'));
+				else if (p.last != null) {
+					if (p.last.description != null)
+						sb.append(p.last.description.replace('\n', '\f'));
+				}
+				f.format("%n");
+			}
+			j.wrap(sb);
+			out.println(sb);
+		}
+		finally {
+			f.close();
+		}
+	}
+
+	interface findOptions extends Options {
+
+	}
+
+	@Description("Find programs from a query")
+	public void _find(findOptions opts) throws Exception {
+		String q = new ExtList<String>(opts._()).join(" ");
+		Iterable< ? extends Program> programs = jpm.find(q);
+		printPrograms(programs);
+	}
+
+	/**
+	 * Some window specific commands
+	 */
+
+	enum Key {
+		HKEY_LOCAL_MACHINE(WinRegistry.HKEY_LOCAL_MACHINE), HKEY_CURRENT_USER(WinRegistry.HKEY_CURRENT_USER);
+
+		int	n;
+
+		Key(int n) {
+			this.n = n;
+		}
+
+		public int value() {
+			return n;
+		}
+	}
+
+	@Arguments(arg = {
+			"key", "[property]"
+	})
+	interface winregOptions extends Options {
+		boolean localMachine();
+	}
+
+	@Description("Windows specific access to the registry")
+	public void _winreg(winregOptions opts) throws Exception {
+		List<String> _ = opts._();
+		String key = _.remove(0);
+		String property = _.isEmpty() ? null : _.remove(0);
+		int n = opts.localMachine() ? WinRegistry.HKEY_LOCAL_MACHINE : WinRegistry.HKEY_CURRENT_USER;
+
+		List<String> keys = WinRegistry.readStringSubKeys(n, key);
+		if (property == null) {
+			Map<String,String> map = WinRegistry.readStringValues(n, key);
+			out.println(map);
+		} else {
+			WinRegistry.readString(n, key, property);
+		}
+	}
+
+	/**
+	 * Make the setup local
+	 */
+	@Arguments(arg = {
+		"user|global"
+	})
+	interface setupOptions extends Options {}
+
+	@Description("Make jpm local/global (probably does not work yet)")
+	public void _setup(setupOptions opts) {
+		String type = opts._().remove(0);
+		if (type.equalsIgnoreCase("user")) {
+			File bin = IO.getFile("~/.jpm/bin");
+			// TODO File global = IO.getFile("~/")
+			// settings.put("library.bin", );
+		} else {
+
+		}
+
+	}
+
+	/**
+	 * Deposit a file in JPM and scan it.
+	 */
+
+	@Arguments(arg = "file")
+	@Description("Deposit a file in a private depository")
+	interface DepositOptions extends Options {
+		@Description("If this file should be scanned")
+		boolean scan();
+
+		@Description("Import message for scanning")
+		String message();
+
+		@Description("Repository path")
+		String path();
+
+		@Description("Override email")
+		String email();
+		
+	}
+
+	@Description("Deposit a file in a private depository")
+	public void _deposit(DepositOptions options) {
+		File f = IO.getFile(base, options._().get(0));
+		if ( f.isFile()) {
+			error("No such file %s", f);
+		}
+
+	}
+}
diff --git a/biz.aQute.jpm/src/aQute/jpm/platform/Linux.java b/biz.aQute.jpm/src/aQute/jpm/platform/Linux.java
new file mode 100644
index 0000000..bf4d48e
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/platform/Linux.java
@@ -0,0 +1,26 @@
+package aQute.jpm.platform;
+
+import java.io.*;
+
+class Linux extends Unix {
+
+	@Override
+	public void shell(String initial) throws IOException {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public String getName() {
+		return "Linux";
+	}
+
+	@Override
+	public void uninstall() {
+
+	}
+	
+	public String toString() {
+		return "Linux";
+	}
+
+}
diff --git a/biz.aQute.jpm/src/aQute/jpm/platform/MacOS.java b/biz.aQute.jpm/src/aQute/jpm/platform/MacOS.java
new file mode 100644
index 0000000..6c46824
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/platform/MacOS.java
@@ -0,0 +1,100 @@
+package aQute.jpm.platform;
+
+import java.io.*;
+import java.util.*;
+
+import aQute.jpm.lib.*;
+import aQute.lib.io.*;
+
+class MacOS extends Unix {
+	File	home	= new File(System.getProperty("user.home"));
+
+	@Override
+	public File getGlobal() {
+		return new File("/Library/Java/PackageManager").getAbsoluteFile();
+	}
+
+	@Override
+	public File getLocal() {
+		return new File(home, "Library/PackageManager").getAbsoluteFile();
+	}
+
+	@Override
+	public void shell(String initial) throws Exception {
+		run("open -n /Applications/Utilities/Terminal.app");
+	}
+
+	@Override
+	public String getName() {
+		return "MacOS";
+	}
+
+	@Override
+	public String createCommand(CommandData data, Map<String,String> map, String... extra) throws Exception {
+		if (data.bin == null)
+			data.bin = getExecutable(data);
+
+		File f = new File(data.bin);
+		if (f.isDirectory()) {
+			f = new File(data.bin, data.name);
+			data.bin = f.getAbsolutePath();
+		}
+
+		if (!data.force && f.exists())
+			return "Command already exists " + data.bin;
+
+		process("macos/command.sh", data, data.bin, map, extra);
+		return null;
+	}
+
+	@Override
+	public String createService(ServiceData data, Map<String,String> map, String ... extra) throws Exception {
+		// File initd = getInitd(data);
+		File launch = getLaunch(data);
+		if (!data.force && launch.exists())
+			return "Cannot create service " + data.name + " because it exists";
+
+		process("macos/launch.sh", data, launch.getAbsolutePath(), map, add(extra, data.serviceLib));
+		return null;
+	}
+
+	@Override
+	public String remove(ServiceData data) {
+		// File initd = getInitd(data);
+		File launch = getLaunch(data);
+
+		if (launch.exists() && !launch.delete())
+			return "Cannot delete service " + data.name + " because it exists and cannot be deleted: " + launch;
+
+		return null;
+	}
+
+	@Override
+	public void installDaemon(boolean user) throws IOException {
+		String dest = "~/Library/LaunchAgents/org.jpm4j.run.plist";
+		if (!user) {
+			dest = "/Library/LaunchAgents/org.jpm4j.run.plist";
+		}
+		IO.copy(getClass().getResource("macos/daemon.plist"), IO.getFile(dest));
+	}
+
+	@Override
+	public void uninstallDaemon(boolean user) throws IOException {
+		if (user)
+			IO.delete(new File("~/Library/LaunchAgents/org.jpm4j.run.plist"));
+		else
+			IO.delete(new File("/Library/LaunchAgents/org.jpm4j.run.plist"));
+	}
+
+	@Override
+	public void uninstall() throws IOException {}
+
+	public String defaultCacertsPassword() {
+		return "changeit";
+	}
+
+	public String toString() {
+		return "MacOS/Darwin";
+	}
+
+}
diff --git a/biz.aQute.jpm/src/aQute/jpm/platform/Platform.java b/biz.aQute.jpm/src/aQute/jpm/platform/Platform.java
new file mode 100644
index 0000000..94dcad2
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/platform/Platform.java
@@ -0,0 +1,162 @@
+package aQute.jpm.platform;
+
+import static aQute.lib.io.IO.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import aQute.jpm.lib.*;
+import aQute.lib.collections.*;
+import aQute.libg.sed.*;
+import aQute.service.reporter.*;
+
+public abstract class Platform {
+	static Platform	platform;
+	static Runtime	runtime	= Runtime.getRuntime();
+	Reporter		reporter;
+
+	/**
+	 * Get the current platform manager.
+	 * 
+	 * @param reporter
+	 * @param jpmx
+	 * @return
+	 */
+	public static Platform getPlatform(Reporter reporter) {
+
+		if (platform == null) {
+
+			String osName = System.getProperty("os.name").toLowerCase();
+			reporter.trace("os.name=%s", osName);
+			if (osName.startsWith("windows"))
+				platform = new Windows();
+			else if (osName.startsWith("mac") || osName.startsWith("darwin"))
+				platform = new MacOS();
+			else
+				platform = new Linux();
+			platform.reporter = reporter;
+			reporter.trace("platform=%s", platform.reporter);
+		}
+		return platform;
+	}
+
+	public abstract File getGlobal();
+
+	public abstract File getLocal();
+
+	abstract public void shell(String initial) throws Exception;
+
+	@Override
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		Formatter formatter = new Formatter(sb);
+		try {
+			formatter.format("Name                %s%n", getName());
+			formatter.format("Local               %s%n", getLocal());
+			formatter.format("Global              %s%n", getGlobal());
+			return formatter.toString();
+		}
+		finally {
+			formatter.close();
+		}
+	}
+
+	abstract public String getName();
+
+	abstract public void uninstall() throws IOException;
+
+	public int run(String args) throws Exception {
+		return runtime.exec(args).waitFor();
+	}
+
+	public abstract String createCommand(CommandData data, Map<String,String> map, String... deps) throws Exception;
+
+	public abstract String createService(ServiceData data, Map<String,String> map, String... deps) throws Exception;
+
+	public abstract String remove(CommandData data) throws Exception;
+
+	public abstract String remove(ServiceData data) throws Exception;
+
+	public abstract int launchService(ServiceData data) throws Exception;
+
+	public abstract void installDaemon(boolean user) throws Exception;
+
+	public abstract void uninstallDaemon(boolean user) throws Exception;
+
+	public abstract void chown(String user, boolean recursive, File file) throws Exception;
+
+	public abstract String user() throws Exception;
+
+	public abstract void deleteCommand(CommandData cmd) throws Exception;
+
+	public String defaultCacertsPassword() {
+		return "changeme";
+	}
+
+	protected void process(String resource, CommandData data, String path, Map<String,String> map, String... extra)
+			throws Exception {
+		File file = new File(path);
+		copy(getClass().getResourceAsStream(resource), file);
+		Sed sed = new Sed(file);
+		sed.setBackup(false);
+		if (data.title == null || data.title.trim().length() == 0)
+			data.title = data.name;
+
+		for (Field key : data.getClass().getFields()) {
+			Object value = key.get(data);
+			if (value == null) {
+				value = "";
+			}
+
+			// We want to enclose the prolog and epilog so they are
+			// executed as one command and thus logged as one command
+			if ("epiplog".equals(key.getName()) || "prolog".equals(key.getName())) {
+				String s = (String) value;
+				if (s != null && s.trim().length() > 0) {
+					value = "(" + s + ")";
+				}
+			}
+			String v = "" + value;
+			v = v.replace("\\", "\\\\");
+			sed.replace("%" + key.getName() + "%", v);
+		}
+		ExtList<String> deps = new ExtList<String>(data.dependencies);
+		for (String x : extra) {
+			deps.add(x);
+		}
+		String classpath = deps.join(File.pathSeparator);
+		sed.replace("%classpath%", classpath.replace("\\", "\\\\"));
+
+		if (map != null) {
+			StringBuilder sb = new StringBuilder();
+			String del = "-D";
+			for (Map.Entry<String,String> e : map.entrySet()) {
+				reporter.trace("define %s=%s", e.getKey(), e.getValue());
+				sed.replace("%" + e.getKey() + "%", e.getValue());
+				sb.append(del).append(e.getKey()).append("=\"").append(e.getValue()).append("\"");
+				del = " -D";
+			}
+			sed.replace("%defines%", sb.toString());
+		} else {
+			sed.replace("%defines%", "");
+		}
+		sed.doIt();
+	}
+
+	protected String[] add(String[] extra, String... more) {
+		if (extra == null || extra.length == 0)
+			return more;
+
+		if (more == null || more.length == 0)
+			return extra;
+
+		String[] result = new String[extra.length + more.length];
+		System.arraycopy(extra, 0, result, 0, extra.length);
+		System.arraycopy(more, 0, result, extra.length, more.length);
+		return result;
+	}
+
+	public abstract void report(Formatter out) throws IOException, Exception;
+
+}
\ No newline at end of file
diff --git a/biz.aQute.jpm/src/aQute/jpm/platform/Service.java b/biz.aQute.jpm/src/aQute/jpm/platform/Service.java
new file mode 100644
index 0000000..bfc267e
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/platform/Service.java
@@ -0,0 +1,11 @@
+package aQute.jpm.platform;
+
+public interface Service {
+	boolean isRunning();
+
+	String status();
+
+	void stop();
+
+	void start();
+}
diff --git a/biz.aQute.jpm/src/aQute/jpm/platform/Unix.java b/biz.aQute.jpm/src/aQute/jpm/platform/Unix.java
new file mode 100644
index 0000000..e47eee2
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/platform/Unix.java
@@ -0,0 +1,202 @@
+package aQute.jpm.platform;
+
+import java.io.*;
+import java.util.*;
+import java.util.regex.*;
+
+import aQute.jpm.lib.*;
+import aQute.lib.io.*;
+import aQute.libg.command.*;
+
+public abstract class Unix extends Platform {
+
+	public static String	BINARIES	= "/usr/bin";
+	public static String	JPM_GLOBAL	= "/var/jpm";
+
+	@Override
+	public File getGlobal() {
+		return new File("/var/jpm");
+	}
+
+	@Override
+	public File getLocal() {
+		File home = new File(System.getProperty("user.home"));
+		return new File(home, ".jpm");
+	}
+
+	@Override
+	public String createCommand(CommandData data, Map<String, String> map, String... extra) throws Exception {
+		if (data.bin == null)
+			data.bin = getExecutable(data);
+
+		File f = new File(data.bin);
+		if (f.isDirectory()) {
+			f = new File(data.bin, data.name);
+			data.bin = f.getAbsolutePath();
+		}
+
+		if (!data.force && f.exists())
+			return "Command already exists " + data.bin;
+
+		process("unix/command.sh", data, data.bin, map, extra);
+		return null;
+	}
+
+	@Override
+	public void deleteCommand(CommandData data) throws Exception {
+		File executable = new File(getExecutable(data));
+		IO.deleteWithException(executable);
+	}
+
+	@Override
+	public String createService(ServiceData data,  Map<String,String> map, String ... extra) throws Exception {
+		File initd = getInitd(data);
+		File launch = getLaunch(data);
+
+		if (!data.force) {
+			if (initd.exists())
+				return "Service already exists in " + initd + ", use --force to override";
+
+			if (launch.exists())
+				return "Service launch file already exists in " + launch + ", use --force to override";
+		}
+
+		process("unix/launch.sh", data, launch.getAbsolutePath(), map, add(extra, data.serviceLib));
+		process("unix/initd.sh", data, initd.getAbsolutePath(), map, add(extra, data.serviceLib));
+		return null;
+	}
+
+	private File getInitd(ServiceData data) {
+		return new File("/etc/init.d/" + data.name);
+	}
+
+	protected File getLaunch(ServiceData data) {
+		return new File(data.sdir, "launch.sh");
+	}
+
+	protected String getExecutable(CommandData data) {
+		return new File(BINARIES + "/" + data.name).getAbsolutePath();
+	}
+
+	@Override
+	public String remove(ServiceData data) {
+		if (!getInitd(data).delete())
+			return "Cannot delete " + getInitd(data);
+
+		File f = new File(getExecutable(data)); 
+		if (!f.delete())
+			return "Cannot delete " + getExecutable(data);
+
+		System.out.println("Removed service data ");
+
+		return null;
+	}
+
+	@Override
+	public String remove(CommandData data) throws Exception {
+		File f = new File(getExecutable(data)); 
+		if (!f.delete())
+			return "Cannot delete " + getExecutable(data);
+
+		return null;
+	}
+
+	@Override
+	public int launchService(ServiceData data) throws Exception {
+		File launch = getLaunch(data);
+		Process p = Runtime.getRuntime().exec(launch.getAbsolutePath(), null, new File(data.work));
+		return p.waitFor();
+	}
+
+	static String	DAEMON			= "\n### JPM BEGIN ###\n" + BINARIES + "/jpm daemon >" + JPM_GLOBAL
+											+ "/daemon.log 2>>" + JPM_GLOBAL + "/daemon.log &\n### JPM END ###\n";
+	static Pattern	DAEMON_PATTERN	= Pattern.compile("\n### JPM BEGIN ###\n.*\n### JPM END ###\n", Pattern.MULTILINE);
+
+	@Override
+	public void installDaemon(boolean user) throws Exception {
+		if (user)
+			throw new IllegalArgumentException("This Unix platform does not support user based agents");
+
+		File rclocal = new File("/etc/rc.d/rc.local");
+		if (!rclocal.isFile())
+			rclocal = new File("/etc/rc.local");
+
+		if (!rclocal.isFile())
+			throw new IllegalArgumentException("Cannot find rc.local in either /etc or /etc/rc.d. Unknown unix");
+
+		String s = IO.collect(rclocal);
+		if (s.contains(DAEMON))
+			return;
+
+		s += DAEMON;
+		IO.store(s, rclocal);
+
+	}
+
+	@Override
+	public void uninstallDaemon(boolean user) throws Exception {
+		if (user)
+			return;
+
+		File rclocal = new File("/etc/rc.d/rc.local");
+		if (!rclocal.isFile())
+			rclocal = new File("/etc/rc.local");
+
+		if (!rclocal.isFile())
+			return;
+
+		String s = IO.collect(rclocal);
+
+		Matcher m = DAEMON_PATTERN.matcher(s);
+		s = m.replaceAll("");
+		s += DAEMON;
+		IO.store(s, rclocal);
+	}
+
+	@Override
+	public void chown(String user, boolean recursive, File file) throws Exception {
+		String cmd = "chown " + (recursive ? " -R " : "") + user + " " + file.getAbsolutePath();
+		if ("root".equals(user))
+			return;
+
+		if ("0".equals(user))
+			return;
+
+		Command chown = new Command(cmd);
+		StringBuilder sb = new StringBuilder();
+
+		int n = chown.execute(sb, sb);
+		if (n != 0)
+			throw new IllegalArgumentException("Changing ownership for " + file + " fails: " + n + " : " + sb);
+	}
+
+	@Override
+	public String user() throws Exception {
+		ProcessBuilder pb = new ProcessBuilder();
+		Map<String,String> environment = pb.environment();
+		String user = environment.get("USER");
+		System.out.println(user);
+		return user;
+		// Command id = new Command("id -nu");
+		// StringBuilder sb = new StringBuilder();
+		//
+		// int n = id.execute(sb,sb);
+		// if ( n != 0)
+		// throw new IllegalArgumentException("Getting user id fails: " + n +
+		// " : " + sb);
+		//
+		// return sb.toString().trim();
+	}
+
+	protected void process(String resource, CommandData data, String file, Map<String,String> map, String... extra) throws Exception {
+		super.process(resource, data, file, map, extra);
+		run("chmod a+x " + file);
+	}
+
+	@Override
+	public void report(Formatter out) throws IOException, Exception {
+		out.format("Name     \t%s\n", getName());
+		out.format("Global   \t%s\n", getGlobal());
+		out.format("Local    \t%s\n", getLocal());
+	}
+}
diff --git a/biz.aQute.jpm/src/aQute/jpm/platform/Windows.java b/biz.aQute.jpm/src/aQute/jpm/platform/Windows.java
new file mode 100644
index 0000000..8dbdb8a
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/platform/Windows.java
@@ -0,0 +1,223 @@
+package aQute.jpm.platform;
+
+/**
+ * http://support.microsoft.com/kb/814596
+ */
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import aQute.jpm.lib.*;
+import aQute.jpm.platform.windows.*;
+import aQute.lib.io.*;
+
+public class Windows extends Platform {
+
+	final static File	home;
+	final static File	bin;
+	final static File	misc;
+
+	static File			javahome;
+
+	static {
+		try {
+			File homex = readkey("Home");
+			if (homex == null) {
+				homex = IO.getFile("~/.jpm");
+			}
+			home = homex;
+
+			misc = new File(home, "misc");
+			misc.mkdirs();
+			bin = new File(home, "Bin");
+			bin.mkdirs();
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+			throw new RuntimeException(e);
+		}
+
+	}
+
+	@Override
+	public File getGlobal() {
+		return home;
+	}
+
+	private static File readkey(String key) throws Exception {
+		String h = WinRegistry.readString(WinRegistry.HKEY_LOCAL_MACHINE, "SOFTWARE\\JPM4j", key);
+		if (h == null)
+			throw new IllegalArgumentException("jpm4j is not installed. Missing registry key HKLM/Software/JPM4j/"
+					+ key);
+		File file = new File(h);
+		file.mkdirs();
+		return file.getAbsoluteFile();
+	}
+
+	@Override
+	public File getLocal() {
+		return IO.getFile("~/.jpm");
+	}
+
+	@Override
+	public void shell(String initial) throws Exception {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public String getName() {
+		return "Windows";
+	}
+
+	/**
+	 * The uninstaller should be used
+	 */
+	@Override
+	public void uninstall() throws IOException {}
+
+	@Override
+	public String createCommand(CommandData data, Map<String,String> map, String... extra) throws Exception {
+		if (data.bin == null)
+			data.bin = getExecutable(data);
+
+		File f = new File(data.bin);
+		if (f.isDirectory()) {
+			f = new File(data.bin, data.name + ".exe");
+			data.bin = f.getAbsolutePath();
+		}
+
+		if (!data.force && f.exists())
+			return "Command already exists " + data.bin + ", try to use --force";
+
+		if (data.name.equals("jpm")) {
+			File exe = new File(misc, "sjpm.exe");
+			File fs = new File(f.getParentFile(), "sjpm.exe");
+			reporter.trace("jpm! %s -> %s", exe, fs);
+			IO.copy(exe, fs);
+		}
+		IO.copy(new File(misc, "runner.exe"), f);
+
+		data.java = getJavaExe();
+		process("windows/command.sh", data, f.getAbsolutePath() + ".jpm", map, extra);
+		return null;
+	}
+
+	protected String getExecutable(CommandData data) {
+		return new File(bin, data.name + ".exe").getAbsolutePath();
+	}
+
+	@Override
+	public String createService(ServiceData data, Map<String,String> map, String... extra) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public String remove(CommandData data) throws Exception {
+		File f = new File(data.bin);
+		if (f.isFile() && !f.delete())
+			return "Could not delete " + data.bin;
+		return null;
+	}
+
+	@Override
+	public String remove(ServiceData data) throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public int launchService(ServiceData data) throws Exception {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+
+	@Override
+	public void installDaemon(boolean user) throws Exception {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public void uninstallDaemon(boolean user) throws Exception {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public void chown(String user, boolean recursive, File file) throws Exception {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public String user() throws Exception {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public void deleteCommand(CommandData cmd) throws Exception {
+		String executable = getExecutable(cmd);
+		File f = new File(executable);
+		File fj = new File(executable + ".jpm");
+		if (cmd.name.equals("jpm")) {
+			reporter.trace("leaving jpm behind");
+			return;
+		} else {
+			IO.deleteWithException(f);
+			IO.deleteWithException(fj);
+		}
+	}
+
+	@Override
+	public String toString() {
+		try {
+			return "Window\nJava Home " + getJavaHome() + "\nJava Exe  " + getJavaExe() + "\nJPM Home  "
+					+ home.getAbsolutePath();
+		}
+		catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	public String getJavaExe() throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
+		return getJavaHome() + "\\bin\\java.exe";
+	}
+
+	public String getJavaHome() throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
+		if (javahome == null) {
+			String version = WinRegistry.readString(WinRegistry.HKEY_LOCAL_MACHINE,
+					"Software\\Javasoft\\Java Runtime Environment", "CurrentVersion");
+			if (version == null)
+				throw new IllegalStateException("No Java installed? Coulnd find version of installed Java");
+
+			String home = WinRegistry.readString(WinRegistry.HKEY_LOCAL_MACHINE,
+					"Software\\Javasoft\\Java Runtime Environment\\" + version, "JavaHome");
+
+			if (home == null)
+				throw new IllegalStateException("No Java installed? Could not find JavaHome for version " + version);
+
+			javahome = new File(home);
+			if (!javahome.isDirectory())
+				throw new IllegalStateException("No Java installed? Java Home could not be found: " + javahome);
+		}
+		return javahome.getAbsolutePath();
+	}
+
+	/**
+	 * Provide as much detail about the jpm environment as possible.
+	 * 
+	 * @throws IOException
+	 * @throws InvocationTargetException
+	 * @throws IllegalAccessException
+	 * @throws IllegalArgumentException
+	 */
+
+	public void report(Formatter f) throws Exception {
+		f.format("Home \t0:%s\n", home);
+		f.format("Java Home \t0:%s\n", getJavaHome());
+		f.format("Java Exe  \t0:%s\n", getJavaExe());
+	}
+}
diff --git a/biz.aQute.jpm/src/aQute/jpm/platform/macos/command.sh b/biz.aQute.jpm/src/aQute/jpm/platform/macos/command.sh
new file mode 100644
index 0000000..b7ccff2
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/platform/macos/command.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec java %defines% -Dpid=$$ -Xdock:name="%title%" %jvmArgs% -cp "%classpath%" %main% "$@"
diff --git a/biz.aQute.jpm/src/aQute/jpm/platform/macos/daemon.plist b/biz.aQute.jpm/src/aQute/jpm/platform/macos/daemon.plist
new file mode 100644
index 0000000..9db370b
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/platform/macos/daemon.plist
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+        <key>Label</key>
+        <string>org.jpm4j.run</string>
+        <key>OnDemand</key>
+        <false/>
+        <key>Program</key>
+        <string>/usr/local/bin/jpm daemon</string>
+</dict>
+</plist>
diff --git a/biz.aQute.jpm/src/aQute/jpm/platform/macos/launch.sh b/biz.aQute.jpm/src/aQute/jpm/platform/macos/launch.sh
new file mode 100644
index 0000000..95dc6e1
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/platform/macos/launch.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+echo "
+#################################################" 2>>%log% >>%log%
+
+%prolog% 2>>%log% >>%log%
+
+sudo -u %user% -i nohup java -Dservice=%name% -Dpid=$$ %jvmArgs% -cp %classpath% aQute.jpm.service.ServiceMain %lock% %main% %args% 2>>%log% >>%log% &
diff --git a/biz.aQute.jpm/src/aQute/jpm/platform/service b/biz.aQute.jpm/src/aQute/jpm/platform/service
new file mode 100644
index 0000000..7d0aec8
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/platform/service
@@ -0,0 +1,2 @@
+#!/bin/sh -e
+/usr/local/bin/jpm $1 `basename $0` $* | sh
diff --git a/biz.aQute.jpm/src/aQute/jpm/platform/unix/command.sh b/biz.aQute.jpm/src/aQute/jpm/platform/unix/command.sh
new file mode 100644
index 0000000..104c5df
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/platform/unix/command.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec java -Dpid=$$ %jvmArgs% -cp "%classpath%" %main% "$@"
diff --git a/biz.aQute.jpm/src/aQute/jpm/platform/unix/initd.sh b/biz.aQute.jpm/src/aQute/jpm/platform/unix/initd.sh
new file mode 100644
index 0000000..41a332e
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/platform/unix/initd.sh
@@ -0,0 +1,2 @@
+#!/bin/sh -e
+jpm $1 `basename $0`
diff --git a/biz.aQute.jpm/src/aQute/jpm/platform/unix/launch.sh b/biz.aQute.jpm/src/aQute/jpm/platform/unix/launch.sh
new file mode 100644
index 0000000..ff53805
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/platform/unix/launch.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+echo "
+#################################################" 2>>%log% >>%log%
+
+%prolog% 2>>%log% >>%log%
+
+su --session-command='nohup java -Dservice=%name% -Dpid=$$ %jvmArgs% -cp %classpath% aQute.jpm.service.ServiceMain %lock% %main% %args%' - %user% 2>>%log% >>%log% &
diff --git a/biz.aQute.jpm/src/aQute/jpm/platform/windows/WinRegistry.java b/biz.aQute.jpm/src/aQute/jpm/platform/windows/WinRegistry.java
new file mode 100644
index 0000000..f6b3b78
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/platform/windows/WinRegistry.java
@@ -0,0 +1,392 @@
+package aQute.jpm.platform.windows;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.prefs.Preferences;
+
+public class WinRegistry {
+  public static final int HKEY_CURRENT_USER = 0x80000001;
+  public static final int HKEY_LOCAL_MACHINE = 0x80000002;
+  public static final int REG_SUCCESS = 0;
+  public static final int REG_NOTFOUND = 2;
+  public static final int REG_ACCESSDENIED = 5;
+
+  private static final int KEY_ALL_ACCESS = 0xf003f;
+  private static final int KEY_READ = 0x20019;
+  private static Preferences userRoot = Preferences.userRoot();
+  private static Preferences systemRoot = Preferences.systemRoot();
+  private static Class<? extends Preferences> userClass = userRoot.getClass();
+  private static Method regOpenKey = null;
+  private static Method regCloseKey = null;
+  private static Method regQueryValueEx = null;
+  private static Method regEnumValue = null;
+  private static Method regQueryInfoKey = null;
+  private static Method regEnumKeyEx = null;
+  private static Method regCreateKeyEx = null;
+  private static Method regSetValueEx = null;
+  private static Method regDeleteKey = null;
+  private static Method regDeleteValue = null;
+
+  static {
+    try {
+      regOpenKey = userClass.getDeclaredMethod("WindowsRegOpenKey",
+          new Class[] { int.class, byte[].class, int.class });
+      regOpenKey.setAccessible(true);
+      regCloseKey = userClass.getDeclaredMethod("WindowsRegCloseKey",
+          new Class[] { int.class });
+      regCloseKey.setAccessible(true);
+      regQueryValueEx = userClass.getDeclaredMethod("WindowsRegQueryValueEx",
+          new Class[] { int.class, byte[].class });
+      regQueryValueEx.setAccessible(true);
+      regEnumValue = userClass.getDeclaredMethod("WindowsRegEnumValue",
+          new Class[] { int.class, int.class, int.class });
+      regEnumValue.setAccessible(true);
+      regQueryInfoKey = userClass.getDeclaredMethod("WindowsRegQueryInfoKey1",
+          new Class[] { int.class });
+      regQueryInfoKey.setAccessible(true);
+      regEnumKeyEx = userClass.getDeclaredMethod(  
+          "WindowsRegEnumKeyEx", new Class[] { int.class, int.class,  
+              int.class });  
+      regEnumKeyEx.setAccessible(true);
+      regCreateKeyEx = userClass.getDeclaredMethod(  
+          "WindowsRegCreateKeyEx", new Class[] { int.class,  
+              byte[].class });  
+      regCreateKeyEx.setAccessible(true);  
+      regSetValueEx = userClass.getDeclaredMethod(  
+          "WindowsRegSetValueEx", new Class[] { int.class,  
+              byte[].class, byte[].class });  
+      regSetValueEx.setAccessible(true); 
+      regDeleteValue = userClass.getDeclaredMethod(  
+          "WindowsRegDeleteValue", new Class[] { int.class,  
+              byte[].class });  
+      regDeleteValue.setAccessible(true); 
+      regDeleteKey = userClass.getDeclaredMethod(  
+          "WindowsRegDeleteKey", new Class[] { int.class,  
+              byte[].class });  
+      regDeleteKey.setAccessible(true); 
+    }
+    catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+
+  private WinRegistry() {  }
+
+  /**
+   * Read a value from key and value name
+   * @param hkey   HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
+   * @param key
+   * @param valueName
+   * @return the value
+   * @throws IllegalArgumentException
+   * @throws IllegalAccessException
+   * @throws InvocationTargetException
+   */
+  public static String readString(int hkey, String key, String valueName) 
+    throws IllegalArgumentException, IllegalAccessException,
+    InvocationTargetException 
+  {
+    if (hkey == HKEY_LOCAL_MACHINE) {
+      return readString(systemRoot, hkey, key, valueName);
+    }
+    else if (hkey == HKEY_CURRENT_USER) {
+      return readString(userRoot, hkey, key, valueName);
+    }
+    else {
+      throw new IllegalArgumentException("hkey=" + hkey);
+    }
+  }
+
+  /**
+   * Read value(s) and value name(s) form given key 
+   * @param hkey  HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
+   * @param key
+   * @return the value name(s) plus the value(s)
+   * @throws IllegalArgumentException
+   * @throws IllegalAccessException
+   * @throws InvocationTargetException
+   */
+  public static Map<String, String> readStringValues(int hkey, String key) 
+    throws IllegalArgumentException, IllegalAccessException,
+    InvocationTargetException 
+  {
+    if (hkey == HKEY_LOCAL_MACHINE) {
+      return readStringValues(systemRoot, hkey, key);
+    }
+    else if (hkey == HKEY_CURRENT_USER) {
+      return readStringValues(userRoot, hkey, key);
+    }
+    else {
+      throw new IllegalArgumentException("hkey=" + hkey);
+    }
+  }
+
+  /**
+   * Read the value name(s) from a given key
+   * @param hkey  HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
+   * @param key
+   * @return the value name(s)
+   * @throws IllegalArgumentException
+   * @throws IllegalAccessException
+   * @throws InvocationTargetException
+   */
+  public static List<String> readStringSubKeys(int hkey, String key) 
+    throws IllegalArgumentException, IllegalAccessException,
+    InvocationTargetException 
+  {
+    if (hkey == HKEY_LOCAL_MACHINE) {
+      return readStringSubKeys(systemRoot, hkey, key);
+    }
+    else if (hkey == HKEY_CURRENT_USER) {
+      return readStringSubKeys(userRoot, hkey, key);
+    }
+    else {
+      throw new IllegalArgumentException("hkey=" + hkey);
+    }
+  }
+
+  /**
+   * Create a key
+   * @param hkey  HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
+   * @param key
+   * @throws IllegalArgumentException
+   * @throws IllegalAccessException
+   * @throws InvocationTargetException
+   */
+  public static void createKey(int hkey, String key) 
+    throws IllegalArgumentException, IllegalAccessException,
+    InvocationTargetException 
+  {
+    int [] ret;
+    if (hkey == HKEY_LOCAL_MACHINE) {
+      ret = createKey(systemRoot, hkey, key);
+      regCloseKey.invoke(systemRoot, new Object[] { new Integer(ret[0]) });
+    }
+    else if (hkey == HKEY_CURRENT_USER) {
+      ret = createKey(userRoot, hkey, key);
+      regCloseKey.invoke(userRoot, new Object[] { new Integer(ret[0]) });
+    }
+    else {
+      throw new IllegalArgumentException("hkey=" + hkey);
+    }
+    if (ret[1] != REG_SUCCESS) {
+      throw new IllegalArgumentException("rc=" + ret[1] + "  key=" + key);
+    }
+  }
+
+  /**
+   * Write a value in a given key/value name
+   * @param hkey
+   * @param key
+   * @param valueName
+   * @param value
+   * @throws IllegalArgumentException
+   * @throws IllegalAccessException
+   * @throws InvocationTargetException
+   */
+  public static void writeStringValue
+    (int hkey, String key, String valueName, String value) 
+    throws IllegalArgumentException, IllegalAccessException,
+    InvocationTargetException 
+  {
+    if (hkey == HKEY_LOCAL_MACHINE) {
+      writeStringValue(systemRoot, hkey, key, valueName, value);
+    }
+    else if (hkey == HKEY_CURRENT_USER) {
+      writeStringValue(userRoot, hkey, key, valueName, value);
+    }
+    else {
+      throw new IllegalArgumentException("hkey=" + hkey);
+    }
+  }
+
+  /**
+   * Delete a given key
+   * @param hkey
+   * @param key
+   * @throws IllegalArgumentException
+   * @throws IllegalAccessException
+   * @throws InvocationTargetException
+   */
+  public static void deleteKey(int hkey, String key) 
+    throws IllegalArgumentException, IllegalAccessException,
+    InvocationTargetException 
+  {
+    int rc = -1;
+    if (hkey == HKEY_LOCAL_MACHINE) {
+      rc = deleteKey(systemRoot, hkey, key);
+    }
+    else if (hkey == HKEY_CURRENT_USER) {
+      rc = deleteKey(userRoot, hkey, key);
+    }
+    if (rc != REG_SUCCESS) {
+      throw new IllegalArgumentException("rc=" + rc + "  key=" + key);
+    }
+  }
+
+  /**
+   * delete a value from a given key/value name
+   * @param hkey
+   * @param key
+   * @param value
+   * @throws IllegalArgumentException
+   * @throws IllegalAccessException
+   * @throws InvocationTargetException
+   */
+  public static void deleteValue(int hkey, String key, String value) 
+    throws IllegalArgumentException, IllegalAccessException,
+    InvocationTargetException 
+  {
+    int rc = -1;
+    if (hkey == HKEY_LOCAL_MACHINE) {
+      rc = deleteValue(systemRoot, hkey, key, value);
+    }
+    else if (hkey == HKEY_CURRENT_USER) {
+      rc = deleteValue(userRoot, hkey, key, value);
+    }
+    if (rc != REG_SUCCESS) {
+      throw new IllegalArgumentException("rc=" + rc + "  key=" + key + "  value=" + value);
+    }
+  }
+
+  // =====================
+
+  private static int deleteValue
+    (Preferences root, int hkey, String key, String value)
+    throws IllegalArgumentException, IllegalAccessException,
+    InvocationTargetException 
+  {
+    int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {
+        new Integer(hkey), toCstr(key), new Integer(KEY_ALL_ACCESS) });
+    if (handles[1] != REG_SUCCESS) {
+      return handles[1];  // can be REG_NOTFOUND, REG_ACCESSDENIED
+    }
+    int rc =((Integer) regDeleteValue.invoke(root,  
+        new Object[] { 
+          new Integer(handles[0]), toCstr(value) 
+          })).intValue();
+    regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
+    return rc;
+  }
+
+  private static int deleteKey(Preferences root, int hkey, String key) 
+    throws IllegalArgumentException, IllegalAccessException,
+    InvocationTargetException 
+  {
+    int rc =((Integer) regDeleteKey.invoke(root,  
+        new Object[] { new Integer(hkey), toCstr(key) })).intValue();
+    return rc;  // can REG_NOTFOUND, REG_ACCESSDENIED, REG_SUCCESS
+  }
+
+  private static String readString(Preferences root, int hkey, String key, String value)
+    throws IllegalArgumentException, IllegalAccessException,
+    InvocationTargetException 
+  {
+    int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {
+        new Integer(hkey), toCstr(key), new Integer(KEY_READ) });
+    if (handles[1] != REG_SUCCESS) {
+      return null; 
+    }
+    byte[] valb = (byte[]) regQueryValueEx.invoke(root, new Object[] {
+        new Integer(handles[0]), toCstr(value) });
+    regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
+    return (valb != null ? new String(valb).trim() : null);
+  }
+
+  private static Map<String,String> readStringValues
+    (Preferences root, int hkey, String key)
+    throws IllegalArgumentException, IllegalAccessException,
+    InvocationTargetException 
+  {
+    HashMap<String, String> results = new HashMap<String,String>();
+    int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {
+        new Integer(hkey), toCstr(key), new Integer(KEY_READ) });
+    if (handles[1] != REG_SUCCESS) {
+      return null;
+    }
+    int[] info = (int[]) regQueryInfoKey.invoke(root,
+        new Object[] { new Integer(handles[0]) });
+
+    int count = info[0]; // count  
+    int maxlen = info[3]; // value length max
+    for(int index=0; index<count; index++)  {
+      byte[] name = (byte[]) regEnumValue.invoke(root, new Object[] {
+          new Integer
+            (handles[0]), new Integer(index), new Integer(maxlen + 1)});
+      if ( name != null) {
+      String value = readString(hkey, key, new String(name));
+      results.put(new String(name).trim(), value);
+      } else {
+    	  System.err.println("huh: " + index);
+      }
+    }
+    regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
+    return results;
+  }
+
+  private static List<String> readStringSubKeys
+    (Preferences root, int hkey, String key)
+    throws IllegalArgumentException, IllegalAccessException,
+    InvocationTargetException 
+  {
+    List<String> results = new ArrayList<String>();
+    int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {
+        new Integer(hkey), toCstr(key), new Integer(KEY_READ) 
+        });
+    if (handles[1] != REG_SUCCESS) {
+      return null;
+    }
+    int[] info = (int[]) regQueryInfoKey.invoke(root,
+        new Object[] { new Integer(handles[0]) });
+
+    int count  = info[0]; // Fix: info[2] was being used here with wrong results. Suggested by davenpcj, confirmed by Petrucio
+    int maxlen = info[3]; // value length max
+    for(int index=0; index<count; index++)  {
+      byte[] name = (byte[]) regEnumKeyEx.invoke(root, new Object[] {
+          new Integer
+            (handles[0]), new Integer(index), new Integer(maxlen + 1)
+          });
+      results.add(new String(name).trim());
+    }
+    regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
+    return results;
+  }
+
+  private static int [] createKey(Preferences root, int hkey, String key)
+    throws IllegalArgumentException, IllegalAccessException,
+    InvocationTargetException 
+  {
+    return  (int[]) regCreateKeyEx.invoke(root,
+        new Object[] { new Integer(hkey), toCstr(key) });
+  }
+
+  private static void writeStringValue 
+    (Preferences root, int hkey, String key, String valueName, String value) 
+    throws IllegalArgumentException, IllegalAccessException,
+    InvocationTargetException 
+  {
+    int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {
+        new Integer(hkey), toCstr(key), new Integer(KEY_ALL_ACCESS) });
+
+    regSetValueEx.invoke(root,  
+        new Object[] { 
+          new Integer(handles[0]), toCstr(valueName), toCstr(value) 
+          }); 
+    regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
+  }
+
+  // utility
+  private static byte[] toCstr(String str) {
+    byte[] result = new byte[str.length() + 1];
+
+    for (int i = 0; i < str.length(); i++) {
+      result[i] = (byte) str.charAt(i);
+    }
+    result[str.length()] = 0;
+    return result;
+  }
+}
diff --git a/biz.aQute.jpm/src/aQute/jpm/platform/windows/command.sh b/biz.aQute.jpm/src/aQute/jpm/platform/windows/command.sh
new file mode 100644
index 0000000..758e8a8
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/platform/windows/command.sh
@@ -0,0 +1 @@
+""%java%" %jvmArgs% -cp "%classpath%" %main%" 
\ No newline at end of file
diff --git a/biz.aQute.jpm/src/aQute/jpm/service/ServiceMain.java b/biz.aQute.jpm/src/aQute/jpm/service/ServiceMain.java
new file mode 100644
index 0000000..0d6af26
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/service/ServiceMain.java
@@ -0,0 +1,156 @@
+package aQute.jpm.service;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.net.*;
+import java.util.*;
+
+import aQute.lib.io.*;
+
+public class ServiceMain extends Thread {
+	static File				lock;
+	Date					last	= new Date();
+	String					message	= "<>";
+	static DatagramSocket	socket;
+	static Class< ? >		mainClass;
+	static Method			serviceMethod;
+	static Thread			mainThread;
+	static final UUID		uuid	= UUID.randomUUID();
+	private boolean			trace	= false;
+
+	public static void main(String args[]) throws Exception, SecurityException, NoSuchMethodException {
+		lock = new File(args[0]).getAbsoluteFile();
+		lock.deleteOnExit();
+
+		if (!lock.exists())
+			throw new IllegalArgumentException("Must start with a valid lock file " + lock);
+
+		
+		socket = new DatagramSocket();
+		ServiceMain main = new ServiceMain();
+
+		main.trace("Port " + socket.getLocalPort());
+
+		write(lock, socket.getLocalPort() + ":" + System.getProperty("pid") + ":" + uuid.toString());
+
+		main.start();
+
+		mainClass = ServiceMain.class.getClassLoader().loadClass(args[1]);
+
+		try {
+			serviceMethod = mainClass.getDeclaredMethod("daemon", boolean.class);
+			serviceMethod.invoke(null, true);
+		}
+		catch (NoSuchMethodException e) {
+			String[] args2 = new String[args.length - 2];
+			System.arraycopy(args, 2, args2, 0, args2.length);
+
+			Method m = mainClass.getDeclaredMethod("main", String[].class);
+			m.invoke(null, (Object) args2);
+		}
+	}
+
+	ServiceMain() {
+		super("jpm main service thread");
+	}
+
+	@Override
+	public void run() {
+		try {
+			byte[] buffer = new byte[1000];
+			DatagramPacket dp = new DatagramPacket(buffer, 1000);
+
+			boolean stopped = false;
+			socket.setSoTimeout(5000);
+
+			while (!isInterrupted() && !stopped) {
+				try {
+					trace("Listening for messages");
+					socket.receive(dp);
+					trace("Received message " + dp.getAddress());
+					if (dp.getAddress().isLoopbackAddress()) {
+
+						String s = new String(dp.getData(), dp.getOffset(), dp.getLength(), "UTF-8");
+						trace("Received message " + s);
+						String parts[] = s.split(":");
+						String reply;
+
+						if (parts[0].equals("STOP")) {
+							stopped = true;
+							reply = "200 STOPPING";
+
+							if (serviceMethod != null) {
+								try {
+									serviceMethod.invoke(null, false);
+								}
+								catch (Exception e) {
+									// Ignore
+								}
+								mainThread.interrupt();
+								mainThread.join(2000);
+							}
+
+						} else if (parts[0].equals("STATUS")) {
+							reply = "200 OK " + last + " " + message;
+						} else if (parts[0].equals("TRACE-ON")) {
+							trace = true;
+							reply = "200 Trace on";
+						} else if (parts[0].equals("TRACE-OFF")) {
+							trace = false;
+							reply = "200 Trace off";
+						} else
+							reply = "404 UNKNOWN REQUEST " + s;
+
+						byte data[] = reply.getBytes("UTF-8");
+						DatagramPacket p = new DatagramPacket(data, 0, data.length, dp.getAddress(), dp.getPort());
+						trace("Sending reply message " + reply);
+						socket.send(p);
+					} else
+						System.err.println("Received UDP from external source");
+				}
+				catch (SocketTimeoutException stoe) {
+					trace("checking lock " + lock + " " + lock.exists());
+					if (!lock.exists())
+						break;
+				}
+			}
+		}
+		catch (Throwable t) {
+			t.printStackTrace();
+		}
+		finally {
+			try {
+				socket.close();
+			}
+			finally {
+				try {
+					lock.delete();
+				}
+				finally {
+					System.exit(1);
+				}
+			}
+		}
+	}
+
+	private void trace(String string) {
+		if (trace)
+			System.err.println("JPM: " + string);
+	}
+
+	private static void write(File f, String response) throws IOException {
+		PrintWriter fw = IO.writer(f);
+		try {
+			fw.append(response);
+		}
+		finally {
+			fw.close();
+		}
+	}
+
+	public synchronized void setMessage(String m) {
+		trace(m);
+		last = new Date();
+		message = m;
+	}
+}
diff --git a/biz.aQute.jpm/src/aQute/jpm/service/TraceSecurityManager.java b/biz.aQute.jpm/src/aQute/jpm/service/TraceSecurityManager.java
new file mode 100644
index 0000000..b3076fb
--- /dev/null
+++ b/biz.aQute.jpm/src/aQute/jpm/service/TraceSecurityManager.java
@@ -0,0 +1,68 @@
+package aQute.jpm.service;
+
+import java.security.*;
+import java.util.*;
+
+public class TraceSecurityManager extends SecurityManager {
+	final HashSet<Permission>	had	= new HashSet<Permission>();
+
+	public TraceSecurityManager() {
+
+		Runtime.getRuntime().addShutdownHook(new Thread() {
+			public void run() {
+				Set<Permission> hadx;
+				synchronized (TraceSecurityManager.this) {
+					 hadx = new HashSet<Permission>(TraceSecurityManager.this.had);
+				}
+				Set<Permission> implied = new HashSet<Permission>();
+
+				for (Permission smaller : hadx) {
+					for (Permission larger : hadx) {
+						if (smaller != larger && larger.implies(smaller))
+							implied.add(smaller);
+					}
+				}
+				hadx.removeAll(implied);
+
+				ArrayList<Permission> sorted = new ArrayList<Permission>(hadx);
+				Collections.sort(sorted, new Comparator<Permission>() {
+
+					public int compare(Permission a, Permission b) {
+						if (a.getClass() == b.getClass()) {
+							if (a.getName().equals(b.getName())) {
+								return a.getActions().compareTo(b.getActions());
+							} else
+								return a.getName().compareTo(b.getName());
+						} else
+							return shorten(a.getClass().getName()).compareTo(shorten(b.getClass().getName()));
+					}
+				});
+				for (Permission p : sorted) {
+					System.err.println(shorten(p.getClass().getName()) + ":" + p.getName() + ":" + p.getActions());
+				}
+			}
+
+			String shorten(String name) {
+				int n = name.lastIndexOf('.');
+				if (n < 0)
+					return name;
+
+				return name.substring(n + 1);
+			}
+		});
+	}
+
+	public synchronized void checkPermission(Permission perm) {
+		if ( perm.getClass() == AllPermission.class)
+			throw new SecurityException();
+		
+		if (had.contains(perm))
+			return;
+
+		had.add(perm);
+	}
+
+	public void checkPermission(Permission perm, Object o) {
+		checkPermission(perm);
+	}
+}
diff --git a/biz.aQute.jpm/test/test/JPMTest.java b/biz.aQute.jpm/test/test/JPMTest.java
new file mode 100644
index 0000000..685de93
--- /dev/null
+++ b/biz.aQute.jpm/test/test/JPMTest.java
@@ -0,0 +1,98 @@
+package test;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import junit.framework.*;
+import aQute.jpm.lib.*;
+import aQute.jpm.platform.*;
+import aQute.libg.reporter.*;
+import aQute.service.library.Library.Revision;
+import aQute.service.reporter.*;
+
+public class JPMTest extends TestCase {
+	static File	cwd	= new File(System.getProperty("user.dir")).getAbsoluteFile();
+
+	static class PLF extends Unix {
+
+		@Override
+		public void shell(String initial) throws Exception {}
+
+		@Override
+		public String getName() {
+			return "Test Platform";
+		}
+
+		@Override
+		public void uninstall() {}
+
+		@Override
+		public File getGlobal() {
+			return new File(cwd, "global").getAbsoluteFile();
+		}
+
+		@Override
+		public File getLocal() {
+			return new File(cwd, "local").getAbsoluteFile();
+		}
+
+		@Override
+		public String createCommand(CommandData data, Map<String,String> map, String ...strings ) throws Exception {
+			return null;
+		}
+
+		@Override
+		public String createService(ServiceData data, Map<String,String> map, String ...strings ) throws Exception {
+			return null;
+		}
+
+		@Override
+		public void installDaemon(boolean user) throws Exception {
+			// TODO Auto-generated method stub
+			
+		}
+		@Override
+		public void uninstallDaemon(boolean user) throws Exception {
+			// TODO Auto-generated method stub
+			
+		}
+	}
+
+	public void testCandidates() throws Exception {
+		Reporter r = new ReporterAdapter();
+		JustAnotherPackageManager jpm = new JustAnotherPackageManager(r);
+		jpm.setPlatform( new PLF());
+		jpm.setLibrary(new URI("http://localhost:8080/rest"));
+
+		ArtifactData a = jpm.getCandidate("aQute.libg", false);
+		assertNotNull(a);
+		
+		a.sync();
+		assertNull(a.error);
+		
+		
+		List<Revision> candidates = jpm.getCandidates("hello");
+		assertNotNull(candidates);
+		
+		candidates = jpm.getCandidates("aQute.libg");
+		assertNotNull(candidates);
+	}
+	
+	
+	public static void testSimple() throws IOException {
+		Reporter r = new ReporterAdapter();
+		JustAnotherPackageManager jpm = new JustAnotherPackageManager(r);
+		Platform plf = new PLF();
+		jpm.setPlatform(plf);
+
+	}
+	
+	public static void testDownload() throws Exception {
+		ReporterAdapter reporter = new ReporterAdapter();
+		JustAnotherPackageManager jpm = new JustAnotherPackageManager(reporter);
+		jpm.setLibrary(new URI("http://localhost:8080/rest"));
+		ArtifactData artifact = jpm.getCandidate("aQute.libg", true);
+		assertNotNull(artifact);
+	}
+}
diff --git a/biz.aQute.junit/.settings/org.eclipse.jdt.core.prefs b/biz.aQute.junit/.settings/org.eclipse.jdt.core.prefs
index 81054b7..1e089dc 100644
--- a/biz.aQute.junit/.settings/org.eclipse.jdt.core.prefs
+++ b/biz.aQute.junit/.settings/org.eclipse.jdt.core.prefs
@@ -1,4 +1,4 @@
-#Tue May 25 12:16:34 CEST 2010
+#Fri Aug 10 14:06:03 CEST 2012
 eclipse.preferences.version=1
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.targetPlatform=jsr14
@@ -7,6 +7,355 @@ org.eclipse.jdt.core.compiler.compliance=1.5
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=ignore
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
 org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=true
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/biz.aQute.junit/.settings/org.eclipse.jdt.ui.prefs b/biz.aQute.junit/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..f5e8897
--- /dev/null
+++ b/biz.aQute.junit/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,61 @@
+#Fri Aug 10 13:48:46 CEST 2012
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=false
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=false
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=false
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
+cleanup_settings_version=2
+eclipse.preferences.version=1
+formatter_profile=_bnd(tools)
+formatter_settings_version=12
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=1
+org.eclipse.jdt.ui.staticondemandthreshold=1
diff --git a/biz.aQute.junit/bnd.bnd b/biz.aQute.junit/bnd.bnd
index 6ccbdcf..f749234 100644
--- a/biz.aQute.junit/bnd.bnd
+++ b/biz.aQute.junit/bnd.bnd
@@ -1,19 +1,29 @@
--buildpath: com.springsource.junit,\
-	ee.minimum;version=1.2.1,\
+-buildpath: com.springsource.org.junit,\
 	osgi.cmpn;version=4.2.1,\
 	biz.aQute.bndlib;version=project,\
 	aQute.libg;version=project,\
-	osgi.core;version=4.2.1
+	osgi.core;version=4.2.1,\
+	ee.j2se;version=${javac.ee}
 	
 Tester-Plugin: aQute.junit.plugin.ProjectTesterImpl
 
 javac.source = 1.5
 javac.target = jsr14
 Private-Package: aQute.junit.*,\
-	junit.framework
-Export-Package: junit.framework; version=3.8
-Import-Package: !aQute.*,\
-	*
+	junit.*,\
+	org.junit.*
+	
+Export-Package: junit.framework; version=3.8,\
+				org.junit.*;version=4.10, \
+				org.hamcrest.*;version=1.0.0
+
+# The dependency on aQute packages is only for the 
+# master side. When launched, those dependencies
+# are not necessary
+Import-Package: aQute.*;resolution:=optional,*
 Bundle-Activator: aQute.junit.Activator
 Embedded-Activator: aQute.junit.Activator
-Bundle-Version: 1.0.0
+Bundle-Version: 1.2.0.${tstamp;yyyyMMdd-HHmmss}
+Bundle-Release: Use main thread for testing, optionally allowing old separate thread model
+
+
diff --git a/biz.aQute.junit/src/aQute/junit/Activator.java b/biz.aQute.junit/src/aQute/junit/Activator.java
index eb0dd8a..49b60c0 100644
--- a/biz.aQute.junit/src/aQute/junit/Activator.java
+++ b/biz.aQute.junit/src/aQute/junit/Activator.java
@@ -2,52 +2,76 @@ package aQute.junit;
 
 import java.io.*;
 import java.lang.reflect.*;
-import java.net.*;
 import java.util.*;
 
 import junit.framework.*;
 
+import org.junit.runner.*;
+import org.junit.runner.manipulation.*;
 import org.osgi.framework.*;
 
 import aQute.junit.constants.*;
 
-public class Activator extends Thread implements BundleActivator, TesterConstants {
+public class Activator implements BundleActivator, TesterConstants, Runnable {
 	BundleContext		context;
 	volatile boolean	active;
 	int					port		= -1;
-	String				reportPath;
 	boolean				continuous	= false;
 	boolean				trace		= false;
 	PrintStream			out			= System.err;
 	JUnitEclipseReport	jUnitEclipseReport;
-	
+	volatile Thread		thread;
+
 	public Activator() {
-		super("bnd Runtime Test Bundle");
 	}
 
 	public void start(BundleContext context) throws Exception {
 		this.context = context;
 		active = true;
-		start();
+		if (!Boolean.valueOf(context.getProperty(TESTER_SEPARATETHREAD)) && 
+				Boolean.valueOf(context.getProperty("launch.services"))) { // can't register services on mini framework
+			Hashtable<String,String> ht = new Hashtable<String,String>();
+			ht.put("main.thread", "true");
+			ht.put(Constants.SERVICE_DESCRIPTION, "JUnit tester");
+			context.registerService(Runnable.class.getName(), this, ht);
+		} else {
+			thread = new Thread(this,"bnd Runtime Test Bundle");
+			thread.start();
+		}
 	}
 
 	public void stop(BundleContext context) throws Exception {
 		active = false;
-		if ( jUnitEclipseReport != null)
+		if (jUnitEclipseReport != null)
 			jUnitEclipseReport.close();
-		interrupt();
-		join(10000);
+		
+		if (thread != null) {
+			thread.interrupt();
+			thread.join(10000);
+		}
 	}
 
 	public void run() {
+		
 		continuous = Boolean.valueOf(context.getProperty(TESTER_CONTINUOUS));
 		trace = context.getProperty(TESTER_TRACE) != null;
+		
+		if (thread == null)
+			trace("running in main thread");
+		
+		// We can be started on our own thread or from the main code
+		thread = Thread.currentThread();
+		
+
 		String testcases = context.getProperty(TESTER_NAMES);
+		trace("test cases %s", testcases);
 		if (context.getProperty(TESTER_PORT) != null) {
 			port = Integer.parseInt(context.getProperty(TESTER_PORT));
 			try {
+				trace("using port %s", port);
 				jUnitEclipseReport = new JUnitEclipseReport(port);
-			} catch (Exception e) {
+			}
+			catch (Exception e) {
 				System.err.println("Cannot create link Eclipse JUnit on port " + port);
 				System.exit(-2);
 			}
@@ -55,29 +79,37 @@ public class Activator extends Thread implements BundleActivator, TesterConstant
 
 		if (testcases == null) {
 			trace("automatic testing of all bundles with Test-Cases header");
-			automatic();
+			try {
+				automatic();
+			}
+			catch (IOException e) {
+				// ignore
+			}
 		} else {
 			trace("receivednames of classes to test %s", testcases);
 			try {
 				int errors = test(null, testcases, null);
 				System.exit(errors);
-			} catch (Exception e) {
+			}
+			catch (Exception e) {
 				e.printStackTrace();
 				System.exit(-2);
 			}
 		}
 	}
 
-	void automatic() {
+	void automatic() throws IOException {
 		String testerDir = context.getProperty(TESTER_DIR);
-		if ( testerDir == null)
-			testerDir ="testdir";
-		
-		
+		if (testerDir == null)
+			testerDir = "testdir";
+
 		final File reportDir = new File(testerDir);
 		final List<Bundle> queue = new Vector<Bundle>();
-		trace( "using %s, needed creation %s", reportDir, reportDir.mkdirs());
-		
+		if (!reportDir.exists() && !reportDir.mkdirs()) {
+			throw new IOException("Could not create directory " + reportDir);
+		}
+		trace("using %s, needed creation %s", reportDir, reportDir.mkdirs());
+
 		trace("adding Bundle Listener for getting test bundle events");
 		context.addBundleListener(new SynchronousBundleListener() {
 			public void bundleChanged(BundleEvent event) {
@@ -100,37 +132,40 @@ public class Activator extends Thread implements BundleActivator, TesterConstant
 				while (queue.isEmpty() && active) {
 					try {
 						queue.wait();
-					} catch (InterruptedException e) {
+					}
+					catch (InterruptedException e) {
 						trace("tests bundle queue interrupted");
-						interrupt();
+						thread.interrupt();
 						break outer;
 					}
 				}
 			}
 			try {
-				bundle = (Bundle) queue.remove(0);
+				bundle = queue.remove(0);
 				trace("received bundle to test: %s", bundle.getLocation());
 				Writer report = getReportWriter(reportDir, bundle);
 				try {
 					trace("test will run");
 					result += test(bundle, (String) bundle.getHeaders().get("Test-Cases"), report);
 					trace("test ran");
-					if ( queue.isEmpty() && !continuous) {
-						trace( "queue " + queue );
+					if (queue.isEmpty() && !continuous) {
+						trace("queue " + queue);
 						System.exit(result);
 					}
-				} finally {
+				}
+				finally {
 					if (report != null)
 						report.close();
 				}
-			} catch (Exception e) {
+			}
+			catch (Exception e) {
 				error("Not sure what happened anymore %s", e);
 				System.exit(-2);
 			}
 		}
 	}
 
-	private void checkBundle(List<Bundle> queue, Bundle bundle) {
+	void checkBundle(List<Bundle> queue, Bundle bundle) {
 		if (bundle.getState() == Bundle.ACTIVE) {
 			String testcases = (String) bundle.getHeaders().get("Test-Cases");
 			if (testcases != null) {
@@ -146,9 +181,9 @@ public class Activator extends Thread implements BundleActivator, TesterConstant
 	private Writer getReportWriter(File reportDir, Bundle bundle) throws IOException {
 		if (reportDir.isDirectory()) {
 			Version v = bundle.getVersion();
-			File f = new File(reportDir, "TEST-" + bundle.getSymbolicName() + "-" + v.getMajor()
-					+ "." + v.getMinor() + "." + v.getMicro() + ".xml");
-			return new FileWriter(f);
+			File f = new File(reportDir, "TEST-" + bundle.getSymbolicName() + "-" + v.getMajor() + "." + v.getMinor()
+					+ "." + v.getMicro() + ".xml");
+			return new OutputStreamWriter(new FileOutputStream(f), "UTF-8");
 		}
 		return null;
 	}
@@ -179,7 +214,7 @@ public class Activator extends Thread implements BundleActivator, TesterConstant
 			Tee systemErr;
 			Tee systemOut;
 
-			systemOut = new Tee(System.out);
+			systemOut = new Tee(System.err);
 			systemErr = new Tee(System.err);
 			systemOut.capture(trace).echo(true);
 			systemErr.capture(trace).echo(true);
@@ -189,6 +224,7 @@ public class Activator extends Thread implements BundleActivator, TesterConstant
 			try {
 
 				BasicTestReport basic = new BasicTestReport(this, systemOut, systemErr) {
+					@Override
 					public void check() {
 						if (!active)
 							result.stop();
@@ -206,9 +242,9 @@ public class Activator extends Thread implements BundleActivator, TesterConstant
 				}
 
 				for (TestReporter tr : reporters) {
-					tr.setup(fw,bundle);
+					tr.setup(fw, bundle);
 				}
-				
+
 				try {
 					TestSuite suite = createSuite(bundle, names, result);
 					trace("created suite " + suite);
@@ -221,16 +257,19 @@ public class Activator extends Thread implements BundleActivator, TesterConstant
 					trace("running suite " + suite);
 					suite.run(result);
 
-				} catch (Throwable t) {
-					trace( t.getMessage());
+				}
+				catch (Throwable t) {
+					trace(t.getMessage());
 					result.addError(null, t);
-				} finally {
+				}
+				finally {
 					for (TestReporter tr : reporters) {
 						tr.end();
 					}
 				}
-			} catch(Throwable t) {
-				System.out.println("exiting " + t);
+			}
+			catch (Throwable t) {
+				System.err.println("exiting " + t);
 				t.printStackTrace();
 			}
 			finally {
@@ -238,10 +277,14 @@ public class Activator extends Thread implements BundleActivator, TesterConstant
 				System.setErr(systemErr.oldStream);
 				trace("unset streams");
 			}
-			System.err.println("Errors: " + result.errorCount());
-			System.err.println("Failures: " + result.failureCount());
+			System.err.println("Tests run  : " + result.runCount());
+			System.err.println("Passed     : " + (result.runCount() - result.errorCount() - result.failureCount()));
+			System.err.println("Errors     : " + result.errorCount());
+			System.err.println("Failures   : " + result.failureCount());
+
 			return result.errorCount() + result.failureCount();
-		} catch (Exception e) {
+		}
+		catch (Exception e) {
 			e.printStackTrace();
 		}
 		return -1;
@@ -250,47 +293,145 @@ public class Activator extends Thread implements BundleActivator, TesterConstant
 	private TestSuite createSuite(Bundle tfw, List<String> testNames, TestResult result) throws Exception {
 		TestSuite suite = new TestSuite();
 		for (String fqn : testNames) {
-			try {
-				int n = fqn.indexOf(':');
-				if (n > 0) {
-					String method = fqn.substring(n + 1);
-					fqn = fqn.substring(0, n);
-					Class<?> clazz = loadClass(tfw, fqn);
-					suite.addTest(TestSuite.createTest(clazz, method));
-				} else {
-					Class<?> clazz = loadClass(tfw, fqn);
-					suite.addTestSuite(clazz);
+			addTest(tfw, suite, fqn, result);
+		}
+		return suite;
+	}
+
+	private void addTest(Bundle tfw, TestSuite suite, String fqn, TestResult testResult) {
+		try {
+			int n = fqn.indexOf(':');
+			if (n > -1) {
+				String method = fqn.substring(n + 1);
+				fqn = fqn.substring(0, n);
+				Class< ? > clazz = loadClass(tfw, fqn);
+				if (clazz != null)
+					addTest(tfw, suite, clazz, testResult, method);
+				else {
+					diagnoseNoClass(tfw, fqn);
+					testResult.addError(suite, new Exception("Cannot load class " + fqn
+							+ ", was it included in the test bundle?"));
+				}
+
+			} else {
+				Class< ? > clazz = loadClass(tfw, fqn);
+				if (clazz != null)
+					addTest(tfw, suite, clazz, testResult, null);
+				else {
+					diagnoseNoClass(tfw, fqn);
+					testResult.addError(suite, new Exception("Cannot load class " + fqn
+							+ ", was it included in the test bundle?"));
 				}
-			} catch (Throwable e) {
-				System.err.println("Can not create test case for: " + fqn + " : " + e);
-				result.addError(suite, e);
 			}
 		}
-		return suite;
+		catch (Throwable e) {
+			System.err.println("Can not create test case for: " + fqn + " : " + e);
+			testResult.addError(suite, e);
+		}
 	}
 
-	private Class<?> loadClass(Bundle tfw, String fqn) {
-		if (tfw != null)
-			try {
-				return tfw.loadClass(fqn);
-			} catch (ClassNotFoundException e1) {
-				return null;
+	private void diagnoseNoClass(Bundle tfw, String fqn) {
+		if ( tfw == null) {
+			error("No class found: %s, target bundle: %s", fqn, tfw);
+			trace("Installed bundles:");
+			for ( Bundle bundle : context.getBundles()) {
+				Class<?> c = loadClass(bundle,fqn);
+				String state;
+				switch(bundle.getState()) {
+					case Bundle.UNINSTALLED: state = "UNINSTALLED"; break;
+					case Bundle.INSTALLED: state = "INSTALLED"; break;
+					case Bundle.RESOLVED: state = "RESOLVED"; break;
+					case Bundle.STARTING: state = "STARTING"; break;
+					case Bundle.STOPPING: state = "STOPPING"; break;
+					case Bundle.ACTIVE: state = "ACTIVE"; break;
+					default:
+						state = "UNKNOWN";
+				}
+				trace("%s %s %s", bundle.getLocation(), state, c != null);
 			}
+		}
+	}
+
+	@SuppressWarnings("unchecked")
+	private void addTest(@SuppressWarnings("unused")
+	Bundle tfw, TestSuite suite, Class< ? > clazz, @SuppressWarnings("unused")
+	TestResult testResult, final String method) {
+		if (TestCase.class.isAssignableFrom(clazz)) {
+			if (method != null) {
+				suite.addTest(TestSuite.createTest(clazz, method));
+				return;
+			}
+			suite.addTestSuite((Class< ? extends TestCase>) clazz);
+			return;
+		}
 
-		Bundle bundles[] = context.getBundles();
-		for (int i = bundles.length - 1; i >= 0; i--) {
+		JUnit4TestAdapter adapter = new JUnit4TestAdapter(clazz);
+		if (method != null) {
 			try {
-				return bundles[i].loadClass(fqn);
-			} catch (Exception e) {
-				// Ignore, looking further
+				adapter.filter(new org.junit.runner.manipulation.Filter() {
+
+					@Override
+					public String describe() {
+						return "Method filter";
+					}
+
+					@Override
+					public boolean shouldRun(Description description) {
+						if (method.equals(description.getMethodName())) {
+							return true;
+						}
+						return false;
+					}
+				});
+			}
+			catch (NoTestsRemainException e) {
+				return;
 			}
 		}
+		suite.addTest(new JUnit4TestAdapter(clazz));
+	}
+
+	private Class< ? > loadClass(Bundle tfw, String fqn) {
+		try {
+			if (tfw != null) {
+				checkResolved(tfw);
+				try {
+					return tfw.loadClass(fqn);
+				}
+				catch (ClassNotFoundException e1) {
+					return null;
+				}
+			}
+
+			Bundle bundles[] = context.getBundles();
+			for (int i = bundles.length - 1; i >= 0; i--) {
+				try {
+					checkResolved(bundles[i]);
+					return bundles[i].loadClass(fqn);
+				}
+				catch (ClassNotFoundException e1) {
+					// try next
+				}
+			}
+		}
+		catch (Exception e) {
+			error("Exception during loading of class: %s. Exception %s and cause %s. This sometimes "
+					+ "happens when there is an error in the static initialization, the class has "
+					+ "no public constructor, it is an inner class, or it has no public access", fqn, e, e.getCause());
+		}
 		return null;
 	}
 
+	private void checkResolved(Bundle bundle) {
+		int state = bundle.getState();
+		if (state == Bundle.INSTALLED || state == Bundle.UNINSTALLED) {
+			trace("unresolved bundle %s", bundle.getLocation());
+		}
+	}
+
 	public int flatten(List<Test> list, TestSuite suite) {
 		int realCount = 0;
-		for (Enumeration<?> e = suite.tests(); e.hasMoreElements();) {
+		for (Enumeration< ? > e = suite.tests(); e.hasMoreElements();) {
 			Test test = (Test) e.nextElement();
 			list.add(test);
 			if (test instanceof TestSuite)
@@ -334,26 +475,26 @@ public class Activator extends Thread implements BundleActivator, TesterConstant
 			if (c == '%') {
 				c = string.charAt(++i);
 				switch (c) {
-				case 's':
-					if (n < objects.length) {
-						Object o = objects[n++];
-						if (o instanceof Throwable) {
-							e = (Throwable) o;
-							if (o instanceof InvocationTargetException) {
-								Throwable t = (InvocationTargetException) o;
-								sb.append(t.getMessage());
-								e = t;
-							} else
-								sb.append(e.getMessage());
-						} else {
-							sb.append(o);
-						}
-					} else
-						sb.append("<no more arguments>");
-					break;
-
-				default:
-					sb.append(c);
+					case 's' :
+						if (n < objects.length) {
+							Object o = objects[n++];
+							if (o instanceof Throwable) {
+								e = (Throwable) o;
+								if (o instanceof InvocationTargetException) {
+									Throwable t = (InvocationTargetException) o;
+									sb.append(t.getMessage());
+									e = t;
+								} else
+									sb.append(e.getMessage());
+							} else {
+								sb.append(o);
+							}
+						} else
+							sb.append("<no more arguments>");
+						break;
+
+					default :
+						sb.append(c);
 				}
 			} else {
 				sb.append(c);
@@ -368,8 +509,4 @@ public class Activator extends Thread implements BundleActivator, TesterConstant
 		message("! ", msg, objects);
 	}
 
-	static void main() throws URISyntaxException {
-		URI uri = new URI("/abc/def");
-	}
-
 }
diff --git a/biz.aQute.junit/src/aQute/junit/BasicTestReport.java b/biz.aQute.junit/src/aQute/junit/BasicTestReport.java
index 427b5c7..4b28e04 100644
--- a/biz.aQute.junit/src/aQute/junit/BasicTestReport.java
+++ b/biz.aQute.junit/src/aQute/junit/BasicTestReport.java
@@ -26,8 +26,8 @@ public class BasicTestReport implements TestListener, TestReporter {
 	public void setup(Bundle fw, Bundle targetBundle) {
 		this.targetBundle = targetBundle;
 	}
-	
-	public void begin(List tests, int realcount) {
+
+	public void begin(List<Test> tests, int realcount) {
 		activator.trace(">>>> %s, tests %s", targetBundle, tests);
 	}
 
@@ -54,21 +54,26 @@ public class BasicTestReport implements TestListener, TestReporter {
 
 		if (b != null) {
 			BundleContext context = b.getBundleContext();
-			activator.trace("got bundle context %s from %s in state %s", context, b, b.getState()	);
+			activator.trace("got bundle context %s from %s in state %s", context, b, b.getState());
 			assert context != null;
 			try {
-				Method m = test.getClass().getMethod("setBundleContext",
-						new Class[] { BundleContext.class });
+				Method m = test.getClass().getMethod("setBundleContext", new Class[] {
+					BundleContext.class
+				});
 				m.setAccessible(true);
-				m.invoke(test, new Object[] { context });
+				m.invoke(test, new Object[] {
+					context
+				});
 				activator.trace("set context through setter");
-			} catch (Exception e) {
+			}
+			catch (Exception e) {
 				Field f;
 				try {
 					f = test.getClass().getField("context");
 					f.set(test, context);
 					activator.trace("set context in field");
-				} catch (Exception e1) {
+				}
+				catch (Exception e1) {
 					// Ok, no problem
 				}
 			}
@@ -79,7 +84,7 @@ public class BasicTestReport implements TestListener, TestReporter {
 	}
 
 	public void endTest(Test test) {
-		activator.trace("  << %s, fails=%s", test, fails);
+		activator.trace("  << %s, fails=%s, errors=%s", test, fails, errors);
 		systemOut.capture(false);
 		systemErr.capture(false);
 		if (fails > 0) {
@@ -108,6 +113,8 @@ public class BasicTestReport implements TestListener, TestReporter {
 	}
 
 	String[] getCaptured() {
-		return new String[] { systemOut.getContent(), systemErr.getContent() };
+		return new String[] {
+				systemOut.getContent(), systemErr.getContent()
+		};
 	}
 }
diff --git a/biz.aQute.junit/src/aQute/junit/JUnitEclipseReport.java b/biz.aQute.junit/src/aQute/junit/JUnitEclipseReport.java
index 1368817..8039d87 100644
--- a/biz.aQute.junit/src/aQute/junit/JUnitEclipseReport.java
+++ b/biz.aQute.junit/src/aQute/junit/JUnitEclipseReport.java
@@ -10,129 +10,132 @@ import junit.framework.*;
 import org.osgi.framework.*;
 
 public class JUnitEclipseReport implements TestReporter {
-    int            port;
-    boolean        open;
-    BufferedReader in;
-    PrintWriter    out;
-    long           startTime;
-    Bundle         targetBundle;
-    List           tests;
-    boolean        verbose = false;
-    Test           current;
-
-    public JUnitEclipseReport(int port) throws Exception {
-        Socket socket = null;
-        for (int i = 0; socket == null && i < 10; i++) {
-            try {
-                socket = new Socket("127.0.0.1", port);
-            } catch (ConnectException ce) {
-                Thread.sleep(i * 100);
-            }
-        }
-        if (socket == null) {
-        	System.err.println("Cannot open the JUnit Port: " + port);
-            System.exit(-2);
-        }
-
-        in = new BufferedReader(new InputStreamReader(socket.getInputStream(),
-                "UTF-8"));
-        out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(),
-                "UTF-8"));
-    }
-
-    public void setup(Bundle fw, Bundle targetBundle) {
-        this.targetBundle = targetBundle;    	
-    }
-    
-    public void begin(List tests, int realcount) {
-        this.tests = tests;
-        message("%TESTC  ", realcount + " v2");
-        report(tests);
-        startTime = System.currentTimeMillis();
-    }
-
-    public void end() {
-        message("%RUNTIME", "" + (System.currentTimeMillis() - startTime));
-        out.flush();
-        out.close();
-    }
-
-    public void addError(Test test, Throwable t) {
-        message("%ERROR  ", test);
-        trace(t);
-    }
-
-    public void addFailure(Test test, AssertionFailedError t) {
-        message("%FAILED ", test);
-        trace(t);
-    }
-
-    void trace(Throwable t) {
-        message("%TRACES ", "");
-        t.printStackTrace(out);
-        out.println();
-        message("%TRACEE ", "");
-    }
-
-    public void endTest(Test test) {
-        message("%TESTE  ", test);
-    }
-
-    public void startTest(Test test) {
-        this.current = test;
-        message("%TESTS  ", test);
-        try {
-            Method m = test.getClass().getMethod("setBundleContext",
-                    new Class[] { BundleContext.class });
-            m.invoke(test, new Object[] { targetBundle.getBundleContext() });
-        } catch (Exception e) {
-
-        }
-    }
-
-    private void message(String key, String payload) {
-        if (key.length() != 8)
-            throw new IllegalArgumentException(key + " is not 8 characters");
-
-        out.print(key);
-        out.println(payload);
-        out.flush();
-        if (verbose)
-            System.out.println(key + payload);
-    }
-
-    private void message(String key, Test test) {
-    	if ( tests == null )
-            message(key, "?,"+test);
-    	else
-    		message(key, (tests.indexOf(test) + 1) + "," + test);
-    }
-
-    private void report(List flattened) {
-        for (int i = 0; i < flattened.size(); i++) {
-            StringBuffer sb = new StringBuffer();
-            sb.append(i + 1);
-            sb.append(",");
-            Test test = (Test) flattened.get(i);
-            sb.append(flattened.get(i));
-            sb.append(",");
-            sb.append(test instanceof TestSuite);
-            sb.append(",");
-            sb.append(test.countTestCases());
-            message("%TSTTREE", sb.toString());
-        }
-    }
-
-    public void aborted() {   
-        end();
-    }
+	BufferedReader	in;
+	PrintWriter		out;
+	long			startTime;
+	Bundle			targetBundle;
+	List<Test>		tests;
+	boolean			verbose	= false;
+	Test			current;
+
+	public JUnitEclipseReport(int port) throws Exception {
+		Socket socket = null;
+		for (int i = 0; socket == null && i < 10; i++) {
+			try {
+				socket = new Socket("127.0.0.1", port);
+			}
+			catch (ConnectException ce) {
+				Thread.sleep(i * 100);
+			}
+		}
+		if (socket == null) {
+			System.err.println("Cannot open the JUnit Port: " + port);
+			System.exit(-2);
+			return;
+		}
+
+		in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
+		out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"));
+	}
+
+	public void setup(Bundle fw, Bundle targetBundle) {
+		this.targetBundle = targetBundle;
+	}
+
+	public void begin(List<Test> tests, int realcount) {
+		this.tests = tests;
+		message("%TESTC  ", realcount + " v2");
+		report(tests);
+		startTime = System.currentTimeMillis();
+	}
+
+	public void end() {
+		message("%RUNTIME", "" + (System.currentTimeMillis() - startTime));
+		out.flush();
+		out.close();
+	}
+
+	public void addError(Test test, Throwable t) {
+		message("%ERROR  ", test);
+		trace(t);
+	}
+
+	public void addFailure(Test test, AssertionFailedError t) {
+		message("%FAILED ", test);
+		trace(t);
+	}
+
+	void trace(Throwable t) {
+		message("%TRACES ", "");
+		t.printStackTrace(out);
+		out.println();
+		message("%TRACEE ", "");
+	}
+
+	public void endTest(Test test) {
+		message("%TESTE  ", test);
+	}
+
+	public void startTest(Test test) {
+		this.current = test;
+		message("%TESTS  ", test);
+		try {
+			Method m = test.getClass().getMethod("setBundleContext", new Class[] {
+				BundleContext.class
+			});
+			m.invoke(test, new Object[] {
+				targetBundle.getBundleContext()
+			});
+		}
+		catch (Exception e) {
+
+		}
+	}
+
+	private void message(String key, String payload) {
+		if (key.length() != 8)
+			throw new IllegalArgumentException(key + " is not 8 characters");
+
+		out.print(key);
+		out.println(payload);
+		out.flush();
+		if (verbose)
+			System.err.println(key + payload);
+	}
+
+	private void message(String key, Test test) {
+		if (tests == null)
+			message(key, "?," + test);
+		else
+			message(key, (tests.indexOf(test) + 1) + "," + test);
+	}
+
+	private void report(List<Test> flattened) {
+		for (int i = 0; i < flattened.size(); i++) {
+			StringBuffer sb = new StringBuffer();
+			sb.append(i + 1);
+			sb.append(",");
+			Test test = flattened.get(i);
+			sb.append(flattened.get(i));
+			sb.append(",");
+			sb.append(test instanceof TestSuite);
+			sb.append(",");
+			sb.append(test.countTestCases());
+			message("%TSTTREE", sb.toString());
+		}
+	}
+
+	public void aborted() {
+		end();
+	}
 
 	public void close() {
-        try {
-            in.close();
-        } catch (Exception ioe) {
-            // ignore
-        }		
+		try {
+			in.close();
+		}
+		catch (Exception ioe) {
+			// ignore
+		}
 	}
 
 }
diff --git a/biz.aQute.junit/src/aQute/junit/JunitXmlReport.java b/biz.aQute.junit/src/aQute/junit/JunitXmlReport.java
index 09ffc26..f47a85c 100644
--- a/biz.aQute.junit/src/aQute/junit/JunitXmlReport.java
+++ b/biz.aQute.junit/src/aQute/junit/JunitXmlReport.java
@@ -10,24 +10,21 @@ import junit.framework.*;
 import org.osgi.framework.*;
 
 public class JunitXmlReport implements TestReporter {
-	Tag					testsuite	= new Tag("testsuite");
-	Tag					testcase;
-	static String		hostname;
-	static DateFormat	df			= new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
-	long				startTime;
-	long				testStartTime;
-	int					tests		= 0;
-	PrintWriter			out;
-	boolean				finished;
-	boolean				progress;
-	Bundle				bundle;
-	BasicTestReport		basic;
-
-	public class LogEntry {
-		String	clazz;
-		String	name;
-		String	message;
-	}
+	Tag				testsuite	= new Tag("testsuite");
+	Tag				testcase;
+	static String	hostname;
+	DateFormat		df			= new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+	long			startTime;
+	long			testStartTime;
+	int				tests		= 0;
+	int				failures	= 0;
+	int				errors		= 0;
+	int				skipped		= 0;
+	PrintWriter		out;
+	boolean			finished;
+	boolean			progress;
+	Bundle			bundle;
+	BasicTestReport	basic;
 
 	public JunitXmlReport(Writer report, Bundle bundle, BasicTestReport basic) throws Exception {
 		if (hostname == null)
@@ -59,7 +56,7 @@ public class JunitXmlReport implements TestReporter {
 		Tag properties = new Tag("properties");
 		testsuite.addContent(properties);
 
-		for (Map.Entry<Object, Object> entry : System.getProperties().entrySet()) {
+		for (Map.Entry<Object,Object> entry : System.getProperties().entrySet()) {
 			Tag property = new Tag(properties, "property");
 			property.addAttribute("name", entry.getKey());
 			property.addAttribute("value", entry.getValue());
@@ -82,7 +79,7 @@ public class JunitXmlReport implements TestReporter {
 
 			bundles.addContent(bundle);
 		}
-		if (bundle != null) {
+		if (targetBundle != null) {
 			String header = (String) targetBundle.getHeaders().get("Bnd-AddXMLToTest");
 			if (header != null) {
 				StringTokenizer st = new StringTokenizer(header, " ,");
@@ -115,22 +112,23 @@ public class JunitXmlReport implements TestReporter {
 		}
 	}
 
-	public void begin(List classNames, int realcount) {
-	}
+	public void begin(List<Test> classNames, int realcount) {}
 
 	public void end() {
 		if (!finished) {
 			finished = true;
 			testsuite.addAttribute("tests", tests);
-			testsuite.addAttribute("time",
-					getFraction(System.currentTimeMillis() - startTime, 1000));
+			testsuite.addAttribute("failures", failures);
+			testsuite.addAttribute("errors", errors);
+			testsuite.addAttribute("skipped", skipped);
+			testsuite.addAttribute("time", getFraction(System.currentTimeMillis() - startTime, 1000));
 			testsuite.addAttribute("timestamp", df.format(new Date()));
 			testsuite.print(0, out);
 			out.close();
 		}
 	}
 
-	private String getFraction(long l, int i) {
+	private String getFraction(long l, @SuppressWarnings("unused") int i) {
 		return (l / 1000) + "." + (l % 1000);
 	}
 
@@ -153,8 +151,7 @@ public class JunitXmlReport implements TestReporter {
 		progress(name);
 	}
 
-	public void setTests(List<Test> flattened) {
-	}
+	public void setTests(@SuppressWarnings("unused") List<Test> flattened) {}
 
 	// <testcase classname="test.AnalyzerTest" name="testMultilevelInheritance"
 	// time="0.772">
@@ -173,10 +170,10 @@ public class JunitXmlReport implements TestReporter {
 		else
 			testcase.addContent(error);
 		progress(" e");
+		errors++;
 	}
 
-	private void progress(String s) {
-	}
+	private void progress(@SuppressWarnings("unused") String s) {}
 
 	private String getTrace(Throwable t) {
 		StringWriter sw = new StringWriter();
@@ -206,22 +203,24 @@ public class JunitXmlReport implements TestReporter {
 		failure.addContent(getTrace(t));
 		testcase.addContent(failure);
 		progress(" f");
+		failures++;
 	}
 
 	public void endTest(Test test) {
 		String[] outs = basic.getCaptured();
 		if (outs[0] != null) {
-			Tag sysout = new Tag(testcase, "sys-out");
+			Tag sysout = new Tag(testcase, "system-out");
 			sysout.addContent(outs[0]);
 		}
 
 		if (outs[1] != null) {
-			Tag sysout = new Tag(testcase, "sys-err");
+			Tag sysout = new Tag(testcase, "system-err");
 			sysout.addContent(outs[1]);
 		}
 
-		testcase
-				.addAttribute("time", getFraction(System.currentTimeMillis() - testStartTime, 1000));
+		testcase.addAttribute("time", getFraction(System.currentTimeMillis() - testStartTime, 1000));
+		tests++;
+		tests++;
 	}
 
 	public void close() {
diff --git a/biz.aQute.junit/src/aQute/junit/Tag.java b/biz.aQute.junit/src/aQute/junit/Tag.java
index 54646a6..a090c54 100755
--- a/biz.aQute.junit/src/aQute/junit/Tag.java
+++ b/biz.aQute.junit/src/aQute/junit/Tag.java
@@ -12,13 +12,21 @@ import java.util.*;
  * objects or other Tag objects.
  */
 public class Tag {
-	Tag parent; // Parent element
-	String name; // Name of the tag
-	Hashtable<String,String> attributes = new Hashtable<String,String>(); // Attributes name -> value
-	Vector<Object> content = new Vector<Object>(); // Content elements
-	boolean cdata;
-
-	static SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss.SSS");
+	Tag							parent;													// Parent
+																							// element
+	String						name;														// Name
+																							// of
+																							// the
+																							// tag
+	Hashtable<String,String>	attributes	= new Hashtable<String,String>();				// Attributes
+																							// name
+																							// ->
+																							// value
+	Vector<Object>				content		= new Vector<Object>();						// Content
+																							// elements
+	boolean						cdata;
+
+	SimpleDateFormat			format		= new SimpleDateFormat("yyyyMMddHHmmss.SSS");
 
 	/**
 	 * Construct a new Tag with a name.
@@ -115,7 +123,7 @@ public class Tag {
 	 * Return the attribute value.
 	 */
 	public String getAttribute(String key) {
-		return (String) attributes.get(key);
+		return attributes.get(key);
 	}
 
 	/**
@@ -144,6 +152,7 @@ public class Tag {
 	 * Return a string representation of this Tag and all its children
 	 * recursively.
 	 */
+	@Override
 	public String toString() {
 		StringWriter sw = new StringWriter();
 		print(0, new PrintWriter(sw));
@@ -196,8 +205,8 @@ public class Tag {
 		pw.print(name);
 
 		for (Enumeration<String> e = attributes.keys(); e.hasMoreElements();) {
-			String key = (String) e.nextElement();
-			String value = escape((String) attributes.get(key));
+			String key = e.nextElement();
+			String value = escape(attributes.get(key));
 			pw.print(' ');
 			pw.print(key);
 			pw.print("=");
@@ -220,14 +229,14 @@ public class Tag {
 						pw.print("<![CDATA[");
 						StringBuffer sb = new StringBuffer();
 						sb.append(content);
-						
+
 						// Unbelievable but Richard had cases
 						// where the contents matched the end ]]>
 						// specifier, so clean it up
 						int l = sb.indexOf("]]>");
-						while ( l >=0) {
-							sb.insert(l+2, '\\');
-							l = sb.indexOf("]]>", l+2);
+						while (l >= 0) {
+							sb.insert(l + 2, '\\');
+							l = sb.indexOf("]]>", l + 2);
 						}
 						pw.print(sb);
 						pw.print("]]>");
@@ -250,12 +259,14 @@ public class Tag {
 
 	private void copyURL(PrintWriter pw, URL url) {
 		try {
-			InputStream in = url.openStream();
-			BufferedReader rdr = new BufferedReader(new InputStreamReader(in, "UTF8"));
+			InputStream in = null;
+			BufferedReader rdr = null;
 			try {
+				in = url.openStream();
+				rdr = new BufferedReader(new InputStreamReader(in, "UTF8"));
 				String line = rdr.readLine();
 				if (line != null) {
-					while (line.trim().startsWith("<?"))
+					while (line != null && line.trim().startsWith("<?"))
 						line = rdr.readLine();
 
 					while (line != null) {
@@ -263,11 +274,18 @@ public class Tag {
 						line = rdr.readLine();
 					}
 				}
-			} finally {
-				in.close();
 			}
-		} catch (Exception e) {
-			System.out.println("Problems copying extra XML");
+			finally {
+				if (rdr != null) {
+					rdr.close();
+				}
+				if (in != null) {
+					in.close();
+				}
+			}
+		}
+		catch (Exception e) {
+			System.err.println("Problems copying extra XML");
 		}
 	}
 
@@ -287,22 +305,22 @@ public class Tag {
 				pos = 0;
 			}
 			switch (c) {
-			case '<':
-				pw.print("<");
-				pos += 4;
-				break;
-			case '>':
-				pw.print(">");
-				pos += 4;
-				break;
-			case '&':
-				pw.print("&");
-				pos += 5;
-				break;
-			default:
-				pw.print(c);
-				pos++;
-				break;
+				case '<' :
+					pw.print("<");
+					pos += 4;
+					break;
+				case '>' :
+					pw.print(">");
+					pos += 4;
+					break;
+				case '&' :
+					pw.print("&");
+					pos += 5;
+					break;
+				default :
+					pw.print(c);
+					pos++;
+					break;
 			}
 
 		}
@@ -316,18 +334,18 @@ public class Tag {
 		for (int i = 0; i < s.length(); i++) {
 			char c = s.charAt(i);
 			switch (c) {
-			case '<':
-				sb.append("<");
-				break;
-			case '>':
-				sb.append(">");
-				break;
-			case '&':
-				sb.append("&");
-				break;
-			default:
-				sb.append(c);
-				break;
+				case '<' :
+					sb.append("<");
+					break;
+				case '>' :
+					sb.append(">");
+					break;
+				case '&' :
+					sb.append("&");
+					break;
+				default :
+					sb.append(c);
+					break;
 			}
 		}
 		return sb.toString();
@@ -391,8 +409,7 @@ public class Tag {
 			Object o = e.nextElement();
 			if (o instanceof Tag) {
 				Tag child = (Tag) o;
-				if (child.getName().equals(elementName)
-						|| elementName.equals("*"))
+				if (child.getName().equals(elementName) || elementName.equals("*"))
 					child.select(remainder, results, mapping);
 			}
 		}
@@ -422,14 +439,11 @@ public class Tag {
 
 		if (mapping == null) {
 			return tn == sn || (sn != null && sn.equals(tn));
-		} else {
-			String suri = sn == null ? mapping.getAttribute("xmlns") : mapping
-					.getAttribute("xmlns:" + sn);
-			String turi = tn == null ? child.findRecursiveAttribute("xmlns")
-					: child.findRecursiveAttribute("xmlns:" + tn);
-			return turi == suri
-					|| (turi != null && suri != null && turi.equals(suri));
 		}
+		String suri = sn == null ? mapping.getAttribute("xmlns") : mapping.getAttribute("xmlns:" + sn);
+		String turi = tn == null ? child.findRecursiveAttribute("xmlns") : child.findRecursiveAttribute("xmlns:"
+				+ tn);
+		return ((turi == null) && (suri == null)) || ((turi != null) && turi.equals(suri));
 	}
 
 	public String getString(String path) {
@@ -475,8 +489,8 @@ public class Tag {
 		if (index > 0) {
 			String ns = name.substring(0, index);
 			return findRecursiveAttribute("xmlns:" + ns);
-		} else
-			return findRecursiveAttribute("xmlns");
+		}
+		return findRecursiveAttribute("xmlns");
 	}
 
 	public String findRecursiveAttribute(String name) {
diff --git a/biz.aQute.junit/src/aQute/junit/Tee.java b/biz.aQute.junit/src/aQute/junit/Tee.java
index 6f46a12..b148208 100644
--- a/biz.aQute.junit/src/aQute/junit/Tee.java
+++ b/biz.aQute.junit/src/aQute/junit/Tee.java
@@ -13,9 +13,15 @@ public class Tee extends OutputStream {
 	}
 
 	public PrintStream getStream() {
-		return new PrintStream(this);
+		try {
+			return new PrintStream(this, false, "UTF-8");
+		}
+		catch (UnsupportedEncodingException e) {
+			return null;
+		}
 	}
 
+	@Override
 	public void write(int character) throws IOException {
 		if (capture)
 			buffer.write(character);
@@ -26,7 +32,12 @@ public class Tee extends OutputStream {
 	public String getContent() {
 		if (buffer.size() == 0)
 			return null;
-		return buffer.toString();
+		try {
+			return buffer.toString("UTF-8");
+		}
+		catch (UnsupportedEncodingException e) {
+			return null;
+		}
 	}
 
 	public Tee clear() {
diff --git a/biz.aQute.junit/src/aQute/junit/TestReporter.java b/biz.aQute.junit/src/aQute/junit/TestReporter.java
index 768dad2..646baf1 100644
--- a/biz.aQute.junit/src/aQute/junit/TestReporter.java
+++ b/biz.aQute.junit/src/aQute/junit/TestReporter.java
@@ -7,8 +7,9 @@ import junit.framework.*;
 import org.osgi.framework.*;
 
 public interface TestReporter extends TestListener {
-    void setup(Bundle framework, Bundle targetBundle);
-	void begin( List<Test> tests, int realcount);
+	void setup(Bundle framework, Bundle targetBundle);
+
+	void begin(List<Test> tests, int realcount);
 
 	void aborted();
 
diff --git a/biz.aQute.junit/src/aQute/junit/constants/TesterConstants.java b/biz.aQute.junit/src/aQute/junit/constants/TesterConstants.java
index 5afa647..582674b 100644
--- a/biz.aQute.junit/src/aQute/junit/constants/TesterConstants.java
+++ b/biz.aQute.junit/src/aQute/junit/constants/TesterConstants.java
@@ -39,4 +39,16 @@ public interface TesterConstants {
 	 */
 	String	TESTER_TRACE		= "tester.trace";
 
+	/**
+	 * Use a new thread to run the tests on (might be needed if a test uses the main thread for some 
+	 * other reason) and for backward compatibility.
+	 * <p/>
+	 * Note: The previous default was a separate thread so this option is mostly for backward
+	 * compatibility and the unlikely case this code is used outside the bnd launcher. This
+	 * approach started to fail when we allowed the embedded activators to start before all
+	 * bundles were started, this created a race condition for class loading. Using the main
+	 * has the guarantee that all bundles have been installed and it is kind of clean as well
+	 * to use this special thread to run all tests on.
+	 */
+	String	TESTER_SEPARATETHREAD			= "tester.separatethread";
 }
diff --git a/biz.aQute.junit/src/aQute/junit/plugin/ProjectTesterImpl.java b/biz.aQute.junit/src/aQute/junit/plugin/ProjectTesterImpl.java
index 0264348..6dbf83a 100644
--- a/biz.aQute.junit/src/aQute/junit/plugin/ProjectTesterImpl.java
+++ b/biz.aQute.junit/src/aQute/junit/plugin/ProjectTesterImpl.java
@@ -1,24 +1,25 @@
 package aQute.junit.plugin;
 
+import java.io.*;
 import java.util.*;
 
 import aQute.bnd.build.*;
+import aQute.bnd.osgi.*;
 import aQute.bnd.service.*;
 import aQute.junit.constants.*;
-import aQute.lib.osgi.*;
 
 public class ProjectTesterImpl extends ProjectTester implements TesterConstants, EclipseJUnitTester {
-	int					port	= -1;
-	String				host;
-	Project				project;
-	String				report;
-	boolean				prepared;
+	int		port	= -1;
+	String	host;
+	Project	project;
+	boolean	prepared;
 
 	public ProjectTesterImpl(Project project) throws Exception {
 		super(project);
 		this.project = project;
 	}
 
+	@Override
 	public boolean prepare() throws Exception {
 		if (!prepared) {
 			prepared = true;
@@ -32,8 +33,16 @@ public class ProjectTesterImpl extends ProjectTester implements TesterConstants,
 			}
 			launcher.getRunProperties().put(TESTER_DIR, getReportDir().getAbsolutePath());
 			launcher.getRunProperties().put(TESTER_CONTINUOUS, "" + getContinuous());
-			if ( Processor.isTrue(project.getProperty(Constants.RUNTRACE)))
+			if (Processor.isTrue(project.getProperty(Constants.RUNTRACE)))
 				launcher.getRunProperties().put(TESTER_TRACE, "true");
+			
+			try {
+				// use reflection to avoid NoSuchMethodError due to change in API
+				File cwd = (File) getClass().getMethod("getCwd").invoke(this);
+				if (cwd != null) launcher.setCwd(cwd);
+			} catch (NoSuchMethodException e){
+				// ignore
+			}
 
 			Collection<String> testnames = getTests();
 			if (testnames.size() > 0) {
@@ -47,6 +56,7 @@ public class ProjectTesterImpl extends ProjectTester implements TesterConstants,
 		return true;
 	}
 
+	@Override
 	public int test() throws Exception {
 		prepare();
 		return getProjectLauncher().launch();
diff --git a/biz.aQute.junit/src/aQute/junit/runtime/OSGiTestCase.java b/biz.aQute.junit/src/aQute/junit/runtime/OSGiTestCase.java
index b99b24c..3c5dcdc 100644
--- a/biz.aQute.junit/src/aQute/junit/runtime/OSGiTestCase.java
+++ b/biz.aQute.junit/src/aQute/junit/runtime/OSGiTestCase.java
@@ -1,18 +1,6 @@
-/*******************************************************************************
- * Copyright (c) 2010 Neil Bartlett.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Neil Bartlett - initial API and implementation
- ******************************************************************************/
 package aQute.junit.runtime;
 
-import java.lang.reflect.*;
 import java.text.*;
-import java.util.*;
 
 import junit.framework.*;
 
@@ -43,7 +31,7 @@ public abstract class OSGiTestCase extends TestCase {
 	 * @param filter
 	 *            An additional service filter, which may be {@code null}.
 	 */
-	protected void assertSvcAvail(Class<?> service, String filter) {
+	protected void assertSvcAvail(Class< ? > service, String filter) {
 		assertSvcAvail(null, service, filter);
 	}
 
@@ -58,17 +46,20 @@ public abstract class OSGiTestCase extends TestCase {
 	 * @param filter
 	 *            An additional service filter, which may be {@code null}.
 	 */
-	protected void assertSvcAvail(String message, Class<?> service, String filter) {
+	protected void assertSvcAvail(String message, Class< ? > service, String filter) {
 		BundleContext context = getBundleContext();
 		ServiceReference[] refs = null;
 		try {
 			refs = context.getServiceReferences(service.getName(), filter);
-		} catch (InvalidSyntaxException e) {
+		}
+		catch (InvalidSyntaxException e) {
 			fail("Invalid filter syntax");
 		}
 
-		if (refs == null || refs.length == 0)
+		if (refs == null || refs.length == 0) {
 			fail(message);
+			return;
+		}
 
 		Object svcObj = context.getService(refs[0]);
 		if (svcObj == null)
@@ -77,7 +68,8 @@ public abstract class OSGiTestCase extends TestCase {
 		try {
 			if (!service.isInstance(svcObj))
 				fail(message);
-		} finally {
+		}
+		finally {
 			context.ungetService(refs[0]);
 		}
 	}
@@ -87,17 +79,15 @@ public abstract class OSGiTestCase extends TestCase {
 	 * Perform the specified operation against a service, or fail immediately if
 	 * a matching service is not available.
 	 * </p>
-	 * 
 	 * <p>
 	 * <strong>Example:</strong>
 	 * </p>
-	 * 
 	 * <p>
 	 * <strong>Example:</strong>
 	 * </p>
 	 * 
 	 * <pre>
-	 * String	reply	= withService(HelloService.class, null, new Operation<HelloService, String>() {
+	 * String	reply	= withService(HelloService.class, null, new Operation<HelloService,String>() {
 	 * 					public String call(HelloService service) {
 	 * 						return service.sayHello();
 	 * 					}
@@ -121,8 +111,7 @@ public abstract class OSGiTestCase extends TestCase {
 	 * @return
 	 * @throws Exception
 	 */
-	protected <S, R> R withService(Class<S> service, String filter,
-			Operation<? super S, R> operation) throws Exception {
+	protected <S, R> R withService(Class<S> service, String filter, Operation< ? super S,R> operation) throws Exception {
 		return withService(service, filter, 0, operation);
 	}
 
@@ -130,13 +119,12 @@ public abstract class OSGiTestCase extends TestCase {
 	 * <p>
 	 * Perform the specified operation against a service, if available.
 	 * </p>
-	 * 
 	 * <p>
 	 * <strong>Example:</strong>
 	 * </p>
 	 * 
 	 * <pre>
-	 * String	reply	= withService(HelloService.class, null, 0, new Operation<HelloService, String>() {
+	 * String	reply	= withService(HelloService.class, null, 0, new Operation<HelloService,String>() {
 	 * 					public String call(HelloService service) {
 	 * 						return service.sayHello();
 	 * 					}
@@ -160,18 +148,20 @@ public abstract class OSGiTestCase extends TestCase {
 	 * @return
 	 * @throws Exception
 	 */
-	protected <S, R> R withService(Class<S> service, String filter, long timeout,
-			Operation<? super S, R> operation) throws Exception {
+	protected <S, R> R withService(Class<S> service, String filter, long timeout, Operation< ? super S,R> operation)
+			throws Exception {
 		BundleContext context = getBundleContext();
 
 		ServiceTracker tracker = null;
 		if (filter != null) {
 			try {
-				Filter combined = FrameworkUtil.createFilter("(" + Constants.OBJECTCLASS + "="
-						+ service.getName() + ")");
+				Filter combined = FrameworkUtil.createFilter("(" + Constants.OBJECTCLASS + "=" + service.getName()
+						+ ")");
 				tracker = new ServiceTracker(context, combined, null);
-			} catch (InvalidSyntaxException e) {
+			}
+			catch (InvalidSyntaxException e) {
 				fail("Invalid filter syntax.");
+				return null;
 			}
 		} else {
 			tracker = new ServiceTracker(context, service.getName(), null);
@@ -188,11 +178,14 @@ public abstract class OSGiTestCase extends TestCase {
 			if (instance == null || !service.isInstance(instance))
 				fail(MessageFormat.format("Service \"{0}\" not available.", service.getName()));
 
+			@SuppressWarnings("unchecked")
 			S casted = (S) instance;
 			return operation.perform(casted);
-		} catch (InterruptedException e) {
+		}
+		catch (InterruptedException e) {
 			fail("Interrupted.");
-		} finally {
+		}
+		finally {
 			tracker.close();
 		}
 
diff --git a/biz.aQute.junit/src/aQute/junit/runtime/Operation.java b/biz.aQute.junit/src/aQute/junit/runtime/Operation.java
index b1000cf..932e2ab 100644
--- a/biz.aQute.junit/src/aQute/junit/runtime/Operation.java
+++ b/biz.aQute.junit/src/aQute/junit/runtime/Operation.java
@@ -1,13 +1,3 @@
-/*******************************************************************************
- * Copyright (c) 2010 Neil Bartlett.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Neil Bartlett - initial API and implementation
- ******************************************************************************/
 package aQute.junit.runtime;
 
 /**
@@ -15,7 +5,6 @@ package aQute.junit.runtime;
  * a result of type <strong>R</strong>
  * 
  * @author Neil Bartlett
- * 
  * @param <S>
  *            The service type
  * @param <R>
diff --git a/biz.aQute.junit/src/aQute/junit/runtime/VoidOperation.java b/biz.aQute.junit/src/aQute/junit/runtime/VoidOperation.java
index bfe376b..2ee8c50 100644
--- a/biz.aQute.junit/src/aQute/junit/runtime/VoidOperation.java
+++ b/biz.aQute.junit/src/aQute/junit/runtime/VoidOperation.java
@@ -1,19 +1,10 @@
-/*******************************************************************************
-* Copyright (c) 2010 Neil Bartlett.
-* All rights reserved. This program and the accompanying materials
-* are made available under the terms of the Eclipse Public License v1.0
-* which accompanies this distribution, and is available at
-* http://www.eclipse.org/legal/epl-v10.html
-*
-* Contributors:
-* Neil Bartlett - initial API and implementation
-******************************************************************************/
 package aQute.junit.runtime;
 
-public abstract class VoidOperation<S> implements Operation<S, Object> {
-public final Object perform(S param) {
-doPerform(param);
-return null;
-}
-protected abstract void doPerform(S param);
+public abstract class VoidOperation<S> implements Operation<S,Object> {
+	public final Object perform(S param) {
+		doPerform(param);
+		return null;
+	}
+
+	protected abstract void doPerform(S param);
 }
\ No newline at end of file
diff --git a/biz.aQute.launcher/.classpath b/biz.aQute.launcher/.classpath
index cdf2145..6d3c62a 100644
--- a/biz.aQute.launcher/.classpath
+++ b/biz.aQute.launcher/.classpath
@@ -1,9 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="src" output="bin_test" path="test"/>
 	<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/biz.aQute.launcher/.settings/org.eclipse.jdt.core.prefs b/biz.aQute.launcher/.settings/org.eclipse.jdt.core.prefs
index 7044377..d3798f5 100644
--- a/biz.aQute.launcher/.settings/org.eclipse.jdt.core.prefs
+++ b/biz.aQute.launcher/.settings/org.eclipse.jdt.core.prefs
@@ -1,12 +1,362 @@
-#Mon May 24 10:59:53 CEST 2010
+#Fri Aug 10 13:46:22 CEST 2012
 eclipse.preferences.version=1
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.targetPlatform=jsr14
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.4
+org.eclipse.jdt.core.compiler.compliance=1.5
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
 org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=ignore
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=true
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/biz.aQute.launcher/.settings/org.eclipse.jdt.ui.prefs b/biz.aQute.launcher/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..f5e8897
--- /dev/null
+++ b/biz.aQute.launcher/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,61 @@
+#Fri Aug 10 13:48:46 CEST 2012
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=false
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=false
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=false
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
+cleanup_settings_version=2
+eclipse.preferences.version=1
+formatter_profile=_bnd(tools)
+formatter_settings_version=12
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=1
+org.eclipse.jdt.ui.staticondemandthreshold=1
diff --git a/biz.aQute.launcher/bnd.bnd b/biz.aQute.launcher/bnd.bnd
index 88ad66a..4a6ac68 100644
--- a/biz.aQute.launcher/bnd.bnd
+++ b/biz.aQute.launcher/bnd.bnd
@@ -1,7 +1,8 @@
 -buildpath: biz.aQute.bndlib;version=project,\
 	aQute.libg;version=project,\
 	osgi.core;version=4.2.1,\
-	junit.osgi;version=3.8.2
+	junit.osgi;version=3.8.2,\
+	ee.j2se;version=${javac.ee}
 #	ee.minimum;version=1.2.1
 	
 	
@@ -9,6 +10,6 @@ Launcher-Plugin: aQute.launcher.plugin.ProjectLauncherImpl
 
 Private-Package: aQute.launcher.*
 	
-Bundle-Version: 1.0.0
+Bundle-Version: 1.0.6
 javac.source = 1.5
-javac.target = jsr14
\ No newline at end of file
+javac.target = jsr14
diff --git a/biz.aQute.launcher/src/aQute/launcher/Launcher.java b/biz.aQute.launcher/src/aQute/launcher/Launcher.java
index e881b7c..221c412 100644
--- a/biz.aQute.launcher/src/aQute/launcher/Launcher.java
+++ b/biz.aQute.launcher/src/aQute/launcher/Launcher.java
@@ -7,7 +7,8 @@ import java.lang.reflect.*;
 import java.net.*;
 import java.security.*;
 import java.util.*;
-import java.util.Map.*;
+import java.util.Map.Entry;
+import java.util.regex.*;
 
 import org.osgi.framework.*;
 import org.osgi.framework.launch.*;
@@ -22,72 +23,121 @@ import aQute.launcher.minifw.*;
  * 1.4.
  */
 public class Launcher implements ServiceListener {
-	private PrintStream						out;
-	private LauncherConstants				parms;
-	private Framework						systemBundle;
-	private final Properties				properties;
-	private boolean							security;
-	private SimplePermissionPolicy			policy;
-	private Runnable						mainThread;
-	private PackageAdmin					padmin;
-	private static File						propertiesFile;
-	private final Timer						timer				= new Timer();
-	private final List<BundleActivator>		embedded			= new ArrayList<BundleActivator>();
-	private TimerTask						watchdog			= null;
-	private final Map<Bundle, Throwable>	errors				= new HashMap<Bundle, Throwable>();
-	private final Map<File, Bundle>			installedBundles	= new LinkedHashMap<File, Bundle>();
+	
+	// Use our own constant for this rather than depend on OSGi core 4.3
+	private static final String FRAMEWORK_SYSTEM_CAPABILITIES_EXTRA = "org.osgi.framework.system.capabilities.extra";
+	
+	private PrintStream					out;
+	LauncherConstants					parms;
+	Framework							systemBundle;
+	volatile boolean					inrefresh;
+	private final Properties			properties;
+	private boolean						security;
+	private SimplePermissionPolicy		policy;
+	private Runnable					mainThread;
+	private PackageAdmin				padmin;
+	private final List<BundleActivator>	embedded			= new ArrayList<BundleActivator>();
+	private final Map<Bundle,Throwable>	errors				= new HashMap<Bundle,Throwable>();
+	private final Map<File,Bundle>		installedBundles	= new LinkedHashMap<File,Bundle>();
+	private File						home				= new File(System.getProperty("user.home"));
+	private File						bnd					= new File(home, "bnd");
+	private List<Bundle>				wantsToBeStarted	= new ArrayList<Bundle>();
 
 	public static void main(String[] args) {
 		try {
+			final InputStream in;
+			final File propertiesFile;
+
 			String path = System.getProperty(LauncherConstants.LAUNCHER_PROPERTIES);
-			assert path != null;
-			propertiesFile = new File(path).getAbsoluteFile();
-			propertiesFile.deleteOnExit();
-			FileInputStream in = new FileInputStream(propertiesFile);
+			if (path != null) {
+				Matcher matcher = Pattern.compile("^([\"'])(.*)\\1$").matcher(path);
+				if (matcher.matches()) {
+					path = matcher.group(2);
+				}
+
+				propertiesFile = new File(path).getAbsoluteFile();
+				if (!propertiesFile.isFile())
+					errorAndExit("Specified launch file `%s' was not found - absolutePath='%s'", path, propertiesFile.getAbsolutePath());
+				in = new FileInputStream(propertiesFile);
+			} else {
+				propertiesFile = null;
+				in = Launcher.class.getClassLoader().getResourceAsStream(DEFAULT_LAUNCHER_PROPERTIES);
+				if (in == null) {
+					printUsage();
+					errorAndExit("Launch file not specified, and no embedded properties found.");
+				}
+			}
+
 			Properties properties = new Properties();
 			try {
 				properties.load(in);
-			} finally {
-				in.close();
 			}
-			Launcher target = new Launcher(properties);
+			finally {
+				if (in != null)
+					in.close();
+			}
+			Launcher target = new Launcher(properties, propertiesFile);
 			target.run(args);
-		} catch (Throwable t) {
+		}
+		catch (Throwable t) {
 			// Last resort ... errors should be handled lower
 			t.printStackTrace(System.err);
 		}
 	}
 
-	public Launcher(Properties properties) throws Exception {
+	private static void printUsage() {
+		System.out.println("Usage: java -Dlauncher.properties=<launcher.properties> -jar <launcher.jar>");
+	}
+
+	private static void errorAndExit(String message, Object... args) {
+		System.err.println(String.format(message, args));
+		System.exit(1);
+	}
+
+	public Launcher(Properties properties, final File propertiesFile) throws Exception {
 		this.properties = properties;
+
+		// Allow the system to override any properties with -Dkey=value
+
+		for (Object key : properties.keySet()) {
+			String s = (String) key;
+			String v = System.getProperty(s);
+			if (v != null)
+				properties.put(key, v);
+		}
+
 		System.getProperties().putAll(properties);
 		this.parms = new LauncherConstants(properties);
 
 		out = System.err;
 		trace("inited runbundles=%s activators=%s timeout=%s", parms.runbundles, parms.activators, parms.timeout);
-		watchdog = new TimerTask() {
-			long	begin	= propertiesFile.lastModified();
+		if (propertiesFile != null && parms.embedded == false) {
+			TimerTask watchdog = new TimerTask() {
+				long	begin	= propertiesFile.lastModified();
 
-			public void run() {
-				if (begin < propertiesFile.lastModified()) {
-					try {
-						FileInputStream in = new FileInputStream(propertiesFile);
-						Properties properties = new Properties();
+				public void run() {
+					if (begin < propertiesFile.lastModified()) {
 						try {
-							properties.load(in);
-						} finally {
-							in.close();
+							FileInputStream in = new FileInputStream(propertiesFile);
+							Properties properties = new Properties();
+							try {
+								properties.load(in);
+							}
+							finally {
+								in.close();
+							}
+							parms = new LauncherConstants(properties);
+							update();
+						}
+						catch (Exception e) {
+							error("Error in updating the framework from the properties: %s", e);
 						}
-						parms = new LauncherConstants(properties);						
-						update();
-					} catch (Exception e) {
-						error("Error in updating the framework from the properties: %s", e);
+						begin = propertiesFile.lastModified();
 					}
-					begin = propertiesFile.lastModified();
 				}
-			}
-		};
-		timer.scheduleAtFixedRate(watchdog, 5000, 1000);
+			};
+			new Timer().scheduleAtFixedRate(watchdog, 5000, 1000);
+		}
 	}
 
 	private void run(String args[]) throws Throwable {
@@ -103,11 +153,13 @@ public class Launcher implements ServiceListener {
 			// Register the command line with ourselves as the
 			// service.
 			if (parms.services) { // Does not work for our dummy framework
-				Hashtable<String, Object> argprops = new Hashtable<String, Object>();
+				Hashtable<String,Object> argprops = new Hashtable<String,Object>();
 				argprops.put(LauncherConstants.LAUNCHER_ARGUMENTS, args);
 				argprops.put(LauncherConstants.LAUNCHER_READY, "true");
-				systemBundle.getBundleContext().registerService(Launcher.class.getName(), this,
-						argprops);
+				argprops.put(Constants.SERVICE_RANKING, -1000);
+				systemBundle.getBundleContext().registerService(new String[] {
+						Object.class.getName(), Launcher.class.getName()
+				}, this, argprops);
 				trace("registered launcher with arguments for syncing");
 			}
 
@@ -122,10 +174,12 @@ public class Launcher implements ServiceListener {
 			}
 			trace("Will run %s as main thread", mainThread);
 			mainThread.run();
-		} catch (Throwable e) {
+		}
+		catch (Throwable e) {
 			error("Unexpected error in the run body: %s", e);
 			throw e;
-		} finally {
+		}
+		finally {
 			systemBundle.stop();
 			trace("stopped system bundle due to leaving run body");
 		}
@@ -165,14 +219,7 @@ public class Launcher implements ServiceListener {
 		} else
 			trace("could not get package admin");
 
-		systemContext.addServiceListener(this,
-				"(&(objectclass=java.lang.Runnable)(main.thread=true))");
-
-		update();
-
-		if (parms.trace) {
-			report(out);
-		}
+		systemContext.addServiceListener(this, "(&(objectclass=java.lang.Runnable)(main.thread=true))");
 
 		// Start embedded activators
 		trace("start embedded activators");
@@ -180,22 +227,30 @@ public class Launcher implements ServiceListener {
 			ClassLoader loader = getClass().getClassLoader();
 			for (Object token : parms.activators) {
 				try {
-					Class<?> clazz = loader.loadClass((String) token);
+					Class< ? > clazz = loader.loadClass((String) token);
 					BundleActivator activator = (BundleActivator) clazz.newInstance();
 					embedded.add(activator);
 					trace("adding activator %s", activator);
-				} catch (Exception e) {
-					throw new IllegalArgumentException("Embedded Bundle Activator incorrect: "
-							+ token + ", " + e);
+				}
+				catch (Exception e) {
+					throw new IllegalArgumentException("Embedded Bundle Activator incorrect: " + token + ", " + e);
 				}
 			}
 		}
+
+		update();
+
+		if (parms.trace) {
+			report(out);
+		}
+
 		int result = LauncherConstants.OK;
 		for (BundleActivator activator : embedded)
 			try {
 				trace("starting activator %s", activator);
 				activator.start(systemContext);
-			} catch (Exception e) {
+			}
+			catch (Exception e) {
 				error("Starting activator %s : %s", activator, e);
 				result = LauncherConstants.ERROR;
 			}
@@ -204,14 +259,72 @@ public class Launcher implements ServiceListener {
 	}
 
 	/**
-	 * @param systemContext
-	 * @throws MalformedURLException
-	 * @throws FileNotFoundException
-	 * @throws IOException
+	 * Ensure that all the bundles in the parameters are actually started. We
+	 * can start in embedded mode (bundles are inside our main jar) or in file
+	 * system mode.
 	 */
-	private void update() throws Exception {
+	void update() throws Exception {
 		trace("Updating framework with %s", parms.runbundles);
+
+		List<Bundle> tobestarted = new ArrayList<Bundle>();
+		if (parms.embedded)
+			installEmbedded(tobestarted);
+		else
+			synchronizeFiles(tobestarted);
+
+		if (padmin != null) {
+			inrefresh = true;
+			padmin.refreshPackages(null);
+			trace("Waiting for refresh to finish");
+
+			// Will be reset by the Framework listener we added
+			// when we created the framework.
+			while (inrefresh)
+				Thread.sleep(100);
+		} else
+			trace("cannot refresh the bundles because there is no Package Admin");
+
+		trace("bundles administered %s", installedBundles.keySet());
+
+		// From now on, the bundles are on their own. They have
+		// by default AllPermission, but if they install bundles
+		// they will not automatically get AllPermission anymore
+		if (security)
+			policy.setDefaultPermissions(null);
+
+		// Get the resolved status
+		if (padmin != null && padmin.resolveBundles(null) == false) {
+			error("could not resolve the bundles");
+			// return LauncherConstants.RESOLVE_ERROR;
+		}
+
+		// Now start all the installed bundles in the same order
+		// (unless they're a fragment)
+
+		trace("Will start bundles: %s", tobestarted);
+		List<Bundle> all = new ArrayList<Bundle>(tobestarted);
+		// Add all bundles that we've tried to start but failed
+		all.addAll(wantsToBeStarted);
 		
+		for (Bundle b : tobestarted) {
+			try {
+				trace("starting %s", b.getSymbolicName());
+				if (!isFragment(b))
+					b.start(Bundle.START_ACTIVATION_POLICY);
+				trace("started  %s", b.getSymbolicName());
+			}
+			catch (BundleException e) {
+				wantsToBeStarted.add(b);
+				error("Failed to start bundle %s-%s, exception %s", b.getSymbolicName(), b.getVersion(), e);
+			}
+		}
+
+	}
+
+	/**
+	 * @param tobestarted
+	 */
+	void synchronizeFiles(List<Bundle> tobestarted) {
 		// Turn the bundle location paths into files
 		List<File> desired = new ArrayList<File>();
 		for (Object o : parms.runbundles) {
@@ -234,14 +347,13 @@ public class Launcher implements ServiceListener {
 		List<File> tobeinstalled = new ArrayList<File>(desired);
 		tobeinstalled.removeAll(installedBundles.keySet());
 
-		List<Bundle> tobestarted = new ArrayList<Bundle>();
-
 		for (File f : tobedeleted)
 			try {
 				trace("uninstalling %s", f);
 				installedBundles.get(f).uninstall();
 				installedBundles.remove(f);
-			} catch (Exception e) {
+			}
+			catch (Exception e) {
 				error("Failed to uninstall bundle %s, exception %s", f, e);
 			}
 
@@ -251,7 +363,8 @@ public class Launcher implements ServiceListener {
 				Bundle b = install(f);
 				installedBundles.put(f, b);
 				tobestarted.add(b);
-			} catch (Exception e) {
+			}
+			catch (Exception e) {
 				error("Failed to uninstall bundle %s, exception %s", f, e);
 			}
 
@@ -260,51 +373,41 @@ public class Launcher implements ServiceListener {
 				Bundle b = installedBundles.get(f);
 				if (b.getLastModified() < f.lastModified()) {
 					trace("updating %s", f);
-					if ( b.getState() == Bundle.ACTIVE) {
+					if (b.getState() == Bundle.ACTIVE) {
 						tobestarted.add(b);
 						b.stop();
 					}
 					b.update();
 				} else
 					trace("bundle is still current according to timestamp %s", f);
-			} catch (Exception e) {
+			}
+			catch (Exception e) {
 				error("Failed to update bundle %s, exception %s", f, e);
 			}
+	}
 
-		if (padmin != null)
-			padmin.refreshPackages(null);
-
-		trace("bundles administered %s", installedBundles.keySet());
-
-		// From now on, the bundles are on their own. They have
-		// by default AllPermission, but if they install bundles
-		// they will not automatically get AllPermission anymore
-		if (security)
-			policy.setDefaultPermissions(null);
-
-		// Get the resolved status
-		if (padmin != null && padmin.resolveBundles(null) == false) {
-			error("could not resolve the bundles");
-			// return LauncherConstants.RESOLVE_ERROR;
-		}
-
-		// Now start all the installed bundles in the same order
-		// (unless they're a fragment)
-		
-		
-		trace("Will start bundles: %s" ,tobestarted);
-		for (Bundle b : tobestarted) {
+	/**
+	 * Install the bundles from the current jar.
+	 * 
+	 * @param tobestarted
+	 * @throws BundleException
+	 * @throws IOException
+	 */
+	void installEmbedded(List<Bundle> tobestarted) throws BundleException, IOException {
+		trace("starting in embedded mode");
+		BundleContext context = systemBundle.getBundleContext();
+		for (Object o : parms.runbundles) {
+			String path = (String) o;
+			trace("installing %s", path);
+			InputStream in = getClass().getClassLoader().getResourceAsStream(path);
 			try {
-				trace("starting %s", b.getSymbolicName());
-				if (!isFragment(b))
-					b.start(Bundle.START_ACTIVATION_POLICY);
-				trace("started  %s", b.getSymbolicName());
-			} catch (BundleException e) {
-				error("Failed to start bundle %s-%s, exception %s", b.getSymbolicName(), b
-						.getVersion(), e);
+				Bundle bundle = context.installBundle(path, in);
+				tobestarted.add(bundle);
+			}
+			finally {
+				in.close();
 			}
 		}
-
 	}
 
 	Bundle install(File f) throws Exception {
@@ -317,13 +420,15 @@ public class Launcher implements ServiceListener {
 				b.update();
 			}
 			return b;
-		} catch (BundleException e) {
+		}
+		catch (BundleException e) {
 			trace("failed reference, will try to install %s with input stream", f.getAbsolutePath());
 			String reference = f.toURI().toURL().toExternalForm();
 			InputStream in = new FileInputStream(f);
 			try {
 				return context.installBundle(reference, in);
-			} finally {
+			}
+			finally {
 				in.close();
 			}
 		}
@@ -333,35 +438,38 @@ public class Launcher implements ServiceListener {
 		// Ensure we properly close in a separate thread so that
 		// we can leverage the main thread, which is required for macs
 		Thread wait = new Thread("FrameworkWaiter") {
+			@Override
 			public void run() {
 				try {
 					FrameworkEvent result = systemBundle.waitForStop(parms.timeout);
-					trace( "framework event " + result + " " + result.getType());
+					trace("framework event " + result + " " + result.getType());
 					Thread.sleep(1000);
 					switch (result.getType()) {
-					case FrameworkEvent.STOPPED:
-						System.exit(LauncherConstants.OK);
-						break;
-					case FrameworkEvent.WAIT_TIMEDOUT:
-						System.exit(LauncherConstants.TIMEDOUT);
-						break;
-
-					case FrameworkEvent.ERROR:
-						System.exit(ERROR);
-						break;
-
-					case FrameworkEvent.WARNING:
-						System.exit(WARNING);
-						break;
-
-					case FrameworkEvent.STOPPED_BOOTCLASSPATH_MODIFIED:
-					case FrameworkEvent.STOPPED_UPDATE:
-						System.exit(UPDATE_NEEDED);
-						break;
+						case FrameworkEvent.STOPPED :
+							System.exit(LauncherConstants.OK);
+							break;
+						case FrameworkEvent.WAIT_TIMEDOUT :
+							System.exit(LauncherConstants.TIMEDOUT);
+							break;
+
+						case FrameworkEvent.ERROR :
+							System.exit(ERROR);
+							break;
+
+						case FrameworkEvent.WARNING :
+							System.exit(WARNING);
+							break;
+
+						case FrameworkEvent.STOPPED_BOOTCLASSPATH_MODIFIED :
+						case FrameworkEvent.STOPPED_UPDATE :
+							System.exit(UPDATE_NEEDED);
+							break;
 					}
-				} catch (InterruptedException e) {
+				}
+				catch (InterruptedException e) {
 					System.exit(CANCELED);
-				} finally {
+				}
+				finally {
 					System.err.println("System exiting due to timeout of " + parms.timeout);
 				}
 			}
@@ -371,15 +479,17 @@ public class Launcher implements ServiceListener {
 
 	private void doSecurity() {
 		try {
-			PermissionInfo allPermissions[] = new PermissionInfo[] { new PermissionInfo(
-					AllPermission.class.getName(), null, null) };
+			PermissionInfo allPermissions[] = new PermissionInfo[] {
+				new PermissionInfo(AllPermission.class.getName(), null, null)
+			};
 			policy = new SimplePermissionPolicy(this, systemBundle.getBundleContext());
 
 			// All bundles installed from the script are getting AllPermission
 			// for now.
 			policy.setDefaultPermissions(allPermissions);
 			security = true;
-		} catch (Throwable t) {
+		}
+		catch (Throwable t) {
 			// This can throw a linkage error when the framework
 			// does not carry the PermissionAdmin class
 			security = false;
@@ -413,19 +523,27 @@ public class Launcher implements ServiceListener {
 	private Framework createFramework() throws Exception {
 		Properties p = new Properties();
 		p.putAll(properties);
-		File workingdir = new File("tmp").getAbsoluteFile();
+		File workingdir = null;
 		if (parms.storageDir != null)
 			workingdir = parms.storageDir;
+		else if (parms.keep && parms.name != null) {
+			workingdir = new File(bnd, parms.name);
+		}
+
+		if (workingdir == null)
+			workingdir = File.createTempFile("osgi.", ".fw");
 
-		trace("using working dir: %s", parms.storageDir);
+		trace("using working dir: %s", workingdir);
 
-		if (!parms.keep) {
+		if (!parms.keep && workingdir.exists()) {
 			trace("deleting working dir %s because not kept", workingdir);
 			delete(workingdir);
 			p.setProperty(Constants.FRAMEWORK_STORAGE_CLEAN, "true");
 		}
 
-		workingdir.mkdirs();
+		if (!workingdir.exists() && !workingdir.mkdirs()) {
+			throw new IOException("Could not create directory " + workingdir);
+		}
 		if (!workingdir.isDirectory())
 			throw new IllegalArgumentException("Cannot create a working dir: " + workingdir);
 
@@ -435,6 +553,11 @@ public class Launcher implements ServiceListener {
 			p.setProperty(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, parms.systemPackages);
 			trace("system packages used: %s", parms.systemPackages);
 		}
+		
+		if (parms.systemCapabilities != null) {
+			p.setProperty(FRAMEWORK_SYSTEM_CAPABILITIES_EXTRA, parms.systemCapabilities);
+			trace("system capabilities used: %s", parms.systemCapabilities);
+		}
 
 		Framework systemBundle;
 
@@ -445,17 +568,16 @@ public class Launcher implements ServiceListener {
 			ClassLoader loader = getClass().getClassLoader();
 
 			// 3) Lookup in META-INF/services
-			List<String> implementations = getMetaInfServices(loader, FrameworkFactory.class
-					.getName());
+			List<String> implementations = getMetaInfServices(loader, FrameworkFactory.class.getName());
 
 			if (implementations.size() == 0)
 				error("Found no fw implementation");
 			if (implementations.size() > 1)
 				error("Found more than one framework implementations: %s", implementations);
 
-			String implementation = (String) implementations.get(0);
+			String implementation = implementations.get(0);
 
-			Class<?> clazz = loader.loadClass(implementation);
+			Class< ? > clazz = loader.loadClass(implementation);
 			FrameworkFactory factory = (FrameworkFactory) clazz.newInstance();
 			trace("Framework factory %s", factory);
 			systemBundle = factory.newFramework(p);
@@ -466,6 +588,27 @@ public class Launcher implements ServiceListener {
 			systemBundle = new MiniFramework(p);
 		}
 		systemBundle.init();
+
+		try {
+			systemBundle.getBundleContext().addFrameworkListener(new FrameworkListener() {
+
+				public void frameworkEvent(FrameworkEvent event) {
+					switch (event.getType()) {
+						case FrameworkEvent.ERROR :
+						case FrameworkEvent.WAIT_TIMEDOUT :
+							trace("Refresh will end due to error or timeout %s", event.toString());
+							
+						case FrameworkEvent.PACKAGES_REFRESHED :
+							inrefresh = false;
+							trace("refresh ended");
+							break;
+					}
+				}
+			});
+		}
+		catch (Exception e) {
+			trace("could not register a framework listener: %s", e);
+		}
 		trace("inited system bundle %s", systemBundle);
 		return systemBundle;
 	}
@@ -486,13 +629,15 @@ public class Launcher implements ServiceListener {
 		List<String> factories = new ArrayList<String>();
 
 		while (e.hasMoreElements()) {
-			URL url = (URL) e.nextElement();
+			URL url = e.nextElement();
 			trace("found META-INF/services in %s", url);
 
-			InputStream in = url.openStream();
+			InputStream in = null;
+			BufferedReader rdr = null;
+			String line;
 			try {
-				BufferedReader rdr = new BufferedReader(new InputStreamReader(in, "UTF-8"));
-				String line;
+				in = url.openStream();
+				rdr = new BufferedReader(new InputStreamReader(in, "UTF-8"));
 				while ((line = rdr.readLine()) != null) {
 					trace(line);
 					line = line.trim();
@@ -500,8 +645,14 @@ public class Launcher implements ServiceListener {
 						factories.add(line);
 					}
 				}
-			} finally {
-				in.close();
+			}
+			finally {
+				if (rdr != null) {
+					rdr.close();
+				}
+				if (in != null) {
+					in.close();
+				}
 			}
 		}
 		return factories;
@@ -515,8 +666,7 @@ public class Launcher implements ServiceListener {
 		String path = f.getAbsolutePath();
 		char first = path.charAt(0);
 		if (path.equals("/") || (first >= 'A' && first <= 'Z' && path.substring(1).equals(":\\")))
-			throw new IllegalArgumentException(
-					"You can not make the root the storage area because it will be deleted");
+			throw new IllegalArgumentException("You can not make the root the storage area because it will be deleted");
 		if (f.isDirectory()) {
 			File fs[] = f.listFiles();
 			for (int i = 0; i < fs.length; i++)
@@ -535,11 +685,11 @@ public class Launcher implements ServiceListener {
 			row(out, "Keep", parms.keep);
 			row(out, "Security", security);
 			list(out, fill("Run bundles", 40), parms.runbundles);
-			list(out, fill("Classpath", 40), split(System.getProperty("java.class.path"),
-					File.pathSeparator));
+			list(out, fill("Classpath", 40), split(System.getProperty("java.class.path"), File.pathSeparator));
 			list(out, fill("System Packages", 40), split(parms.systemPackages, ","));
+			list(out, fill("System Capabilities", 40), split(parms.systemCapabilities, ","));
 			row(out, "Properties");
-			for (Entry<Object, Object> entry : properties.entrySet()) {
+			for (Entry<Object,Object> entry : properties.entrySet()) {
 				String key = (String) entry.getKey();
 				String value = (String) entry.getValue();
 				row(out, key, value);
@@ -561,7 +711,7 @@ public class Launcher implements ServiceListener {
 							out.print(fill(toDate(f.lastModified()), 14));
 						else
 							out.print(fill("<>", 14));
-						
+
 						if (errors.containsKey(bundles[i])) {
 							out.print(fill(loc, 50));
 							out.print(errors.get(bundles[i]).getMessage());
@@ -572,7 +722,8 @@ public class Launcher implements ServiceListener {
 					}
 				}
 			}
-		} catch (Throwable t) {
+		}
+		catch (Throwable t) {
 			error("Sorry, can't print framework: %s", t);
 		}
 	}
@@ -581,9 +732,9 @@ public class Launcher implements ServiceListener {
 		boolean fill = true;
 		for (Object p : parms) {
 			if (fill)
-				out.print(fill(p.toString(), 40));
+				out.print(fill(p + "", 40));
 			else
-				out.print(p.toString());
+				out.print(p);
 			fill = false;
 		}
 		out.println();
@@ -592,9 +743,8 @@ public class Launcher implements ServiceListener {
 	String toDate(long t) {
 		Calendar c = Calendar.getInstance();
 		c.setTimeInMillis(t);
-		return fill(c.get(Calendar.YEAR), 4) + fill(c.get(Calendar.MONTH), 2)
-				+ fill(c.get(Calendar.DAY_OF_MONTH), 2) + fill(c.get(Calendar.HOUR_OF_DAY), 2)
-				+ fill(c.get(Calendar.MINUTE), 2);
+		return fill(c.get(Calendar.YEAR), 4) + fill(c.get(Calendar.MONTH), 2) + fill(c.get(Calendar.DAY_OF_MONTH), 2)
+				+ fill(c.get(Calendar.HOUR_OF_DAY), 2) + fill(c.get(Calendar.MINUTE), 2);
 	}
 
 	private String fill(int n, int width) {
@@ -606,7 +756,7 @@ public class Launcher implements ServiceListener {
 	}
 
 	private String fill(String s, int width, char filler, int dir) {
-		StringBuffer sb = new StringBuffer();
+		StringBuilder sb = new StringBuilder();
 		if (s.length() > width) {
 			int half = (width - 1) / 2;
 			return s.substring(0, half) + ".." + s.substring(s.length() - half);
@@ -628,23 +778,23 @@ public class Launcher implements ServiceListener {
 
 	private String toState(int state) {
 		switch (state) {
-		case Bundle.INSTALLED:
-			return "INSTL";
-		case Bundle.RESOLVED:
-			return "RSLVD";
-		case Bundle.STARTING:
-			return "STRTD";
-		case Bundle.STOPPING:
-			return "STPPD";
-		case Bundle.ACTIVE:
-			return "ACTIV";
-		case Bundle.UNINSTALLED:
-			return "UNNST";
+			case Bundle.INSTALLED :
+				return "INSTL";
+			case Bundle.RESOLVED :
+				return "RSLVD";
+			case Bundle.STARTING :
+				return "STRTD";
+			case Bundle.STOPPING :
+				return "STPPD";
+			case Bundle.ACTIVE :
+				return "ACTIV";
+			case Bundle.UNINSTALLED :
+				return "UNNST";
 		}
 		return "? " + state;
 	}
 
-	private void list(PrintStream out, String del, List<?> l) {
+	private void list(PrintStream out, String del, List< ? > l) {
 		for (Object o : l) {
 			String s = o.toString();
 			out.print(del);
@@ -655,47 +805,47 @@ public class Launcher implements ServiceListener {
 
 	public int translateToError(BundleException e) {
 		switch (e.getType()) {
-		case BundleException.ACTIVATOR_ERROR:
-			return LauncherConstants.ACTIVATOR_ERROR;
+			case BundleException.ACTIVATOR_ERROR :
+				return LauncherConstants.ACTIVATOR_ERROR;
 
-		case BundleException.DUPLICATE_BUNDLE_ERROR:
-			return LauncherConstants.DUPLICATE_BUNDLE;
+			case BundleException.DUPLICATE_BUNDLE_ERROR :
+				return LauncherConstants.DUPLICATE_BUNDLE;
 
-		case BundleException.RESOLVE_ERROR:
-			return LauncherConstants.RESOLVE_ERROR;
+			case BundleException.RESOLVE_ERROR :
+				return LauncherConstants.RESOLVE_ERROR;
 
-		case BundleException.INVALID_OPERATION:
-		case BundleException.MANIFEST_ERROR:
-		case BundleException.NATIVECODE_ERROR:
-		case BundleException.STATECHANGE_ERROR:
-		case BundleException.UNSUPPORTED_OPERATION:
-		case BundleException.UNSPECIFIED:
-		default:
-			return ERROR;
+			case BundleException.INVALID_OPERATION :
+			case BundleException.MANIFEST_ERROR :
+			case BundleException.NATIVECODE_ERROR :
+			case BundleException.STATECHANGE_ERROR :
+			case BundleException.UNSUPPORTED_OPERATION :
+			case BundleException.UNSPECIFIED :
+			default :
+				return ERROR;
 		}
 	}
 
 	public String translateToMessage(BundleException e) {
 		switch (e.getType()) {
-		case BundleException.ACTIVATOR_ERROR:
-			Throwable t = e.getCause();
-			StackTraceElement[] stackTrace = t.getStackTrace();
-			if (stackTrace == null || stackTrace.length == 0)
-				return "activator error " + t.getMessage();
-			StackTraceElement top = stackTrace[0];
-			return "activator error " + t.getMessage() + " from: " + top.getClassName() + ":"
-					+ top.getMethodName() + "#" + top.getLineNumber();
-
-		case BundleException.DUPLICATE_BUNDLE_ERROR:
-		case BundleException.RESOLVE_ERROR:
-		case BundleException.INVALID_OPERATION:
-		case BundleException.MANIFEST_ERROR:
-		case BundleException.NATIVECODE_ERROR:
-		case BundleException.STATECHANGE_ERROR:
-		case BundleException.UNSUPPORTED_OPERATION:
-		case BundleException.UNSPECIFIED:
-		default:
-			return e.getMessage();
+			case BundleException.ACTIVATOR_ERROR :
+				Throwable t = e.getCause();
+				StackTraceElement[] stackTrace = t.getStackTrace();
+				if (stackTrace == null || stackTrace.length == 0)
+					return "activator error " + t.getMessage();
+				StackTraceElement top = stackTrace[0];
+				return "activator error " + t.getMessage() + " from: " + top.getClassName() + ":" + top.getMethodName()
+						+ "#" + top.getLineNumber();
+
+			case BundleException.DUPLICATE_BUNDLE_ERROR :
+			case BundleException.RESOLVE_ERROR :
+			case BundleException.INVALID_OPERATION :
+			case BundleException.MANIFEST_ERROR :
+			case BundleException.NATIVECODE_ERROR :
+			case BundleException.STATECHANGE_ERROR :
+			case BundleException.UNSUPPORTED_OPERATION :
+			case BundleException.UNSPECIFIED :
+			default :
+				return e.getMessage();
 		}
 	}
 
@@ -703,11 +853,13 @@ public class Launcher implements ServiceListener {
 
 	class AllPolicy extends Policy {
 
+		@Override
 		public PermissionCollection getPermissions(CodeSource codesource) {
 			trace("Granting AllPermission to %s", codesource.getLocation());
 			return all;
 		}
 
+		@Override
 		public void refresh() {
 			trace("Policy refresh");
 		}
@@ -725,13 +877,15 @@ public class Launcher implements ServiceListener {
 			setReadOnly();
 		}
 
-		public void add(Permission permission) {
-		}
+		@Override
+		public void add(Permission permission) {}
 
+		@Override
 		public Enumeration<Permission> elements() {
 			return list.elements();
 		}
 
+		@Override
 		public boolean implies(Permission permission) {
 			return true;
 		}
@@ -739,8 +893,7 @@ public class Launcher implements ServiceListener {
 
 	public synchronized void serviceChanged(ServiceEvent event) {
 		if (event.getType() == ServiceEvent.REGISTERED) {
-			mainThread = (Runnable) systemBundle.getBundleContext().getService(
-					event.getServiceReference());
+			mainThread = (Runnable) systemBundle.getBundleContext().getService(event.getServiceReference());
 			notifyAll();
 		}
 	}
@@ -754,7 +907,7 @@ public class Launcher implements ServiceListener {
 	private void message(String prefix, String string, Object[] objects) {
 		Throwable e = null;
 
-		StringBuffer sb = new StringBuffer();
+		StringBuilder sb = new StringBuilder();
 		int n = 0;
 		sb.append(prefix);
 		for (int i = 0; i < string.length(); i++) {
@@ -762,28 +915,28 @@ public class Launcher implements ServiceListener {
 			if (c == '%') {
 				c = string.charAt(++i);
 				switch (c) {
-				case 's':
-					if (n < objects.length) {
-						Object o = objects[n++];
-						if (o instanceof Throwable) {
-							e = (Throwable) o;
-							if (o instanceof BundleException) {
-								sb.append(translateToMessage((BundleException) o));
-							} else if (o instanceof InvocationTargetException) {
-								Throwable t = (InvocationTargetException) o;
-								sb.append(t.getMessage());
-								e = t;
-							} else
-								sb.append(e.getMessage());
-						} else {
-							sb.append(o);
-						}
-					} else
-						sb.append("<no more arguments>");
-					break;
+					case 's' :
+						if (n < objects.length) {
+							Object o = objects[n++];
+							if (o instanceof Throwable) {
+								e = (Throwable) o;
+								if (o instanceof BundleException) {
+									sb.append(translateToMessage((BundleException) o));
+								} else if (o instanceof InvocationTargetException) {
+									Throwable t = (InvocationTargetException) o;
+									sb.append(t.getMessage());
+									e = t;
+								} else
+									sb.append(e.getMessage());
+							} else {
+								sb.append(o);
+							}
+						} else
+							sb.append("<no more arguments>");
+						break;
 
-				default:
-					sb.append(c);
+					default :
+						sb.append(c);
 				}
 			} else {
 				sb.append(c);
diff --git a/biz.aQute.launcher/src/aQute/launcher/SimplePermissionPolicy.java b/biz.aQute.launcher/src/aQute/launcher/SimplePermissionPolicy.java
index a0780d7..7de4d78 100644
--- a/biz.aQute.launcher/src/aQute/launcher/SimplePermissionPolicy.java
+++ b/biz.aQute.launcher/src/aQute/launcher/SimplePermissionPolicy.java
@@ -55,7 +55,8 @@ public class SimplePermissionPolicy implements SynchronousBundleListener {
 			PermissionInfo[] info;
 			try {
 				info = parse(in);
-			} finally {
+			}
+			finally {
 				in.close();
 			}
 			permissionAdmin.setDefaultPermissions(info);
@@ -82,14 +83,12 @@ public class SimplePermissionPolicy implements SynchronousBundleListener {
 		if (info == null) {
 			launcher.trace("Using default permissions for %s", bundle.getLocation());
 			info = defaultPermissions;
-		}
-		else
+		} else
 			launcher.trace("For permissions inside bundle %s", bundle.getLocation());
 
-		
 		if (info != null && info.length > 0) {
 			bundles.add(bundle);
-			permissionAdmin.setPermissions(bundle.getLocation(), info);			
+			permissionAdmin.setPermissions(bundle.getLocation(), info);
 		} else
 			launcher.trace("No permissions for %s", bundle.getLocation());
 	}
@@ -107,9 +106,9 @@ public class SimplePermissionPolicy implements SynchronousBundleListener {
 			try {
 				InputStream in = url.openStream();
 				info = parse(in);
-			} catch (IOException e) {
-				System.out.println("Unable to read permission info for bundle  "
-						+ bundle.getLocation() + " " + e);
+			}
+			catch (IOException e) {
+				System.err.println("Unable to read permission info for bundle  " + bundle.getLocation() + " " + e);
 			}
 		return info;
 	}
@@ -130,12 +129,14 @@ public class SimplePermissionPolicy implements SynchronousBundleListener {
 						continue;
 					try {
 						permissions.add(new PermissionInfo(line));
-					} catch (IllegalArgumentException iae) {
+					}
+					catch (IllegalArgumentException iae) {
 						/* incorrectly encoded permission */
-						System.out.println("Permission incorrectly encoded: " + line + " " + iae);
+						System.err.println("Permission incorrectly encoded: " + line + " " + iae);
 					}
 				}
-			} finally {
+			}
+			finally {
 				in.close();
 			}
 			int size = permissions.size();
@@ -178,13 +179,13 @@ public class SimplePermissionPolicy implements SynchronousBundleListener {
 			return;
 		int type = event.getType();
 		switch (type) {
-		case BundleEvent.INSTALLED:
-		case BundleEvent.UPDATED:
-			setPermissions(bundle);
-			break;
-		case BundleEvent.UNINSTALLED:
-			clearPermissions(bundle);
-			break;
+			case BundleEvent.INSTALLED :
+			case BundleEvent.UPDATED :
+				setPermissions(bundle);
+				break;
+			case BundleEvent.UNINSTALLED :
+				clearPermissions(bundle);
+				break;
 		}
 	}
 
diff --git a/biz.aQute.launcher/src/aQute/launcher/constants/LauncherConstants.java b/biz.aQute.launcher/src/aQute/launcher/constants/LauncherConstants.java
index a8051bb..c0764d7 100644
--- a/biz.aQute.launcher/src/aQute/launcher/constants/LauncherConstants.java
+++ b/biz.aQute.launcher/src/aQute/launcher/constants/LauncherConstants.java
@@ -5,34 +5,37 @@ import java.util.*;
 
 public class LauncherConstants {
 
-	public final static String	LAUNCHER_PROPERTIES		= "launcher.properties";
-	public final static String	LAUNCHER_ARGUMENTS		= "launcher.arguments";
-	public final static String	LAUNCHER_READY			= "launcher.ready";
+	public final static String	LAUNCHER_PROPERTIES			= "launcher.properties";
+	public final static String	DEFAULT_LAUNCHER_PROPERTIES	= "launcher.properties";
+	public final static String	LAUNCHER_ARGUMENTS			= "launcher.arguments";
+	public final static String	LAUNCHER_READY				= "launcher.ready";
 
 	// MUST BE ALIGNED WITH ProjectLauncher! Donot want to create coupling
 	// so cannot refer.
-	public final static int		OK						= 0;
-	public final static int		ERROR					= -2;
-	public final static int		WARNING					= -1;
-	public final static int		TIMEDOUT				= -3;
-	public final static int		UPDATE_NEEDED			= -4;
-	public final static int		CANCELED				= -5;
-	public final static int		DUPLICATE_BUNDLE		= -6;
-	public final static int		RESOLVE_ERROR			= -7;
-	public final static int		ACTIVATOR_ERROR			= -8;
+	public final static int		OK							= 0;
+	public final static int		ERROR						= -2;
+	public final static int		WARNING						= -1;
+	public final static int		TIMEDOUT					= -3;
+	public final static int		UPDATE_NEEDED				= -4;
+	public final static int		CANCELED					= -5;
+	public final static int		DUPLICATE_BUNDLE			= -6;
+	public final static int		RESOLVE_ERROR				= -7;
+	public final static int		ACTIVATOR_ERROR				= -8;
 	// Start custom errors from here
-	public final static int		CUSTOM_LAUNCHER			= -128;
+	public final static int		CUSTOM_LAUNCHER				= -128;
 
 	// Local names
-	final static String			LAUNCH_SERVICES			= "launch.services";
-	final static String			LAUNCH_STORAGE_DIR		= "launch.storage.dir";
-	final static String			LAUNCH_KEEP				= "launch.keep";
-	final static String			LAUNCH_RUNBUNDLES		= "launch.bundles";
-	final static String			LAUNCH_SYSTEMPACKAGES	= "launch.system.packages";
-	final static String			LAUNCH_TRACE			= "launch.trace";
-	final static String			LAUNCH_TIMEOUT			= "launch.timeout";
-	final static String			LAUNCH_ACTIVATORS		= "launch.activators";
-
+	final static String			LAUNCH_SERVICES				= "launch.services";
+	final static String			LAUNCH_STORAGE_DIR			= "launch.storage.dir";
+	final static String			LAUNCH_KEEP					= "launch.keep";
+	final static String			LAUNCH_RUNBUNDLES			= "launch.bundles";
+	final static String			LAUNCH_SYSTEMPACKAGES		= "launch.system.packages";
+	final static String			LAUNCH_SYSTEMCAPABILITIES	= "launch.system.capabilities";
+	final static String			LAUNCH_TRACE				= "launch.trace";
+	final static String			LAUNCH_TIMEOUT				= "launch.timeout";
+	final static String			LAUNCH_ACTIVATORS			= "launch.activators";
+	final static String			LAUNCH_EMBEDDED				= "launch.embedded";
+	final static String			LAUNCH_NAME					= "launch.name";
 	/**
 	 * The command line arguments of the launcher. Launcher are not supposed to
 	 * eat any arguments, they should use -D VM arguments so that applications
@@ -41,14 +44,17 @@ public class LauncherConstants {
 	 */
 
 	public boolean				services;
-	public File					storageDir				= new File("");
+	public File					storageDir;
 	public boolean				keep;
-	public final List<String>	runbundles				= new ArrayList<String>();
+	public final List<String>	runbundles					= new ArrayList<String>();
 	public String				systemPackages;
+	public String				systemCapabilities;
 	public boolean				trace;
 	public long					timeout;
-	public final List<String>	activators				= new ArrayList<String>();
-	public Map<String, String>	runProperties			= new HashMap<String, String>();
+	public final List<String>	activators					= new ArrayList<String>();
+	public Map<String,String>	runProperties				= new HashMap<String,String>();
+	public boolean				embedded					= false;
+	public String				name;
 
 	/**
 	 * Translate a constants to properties.
@@ -58,20 +64,28 @@ public class LauncherConstants {
 	public Properties getProperties() {
 		Properties p = new Properties();
 		p.setProperty(LAUNCH_SERVICES, services + "");
-		p.setProperty(LAUNCH_STORAGE_DIR, storageDir.getAbsolutePath());
+		if (storageDir != null)
+			p.setProperty(LAUNCH_STORAGE_DIR, storageDir.getAbsolutePath());
 		p.setProperty(LAUNCH_KEEP, keep + "");
 		p.setProperty(LAUNCH_RUNBUNDLES, join(runbundles, ","));
 		if (systemPackages != null)
 			p.setProperty(LAUNCH_SYSTEMPACKAGES, systemPackages + "");
+		if (systemCapabilities != null)
+			p.setProperty(LAUNCH_SYSTEMCAPABILITIES, systemCapabilities + "");
 		p.setProperty(LAUNCH_TRACE, trace + "");
 		p.setProperty(LAUNCH_TIMEOUT, timeout + "");
 		p.setProperty(LAUNCH_ACTIVATORS, join(activators, ","));
-
-		for (Map.Entry<String, String> entry : runProperties.entrySet()) {
-			if (entry.getValue() == null)
-				p.remove(entry.getKey());
-			else
+		p.setProperty(LAUNCH_EMBEDDED, embedded + "");
+		if (name != null)
+			p.setProperty(LAUNCH_NAME, name);
+
+		for (Map.Entry<String,String> entry : runProperties.entrySet()) {
+			if (entry.getValue() == null) {
+				if (entry.getKey() != null)
+					p.remove(entry.getKey());
+			} else {
 				p.put(entry.getKey(), entry.getValue());
+			}
 
 		}
 		return p;
@@ -81,8 +95,7 @@ public class LauncherConstants {
 	 * Empty constructor for the plugin
 	 */
 
-	public LauncherConstants() {
-	}
+	public LauncherConstants() {}
 
 	/**
 	 * Create a constants from properties.
@@ -91,18 +104,23 @@ public class LauncherConstants {
 	 */
 	public LauncherConstants(Properties p) {
 		services = Boolean.valueOf(p.getProperty(LAUNCH_SERVICES));
-		storageDir = new File(p.getProperty(LAUNCH_STORAGE_DIR));
+		if (p.getProperty(LAUNCH_STORAGE_DIR) != null)
+			storageDir = new File(p.getProperty(LAUNCH_STORAGE_DIR));
 		keep = Boolean.valueOf(p.getProperty(LAUNCH_KEEP));
 		runbundles.addAll(split(p.getProperty(LAUNCH_RUNBUNDLES), ","));
 		systemPackages = p.getProperty(LAUNCH_SYSTEMPACKAGES);
+		systemCapabilities = p.getProperty(LAUNCH_SYSTEMCAPABILITIES);
 		trace = Boolean.valueOf(p.getProperty(LAUNCH_TRACE));
 		timeout = Long.parseLong(p.getProperty(LAUNCH_TIMEOUT));
 		activators.addAll(split(p.getProperty(LAUNCH_ACTIVATORS), " ,"));
-		Map<String, String> map = (Map) p;
+		String s = p.getProperty(LAUNCH_EMBEDDED);
+		embedded = s != null && Boolean.parseBoolean(s);
+		name = p.getProperty(LAUNCH_NAME);
+		Map<String,String> map = (Map) p;
 		runProperties.putAll(map);
 	}
 
-	private Collection<? extends String> split(String property, String string) {
+	private Collection< ? extends String> split(String property, String string) {
 		List<String> result = new ArrayList<String>();
 		StringTokenizer st = new StringTokenizer(property, string);
 		while (st.hasMoreTokens()) {
@@ -112,8 +130,8 @@ public class LauncherConstants {
 		return result;
 	}
 
-	private static String join(List<?> runbundles2, String string) {
-		StringBuffer sb = new StringBuffer();
+	private static String join(List< ? > runbundles2, String string) {
+		StringBuilder sb = new StringBuilder();
 		String del = "";
 		for (Object r : runbundles2) {
 			sb.append(del);
diff --git a/biz.aQute.launcher/src/aQute/launcher/minifw/Context.java b/biz.aQute.launcher/src/aQute/launcher/minifw/Context.java
index 5a2e38e..3761a8a 100644
--- a/biz.aQute.launcher/src/aQute/launcher/minifw/Context.java
+++ b/biz.aQute.launcher/src/aQute/launcher/minifw/Context.java
@@ -9,326 +9,324 @@ import java.util.zip.*;
 import org.osgi.framework.*;
 
 public class Context extends URLClassLoader implements Bundle, BundleContext, BundleReference {
-    long            id;
-    MiniFramework   fw;
-    String          location;
-    int             state = Bundle.INSTALLED;
-    JarFile         jar;
-    Manifest        manifest;
-    TreeSet         keys;
-    private TreeSet paths;
-	private File	jarFile;
-
-    class Dict extends Dictionary {
-
-        public Enumeration elements() {
-            return Collections.enumeration(manifest.getMainAttributes()
-                    .values());
-        }
-
-        public Object get(Object key) {
-            Object o = manifest.getMainAttributes().getValue((String) key);
-            return o;
-        }
-
-        public boolean isEmpty() {
-            return manifest.getMainAttributes().isEmpty();
-        }
-
-        public Enumeration keys() {
-            Vector v = new Vector();
-            for (Iterator i = manifest.getMainAttributes().keySet().iterator(); i
-                    .hasNext();) {
-                Attributes.Name name = (Attributes.Name) i.next();
-                v.add(name.toString());
-            }
-            return v.elements();
-        }
-
-        public Object put(Object key, Object value) {
-            throw new UnsupportedOperationException();
-        }
-
-        public Object remove(Object key) {
-            throw new UnsupportedOperationException();
-        }
-
-        public int size() {
-            return manifest.getMainAttributes().size();
-        }
-
-    }
-
-    public Context(MiniFramework fw, ClassLoader parent, int id, String location)
-            throws Exception {
-        super(new URL[] { new File(location).toURI().toURL() }, parent);
-        this.fw = fw;
-        this.id = id;
-        this.location = location;
-        
-        jar = new JarFile(jarFile = new File(location));
-//        Enumeration<JarEntry> entries = jar.entries();
-//        while ( entries.hasMoreElements())
-//        	System.out.println(entries.nextElement().getName());
-        
-        manifest = jar.getManifest();
-        jar.close();
-    }
-
-    public BundleContext getBundleContext() {
-        return this;
-    }
-
-    public long getBundleId() {
-        return id;
-    }
-
-    public URL getEntry(String path) {
-    	if ( path.startsWith("/"))
-    		path = path.substring(1);
-        return getResource(path);
-    }
-
-    public Enumeration getEntryPaths(String path) {
-        throw new UnsupportedOperationException();
-    }
-
-    public Dictionary getHeaders() {
-        return new Dict();
-    }
-
-    public Dictionary getHeaders(String locale) {
-        return new Dict();
-    }
-
-    public long getLastModified() {
-        return jarFile.lastModified();
-    }
-
-    public String getLocation() {
-        return location;
-    }
-
-    public Enumeration findEntries(String path, String filePattern,
-            boolean recurse) {
-
-        try {
-            if (path.startsWith("/"))
-                path = path.substring(1);
-            if (!path.endsWith("/"))
-                path += "/";
-
-            Vector paths = new Vector();
-            for (Iterator i = getPaths().iterator(); i.hasNext();) {
-                String entry = (String) i.next();
-                if (entry.startsWith(path)) {
-                    if (recurse || entry.indexOf('/', path.length()) < 0) {
-                        if (filePattern == null || matches(entry, filePattern)) {
-                            URL url = getResource(entry);
-                            if (url == null) {
-                                System.err
-                                        .println("Cannot load resource that should be there: "
-                                                + entry);
-                            } else
-                                paths.add(url);
-                        }
-                    }
-                }
-            }
-            return paths.elements();
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static boolean matches(String path, String filePattern) {
-        do {
-            int part = filePattern.indexOf('*');
-            if (part < 0) {
-                return path.indexOf(filePattern) >= 0;
-            } else {
-                String match = filePattern.substring(0, part);
-                int m = path.indexOf(match);
-                if (m < 0)
-                    return false;
-
-                path = path.substring(m + match.length());
-                filePattern = filePattern.substring(part + 1);
-            }
-        } while (true);
-    }
-
-    private Collection getPaths() throws Exception {
-        if (paths != null)
-            return paths;
-
-        paths = new TreeSet();
-        JarFile jar = new JarFile(new File(location));
-        try {
-            for (Enumeration e = jar.entries(); e.hasMoreElements();) {
-                ZipEntry entry = (JarEntry) e.nextElement();
-                paths.add(entry.getName());
-            }
-        } finally {
-            jar.close();
-        }
-        return paths;
-    }
-
-    public ServiceReference[] getRegisteredServices() {
-        return null;
-    }
-
-    public ServiceReference[] getServicesInUse() {
-        return null;
-    }
-
-    public Map getSignerCertificates(int signersType) {
-        throw new UnsupportedOperationException();
-    }
-
-    public int getState() {
-        return state;
-    }
-
-    public String getSymbolicName() {
-        return ((String)getHeaders().get("Bundle-SymbolicName")).trim();
-    }
-
-    public Version getVersion() {
-        String v = ((String)getHeaders().get("Bundle-Version")).trim();
-        if ( v == null)
-        	return new Version("0");
-        else
-        	return new Version(v);
-    }
-
-    public boolean hasPermission(Object permission) {
-        return true;
-    }
-
-    public void start() throws BundleException {
-        state = Bundle.ACTIVE;
-    }
-
-    public void start(int options) throws BundleException {
-        state = Bundle.ACTIVE;
-    }
-
-    public void stop() throws BundleException {
-        state = Bundle.RESOLVED;
-    }
-
-    public void stop(int options) throws BundleException {
-        state = Bundle.RESOLVED;
-    }
-
-    public void uninstall() throws BundleException {
-        state = Bundle.UNINSTALLED;
-    }
-
-    public void update() throws BundleException {
-        throw new UnsupportedOperationException();
-    }
-
-    public void update(InputStream in) throws BundleException {
-        throw new UnsupportedOperationException();
-    }
-
-    public void addBundleListener(BundleListener listener) {
-        throw new UnsupportedOperationException();
-    }
-
-    public void addFrameworkListener(FrameworkListener listener) {
-        throw new UnsupportedOperationException();
-    }
-
-    public void addServiceListener(ServiceListener listener) {
-        throw new UnsupportedOperationException();
-    }
-
-    public void addServiceListener(ServiceListener listener, String filter) {
-        throw new UnsupportedOperationException();
-    }
-
-    public Filter createFilter(String filter) throws InvalidSyntaxException {
-        throw new UnsupportedOperationException();
-    }
-
-    public ServiceReference[] getAllServiceReferences(String clazz,
-            String filter) throws InvalidSyntaxException {
-        throw new UnsupportedOperationException();
-    }
-
-    public Bundle getBundle() {
-        return this;
-    }
-
-    public Bundle getBundle(long id) {
-        return fw.getBundle(id);
-    }
-
-    public Bundle[] getBundles() {
-        return fw.getBundles();
-    }
-
-    public File getDataFile(String filename) {
-        return null;
-    }
-
-    public String getProperty(String key) {
-        return fw.getProperty(key);
-    }
-
-    public Object getService(ServiceReference reference) {
-        throw new UnsupportedOperationException();
-    }
-
-    public ServiceReference getServiceReference(String clazz) {
-        return null;
-    }
-
-    public ServiceReference[] getServiceReferences(String clazz, String filter)
-            throws InvalidSyntaxException {
-        return null;
-    }
-
-    public Bundle installBundle(String location) throws BundleException {
-        return fw.installBundle(location);
-    }
-
-    public Bundle installBundle(String location, InputStream input)
-            throws BundleException {
-        return fw.installBundle(location, input);
-    }
-
-    public ServiceRegistration registerService(String[] clazzes,
-            Object service, Dictionary properties) {
-        throw new UnsupportedOperationException();
-    }
-
-    public ServiceRegistration registerService(String clazz, Object service,
-            Dictionary properties) {
-        throw new UnsupportedOperationException();
-    }
-
-    public void removeBundleListener(BundleListener listener) {
-        throw new UnsupportedOperationException();
-    }
-
-    public void removeFrameworkListener(FrameworkListener listener) {
-        throw new UnsupportedOperationException();
-    }
-
-    public void removeServiceListener(ServiceListener listener) {
-        throw new UnsupportedOperationException();
-    }
-
-    public boolean ungetService(ServiceReference reference) {
-        throw new UnsupportedOperationException();
-    }
-
-    public String toString() {
-        return id + " " + location;
-    }
+	long					id;
+	MiniFramework			fw;
+	String					location;
+	int						state	= Bundle.INSTALLED;
+	JarFile					jar;
+	Manifest				manifest;
+	private TreeSet<String>	paths;
+	private File			jarFile;
+
+	class Dict extends Dictionary<String,Object> {
+
+		@Override
+		public Enumeration<Object> elements() {
+			return Collections.enumeration(manifest.getMainAttributes().values());
+		}
+
+		@Override
+		public Object get(Object key) {
+			Object o = manifest.getMainAttributes().getValue((String) key);
+			return o;
+		}
+
+		@Override
+		public boolean isEmpty() {
+			return manifest.getMainAttributes().isEmpty();
+		}
+
+		@Override
+		public Enumeration<String> keys() {
+			Vector<String> v = new Vector<String>();
+			for (Iterator<Object> i = manifest.getMainAttributes().keySet().iterator(); i.hasNext();) {
+				Attributes.Name name = (Attributes.Name) i.next();
+				v.add(name.toString());
+			}
+			return v.elements();
+		}
+
+		@Override
+		public Object put(String key, Object value) {
+			throw new UnsupportedOperationException();
+		}
+
+		@Override
+		public Object remove(Object key) {
+			throw new UnsupportedOperationException();
+		}
+
+		@Override
+		public int size() {
+			return manifest.getMainAttributes().size();
+		}
+
+	}
+
+	public Context(MiniFramework fw, ClassLoader parent, int id, String location) throws Exception {
+		super(new URL[] {
+			new File(location).toURI().toURL()
+		}, parent);
+		this.fw = fw;
+		this.id = id;
+		this.location = location;
+
+		jar = new JarFile(jarFile = new File(location));
+		// Enumeration<JarEntry> entries = jar.entries();
+		// while ( entries.hasMoreElements())
+		// System.err.println(entries.nextElement().getName());
+
+		manifest = jar.getManifest();
+		jar.close();
+	}
+
+	public BundleContext getBundleContext() {
+		return this;
+	}
+
+	public long getBundleId() {
+		return id;
+	}
+
+	public URL getEntry(String path) {
+		if (path.startsWith("/"))
+			path = path.substring(1);
+		return getResource(path);
+	}
+
+	public Enumeration< ? > getEntryPaths(String path) {
+		throw new UnsupportedOperationException();
+	}
+
+	public Dictionary<String,Object> getHeaders() {
+		return new Dict();
+	}
+
+	public Dictionary<String,Object> getHeaders(String locale) {
+		return new Dict();
+	}
+
+	public long getLastModified() {
+		return jarFile.lastModified();
+	}
+
+	public String getLocation() {
+		return location;
+	}
+
+	public Enumeration<URL> findEntries(String path, String filePattern, boolean recurse) {
+
+		try {
+			if (path.startsWith("/"))
+				path = path.substring(1);
+			if (!path.endsWith("/"))
+				path += "/";
+
+			Vector<URL> paths = new Vector<URL>();
+			for (Iterator<String> i = getPaths().iterator(); i.hasNext();) {
+				String entry = i.next();
+				if (entry.startsWith(path)) {
+					if (recurse || entry.indexOf('/', path.length()) < 0) {
+						if (filePattern == null || matches(entry, filePattern)) {
+							URL url = getResource(entry);
+							if (url == null) {
+								System.err.println("Cannot load resource that should be there: " + entry);
+							} else
+								paths.add(url);
+						}
+					}
+				}
+			}
+			return paths.elements();
+		}
+		catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	public static boolean matches(String path, String filePattern) {
+		do {
+			int part = filePattern.indexOf('*');
+			if (part < 0) {
+				return path.indexOf(filePattern) >= 0;
+			}
+			String match = filePattern.substring(0, part);
+			int m = path.indexOf(match);
+			if (m < 0)
+				return false;
+
+			path = path.substring(m + match.length());
+			filePattern = filePattern.substring(part + 1);
+		} while (true);
+	}
+
+	private Collection<String> getPaths() throws Exception {
+		if (paths != null)
+			return paths;
+
+		paths = new TreeSet<String>();
+		JarFile jar = new JarFile(new File(location));
+		try {
+			for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements();) {
+				ZipEntry entry = e.nextElement();
+				paths.add(entry.getName());
+			}
+		}
+		finally {
+			jar.close();
+		}
+		return paths;
+	}
+
+	public ServiceReference[] getRegisteredServices() {
+		return null;
+	}
+
+	public ServiceReference[] getServicesInUse() {
+		return null;
+	}
+
+	public Map< ? , ? > getSignerCertificates(int signersType) {
+		throw new UnsupportedOperationException();
+	}
+
+	public int getState() {
+		return state;
+	}
+
+	public String getSymbolicName() {
+		return ((String) getHeaders().get("Bundle-SymbolicName")).trim();
+	}
+
+	public Version getVersion() {
+		String v = ((String) getHeaders().get("Bundle-Version")).trim();
+		if (v == null)
+			return new Version("0");
+		return new Version(v);
+	}
+
+	public boolean hasPermission(Object permission) {
+		return true;
+	}
+
+	public void start() throws BundleException {
+		state = Bundle.ACTIVE;
+	}
+
+	public void start(int options) throws BundleException {
+		state = Bundle.ACTIVE;
+	}
+
+	public void stop() throws BundleException {
+		state = Bundle.RESOLVED;
+	}
+
+	public void stop(int options) throws BundleException {
+		state = Bundle.RESOLVED;
+	}
+
+	public void uninstall() throws BundleException {
+		state = Bundle.UNINSTALLED;
+	}
+
+	public void update() throws BundleException {
+		throw new UnsupportedOperationException();
+	}
+
+	public void update(InputStream in) throws BundleException {
+		throw new UnsupportedOperationException();
+	}
+
+	public void addBundleListener(BundleListener listener) {
+		throw new UnsupportedOperationException();
+	}
+
+	public void addFrameworkListener(FrameworkListener listener) {
+		throw new UnsupportedOperationException();
+	}
+
+	public void addServiceListener(ServiceListener listener) {
+		throw new UnsupportedOperationException();
+	}
+
+	public void addServiceListener(ServiceListener listener, String filter) {
+		throw new UnsupportedOperationException();
+	}
+
+	public Filter createFilter(String filter) throws InvalidSyntaxException {
+		throw new UnsupportedOperationException();
+	}
+
+	public ServiceReference[] getAllServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
+		throw new UnsupportedOperationException();
+	}
+
+	public Bundle getBundle() {
+		return this;
+	}
+
+	public Bundle getBundle(long id) {
+		return fw.getBundle(id);
+	}
+
+	public Bundle[] getBundles() {
+		return fw.getBundles();
+	}
+
+	public File getDataFile(String filename) {
+		return null;
+	}
+
+	public String getProperty(String key) {
+		return fw.getProperty(key);
+	}
+
+	public Object getService(ServiceReference reference) {
+		throw new UnsupportedOperationException();
+	}
+
+	public ServiceReference getServiceReference(String clazz) {
+		return null;
+	}
+
+	public ServiceReference[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
+		return null;
+	}
+
+	public Bundle installBundle(String location) throws BundleException {
+		return fw.installBundle(location);
+	}
+
+	public Bundle installBundle(String location, InputStream input) throws BundleException {
+		return fw.installBundle(location, input);
+	}
+
+	public ServiceRegistration registerService(String[] clazzes, Object service, Dictionary properties) {
+		throw new UnsupportedOperationException();
+	}
+
+	public ServiceRegistration registerService(String clazz, Object service, Dictionary properties) {
+		throw new UnsupportedOperationException();
+	}
+
+	public void removeBundleListener(BundleListener listener) {
+		throw new UnsupportedOperationException();
+	}
+
+	public void removeFrameworkListener(FrameworkListener listener) {
+		throw new UnsupportedOperationException();
+	}
+
+	public void removeServiceListener(ServiceListener listener) {
+		throw new UnsupportedOperationException();
+	}
+
+	public boolean ungetService(ServiceReference reference) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public String toString() {
+		return id + " " + location;
+	}
 }
diff --git a/biz.aQute.launcher/src/aQute/launcher/minifw/MiniFramework.java b/biz.aQute.launcher/src/aQute/launcher/minifw/MiniFramework.java
index 3ccf0c0..7d910c5 100644
--- a/biz.aQute.launcher/src/aQute/launcher/minifw/MiniFramework.java
+++ b/biz.aQute.launcher/src/aQute/launcher/minifw/MiniFramework.java
@@ -8,14 +8,14 @@ import org.osgi.framework.*;
 import org.osgi.framework.launch.*;
 
 public class MiniFramework implements Framework, Bundle, BundleContext {
-	ClassLoader	loader;
-	Properties	properties;
-	Map			bundles	= new HashMap();
-	int			ID		= 1;
-	int			state	= Bundle.INSTALLED;
-	ClassLoader	last;
-
-	public MiniFramework(Map properties) {
+	ClassLoader			loader;
+	Properties			properties;
+	Map<Long,Bundle>	bundles	= new HashMap<Long,Bundle>();
+	int					ID		= 1;
+	int					state	= Bundle.INSTALLED;
+	ClassLoader			last;
+
+	public MiniFramework(Map<Object,Object> properties) {
 		this.properties = new Properties(System.getProperties());
 		this.properties.putAll(properties);
 
@@ -35,8 +35,6 @@ public class MiniFramework implements Framework, Bundle, BundleContext {
 				long wait = deadline - System.currentTimeMillis();
 				if (wait <= 0)
 					return new FrameworkEvent(FrameworkEvent.WAIT_TIMEDOUT, this, null);
-			} else {
-				;
 			}
 			Thread.sleep(100);
 		}
@@ -57,15 +55,15 @@ public class MiniFramework implements Framework, Bundle, BundleContext {
 		return loader.getResource(path);
 	}
 
-	public Enumeration getEntryPaths(String path) {
+	public Enumeration< ? > getEntryPaths(String path) {
 		throw new UnsupportedOperationException();
 	}
 
-	public Dictionary getHeaders() {
-		return new Hashtable();
+	public Dictionary<String,String> getHeaders() {
+		return new Hashtable<String,String>();
 	}
 
-	public Dictionary getHeaders(String locale) {
+	public Dictionary< ? , ? > getHeaders(String locale) {
 		throw new UnsupportedOperationException();
 	}
 
@@ -81,7 +79,7 @@ public class MiniFramework implements Framework, Bundle, BundleContext {
 		return loader.getResource(name);
 	}
 
-	public Enumeration getResources(String name) throws IOException {
+	public Enumeration<URL> getResources(String name) throws IOException {
 		return loader.getResources(name);
 	}
 
@@ -101,23 +99,20 @@ public class MiniFramework implements Framework, Bundle, BundleContext {
 		return true;
 	}
 
-	public Class loadClass(String name) throws ClassNotFoundException {
+	public Class< ? > loadClass(String name) throws ClassNotFoundException {
 		return loader.loadClass(name);
 	}
 
-	public void start() {
-	}
+	public void start() {}
 
-	public void start(int options) {
-	}
+	public void start(int options) {}
 
 	public synchronized void stop() {
 		state = Bundle.UNINSTALLED;
 		notifyAll();
 	}
 
-	public void stop(int options) throws BundleException {
-	}
+	public void stop(int options) throws BundleException {}
 
 	public Bundle getBundle() {
 		return this;
@@ -125,13 +120,13 @@ public class MiniFramework implements Framework, Bundle, BundleContext {
 
 	public Bundle getBundle(long id) {
 		Long l = new Long(id);
-		Bundle b = (Bundle) bundles.get(l);
+		Bundle b = bundles.get(l);
 		return b;
 	}
 
 	public Bundle[] getBundles() {
 		Bundle[] bs = new Bundle[bundles.size()];
-		return (Bundle[]) bundles.values().toArray(bs);
+		return bundles.values().toArray(bs);
 	}
 
 	public File getDataFile(String filename) {
@@ -143,21 +138,21 @@ public class MiniFramework implements Framework, Bundle, BundleContext {
 	}
 
 	public Bundle installBundle(String location) throws BundleException {
-		if (location.startsWith("reference:"))
-			location = location.substring("reference:".length()).trim();
-
-		if (location.startsWith("file:"))
-			location = location.substring("file:".length()).trim();
+		try {
+			if (location.startsWith("reference:"))
+				location = new File(new URL(location.substring("reference:".length())).toURI()).getPath();
+			else if (location.startsWith("file:"))
+				location = new File(location.substring("file:".length())).getPath();
 
-		while (location.startsWith("//"))
-			location = location.substring(1);
+			while (location.startsWith("//"))
+				location = location.substring(1);
 
-		try {
 			Context c = new Context(this, last, ++ID, location);
 			bundles.put(new Long(c.id), c);
 			last = c;
 			return c;
-		} catch (Exception e) {
+		}
+		catch (Exception e) {
 			throw new BundleException("Failed to install", e);
 		}
 	}
@@ -167,8 +162,10 @@ public class MiniFramework implements Framework, Bundle, BundleContext {
 		try {
 			in.close();
 			try {
+				@SuppressWarnings("unused")
 				URL url = new URL(location);
-			} catch (MalformedURLException e) {
+			}
+			catch (MalformedURLException e) {
 				throw new BundleException(
 						"For the mini framework, the location must be a proper URL even though this is not required by the specification "
 								+ location, e);
@@ -177,12 +174,13 @@ public class MiniFramework implements Framework, Bundle, BundleContext {
 			bundles.put(new Long(c.id), c);
 			last = c;
 			return c;
-		} catch (Exception e) {
+		}
+		catch (Exception e) {
 			throw new BundleException("Can't install " + location, e);
 		}
 	}
 
-	public Enumeration findEntries(String path, String filePattern, boolean recurse) {
+	public Enumeration< ? > findEntries(String path, String filePattern, boolean recurse) {
 		throw new UnsupportedOperationException();
 	}
 
@@ -194,7 +192,7 @@ public class MiniFramework implements Framework, Bundle, BundleContext {
 		throw new UnsupportedOperationException();
 	}
 
-	public Map getSignerCertificates(int signersType) {
+	public Map< ? , ? > getSignerCertificates(int signersType) {
 		throw new UnsupportedOperationException();
 	}
 
@@ -230,8 +228,7 @@ public class MiniFramework implements Framework, Bundle, BundleContext {
 		return FrameworkUtil.createFilter(filter);
 	}
 
-	public ServiceReference[] getAllServiceReferences(String clazz, String filter)
-			throws InvalidSyntaxException {
+	public ServiceReference[] getAllServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
 		throw new UnsupportedOperationException();
 	}
 
@@ -243,13 +240,11 @@ public class MiniFramework implements Framework, Bundle, BundleContext {
 		return null;
 	}
 
-	public ServiceReference[] getServiceReferences(String clazz, String filter)
-			throws InvalidSyntaxException {
+	public ServiceReference[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
 		return null;
 	}
 
-	public ServiceRegistration registerService(String[] clazzes, Object service,
-			Dictionary properties) {
+	public ServiceRegistration registerService(String[] clazzes, Object service, Dictionary properties) {
 		throw new UnsupportedOperationException();
 	}
 
@@ -273,17 +268,19 @@ public class MiniFramework implements Framework, Bundle, BundleContext {
 		throw new UnsupportedOperationException();
 	}
 
+	@Override
 	public String toString() {
 		return "Mini framework";
 	}
 
 	class Loader extends ClassLoader {
-		public Class findClass(String name) throws ClassNotFoundException {
-			for (Iterator i = bundles.values().iterator(); i.hasNext();) {
-				Bundle b = (Bundle) i;
+		@Override
+		public Class< ? > findClass(String name) throws ClassNotFoundException {
+			for (Bundle b : bundles.values()) {
 				try {
 					return b.loadClass(name);
-				} catch (ClassNotFoundException e) {
+				}
+				catch (ClassNotFoundException e) {
 					// Ignore, try next
 				}
 			}
diff --git a/biz.aQute.launcher/src/aQute/launcher/plugin/ProjectLauncherImpl.java b/biz.aQute.launcher/src/aQute/launcher/plugin/ProjectLauncherImpl.java
index f73e2eb..6709105 100644
--- a/biz.aQute.launcher/src/aQute/launcher/plugin/ProjectLauncherImpl.java
+++ b/biz.aQute.launcher/src/aQute/launcher/plugin/ProjectLauncherImpl.java
@@ -1,17 +1,13 @@
 package aQute.launcher.plugin;
 
 import java.io.*;
-import java.text.MessageFormat;
+import java.text.*;
 import java.util.*;
 import java.util.jar.*;
 
 import aQute.bnd.build.*;
-import aQute.bnd.service.RepositoryPlugin.Strategy;
+import aQute.bnd.osgi.*;
 import aQute.launcher.constants.*;
-import aQute.lib.io.*;
-import aQute.lib.osgi.*;
-import aQute.libg.generics.*;
-import static aQute.lib.osgi.Constants.*;
 
 public class ProjectLauncherImpl extends ProjectLauncher {
 	final private Project	project;
@@ -23,9 +19,9 @@ public class ProjectLauncherImpl extends ProjectLauncher {
 		project.trace("created a aQute launcher plugin");
 		this.project = project;
 		propertiesFile = File.createTempFile("launch", ".properties", project.getTarget());
-		project.trace(MessageFormat.format("launcher plugin using temp launch file {0}", propertiesFile.getAbsolutePath()));
-		addRunVM("-D" + LauncherConstants.LAUNCHER_PROPERTIES + "="
-				+ propertiesFile.getAbsolutePath());
+		project.trace(MessageFormat.format("launcher plugin using temp launch file {0}",
+				propertiesFile.getAbsolutePath()));
+		addRunVM("-D" + LauncherConstants.LAUNCHER_PROPERTIES + "=\"" + propertiesFile.getAbsolutePath() + "\"");
 
 		if (project.getRunProperties().get("noframework") != null) {
 			setRunFramework(NONE);
@@ -35,46 +31,60 @@ public class ProjectLauncherImpl extends ProjectLauncher {
 		super.addDefault(Constants.DEFAULT_LAUNCHER_BSN);
 	}
 
+	/**
+	 * Cleanup the properties file. Is called after the process terminates.
+	 */
+
+	@Override
+	public void cleanup() {
+		propertiesFile.delete();
+		project.trace("Deleted ", propertiesFile.getAbsolutePath());
+	}
+
+	@Override
 	public String getMainTypeName() {
 		return "aQute.launcher.Launcher";
 	}
 
+	@Override
 	public void update() throws Exception {
 		updateFromProject();
 		writeProperties();
 	}
-	
-	
+
+	@Override
 	public int launch() throws Exception {
 		prepare();
 		return super.launch();
 	}
 
+	@Override
 	public void prepare() throws Exception {
 		if (prepared)
 			return;
 		prepared = true;
 		writeProperties();
 	}
-	
+
 	void writeProperties() throws Exception {
 		LauncherConstants lc = getConstants(getRunBundles());
 		OutputStream out = new FileOutputStream(propertiesFile);
 		try {
 			lc.getProperties().store(out, "Launching " + project);
-		} finally {
+		}
+		finally {
 			out.close();
 		}
 	}
 
 	/**
-	 * @return 
+	 * @return
 	 * @throws Exception
 	 * @throws FileNotFoundException
 	 * @throws IOException
 	 */
-	private LauncherConstants getConstants(Collection<String> runbundles) throws Exception,
-			FileNotFoundException, IOException {
+	private LauncherConstants getConstants(Collection<String> runbundles) throws Exception, FileNotFoundException,
+			IOException {
 		project.trace("preparing the aQute launcher plugin");
 
 		LauncherConstants lc = new LauncherConstants();
@@ -82,75 +92,107 @@ public class ProjectLauncherImpl extends ProjectLauncher {
 		lc.runProperties = getRunProperties();
 		lc.storageDir = getStorageDir();
 		lc.keep = isKeep();
-		lc.runbundles.addAll(getRunBundles());
+		lc.runbundles.addAll(runbundles);
 		lc.trace = getTrace();
 		lc.timeout = getTimeout();
 		lc.services = super.getRunFramework() == SERVICES ? true : false;
 		lc.activators.addAll(getActivators());
+		lc.name = getProject().getName();
 
-		if (!getSystemPackages().isEmpty()) {
-			lc.systemPackages = Processor.printClauses(getSystemPackages());
+		try {
+			// If the workspace contains a newer version of biz.aQute.launcher than the version of bnd(tools) used
+			// then this could throw NoSuchMethodError. For now just ignore it.
+			Map<String, ? extends Map<String,String>> systemPkgs = getSystemPackages();
+			if (systemPkgs != null && !systemPkgs.isEmpty())
+				lc.systemPackages = Processor.printClauses(systemPkgs);
+		} catch (Throwable e) {
 		}
-		return lc;
 		
+		try {
+			// If the workspace contains a newer version of biz.aQute.launcher than the version of bnd(tools) used
+			// then this could throw NoSuchMethodError. For now just ignore it.
+			String systemCaps = getSystemCapabilities();
+			if (systemCaps != null) {
+				systemCaps = systemCaps.trim();
+				if (systemCaps.length() > 0)
+					lc.systemCapabilities = systemCaps;
+			}
+		} catch (Throwable e) {
+		}
+		return lc;
+
 	}
 
 	/**
-	 * Create a standalone executable
-	 * @throws Exception 
-	 * @throws IOException 
-	 * @throws FileNotFoundException 
+	 * Create a standalone executable. All entries on the runpath are rolled out
+	 * into the JAR and the runbundles are copied to a directory in the jar. The
+	 * launcher will see that it starts in embedded mode and will automatically
+	 * detect that it should load the bundles from inside. This is drive by the
+	 * launcher.embedded flag.
+	 * 
+	 * @throws Exception
 	 */
 
+	@Override
 	public Jar executable() throws Exception {
 		Jar jar = new Jar(project.getName());
-		
-		Collection<String> runbundles = copyBundles(jar, getRunBundles());
-		LauncherConstants lc = getConstants(runbundles);
-		final Properties p = lc.getProperties();
-		p.setProperty(RUNBUNDLES, Processor.join(runbundles,", \\\n  ") );
 
-		jar.putResource("descriptor.properties", new WriteResource() {
-			@Override public void write(OutputStream outStream) throws IOException, Exception {
-				p.store(outStream, "comment");
+		// Copy the class path of the launched VM to this bundle
+		// but in reverse order so that the order matches the classpath (first
+		// wins).
+		List<String> runpath = getRunpath();
+		Collections.reverse(runpath);
+
+		for (String path : runpath) {
+			project.trace("embedding runpath %s", path);
+			File file = new File(path);
+			if (!file.isFile())
+				project.error("Invalid entry on runpath %s", file);
+			else {
+				Jar from = new Jar(file);
+				jar.addAll(from);
 			}
-			@Override public long lastModified() {
-				return 0L;
-			}
-		});
+		}
 
-		List<String> paths = Create.list();
-		paths.addAll( getRunpath());
-		paths.add( project.getBundle("biz.aQute.launcher", null, Strategy.HIGHEST, null).getFile().getAbsolutePath());
-		
-		for ( String path : paths) {
-			File f = IO.getFile(project.getBase(), path);
-			Jar roll = new Jar(f);
-			jar.addAll(roll);
+		// Copy the bundles to the JAR
+
+		List<String> runbundles = (List<String>) getRunBundles();
+		List<String> actualPaths = new ArrayList<String>();
+
+		for (String path : runbundles) {
+			project.trace("embedding run bundles %s", path);
+			File file = new File(path);
+			String newPath = "jar/" + file.getName();
+			jar.putResource(newPath, new FileResource(file));
+			actualPaths.add(newPath);
 		}
-		
+
+		LauncherConstants lc = getConstants(actualPaths);
+		lc.embedded = true;
+		lc.storageDir = null; // cannot use local info
+
+		final Properties p = lc.getProperties();
+
+		ByteArrayOutputStream bout = new ByteArrayOutputStream();
+		p.store(bout, "");
+		jar.putResource(LauncherConstants.DEFAULT_LAUNCHER_PROPERTIES, new EmbeddedResource(bout.toByteArray(), 0L));
+
+		// Remove signer files, we have a different manifest now
+		Set<String> set = new HashSet<String>();
+		for (Object pp : jar.getResources().keySet()) {
+			String path = (String) pp;
+			if (path.matches("META-INF/.*\\.(SF|RSA|DSA)$"))
+				set.add(path);
+		}
+
+		for (String path : set)
+			jar.remove(path);
+
+		// And set the manifest
 		Manifest m = new Manifest();
 		m.getMainAttributes().putValue("Main-Class", "aQute.launcher.Launcher");
 		jar.setManifest(m);
 		return jar;
 	}
 
-	/**
-	 * @param jar
-	 */
-	private Collection<String> copyBundles(Jar jar, Collection<String> runbundles) {
-		List<String> list = Create.list();
-		
-		for (String s : runbundles) {
-			File f = IO.getFile(new File("").getAbsoluteFile(), s);
-			if (!f.isFile()) {
-				project.error("In exec, cannot find runbundle %s for project %s", f, project);
-			} else {
-				String path = "jar/" + f.getName();
-				list.add(path);
-			}
-		}
-		return list;
-	}
-
 }
diff --git a/biz.aQute.launcher/src/test/MiniFrameworkTest.java b/biz.aQute.launcher/src/test/MiniFrameworkTest.java
new file mode 100644
index 0000000..ef92e1d
--- /dev/null
+++ b/biz.aQute.launcher/src/test/MiniFrameworkTest.java
@@ -0,0 +1,34 @@
+package test;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import junit.framework.*;
+
+import org.osgi.framework.*;
+
+import aQute.launcher.minifw.*;
+
+public class MiniFrameworkTest extends TestCase {
+
+	public static void testSimple() throws Exception {
+		Properties properties = new Properties();
+		MiniFramework framework = new MiniFramework(properties);
+		URL url = new File("src/test/demo.jar").toURI().toURL();
+
+		url.openStream().close();
+		framework.init();
+
+		Bundle b = framework.installBundle("reference:" + url.toExternalForm());
+		assertNotNull(b);
+
+		Bundle[] bundles = framework.getBundles();
+		assertNotNull(bundles);
+		assertEquals(2, bundles.length);
+
+		Class< ? > c = b.loadClass("test.TestActivator");
+		assertNotNull(c);
+
+	}
+}
diff --git a/biz.aQute.launcher/src/test/ProjectLaunchImplTest.java b/biz.aQute.launcher/src/test/ProjectLaunchImplTest.java
new file mode 100644
index 0000000..e35a15d
--- /dev/null
+++ b/biz.aQute.launcher/src/test/ProjectLaunchImplTest.java
@@ -0,0 +1,43 @@
+package test;
+
+import java.io.*;
+import java.util.*;
+import java.util.regex.*;
+
+import junit.framework.*;
+import aQute.bnd.build.*;
+import aQute.launcher.constants.*;
+import aQute.launcher.plugin.*;
+
+public class ProjectLaunchImplTest extends TestCase {
+	public static void testParseRunProperties() throws Exception {
+		Workspace ws = Workspace.getWorkspace(new File("src/test/ws"));
+		Project project = ws.getProject("p1");
+
+		ProjectLauncherImpl launcher = new ProjectLauncherImpl(project);
+		launcher.prepare();
+
+		String arg = launcher.getRunVM().iterator().next();
+		String s = "-D" + LauncherConstants.LAUNCHER_PROPERTIES + "=";
+		String propertiesPath = arg.substring(s.length());
+		Matcher matcher = Pattern.compile("^([\"'])(.*)\\1$").matcher(propertiesPath);
+		if (matcher.matches()) {
+			propertiesPath = matcher.group(2);
+		}
+
+		Properties launchProps = new Properties();
+		launchProps.load(new FileInputStream(new File(propertiesPath)));
+		assertEquals(new File("src/test/ws/p1/generated/p1.jar").getAbsolutePath(), launchProps.get("launch.bundles"));
+	}
+	
+	public static void testParseSystemCapabilities() throws Exception {
+		Workspace ws = Workspace.getWorkspace(new File("src/test/ws"));
+		Project project = ws.getProject("p1");
+
+		ProjectLauncherImpl launcher = new ProjectLauncherImpl(project);
+		launcher.prepare();
+		
+		String systemCaps = launcher.getSystemCapabilities();
+		assertEquals("osgi.native;osgi.native.osname:List<String>=\"Win7,Windows7,Windows 7\";osgi.native.osversion:Version=6.1", systemCaps);
+	}
+}
diff --git a/biz.aQute.bndlib/test/ws/cnf/build.bnd b/biz.aQute.launcher/src/test/ws/cnf/build.bnd
similarity index 100%
rename from biz.aQute.bndlib/test/ws/cnf/build.bnd
rename to biz.aQute.launcher/src/test/ws/cnf/build.bnd
diff --git a/biz.aQute.launcher/src/test/ws/p1/bnd.bnd b/biz.aQute.launcher/src/test/ws/p1/bnd.bnd
new file mode 100644
index 0000000..3fb861e
--- /dev/null
+++ b/biz.aQute.launcher/src/test/ws/p1/bnd.bnd
@@ -0,0 +1,3 @@
+-runfw: org.apache.felix.framework
+-runproperties: =
+-runsystemcapabilities: osgi.native;osgi.native.osname:List<String>="Win7,Windows7,Windows 7";osgi.native.osversion:Version=6.1
\ No newline at end of file
diff --git a/biz.aQute.launcher/test/test/MiniFrameworkTest.java b/biz.aQute.launcher/test/test/MiniFrameworkTest.java
deleted file mode 100644
index 8dc7a1a..0000000
--- a/biz.aQute.launcher/test/test/MiniFrameworkTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package test;
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-
-import junit.framework.*;
-
-import org.osgi.framework.*;
-
-import aQute.launcher.minifw.*;
-
-public class MiniFrameworkTest extends TestCase {
-	
-	public void testSimple() throws Exception {
-		Properties properties = new Properties();
-		MiniFramework	framework = new MiniFramework(properties);
-		URL url = new File("test/test/demo.jar").toURI().toURL();
-		
-		url.openStream().close();
-		framework.init();
-		
-		Bundle b = framework.installBundle("reference:" + url.toExternalForm());
-		assertNotNull(b);
-		
-		Bundle [] bundles = framework.getBundles();
-		assertNotNull(bundles);
-		assertEquals( 2, bundles.length);
-		
-		Class<?> c = b.loadClass("test.TestActivator");
-		assertNotNull(c);
-		
-	}
-}
diff --git a/biz.aQute.repository/.classpath b/biz.aQute.repository/.classpath
new file mode 100644
index 0000000..6d3c62a
--- /dev/null
+++ b/biz.aQute.repository/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/biz.aQute.repository/.project b/biz.aQute.repository/.project
new file mode 100644
index 0000000..fa41f46
--- /dev/null
+++ b/biz.aQute.repository/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>biz.aQute.repository</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>bndtools.core.bndbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>bndtools.core.bndnature</nature>
+	</natures>
+</projectDescription>
diff --git a/biz.aQute.repository/.settings/org.eclipse.core.resources.prefs b/biz.aQute.repository/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..f6822ac
--- /dev/null
+++ b/biz.aQute.repository/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Mon Sep 19 11:00:09 EDT 2005
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/biz.aQute.repository/.settings/org.eclipse.core.runtime.prefs b/biz.aQute.repository/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..d7b5655
--- /dev/null
+++ b/biz.aQute.repository/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Tue Dec 14 12:22:25 EST 2010
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/biz.aQute.repository/.settings/org.eclipse.jdt.core.prefs b/biz.aQute.repository/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..2301ac5
--- /dev/null
+++ b/biz.aQute.repository/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,361 @@
+#Fri Aug 10 13:46:22 CEST 2012
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=ignore
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=true
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/biz.aQute.repository/.settings/org.eclipse.jdt.ui.prefs b/biz.aQute.repository/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..f5e8897
--- /dev/null
+++ b/biz.aQute.repository/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,61 @@
+#Fri Aug 10 13:48:46 CEST 2012
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=false
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=false
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=false
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
+cleanup_settings_version=2
+eclipse.preferences.version=1
+formatter_profile=_bnd(tools)
+formatter_settings_version=12
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=1
+org.eclipse.jdt.ui.staticondemandthreshold=1
diff --git a/biz.aQute.repository/bnd.bnd b/biz.aQute.repository/bnd.bnd
new file mode 100644
index 0000000..20d9630
--- /dev/null
+++ b/biz.aQute.repository/bnd.bnd
@@ -0,0 +1,85 @@
+Bundle-Version: 2.1.0.${tstamp;yyyyMMdd-HHmmss}_${Git-Descriptor}
+
+jetty.libs: lib/javax.servlet-2.5.0.jar;version=file,\
+	lib/jetty-continuation-7.6.3.v20120416.jar;version=file,\
+	lib/jetty-http-7.6.3.v20120416.jar;version=file,\
+	lib/jetty-io-7.6.3.v20120416.jar;version=file,\
+	lib/jetty-security-7.6.3.v20120416.jar;version=file,\
+	lib/jetty-server-7.6.3.v20120416.jar;version=file,\
+	lib/jetty-util-7.6.3.v20120416.jar;version=file
+
+-buildpath: osgi.core;version=4.2,\
+	aQute.libg;version=project,\
+	biz.aQute.bndlib;version=latest,\
+	org.osgi.impl.bundle.bindex,\
+	org.osgi.impl.bundle.repoindex.lib;version=0.0.4,\
+	junit.osgi,\
+	osgi.cmpn;version=4.3.0,\
+	osgi.r5;version=1.0.1,\
+	javax.xml.stream-1.0.1.jar;version=file,\
+	org.mockito.mockito-all,\
+	ee.j2se;version=${javac.ee},\
+	${jetty.libs}
+
+Bnd-Plugins:
+	aQute.bnd.deployer.repository.FixedIndexedRepo,\
+	aQute.bnd.deployer.repository.LocalIndexedRepo,\
+	aQute.bnd.deployer.deployer.obr.OBR,\
+	aQute.bnd.deployer.deployer.obr.LocalOBR,\
+	aQute.bnd.deployer.deployer.http.HttpBasicAuthURLConnector
+
+Export-Package:\
+	aQute.bnd.deployer.http,\
+	aQute.bnd.deployer.obr,\
+	aQute.bnd.deployer.repository,\
+	aQute.bnd.deployer.repository.api,\
+	aQute.bnd.deployer.repository.providers,\
+	org.osgi.service.indexer;provide:=true,\
+	org.osgi.service.bindex;version=1.0;provide:=true,\
+	org.osgi.service.coordinator;-split-package:=merge-first,\
+	org.osgi.service.log;provide:=true;-split-package:=merge-first
+
+bindex-pkgs: \
+	org.osgi.service.obr,\
+	org.osgi.impl.bundle.bindex,\
+	org.osgi.impl.bundle.obr.resource,\
+	org.kxml2.io,\
+	org.xmlpull.v1
+
+repoindex-pkgs: \
+	org.osgi.service.indexer.impl,\
+	org.osgi.service.indexer.impl.types,\
+	org.osgi.service.indexer.impl.util,\
+	aQute.bnd.osgi.resource,\
+	org.osgi.resource;-split-package:=first
+
+libg-pkgs: \
+	aQute.lib.io;-split-package:=first,\
+	aQute.lib.filter;-split-package:=first,\
+	aQute.lib.base64;-split-package:=first,\
+	aQute.bnd.filerepo,\
+	aQute.libg.generics;-split-package:=first,\
+	aQute.libg.glob;-split-package:=first,\
+	aQute.libg.gzip;-split-package:=first,\
+	aQute.libg.tuple;-split-package:=first,\
+	aQute.libg.filters;-split-package:=first
+
+# NB: `org.osgi.framework` API is included in Private-Package for running outside of OSGi.
+Private-Package:\
+	${bindex-pkgs},\
+	${repoindex-pkgs},\
+	org.osgi.framework;-split-package:=first,\
+
+Conditional-Package:\
+	aQute.lib.*;-split-package:=first,\
+	aQute.libg.*;-split-package:=first
+
+# We must also explicitly import `org.osgi.framework` etc. for when we *are* running in OSGi.
+Import-Package:\
+	org.osgi.framework;version='[1.5,2)',\
+	org.osgi.service.bindex,\
+	org.osgi.service.repository,\
+	org.osgi.resource,\
+	org.osgi.service.log,\
+	aQute.bnd.osgi.resource,\
+	*
diff --git a/biz.aQute.repository/build.xml b/biz.aQute.repository/build.xml
new file mode 100644
index 0000000..23063e2
--- /dev/null
+++ b/biz.aQute.repository/build.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="project" default="build"> 
+	<import file="../cnf/build.xml"/>
+</project>
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/Constants.java b/biz.aQute.repository/src/aQute/bnd/deployer/Constants.java
new file mode 100644
index 0000000..3a21518
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/Constants.java
@@ -0,0 +1,5 @@
+package aQute.bnd.deployer;
+
+public class Constants {
+	public static final String	UTF8	= "UTF-8";
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/http/DefaultURLConnector.java b/biz.aQute.repository/src/aQute/bnd/deployer/http/DefaultURLConnector.java
new file mode 100644
index 0000000..f77dbc8
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/http/DefaultURLConnector.java
@@ -0,0 +1,79 @@
+package aQute.bnd.deployer.http;
+
+import java.io.*;
+import java.net.*;
+import java.security.*;
+import java.util.*;
+
+import aQute.bnd.service.*;
+import aQute.bnd.service.url.*;
+import aQute.service.reporter.*;
+
+public class DefaultURLConnector implements URLConnector, Plugin {
+
+	private static final String	HEADER_IF_NONE_MATCH	= "If-None-Match";
+	private static final String	HEADER_ETAG				= "ETag";
+	private static final int	RESPONSE_NOT_MODIFIED	= 304;
+
+	private boolean				disableServerVerify		= false;
+	private Reporter			reporter				= null;	
+
+	public InputStream connect(URL url) throws IOException {
+		if (url == null)
+			throw new IOException("Can't connect to null URL");
+		TaggedData data = connectTagged(url);
+		return data.getInputStream();
+	}
+
+	public void setProperties(Map<String,String> map) {
+		disableServerVerify = "true".equalsIgnoreCase(map.get(HttpsUtil.PROP_DISABLE_SERVER_CERT_VERIFY));
+	}
+
+	public void setReporter(Reporter reporter) {
+		this.reporter = reporter;
+	}
+
+	public TaggedData connectTagged(URL url) throws IOException {
+		return connectTagged(url, null);
+	}
+
+	public TaggedData connectTagged(URL url, String tag) throws IOException {
+		TaggedData result;
+
+		URLConnection connection = url.openConnection();
+		try {
+			if (disableServerVerify)
+				HttpsUtil.disableServerVerification(connection);
+		}
+		catch (GeneralSecurityException e) {
+			if (reporter != null)
+				reporter.error("Error attempting to disable SSL server certificate verification: %s", e);
+			throw new IOException("Error attempting to disable SSL server certificate verification.");
+		}
+
+		if (connection instanceof HttpURLConnection) {
+			// Turn on caching and send the ETag
+			HttpURLConnection httpConnection = (HttpURLConnection) connection;
+			httpConnection.setUseCaches(true);
+			if (tag != null)
+				httpConnection.setRequestProperty(HEADER_IF_NONE_MATCH, tag);
+
+			httpConnection.connect();
+
+			int responseCode = httpConnection.getResponseCode();
+			if (responseCode == RESPONSE_NOT_MODIFIED) {
+				result = null;
+				httpConnection.disconnect();
+			} else {
+				String responseTag = httpConnection.getHeaderField(HEADER_ETAG);
+				result = new TaggedData(responseTag, connection.getInputStream());
+			}
+		} else {
+			// Non-HTTP so ignore all this tagging malarky
+			result = new TaggedData(null, connection.getInputStream());
+		}
+
+		return result;
+	}
+
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/http/HttpBasicAuthURLConnector.java b/biz.aQute.repository/src/aQute/bnd/deployer/http/HttpBasicAuthURLConnector.java
new file mode 100644
index 0000000..5459143
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/http/HttpBasicAuthURLConnector.java
@@ -0,0 +1,173 @@
+package aQute.bnd.deployer.http;
+
+import java.io.*;
+import java.net.*;
+import java.security.*;
+import java.util.*;
+import java.util.concurrent.atomic.*;
+import java.util.regex.*;
+
+import aQute.bnd.deployer.*;
+import aQute.bnd.service.*;
+import aQute.bnd.service.url.*;
+import aQute.lib.base64.*;
+import aQute.lib.io.*;
+import aQute.libg.glob.*;
+import aQute.service.reporter.*;
+
+public class HttpBasicAuthURLConnector implements URLConnector, Plugin {
+
+	private static final String	PREFIX_PATTERN			= "pattern.";
+	private static final String	PREFIX_USER				= "uid.";
+	private static final String	PREFIX_PASSWORD			= "pwd.";
+
+	private static final String	HEADER_AUTHORIZATION	= "Authorization";
+	private static final String	PREFIX_BASIC_AUTH		= "Basic ";
+
+	private static final String	HEADER_IF_NONE_MATCH	= "If-None-Match";
+	private static final String	HEADER_ETAG				= "ETag";
+	private static final int	RESPONSE_NOT_MODIFIED	= 304;
+
+	private static class Mapping {
+		String	name;
+		Glob	urlPattern;
+		String	user;
+		String	pass;
+
+		Mapping(String name, Glob urlPattern, String user, String pass) {
+			this.name = name;
+			this.urlPattern = urlPattern;
+			this.user = user;
+			this.pass = pass;
+		}
+	}
+
+	private final AtomicBoolean	inited				= new AtomicBoolean(false);
+	private final List<Mapping>	mappings			= new LinkedList<Mapping>();
+
+	private Reporter			reporter;
+	private String				configFileList;
+	private boolean				disableSslVerify	= false;
+
+	public void setReporter(Reporter reporter) {
+		this.reporter = reporter;
+	}
+
+	public void setProperties(Map<String,String> map) {
+		configFileList = map.get("configs");
+		if (configFileList == null)
+			throw new IllegalArgumentException("'configs' must be specified on HttpBasicAuthURLConnector");
+		disableSslVerify = "true".equalsIgnoreCase(map.get(HttpsUtil.PROP_DISABLE_SERVER_CERT_VERIFY));
+	}
+
+	protected void init() {
+		if (inited.compareAndSet(false, true)) {
+			mappings.clear();
+
+			StringTokenizer tokenizer = new StringTokenizer(configFileList, ",");
+			while (tokenizer.hasMoreTokens()) {
+				String configFileName = tokenizer.nextToken().trim();
+
+				File file = new File(configFileName);
+				if (file.exists()) {
+					Properties props = new Properties();
+					InputStream stream = null;
+					try {
+						stream = new FileInputStream(file);
+						props.load(stream);
+
+						for (Object key : props.keySet()) {
+							String name = (String) key;
+
+							if (name.startsWith(PREFIX_PATTERN)) {
+								String id = name.substring(PREFIX_PATTERN.length());
+
+								Glob glob = new Glob(props.getProperty(name));
+								String uid = props.getProperty(PREFIX_USER + id);
+								String pwd = props.getProperty(PREFIX_PASSWORD + id);
+
+								mappings.add(new Mapping(id, glob, uid, pwd));
+							}
+						}
+					}
+					catch (IOException e) {
+						if (reporter != null)
+							reporter.error("Failed to load %s", configFileName);
+					}
+					finally {
+						if (stream != null)
+							IO.close(stream);
+					}
+				}
+			}
+		}
+	}
+
+	public InputStream connect(URL url) throws IOException {
+		TaggedData data = connectTagged(url, null);
+		if (data == null)
+			throw new IOException("HTTP server did not respond with data.");
+
+		return data.getInputStream();
+	}
+
+	public TaggedData connectTagged(URL url) throws IOException {
+		return connectTagged(url, null);
+	}
+
+	public TaggedData connectTagged(URL url, String tag) throws IOException {
+		init();
+
+		for (Mapping mapping : mappings) {
+			Matcher matcher = mapping.urlPattern.matcher(url.toString());
+			if (matcher.find()) {
+				if (reporter != null)
+					reporter.trace("Found username %s, password ***** for URL '%s'. Matched on pattern %s=%s",
+							mapping.user, url, mapping.name, mapping.urlPattern.toString());
+				return connectTagged(url, tag, mapping.user, mapping.pass);
+			}
+		}
+		if (reporter != null)
+			reporter.trace("No username/password found for URL '%s'.", url);
+		return connectTagged(url, tag, null, null);
+	}
+
+	private TaggedData connectTagged(URL url, String tag, String user, String pass) throws IOException {
+		TaggedData result;
+
+		HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+		try {
+			if (disableSslVerify)
+				HttpsUtil.disableServerVerification(connection);
+		}
+		catch (GeneralSecurityException e) {
+			if (reporter != null)
+				reporter.error("Error attempting to disable SSL server certificate verification: %s", e);
+			throw new IOException("Error attempting to disable SSL server certificate verification.");
+		}
+
+		// Add the authorization string using HTTP Basic Auth
+		if (user != null && pass != null) {
+			String authString = user + ":" + pass;
+			String encoded = Base64.encodeBase64(authString.getBytes(Constants.UTF8));
+			connection.setRequestProperty(HEADER_AUTHORIZATION, PREFIX_BASIC_AUTH + encoded);
+		}
+
+		// Add the ETag
+		if (tag != null)
+			connection.setRequestProperty(HEADER_IF_NONE_MATCH, tag);
+
+		connection.connect();
+
+		int responseCode = connection.getResponseCode();
+		if (responseCode == RESPONSE_NOT_MODIFIED)
+			result = null;
+		else {
+			String responseTag = connection.getHeaderField(HEADER_ETAG);
+			result = new TaggedData(responseTag, connection.getInputStream());
+		}
+
+		return result;
+	}
+
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/http/HttpsUtil.java b/biz.aQute.repository/src/aQute/bnd/deployer/http/HttpsUtil.java
new file mode 100644
index 0000000..a5427f4
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/http/HttpsUtil.java
@@ -0,0 +1,43 @@
+package aQute.bnd.deployer.http;
+
+import java.net.*;
+import java.security.*;
+import java.security.cert.*;
+
+import javax.net.ssl.*;
+
+public class HttpsUtil {
+
+	public static final String	PROP_DISABLE_SERVER_CERT_VERIFY	= "disableServerVerify";
+
+	static void disableServerVerification(URLConnection connection) throws GeneralSecurityException {
+		if (!(connection instanceof HttpsURLConnection))
+			return;
+
+		HttpsURLConnection httpsConnection = (HttpsURLConnection) connection;
+		TrustManager[] trustAllCerts = new TrustManager[] {
+			new X509TrustManager() {
+				public X509Certificate[] getAcceptedIssuers() {
+					return null;
+				}
+
+				public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {}
+
+				public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {}
+			}
+		};
+
+		SSLContext sslContext = SSLContext.getInstance("TLS");
+		sslContext.init(null, trustAllCerts, new SecureRandom());
+
+		SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
+		httpsConnection.setSSLSocketFactory(sslSocketFactory);
+
+		HostnameVerifier trustAnyHost = new HostnameVerifier() {
+			public boolean verify(String string, SSLSession session) {
+				return true;
+			}
+		};
+		httpsConnection.setHostnameVerifier(trustAnyHost);
+	}
+}
\ No newline at end of file
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/obr/Conversions.java b/biz.aQute.repository/src/aQute/bnd/deployer/obr/Conversions.java
new file mode 100644
index 0000000..c555cee
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/obr/Conversions.java
@@ -0,0 +1,28 @@
+package aQute.bnd.deployer.obr;
+
+import java.util.*;
+
+import aQute.bnd.deployer.repository.*;
+
+public class Conversions {
+
+	/** Converts legacy repository properties to new property names.
+	 * @param map
+	 * @return
+	 */
+	public static final Map<String,String> convertConfig(Map<String,String> map) {
+		if (!map.containsKey(AbstractIndexedRepo.PROP_REPO_TYPE))
+			map.put(AbstractIndexedRepo.PROP_REPO_TYPE, AbstractIndexedRepo.REPO_TYPE_OBR);
+
+		String location = map.get("location");
+		if (location != null)
+			map.put(FixedIndexedRepo.PROP_LOCATIONS, location);
+		
+		String mode = map.get("mode");
+		if (mode != null)
+			map.put(AbstractIndexedRepo.PROP_RESOLUTION_PHASE, mode);
+
+		return map;
+	}
+
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/obr/LocalOBR.java b/biz.aQute.repository/src/aQute/bnd/deployer/obr/LocalOBR.java
new file mode 100644
index 0000000..b4a2623
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/obr/LocalOBR.java
@@ -0,0 +1,14 @@
+package aQute.bnd.deployer.obr;
+
+import java.util.*;
+
+import aQute.bnd.deployer.repository.*;
+
+public class LocalOBR extends LocalIndexedRepo {
+
+	@Override
+	public synchronized void setProperties(Map<String,String> map) {
+		super.setProperties(Conversions.convertConfig(map));
+	}
+
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/obr/NexusOBR.java b/biz.aQute.repository/src/aQute/bnd/deployer/obr/NexusOBR.java
new file mode 100644
index 0000000..17764d4
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/obr/NexusOBR.java
@@ -0,0 +1,280 @@
+package aQute.bnd.deployer.obr;
+
+import java.io.*;
+import java.net.*;
+import java.security.*;
+import java.util.*;
+
+import aQute.bnd.deployer.repository.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.version.*;
+import aQute.lib.base64.*;
+import aQute.lib.io.*;
+
+/**
+ * A read-write nexus OBR-based repository.
+ * 
+ * <p>
+ * You will need to install the nexus-obr-plugin in nexus (you can download it
+ * on <a href="http://search.maven.org/#search|ga|1|a%3A%22nexus-obr-plugin%22">
+ * maven central</a>)
+ * </p>
+ * 
+ * <p>
+ * <h2>Properties</h2>
+ * <ul>
+ * <li><b>repositoryUrl</b>: the nexus repository url
+ * (http://localhost:8081/nexus/content/repositories/obr/ for example)</li>
+ * <li><b>username</b>: the username; defaults to "deployment"</li>
+ * <li><b>password</b>: the password; defaults to "deployment123"</li>
+ * <li><b>name</b>: repository name; defaults to the nexus repository url</li>
+ * <li><b>cache</b>: local cache directory. May be omitted, in which case a
+ * default directory will be used.</li>
+ * <li><b>readonly</b>: if readonly, no bundle can be added to the repository
+ * </ul>
+ * </p>
+ * <p>
+ * <h2>Example</h2>
+ * 
+ * <pre>
+ * -plugin: aQute.bnd.deployer.obr.NexusOBR;readonly=false;repositoryUrl=http://localhost:8081/nexus/content/repositories/obr/;username=deployment;password=deployment123;name=nexus-obr
+ * </pre>
+ * 
+ * </p>
+ * 
+ * @author Cedric Chabanois <cchabanois at gmail.com>
+ * 
+ */
+public class NexusOBR extends AbstractIndexedRepo {
+	private static final String DEFAULT_PASSWORD = "deployment123";
+	private static final String DEFAULT_USERNAME = "deployment";
+	private static final String EMPTY_REPOSITORY_URL = "";
+	private static final String DEFAULT_CACHE_DIR = ".bnd" + File.separator
+			+ "cache";
+	public static final String PROP_CACHE = "cache";
+	public static final String PROP_REPOSITORY_URL = "repositoryUrl";
+	public static final String PROP_READONLY = "readonly";
+	public static final String PROP_USERNAME = "username";
+	public static final String PROP_PASSWORD = "password";
+	protected File cacheDir = new File(System.getProperty("user.home")
+			+ File.separator + DEFAULT_CACHE_DIR);
+	private String nexusRepositoryUrl;
+	private boolean readOnly;
+	private String username = DEFAULT_USERNAME;
+	private String password = DEFAULT_PASSWORD;
+
+	@Override
+	public synchronized void setProperties(Map<String, String> map) {
+		super.setProperties(map);
+		readOnly = Boolean.parseBoolean(map.get(PROP_READONLY));
+		if (map.containsKey(PROP_USERNAME)) {
+			username = map.get(PROP_USERNAME);
+		}
+		if (map.containsKey(PROP_PASSWORD)) {
+			password = map.get(PROP_PASSWORD);
+		}
+		nexusRepositoryUrl = map.get(PROP_REPOSITORY_URL);
+		if (nexusRepositoryUrl != null && !nexusRepositoryUrl.endsWith("/")) {
+			nexusRepositoryUrl = nexusRepositoryUrl + '/';
+		}
+
+		String cachePath = map.get(PROP_CACHE);
+		if (cachePath != null) {
+			cacheDir = new File(cachePath);
+			if (!cacheDir.isDirectory())
+				try {
+					throw new IllegalArgumentException(
+							String.format(
+									"Cache path '%s' does not exist, or is not a directory.",
+									cacheDir.getCanonicalPath()));
+				} catch (IOException e) {
+					throw new IllegalArgumentException(
+							"Could not get cacheDir canonical path", e);
+				}
+		}
+	}
+
+	@Override
+	public boolean canWrite() {
+		return true;
+	}
+
+	public File getCacheDirectory() {
+		return cacheDir;
+	}
+
+	public String getLocation() {
+		if (nexusRepositoryUrl == null)
+			return EMPTY_REPOSITORY_URL;
+		else
+			return nexusRepositoryUrl;
+
+	}
+
+	@Override
+	protected List<URI> loadIndexes() throws Exception {
+		List<URI> result;
+		if (nexusRepositoryUrl != null) {
+			result = new ArrayList<URI>();
+
+			result.add(new URL(nexusRepositoryUrl + ".meta/obr.xml").toURI());
+		} else {
+			result = Collections.emptyList();
+		}
+		return result;
+	}
+
+	public void setCacheDirectory(File cacheDir) {
+		if (cacheDir == null)
+			throw new IllegalArgumentException(
+					"null cache directory not permitted");
+		this.cacheDir = cacheDir;
+	}
+
+	@Override
+	public synchronized PutResult put(InputStream stream, PutOptions options)
+			throws Exception {
+		/* determine if the put is allowed */
+		if (readOnly) {
+			throw new IOException("Repository is read-only");
+		}
+
+		if (options == null)
+			options = DEFAULTOPTIONS;
+
+		/* both parameters are required */
+		if (stream == null)
+			throw new IllegalArgumentException(
+					"No stream and/or options specified");
+
+		/*
+		 * setup a new stream that encapsulates the stream and calculates (when
+		 * needed) the digest
+		 */
+		DigestInputStream dis = new DigestInputStream(stream,
+				MessageDigest.getInstance("SHA-1"));
+
+		File tmpFile = null;
+		try {
+			/*
+			 * copy the artifact from the (new/digest) stream into a temporary
+			 * file in the root directory of the repository
+			 */
+			tmpFile = IO.createTempFile(null, "put", ".bnd");
+			IO.copy(dis, tmpFile);
+
+			/* beforeGet the digest if available */
+			byte[] disDigest = dis.getMessageDigest().digest();
+
+			if (options.digest != null
+					&& !Arrays.equals(options.digest, disDigest))
+				throw new IOException(
+						"Retrieved artifact digest doesn't match specified digest");
+
+			/* put the artifact into the repository (from the temporary file) */
+			URL url = putArtifact(tmpFile);
+
+			PutResult result = new PutResult();
+			if (url != null) {
+				result.digest = disDigest;
+				result.artifact = url.toURI();
+			}
+
+			return result;
+		} finally {
+			if (tmpFile != null && tmpFile.exists()) {
+				IO.delete(tmpFile);
+			}
+		}
+	}
+
+	protected URL putArtifact(File tmpFile) throws Exception {
+		assert (tmpFile != null);
+		assert (tmpFile.isFile());
+
+		init();
+
+		Version version;
+		String bsn;
+		Jar jar = new Jar(tmpFile);
+		try {
+			bsn = jar.getBsn();
+			if (bsn == null || !Verifier.isBsn(bsn))
+				throw new IllegalArgumentException(
+						"Jar does not have a Bundle-SymbolicName manifest header");
+
+			String versionString = jar.getVersion();
+			if (versionString == null)
+				versionString = "0";
+			else if (!Verifier.isVersion(versionString))
+				throw new IllegalArgumentException("Invalid version "
+						+ versionString + " in file " + tmpFile);
+
+			version = Version.parseVersion(versionString);
+		} finally {
+			jar.close();
+		}
+		URL url = put(tmpFile, bsn, version);
+		reset();
+		return url;
+	}
+
+	protected URL put(File file, String bsn, Version version)
+			throws IOException {
+		URL url = getTargetURL(bsn, version);
+		HttpURLConnection httpUrlConnection = null;
+		FileInputStream is = null;
+		OutputStream out = null;
+		try {
+			is = new FileInputStream(file);
+			httpUrlConnection = (HttpURLConnection) url.openConnection();
+			httpUrlConnection.setDoOutput(true);
+			httpUrlConnection.setFixedLengthStreamingMode((int) file.length());
+			httpUrlConnection.setRequestMethod("PUT");
+			if (username != null && password != null) {
+				String userPassword = username + ":" + password;
+				httpUrlConnection.setRequestProperty("Authorization", "Basic "
+						+ Base64.encodeBase64(userPassword.getBytes("UTF-8")));
+			}
+			out = httpUrlConnection.getOutputStream();
+			byte[] buffer = new byte[8192];
+			while (true) {
+				int length = is.read(buffer);
+				if (length < 0)
+					break;
+				out.write(buffer, 0, length);
+			}
+			int respondeCode = httpUrlConnection.getResponseCode();
+			// response code will be 201 (Created) if new bundle is successfully added
+			if (respondeCode < 200 || respondeCode > 300) {
+				throw new IOException(httpUrlConnection.getResponseMessage());
+			}
+		} finally {
+			if (is != null) {
+				is.close();
+			}
+			if (out != null) {
+				out.close();
+			}
+			if (httpUrlConnection != null) {
+				httpUrlConnection.disconnect();
+			}
+		}
+		return url;
+	}
+
+	@Override
+	public synchronized String getName() {
+		if (name != null && !name.equals(this.getClass().getName()))
+			return name;
+
+		return nexusRepositoryUrl;
+	}
+
+	private URL getTargetURL(String bsn, Version version)
+			throws MalformedURLException {
+		return new URL(nexusRepositoryUrl + bsn + "/" + bsn + "-" + version
+				+ ".jar");
+	}
+
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/obr/OBR.java b/biz.aQute.repository/src/aQute/bnd/deployer/obr/OBR.java
new file mode 100644
index 0000000..fccdc65
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/obr/OBR.java
@@ -0,0 +1,36 @@
+package aQute.bnd.deployer.obr;
+
+import java.util.*;
+
+import aQute.bnd.deployer.repository.*;
+
+/**
+ * A simple read-only OBR-based repository that uses a list of index locations
+ * and a basic local cache.
+ * <p>
+ * <h2>Properties</h2>
+ * <ul>
+ * <li><b>locations:</b> comma-separated list of index URLs. <b>NB:</b> surround
+ * with single quotes!</li>
+ * <li><b>name:</b> repository name; defaults to the index URLs.
+ * <li><b>cache:</b> local cache directory. May be omitted, in which case the
+ * repository will only be able to serve resources with {@code file:} URLs.</li>
+ * <li><b>location:</b> (deprecated) alias for "locations".
+ * </ul>
+ * <p>
+ * <h2>Example</h2>
+ * 
+ * <pre>
+ * -plugin: aQute.lib.deployer.obr.OBR;locations='http://www.example.com/repository.xml';cache=${workspace}/.cache
+ * </pre>
+ * 
+ * @author Neil Bartlett
+ */
+public class OBR extends FixedIndexedRepo {
+
+	@Override
+	public synchronized void setProperties(Map<String,String> map) {
+		super.setProperties(Conversions.convertConfig(map));
+	}
+
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/AbstractIndexedRepo.java b/biz.aQute.repository/src/aQute/bnd/deployer/repository/AbstractIndexedRepo.java
new file mode 100644
index 0000000..320a7dc
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/AbstractIndexedRepo.java
@@ -0,0 +1,702 @@
+package aQute.bnd.deployer.repository;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.Map.Entry;
+
+import org.osgi.framework.namespace.*;
+import org.osgi.impl.bundle.bindex.*;
+import org.osgi.resource.*;
+import org.osgi.resource.Resource;
+import org.osgi.service.bindex.*;
+import org.osgi.service.log.*;
+import org.osgi.service.repository.*;
+
+import aQute.bnd.deployer.http.*;
+import aQute.bnd.deployer.repository.CachingUriResourceHandle.CachingMode;
+import aQute.bnd.deployer.repository.api.*;
+import aQute.bnd.deployer.repository.providers.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.*;
+import aQute.bnd.service.ResourceHandle.Location;
+import aQute.bnd.service.url.*;
+import aQute.bnd.version.*;
+import aQute.lib.collections.*;
+import aQute.lib.filter.*;
+import aQute.lib.io.*;
+import aQute.libg.generics.*;
+import aQute.libg.glob.*;
+import aQute.libg.gzip.*;
+import aQute.service.reporter.*;
+
+/**
+ * Abstract base class for indexed repositories.
+ * <p>
+ * The repository implementation is read-only by default. To implement a
+ * writable repository, subclasses should override {@link #canWrite()} and
+ * {@link #put(Jar)}.
+ * 
+ * @author Neil Bartlett
+ */
+ at SuppressWarnings("synthetic-access")
+public abstract class AbstractIndexedRepo implements RegistryPlugin, Plugin, RemoteRepositoryPlugin, IndexProvider, Repository {
+
+	public static final String									PROP_NAME						= "name";
+	public static final String									PROP_REPO_TYPE					= "type";
+	public static final String									PROP_RESOLUTION_PHASE			= "phase";
+	public static final String									PROP_RESOLUTION_PHASE_ANY		= "any";
+
+	public static final String									REPO_TYPE_R5					= R5RepoContentProvider.NAME;
+	public static final String									REPO_TYPE_OBR					= ObrContentProvider.NAME;
+
+	private static final int									READ_AHEAD_MAX					= 5 * 1024 * 1024;
+
+	private final BundleIndexer								obrIndexer						= new BundleIndexerImpl();
+	protected final Map<String,IRepositoryContentProvider>	allContentProviders				= new HashMap<String,IRepositoryContentProvider>(5);
+	protected final List<IRepositoryContentProvider>		generatingProviders				= new LinkedList<IRepositoryContentProvider>();
+
+	protected Registry											registry;
+	protected Reporter											reporter;
+	protected LogService										logService						= new NullLogService();
+	protected String											name							= this.getClass().getName();
+	protected Set<ResolutionPhase>								supportedPhases					= EnumSet.allOf(ResolutionPhase.class);
+
+	private List<URI>											indexLocations;
+
+	private String												requestedContentProviderList	= null;
+
+	private boolean												initialised						= false;
+
+	private final CapabilityIndex							capabilityIndex					= new CapabilityIndex();
+	private final Map<String,SortedMap<Version,Resource>>	bsnMap							= new HashMap<String,SortedMap<Version,Resource>>();
+
+	protected AbstractIndexedRepo() {
+		allContentProviders.put(REPO_TYPE_R5, new R5RepoContentProvider());
+		allContentProviders.put(REPO_TYPE_OBR, new ObrContentProvider(obrIndexer));
+
+		generatingProviders.add(allContentProviders.get(REPO_TYPE_R5));
+	}
+
+	public synchronized void reset() {
+		initialised = false;
+	}
+
+	private synchronized void clear() {
+		bsnMap.clear();
+		capabilityIndex.clear();
+	}
+
+	protected abstract List<URI> loadIndexes() throws Exception;
+
+	protected synchronized void loadAllContentProviders() {
+		if (registry == null)
+			return;
+
+		List<IRepositoryContentProvider> extraProviders = registry.getPlugins(IRepositoryContentProvider.class);
+
+		for (IRepositoryContentProvider provider : extraProviders) {
+			String providerName = provider.getName();
+			if (allContentProviders.containsKey(providerName)) {
+				warning("Repository content provider with name \"%s\" is already registered.", providerName);
+			} else {
+				allContentProviders.put(providerName, provider);
+			}
+		}
+	}
+
+	protected final synchronized void init() throws Exception {
+		if (!initialised) {
+			clear();
+
+			// Load the available providers from the workspace plugins.
+			loadAllContentProviders();
+
+			// Load the request repository content providers, if specified
+			if (requestedContentProviderList != null && requestedContentProviderList.length() > 0) {
+				generatingProviders.clear();
+
+				// Find the requested providers from the available ones.
+				StringTokenizer tokenizer = new StringTokenizer(requestedContentProviderList, "|");
+				while (tokenizer.hasMoreTokens()) {
+					String token = tokenizer.nextToken().trim();
+					IRepositoryContentProvider provider = allContentProviders.get(token);
+					if (provider == null) {
+						warning("Unknown repository content provider \"%s\".", token);
+					} else {
+						generatingProviders.add(provider);
+					}
+				}
+				if (generatingProviders.isEmpty()) {
+					warning("No valid repository index generators were found, requested list was: [%s]", requestedContentProviderList);
+				}
+			}
+
+			// Initialise index locations
+			indexLocations = loadIndexes();
+
+			// Create the callback for new referral and resource objects
+			final URLConnector connector = getConnector();
+			IRepositoryIndexProcessor processor = new IRepositoryIndexProcessor() {
+
+				public void processResource(Resource resource) {
+					addResourceToIndex(resource);
+				}
+
+				public void processReferral(URI parentUri, Referral referral, int maxDepth, int currentDepth) {
+					try {
+						URI indexLocation = new URI(referral.getUrl());
+						try {
+							CachingUriResourceHandle indexHandle = new CachingUriResourceHandle(indexLocation, getCacheDirectory(), connector, (String) null);
+							indexHandle.setReporter(reporter);
+							readIndex(indexLocation.getPath(), indexLocation, new FileInputStream(indexHandle.request()), this);
+						}
+						catch (Exception e) {
+							warning("Unable to read referral index at URL '%s' from parent index '%s': %s", indexLocation, parentUri, e);
+						}
+
+					}
+					catch (URISyntaxException e) {
+						warning("Invalid referral URL '%s' from parent index '%s': %s", referral.getUrl(), parentUri, e);
+					}
+				}
+
+			};
+
+			// Parse the indexes
+			for (URI indexLocation : indexLocations) {
+				try {
+					CachingUriResourceHandle indexHandle = new CachingUriResourceHandle(indexLocation, getCacheDirectory(), connector, (String) null);
+					indexHandle.setReporter(reporter);
+					File indexFile = indexHandle.request();
+					InputStream indexStream = GZipUtils.detectCompression(new FileInputStream(indexFile));
+					readIndex(indexFile.getName(), indexLocation, indexStream, processor);
+				}
+				catch (Exception e) {
+					warning("Unable to read index at URL '%s': %s", indexLocation, e);
+				}
+			}
+
+			initialised = true;
+		}
+	}
+
+	public final List<URI> getIndexLocations() throws Exception {
+		init();
+		return Collections.unmodifiableList(indexLocations);
+	}
+
+	private URLConnector getConnector() {
+		URLConnector connector;
+		synchronized (this) {
+			connector = registry != null ? registry.getPlugin(URLConnector.class) : null;
+		}
+		if (connector == null)
+			connector = new DefaultURLConnector();
+		return connector;
+	}
+
+	public synchronized final void setRegistry(Registry registry) {
+		this.registry = registry;
+	}
+
+	public synchronized void setProperties(Map<String,String> map) {
+		if (map.containsKey(PROP_NAME))
+			name = map.get(PROP_NAME);
+
+		if (map.containsKey(PROP_RESOLUTION_PHASE)) {
+			supportedPhases = EnumSet.noneOf(ResolutionPhase.class);
+			StringTokenizer tokenizer = new StringTokenizer(map.get(PROP_RESOLUTION_PHASE), ",");
+			while (tokenizer.hasMoreTokens()) {
+				String token = tokenizer.nextToken().trim();
+				if (PROP_RESOLUTION_PHASE_ANY.equalsIgnoreCase(token))
+					supportedPhases = EnumSet.allOf(ResolutionPhase.class);
+				else {
+					try {
+						supportedPhases.add(ResolutionPhase.valueOf(token));
+					}
+					catch (Exception e) {
+						error("Unknown OBR resolution mode: " + token);
+					}
+				}
+			}
+		}
+
+		requestedContentProviderList = map.get(PROP_REPO_TYPE);
+	}
+
+	public File[] get(String bsn, String range) throws Exception {
+		ResourceHandle[] handles = getHandles(bsn, range);
+
+		return requestAll(handles);
+	}
+
+	protected static File[] requestAll(ResourceHandle[] handles) throws IOException {
+		File[] result;
+		if (handles == null)
+			result = new File[0];
+		else {
+			result = new File[handles.length];
+			for (int i = 0; i < result.length; i++) {
+				result[i] = handles[i].request();
+			}
+		}
+		return result;
+	}
+
+	protected ResourceHandle[] getHandles(String bsn, String rangeStr) throws Exception {
+		init();
+
+		// If the range is set to "project", we cannot resolve it.
+		if ("project".equals(rangeStr))
+			return null;
+
+		SortedMap<Version,Resource> versionMap = bsnMap.get(bsn);
+		if (versionMap == null || versionMap.isEmpty())
+			return null;
+		List<Resource> resources = narrowVersionsByVersionRange(versionMap, rangeStr);
+		List<ResourceHandle> handles = mapResourcesToHandles(resources);
+
+		return (ResourceHandle[]) handles.toArray(new ResourceHandle[handles.size()]);
+	}
+
+	public synchronized void setReporter(Reporter reporter) {
+		this.reporter = reporter;
+		this.logService = new ReporterLogService(reporter);
+	}
+
+	public File get(String bsn, String range, Strategy strategy, Map<String,String> properties) throws Exception {
+		ResourceHandle handle = getHandle(bsn, range, strategy, properties);
+		return handle != null ? handle.request() : null;
+	}
+
+	public ResourceHandle getHandle(String bsn, String range, Strategy strategy, Map<String,String> properties)
+			throws Exception {
+		init();
+		ResourceHandle result;
+		if (bsn != null)
+			result = resolveBundle(bsn, range, strategy);
+		else {
+			throw new IllegalArgumentException("Cannot resolve bundle: bundle symbolic name not specified.");
+		}
+		return result;
+	}
+
+	public boolean canWrite() {
+		return false;
+	}
+
+	public PutResult put(InputStream stream, PutOptions options) throws Exception {
+		throw new UnsupportedOperationException("Read-only repository.");
+	}
+
+	public List<String> list(String pattern) throws Exception {
+		init();
+		Glob glob = pattern != null ? new Glob(pattern) : null;
+		List<String> result = new LinkedList<String>();
+
+		for (String bsn : bsnMap.keySet()) {
+			if (glob == null || glob.matcher(bsn).matches())
+				result.add(bsn);
+		}
+
+		return result;
+	}
+
+	public SortedSet<Version> versions(String bsn) throws Exception {
+		init();
+		SortedMap<Version,Resource> versionMap = bsnMap.get(bsn);
+		if (versionMap == null || versionMap.isEmpty())
+			return SortedList.empty();
+		
+		return new SortedList<Version>(versionMap.keySet());
+	}
+
+	public synchronized String getName() {
+		return name;
+	}
+	
+	public Map<Requirement,Collection<Capability>> findProviders(Collection< ? extends Requirement> requirements) {
+		try {
+			init();
+		}
+		catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		
+		Map<Requirement,Collection<Capability>> result = new HashMap<Requirement,Collection<Capability>>();
+		for (Requirement requirement : requirements) {
+			List<Capability> matches = new LinkedList<Capability>();
+			result.put(requirement, matches);
+
+			capabilityIndex.appendMatchingCapabilities(requirement, matches);
+		}
+		return result;
+	}
+
+	void addResourceToIndex(Resource resource) {
+		// Add to the bundle identity map
+		String id = getResourceIdentity(resource);
+		if (id == null)
+			return;
+		
+		Version version = getResourceVersion(resource);
+		SortedMap<Version,Resource> versionMap = bsnMap.get(id);
+		if (versionMap == null) {
+			versionMap = new TreeMap<Version,Resource>();
+			bsnMap.put(id, versionMap);
+		}
+		versionMap.put(version, resource);
+		
+		// Add capabilities to the capability index
+		capabilityIndex.addResource(resource);
+	}
+	
+	static Capability getIdentityCapability(Resource resource) {
+		List<Capability> identityCaps = resource.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE);
+		if (identityCaps == null || identityCaps.isEmpty())
+			throw new IllegalArgumentException("Resource has no identity capability.");
+		return identityCaps.iterator().next();
+	}
+	
+	static String getResourceIdentity(Resource resource) {
+		return (String) getIdentityCapability(resource).getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE);
+	}
+
+	static Version getResourceVersion(Resource resource) {
+		Version result;
+		
+		Object versionObj = getIdentityCapability(resource).getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+		if (versionObj == null) {
+			result = Version.emptyVersion;
+		} else if (versionObj instanceof org.osgi.framework.Version) {
+			org.osgi.framework.Version v = (org.osgi.framework.Version) versionObj;
+			result = new Version(v.toString());
+		} else {
+			throw new IllegalArgumentException("Cannot convert to Version from type: " + versionObj.getClass());
+		}
+		
+		return result;
+	}
+	
+	static URI getContentUrl(Resource resource) {
+		List<Capability> caps = resource.getCapabilities(ContentNamespace.CONTENT_NAMESPACE);
+		if (caps == null || caps.isEmpty())
+			throw new IllegalArgumentException("Resource has no content capability");
+
+		Object uri = caps.iterator().next().getAttributes().get(ContentNamespace.CAPABILITY_URL_ATTRIBUTE);
+		if (uri == null)
+			throw new IllegalArgumentException("Resource content has no 'uri' attribute.");
+		if (uri instanceof URI)
+			return (URI) uri;
+		
+		try {
+			if (uri instanceof URL)
+				return ((URL) uri).toURI();
+			if (uri instanceof String)
+				return new URI((String) uri);
+		}
+		catch (URISyntaxException e) {
+			throw new IllegalArgumentException("Failed to convert resource content location to a valid URI.", e);
+		}
+		
+		throw new IllegalArgumentException("Failed to convert resource content location to a valid URI.");
+	}
+	
+	static String getContentSha(Resource resource) {
+		List<Capability> caps = resource.getCapabilities(ContentNamespace.CONTENT_NAMESPACE);
+		if (caps == null || caps.isEmpty())
+			return null;
+		
+		Object contentObj = caps.iterator().next().getAttributes().get(ContentNamespace.CONTENT_NAMESPACE);
+		if (contentObj == null)
+			return null;
+		if (contentObj instanceof String)
+			return (String) contentObj;
+		
+		throw new IllegalArgumentException("Content attribute is wrong type: " + contentObj.getClass().toString() + " (expected String).");
+	}
+
+	private void readIndex(String name, URI baseUri, InputStream stream, IRepositoryIndexProcessor listener)
+			throws Exception {
+		// Make sure we have a buffering stream
+		InputStream bufferedStream;
+		if (stream.markSupported())
+			bufferedStream = stream;
+		else
+			bufferedStream = new BufferedInputStream(stream);
+
+		// Find a compatible content provider for the input
+		IRepositoryContentProvider selectedProvider = null;
+		IRepositoryContentProvider maybeSelectedProvider = null;
+		for (Entry<String,IRepositoryContentProvider> entry : allContentProviders.entrySet()) {
+			IRepositoryContentProvider provider = entry.getValue();
+
+			CheckResult checkResult;
+			try {
+				bufferedStream.mark(READ_AHEAD_MAX);
+				checkResult = provider.checkStream(name, new ProtectedStream(bufferedStream));
+			}
+			finally {
+				bufferedStream.reset();
+			}
+
+			if (checkResult.getDecision() == Decision.accept) {
+				selectedProvider = provider;
+				break;
+			} else if (checkResult.getDecision() == Decision.undecided) {
+				warning("Content provider '%s' was unable to determine compatibility with index at URL '%s': %s",
+						provider.getName(), baseUri, checkResult.getMessage());
+				if (maybeSelectedProvider == null)
+					maybeSelectedProvider = provider;
+			}
+		}
+
+		// If no provider answered definitively, fall back to the first
+		// undecided provider, with an appropriate warning.
+		if (selectedProvider == null) {
+			if (maybeSelectedProvider != null) {
+				selectedProvider = maybeSelectedProvider;
+				warning("No content provider matches the specified index unambiguously. Selected '%s' arbitrarily.",
+						selectedProvider.getName());
+			} else {
+				throw new IOException("No content provider understands the specified index.");
+			}
+		}
+
+		// Finally, parse the damn file.
+		try {
+			selectedProvider.parseIndex(bufferedStream, baseUri, listener, logService);
+		}
+		finally {
+			IO.close(bufferedStream);
+		}
+	}
+
+	static List<Resource> narrowVersionsByFilter(String pkgName, SortedMap<Version,Resource> versionMap, Filter filter) {
+		List<Resource> result = new ArrayList<Resource>(versionMap.size());
+
+		Dictionary<String,String> dict = new Hashtable<String,String>();
+		dict.put("package", pkgName);
+
+		for (Entry<Version,Resource> entry : versionMap.entrySet()) {
+			dict.put("version", entry.getKey().toString());
+			if (filter.match(dict))
+				result.add(entry.getValue());
+		}
+
+		return result;
+	}
+
+	static List<Resource> narrowVersionsByVersionRange(SortedMap<Version,Resource> versionMap, String rangeStr) {
+		List<Resource> result;
+		if ("latest".equals(rangeStr)) {
+			Version highest = versionMap.lastKey();
+			result = Create.list(new Resource[] {
+				versionMap.get(highest)
+			});
+		} else {
+			VersionRange range = rangeStr != null ? new VersionRange(rangeStr) : null;
+
+			// optimisation: skip versions definitely less than the range
+			if (range != null && range.getLow() != null)
+				versionMap = versionMap.tailMap(range.getLow());
+
+			result = new ArrayList<Resource>(versionMap.size());
+			for (Entry<Version,Resource> entry : versionMap.entrySet()) {
+				Version version = entry.getKey();
+				if (range == null || range.includes(version))
+					result.add(entry.getValue());
+
+				// optimisation: skip versions definitely higher than the range
+				if (range != null && range.isRange() && version.compareTo(range.getHigh()) >= 0)
+					break;
+			}
+		}
+		return result;
+	}
+
+	List<ResourceHandle> mapResourcesToHandles(Collection<Resource> resources) throws Exception {
+		List<ResourceHandle> result = new ArrayList<ResourceHandle>(resources.size());
+
+		for (Resource resource : resources) {
+			ResourceHandle handle = mapResourceToHandle(resource);
+			if (handle != null)
+				result.add(handle);
+		}
+
+		return result;
+	}
+
+	ResourceHandle mapResourceToHandle(Resource resource) throws Exception {
+		ResourceHandle result = null;
+
+		CachingUriResourceHandle handle;
+		try {
+			handle = new CachingUriResourceHandle(getContentUrl(resource), getCacheDirectory(), getConnector(), getContentSha(resource));
+		}
+		catch (FileNotFoundException e) {
+			throw new FileNotFoundException("Broken link in repository index: " + e.getMessage());
+		}
+		if (handle.getLocation() == Location.local || getCacheDirectory() != null)
+			result = handle;
+
+		return result;
+	}
+
+	ResourceHandle resolveBundle(String bsn, String rangeStr, Strategy strategy) throws Exception {
+		if (rangeStr == null)
+			rangeStr = "0.0.0";
+
+		if (strategy == Strategy.EXACT) {
+			return findExactMatch(bsn, rangeStr, bsnMap);
+		}
+
+		ResourceHandle[] handles = getHandles(bsn, rangeStr);
+		ResourceHandle selected;
+		if (handles == null || handles.length == 0)
+			selected = null;
+		else {
+			switch (strategy) {
+				case LOWEST :
+					selected = handles[0];
+					break;
+				default :
+					selected = handles[handles.length - 1];
+			}
+		}
+		return selected;
+	}
+
+	static String listToString(List< ? > list) {
+		StringBuilder builder = new StringBuilder();
+
+		int count = 0;
+		for (Object item : list) {
+			if (count++ > 0)
+				builder.append(',');
+			builder.append(item);
+		}
+
+		return builder.toString();
+	}
+
+	ResourceHandle findExactMatch(String identity, String version, Map<String,SortedMap<Version,Resource>> resourceMap) throws Exception {
+		Resource resource;
+		VersionRange range = new VersionRange(version);
+		if (range.isRange())
+			return null;
+
+		SortedMap<Version,Resource> versions = resourceMap.get(identity);
+		if (versions == null)
+			return null;
+
+		resource = findVersion(range.getLow(), versions);
+		if (resource == null)
+			return null;
+
+		return mapResourceToHandle(resource);
+	}
+
+	static Resource findVersion(Version version, SortedMap<Version,Resource> versions) {
+		if (version.getQualifier() != null && version.getQualifier().length() > 0) {
+			return versions.get(version);
+		}
+
+		Resource latest = null;
+		for (Map.Entry<Version,Resource> entry : versions.entrySet()) {
+			if (version.getMicro() == entry.getKey().getMicro() && version.getMinor() == entry.getKey().getMinor()
+					&& version.getMajor() == entry.getKey().getMajor()) {
+				latest = entry.getValue();
+				continue;
+			}
+			if (compare(version, entry.getKey()) < 0) {
+				break;
+			}
+		}
+		return latest;
+	}
+
+	private static int compare(Version v1, Version v2) {
+
+		if (v1.getMajor() != v2.getMajor())
+			return v1.getMajor() - v2.getMajor();
+
+		if (v1.getMinor() != v2.getMinor())
+			return v1.getMinor() - v2.getMinor();
+
+		if (v1.getMicro() != v2.getMicro())
+			return v1.getMicro() - v2.getMicro();
+
+		return 0;
+	}
+
+	/**
+	 * Utility function for parsing lists of URLs.
+	 * 
+	 * @param locationsStr
+	 *            Comma-separated list of URLs
+	 * @throws MalformedURLException
+	 * @throws URISyntaxException 
+	 */
+	protected static List<URI> parseLocations(String locationsStr) throws MalformedURLException, URISyntaxException {
+		StringTokenizer tok = new StringTokenizer(locationsStr, ",");
+		List<URI> urls = new ArrayList<URI>(tok.countTokens());
+		while (tok.hasMoreTokens()) {
+			String urlStr = tok.nextToken().trim();
+			urls.add(new URL(urlStr).toURI());
+		}
+		return urls;
+	}
+
+	public Set<ResolutionPhase> getSupportedPhases() {
+		return supportedPhases;
+	}
+
+	@Override
+	public String toString() {
+		return getName();
+	}
+
+	/**
+	 * This can be optimized to use the download technique with the listeners.
+	 * Now just a quick hack to make it work. I actually think these classes
+	 * should extend FileRepo. TODO 
+	 */
+	public File get(String bsn, Version version, Map<String,String> properties, DownloadListener... listeners)
+			throws Exception {
+		init();
+		ResourceHandle handle = resolveBundle(bsn, version.toString(), Strategy.EXACT);
+		if (handle == null)
+			return null;
+
+		File f = handle.request();
+		if (f == null)
+			return null;
+
+		for (DownloadListener l : listeners) {
+			try {
+				l.success(f);
+			}
+			catch (Exception e) {
+				error("Download listener for %s: %s", f, e);
+			}
+		}
+		return f;
+	}
+	
+	private void error(String format, Object... args) {
+		if (reporter != null)
+			reporter.error(format, args);
+		else
+			System.err.println(String.format(format, args));
+	}
+
+	private void warning(String format, Object... args) {
+		if (reporter != null)
+			reporter.warning(format, args);
+		else
+			System.err.println(String.format(format, args));
+	}
+
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/CachingUriResourceHandle.java b/biz.aQute.repository/src/aQute/bnd/deployer/repository/CachingUriResourceHandle.java
new file mode 100644
index 0000000..aaa63ca
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/CachingUriResourceHandle.java
@@ -0,0 +1,350 @@
+package aQute.bnd.deployer.repository;
+
+import java.io.*;
+import java.net.*;
+import java.security.*;
+
+import aQute.bnd.deployer.http.*;
+import aQute.bnd.service.*;
+import aQute.bnd.service.url.*;
+import aQute.lib.hex.*;
+import aQute.lib.io.*;
+import aQute.service.reporter.*;
+
+/**
+ * <p>
+ * This resource handler downloads remote resources on demand, and caches them
+ * as local files. Resources that are already local (i.e. <code>file:...</code>
+ * URLs) are returned directly.
+ * </p>
+ * <p>
+ * Two alternative caching modes are available. When the mode is
+ * {@link CachingMode#PreferCache}, the cached file will always be returned if
+ * it exists; therefore to refresh from the remote resource it will be necessary
+ * to delete the cache. When the mode is {@link CachingMode#PreferRemote}, the
+ * first call to {@link #request()} will always attempt to download the remote
+ * resource, and only uses the pre-downloaded cache if the remote could not be
+ * downloaded (e.g. because the network is offline).
+ * </p>
+ * 
+ * @author njbartlett
+ */
+public class CachingUriResourceHandle implements ResourceHandle {
+
+	private static final String SHA_256 = "SHA-256";
+
+	@Deprecated
+	public static enum CachingMode {
+		/**
+		 * Always use the cached file, if it exists.
+		 */
+		@Deprecated
+		PreferCache,
+
+		/**
+		 * Download the remote resource if possible, falling back to the cached
+		 * file if remote fails. Subsequently the cached resource will be used.
+		 */
+		@Deprecated
+		PreferRemote;
+	}
+
+	static final String FILE_SCHEME = "file";
+	static final String	FILE_PREFIX	= FILE_SCHEME + ":";
+	
+	static final String HTTP_SCHEME = "http";
+	static final String	HTTP_PREFIX	= HTTP_SCHEME + ":";
+	static final String	UTF_8		= "UTF-8";
+
+	final File			cacheDir;
+	final URLConnector	connector;
+
+	// The resolved, absolute URL of the resource
+	final URL			url;
+	final String		sha;
+
+	// The local file, if the resource IS a file, otherwise null.
+	final File			localFile;
+
+	// The cached file copy of the resource, if it is remote and has been
+	// downloaded.
+	final File			cachedFile;
+	final File			shaFile;
+
+	final CachingMode	mode;
+
+	Reporter			reporter;
+
+	@Deprecated
+	public CachingUriResourceHandle(URI uri, File cacheDir, CachingMode mode) throws IOException {
+		this(uri, cacheDir, new DefaultURLConnector(), mode);
+	}
+	
+	@Deprecated
+	public CachingUriResourceHandle(URI uri, File cacheDir, URLConnector connector, CachingMode mode) throws IOException {
+		this(uri, cacheDir, connector, mode, null);
+	}
+
+	public CachingUriResourceHandle(URI uri, final File cacheDir, URLConnector connector, String sha) throws IOException {
+		this(uri, cacheDir, connector, CachingMode.PreferRemote, sha);
+	}
+	
+	@Deprecated
+	public CachingUriResourceHandle(URI uri, final File cacheDir, URLConnector connector, CachingMode mode, String sha) throws IOException {
+		this.cacheDir = cacheDir;
+		this.connector = connector;
+		this.mode = mode;
+		this.sha = sha;
+
+		if (!uri.isAbsolute())
+			throw new IllegalArgumentException("Relative URIs are not permitted.");
+		
+		if (FILE_SCHEME.equals(uri.getScheme())) {
+			this.localFile = new File(uri.getPath());
+			this.url = uri.toURL();
+			this.cachedFile = null;
+			this.shaFile = null;
+		} else {
+			this.url = uri.toURL();
+			this.localFile = null;
+			this.cachedFile = mapRemoteURL(url);
+			this.shaFile = mapSHAFile(cachedFile);
+		}
+	}
+
+	public void setReporter(Reporter reporter) {
+		this.reporter = reporter;
+	}
+
+	static File resolveFile(String baseFileName, String fileName) {
+		File resolved;
+
+		File baseFile = new File(baseFileName);
+		if (baseFile.isDirectory())
+			resolved = new File(baseFile, fileName);
+		else if (baseFile.isFile())
+			resolved = new File(baseFile.getParentFile(), fileName);
+		else
+			throw new IllegalArgumentException("Cannot resolve relative to non-existant base file path: "
+					+ baseFileName);
+
+		return resolved;
+	}
+
+	private File mapRemoteURL(URL url) throws UnsupportedEncodingException, IOException {
+
+		String localDirName;
+		String localFileName;
+
+		String fullUrl = url.toExternalForm();
+		int lastSlashIndex = fullUrl.lastIndexOf('/');
+
+		File localDir;
+		if (lastSlashIndex > -1) {
+			localDirName = URLEncoder.encode(fullUrl.substring(0, lastSlashIndex), UTF_8);
+			localDir = new File(cacheDir, localDirName);
+			if (localDir.exists() && !localDir.isDirectory()) {
+				localDir = cacheDir;
+				localFileName = URLEncoder.encode(fullUrl, UTF_8);
+			} else {
+				localFileName = URLEncoder.encode(fullUrl.substring(lastSlashIndex + 1), UTF_8);
+			}
+		} else {
+			localDir = cacheDir;
+			localFileName = URLEncoder.encode(fullUrl, UTF_8);
+		}
+		if (!localDir.exists() && !localDir.mkdirs()) {
+			throw new IOException("Could not create directory " + localDir);
+		}
+
+		return new File(localDir, localFileName);
+	}
+
+	private static File mapSHAFile(File cachedFile) {
+		return new File(cachedFile.getAbsolutePath() + ".sha");
+	}
+
+	public String getName() {
+		return url.toString();
+	}
+
+	public Location getLocation() {
+		Location result;
+
+		if (localFile != null)
+			result = Location.local;
+		else if (cachedFile.exists())
+			result = Location.remote_cached;
+		else
+			result = Location.remote;
+
+		return result;
+	}
+
+	public File request() throws IOException {
+		if (localFile != null)
+			return localFile;
+		if (cachedFile == null)
+			throw new IllegalStateException("Invalid URLResourceHandle: both local file and cache file location are uninitialised.");
+
+		// Check whether the cached copy exist and has the right SHA.
+		boolean cacheExists = cachedFile.isFile();
+		boolean cacheValidated;
+		if (cacheExists) {
+			if (sha == null)
+				cacheValidated = false;
+			else {
+				String cachedSHA = getCachedSHA();
+				cacheValidated = sha.equalsIgnoreCase(cachedSHA);
+			}
+		} else {
+			cacheValidated = false;
+		}
+
+		if (cacheValidated)
+			return cachedFile;
+
+		try {
+			InputStream data = connector.connect(url);
+
+			// Save the data to the cache
+			ensureCacheDirExists();
+			String serverSHA = copyWithSHA(data, new FileOutputStream(cachedFile));
+			
+			// Check the SHA of the received data
+			if (sha != null && !sha.equalsIgnoreCase(serverSHA)) {
+				shaFile.delete();
+				cachedFile.delete();
+				throw new IOException(String.format("Invalid SHA on remote resource", url));
+			}
+			saveSHAFile(serverSHA);
+			
+			return cachedFile;
+		}
+		catch (IOException e) {
+			if (sha == null) {
+				// Remote access failed, use the cache if it exists AND if the original SHA was not known.
+				if (cacheExists) {
+					if (reporter != null)
+						reporter.warning("Download of remote resource %s failed, using local cache %s. Original exception: %s. Trace: %s", url, cachedFile, e, collectStackTrace(e));
+					return cachedFile;
+				} else {
+					if (reporter != null)
+						reporter.error("Download of remote resource %s failed and cache file %s not available. Original exception: %s. Trace: %s", url, cachedFile, e, collectStackTrace(e));
+					throw new IOException(String.format("Download of remote resource %s failed and cache file %s not available, see log for details.", url, cachedFile));
+				}
+			} else {
+				// Can only get here if the cache was missing or didn't match the SHA, and remote access failed.
+				if (reporter != null)
+					reporter.error("Download of remote resource %s failed and cache file %s unavailable/invalid. Original exception: %s. Trace: %s", url, cachedFile, e, collectStackTrace(e));
+				throw new IOException(String.format("Download of remote resource %s failed and cache file %s unavailable/invalid, see log for details.", url, cachedFile));
+			}
+		}
+	}
+	
+	private String copyWithSHA(InputStream input, FileOutputStream output) throws IOException {
+		MessageDigest digest;
+		
+		try {
+			digest = MessageDigest.getInstance(SHA_256);
+			DigestOutputStream digestOutput = new DigestOutputStream(output, digest);
+			IO.copy(input, digestOutput);
+			return Hex.toHexString(digest.digest());
+		}
+		catch (NoSuchAlgorithmException e) {
+			// Can't happen... hopefully...
+			throw new IOException(e.getMessage());
+		} finally {
+			IO.close(input);
+			IO.close(output);
+		}
+	}
+	
+
+	private void ensureCacheDirExists() throws IOException {
+		if (cacheDir.isDirectory())
+			return;
+		
+		if (cacheDir.exists()) {
+			String message = String.format("Cannot create cache directory in path %s: the path exists but is not a directory", cacheDir.getCanonicalPath());
+			if (reporter != null)
+				reporter.error(message);
+			throw new IOException(message);
+		}
+		
+		if (!cacheDir.mkdirs()) {
+			String message = String.format("Failed to create cache directory in path %s", cacheDir.getCanonicalPath());
+			if (reporter != null)
+				reporter.error(message);
+			throw new IOException(message);
+		}
+	}
+
+	private static String collectStackTrace(Throwable t) {
+		try {
+			ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+			PrintStream pps = new PrintStream(buffer, false, "UTF-8");
+			t.printStackTrace(pps);
+			return buffer.toString("UTF-8");
+		}
+		catch (UnsupportedEncodingException e) {
+			return null;
+		}
+	}
+
+	String getCachedSHA() throws IOException {
+		String content = readSHAFile();
+		if (content == null) {
+			content = calculateSHA(cachedFile);
+			saveSHAFile(content);
+		}
+		return content;
+	}
+	
+	static String calculateSHA(File file) throws IOException {
+		MessageDigest digest;
+		byte[] buf = new byte[1024];
+		
+		InputStream stream = null;
+		try {
+			digest = MessageDigest.getInstance(SHA_256);
+			stream = new FileInputStream(file);
+			while (true) {
+				int bytesRead = stream.read(buf, 0, 1024);
+				if (bytesRead < 0)
+					break;
+				
+				digest.update(buf, 0, bytesRead);
+			}
+		} catch (NoSuchAlgorithmException e) {
+			// Can't happen... hopefully...
+			throw new IOException(e.getMessage());
+		} finally {
+			if (stream != null) stream.close();
+		}
+		
+		return Hex.toHexString(digest.digest());
+	}
+	
+	String readSHAFile() throws IOException {
+		String result;
+		if (shaFile != null && shaFile.isFile())
+			result = IO.collect(shaFile);
+		else
+			result = null;
+		return result;
+	}
+	
+	void saveSHAFile(String contents) {
+		try {
+			IO.copy(IO.stream(contents), shaFile);
+		}
+		catch (IOException e) {
+			shaFile.delete();
+			// Errors saving the SHA should not interfere with the download
+			if (reporter != null)
+				reporter.error("Failed to save SHA file %s (%s)", shaFile, e.getMessage());
+		}
+	}
+
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/CapabilityIndex.java b/biz.aQute.repository/src/aQute/bnd/deployer/repository/CapabilityIndex.java
new file mode 100644
index 0000000..d8b8860
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/CapabilityIndex.java
@@ -0,0 +1,61 @@
+package aQute.bnd.deployer.repository;
+
+import java.util.*;
+
+import org.osgi.framework.*;
+import org.osgi.resource.*;
+
+
+public class CapabilityIndex {
+
+	private final Map<String,List<Capability>>	capabilityMap	= new HashMap<String,List<Capability>>();
+
+	public void clear() {
+		capabilityMap.clear();
+	}
+
+	public void addResource(Resource resource) {
+		List<Capability> capabilities = resource.getCapabilities(null);
+		if (capabilities == null)
+			return;
+
+		for (Capability cap : capabilities) {
+			addCapability(cap);
+		}
+	}
+	
+	public void addCapability(Capability cap) {
+		List<Capability> list = capabilityMap.get(cap.getNamespace());
+		if (list == null) {
+			list = new LinkedList<Capability>();
+			capabilityMap.put(cap.getNamespace(), list);
+		}
+		list.add(cap);
+	}
+
+	public void appendMatchingCapabilities(Requirement requirement, Collection< ? super Capability> capabilities) {
+		List<Capability> caps = capabilityMap.get(requirement.getNamespace());
+		if (caps == null || caps.isEmpty())
+			return;
+
+		try {
+			String filterStr = requirement.getDirectives().get(Namespace.REQUIREMENT_FILTER_DIRECTIVE);
+			Filter filter = filterStr != null ? FrameworkUtil.createFilter(filterStr) : null;
+
+			for (Capability cap : caps) {
+				boolean match;
+				if (filter == null)
+					match = true;
+				else
+					match = filter.match(new MapToDictionaryAdapter(cap.getAttributes()));
+
+				if (match)
+					capabilities.add(cap);
+			}
+		}
+		catch (InvalidSyntaxException e) {
+			// Assume no matches
+		}
+	}
+
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/FixedIndexedRepo.java b/biz.aQute.repository/src/aQute/bnd/deployer/repository/FixedIndexedRepo.java
new file mode 100644
index 0000000..9e15425
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/FixedIndexedRepo.java
@@ -0,0 +1,99 @@
+package aQute.bnd.deployer.repository;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+/**
+ * A simple read-only OBR-based repository that uses a list of index locations
+ * and a basic local cache.
+ * <p>
+ * <h2>Properties</h2>
+ * <ul>
+ * <li><b>locations:</b> comma-separated list of index URLs. <b>NB:</b> surround
+ * with single quotes!</li>
+ * <li><b>name:</b> repository name; defaults to the index URLs.
+ * <li><b>cache:</b> local cache directory. May be omitted, in which case the
+ * repository will only be able to serve resources with {@code file:} URLs.</li>
+ * <li><b>location:</b> (deprecated) alias for "locations".
+ * </ul>
+ * <p>
+ * <h2>Example</h2>
+ * 
+ * <pre>
+ * -plugin: aQute.lib.repository.FixedIndexedRepo;locations='http://www.example.com/repository.xml';cache=${workspace}/.cache
+ * </pre>
+ * 
+ * @author Neil Bartlett
+ */
+public class FixedIndexedRepo extends AbstractIndexedRepo {
+
+	private static final String	EMPTY_LOCATION	= "";
+	private static final String DEFAULT_CACHE_DIR = ".bnd" + File.separator + "cache";
+
+	public static final String	PROP_LOCATIONS	= "locations";
+	public static final String	PROP_CACHE		= "cache";
+
+	private String				locations;
+	protected File				cacheDir = new File(System.getProperty("user.home") + File.separator + DEFAULT_CACHE_DIR);
+
+	public synchronized void setProperties(Map<String,String> map) {
+		super.setProperties(map);
+
+		locations = map.get(PROP_LOCATIONS);
+		String cachePath = map.get(PROP_CACHE);
+		if (cachePath != null) {
+			cacheDir = new File(cachePath);
+			if (!cacheDir.isDirectory())
+				try {
+					throw new IllegalArgumentException(String.format(
+							"Cache path '%s' does not exist, or is not a directory.", cacheDir.getCanonicalPath()));
+				}
+				catch (IOException e) {
+					throw new IllegalArgumentException("Could not get cacheDir canonical path", e);
+				}
+		}
+	}
+
+	@Override
+	protected List<URI> loadIndexes() throws Exception {
+		List<URI> result;
+		try {
+			if (locations != null)
+				result = parseLocations(locations);
+			else
+				result = Collections.emptyList();
+		}
+		catch (MalformedURLException e) {
+			throw new IllegalArgumentException(String.format("Invalid location, unable to parse as URL list: %s",
+					locations), e);
+		}
+		return result;
+	}
+
+	public synchronized File getCacheDirectory() {
+		return cacheDir;
+	}
+
+	public void setCacheDirectory(File cacheDir) {
+		if (cacheDir == null)
+			throw new IllegalArgumentException("null cache directory not permitted");
+		this.cacheDir = cacheDir;
+	}
+
+	@Override
+	public synchronized String getName() {
+		if (name != null && !name.equals(this.getClass().getName()))
+			return name;
+
+		return locations;
+	}
+
+	public String getLocation() {
+		if (locations == null)
+			return EMPTY_LOCATION;
+		else
+			return locations.toString();
+	}
+
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/LocalIndexedRepo.java b/biz.aQute.repository/src/aQute/bnd/deployer/repository/LocalIndexedRepo.java
new file mode 100644
index 0000000..bdc98b7
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/LocalIndexedRepo.java
@@ -0,0 +1,353 @@
+package aQute.bnd.deployer.repository;
+
+import java.io.*;
+import java.net.*;
+import java.security.*;
+import java.util.*;
+
+import org.osgi.service.coordinator.*;
+import org.osgi.service.log.*;
+
+import aQute.bnd.deployer.repository.api.*;
+import aQute.bnd.filerepo.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.*;
+import aQute.bnd.version.*;
+import aQute.lib.io.*;
+
+public class LocalIndexedRepo extends FixedIndexedRepo implements Refreshable, Participant {
+
+	private static final String			CACHE_PATH				= ".cache";
+	public static final String			PROP_LOCAL_DIR			= "local";
+	public static final String			PROP_READONLY			= "readonly";
+	public static final String			PROP_PRETTY				= "pretty";
+	public static final String			PROP_OVERWRITE			= "overwrite";
+
+	private static final VersionRange	RANGE_ANY				= new VersionRange(Version.LOWEST.toString());
+
+	private FileRepo					storageRepo;
+	private boolean						readOnly;
+	private boolean						pretty					= false;
+	private boolean						overwrite				= true;
+	private File						storageDir;
+
+	// @GuardedBy("newFilesInCoordination")
+	private final List<URI>				newFilesInCoordination	= new LinkedList<URI>();
+
+	@Override
+	public synchronized void setProperties(Map<String,String> map) {
+		super.setProperties(map);
+
+		// Load essential properties
+		String localDirPath = map.get(PROP_LOCAL_DIR);
+		if (localDirPath == null)
+			throw new IllegalArgumentException(String.format("Attribute '%s' must be set on %s plugin.",
+					PROP_LOCAL_DIR, getClass().getName()));
+
+		storageDir = new File(localDirPath);
+		if (storageDir.exists() && !storageDir.isDirectory())
+			throw new IllegalArgumentException(String.format("Local path '%s' exists and is not a directory.",
+					localDirPath));
+
+		readOnly = Boolean.parseBoolean(map.get(PROP_READONLY));
+		pretty = Boolean.parseBoolean(map.get(PROP_PRETTY));
+		overwrite = map.get(PROP_OVERWRITE) == null ? true : Boolean.parseBoolean(map.get(PROP_OVERWRITE));
+
+		// Configure the storage repository
+		storageRepo = new FileRepo(storageDir);
+
+		// Set the local index and cache directory locations
+		cacheDir = new File(storageDir, CACHE_PATH);
+		if (cacheDir.exists() && !cacheDir.isDirectory())
+			throw new IllegalArgumentException(String.format(
+					"Cannot create repository cache: '%s' already exists but is not directory.",
+					cacheDir.getAbsolutePath()));
+	}
+
+	@Override
+	protected synchronized List<URI> loadIndexes() throws Exception {
+		Collection<URI> remotes = super.loadIndexes();
+		List<URI> indexes = new ArrayList<URI>(remotes.size() + generatingProviders.size());
+
+		for (IRepositoryContentProvider contentProvider : generatingProviders) {
+			File indexFile = getIndexFile(contentProvider);
+			try {
+				if (indexFile.exists()) {
+					indexes.add(indexFile.toURI());
+				} else {
+					if (contentProvider.supportsGeneration()) {
+						generateIndex(indexFile, contentProvider);
+						indexes.add(indexFile.toURI());
+					}
+				}
+			}
+			catch (Exception e) {
+				logService.log(LogService.LOG_ERROR, String.format(
+						"Unable to load/generate index file '%s' for repository type %s", indexFile,
+						contentProvider.getName()), e);
+			}
+		}
+
+		indexes.addAll(remotes);
+		return indexes;
+	}
+
+	private File getIndexFile(IRepositoryContentProvider contentProvider) {
+		String indexFileName = contentProvider.getDefaultIndexName(pretty);
+		File indexFile = new File(storageDir, indexFileName);
+		return indexFile;
+	}
+
+	private synchronized void regenerateAllIndexes() {
+		for (IRepositoryContentProvider provider : generatingProviders) {
+			if (!provider.supportsGeneration()) {
+				logService.log(LogService.LOG_WARNING,
+						String.format("Repository type '%s' does not support index generation.", provider.getName()));
+				continue;
+			}
+			File indexFile = getIndexFile(provider);
+			try {
+				generateIndex(indexFile, provider);
+			}
+			catch (Exception e) {
+				logService.log(LogService.LOG_ERROR, String.format(
+						"Unable to regenerate index file '%s' for repository type %s", indexFile, provider.getName()),
+						e);
+			}
+		}
+	}
+
+	private synchronized void generateIndex(File indexFile, IRepositoryContentProvider provider) throws Exception {
+		if (indexFile.exists() && !indexFile.isFile())
+			throw new IllegalArgumentException(String.format(
+					"Cannot create file: '%s' already exists but is not a plain file.", indexFile.getAbsoluteFile()));
+
+		Set<File> allFiles = new HashSet<File>();
+		gatherFiles(allFiles);
+
+		FileOutputStream out = null;
+		try {
+			if (!storageDir.exists() && !storageDir.mkdirs()) {
+				throw new IOException("Could not create directory " + storageDir);
+			}
+			out = new FileOutputStream(indexFile);
+
+			URI rootUri = storageDir.getCanonicalFile().toURI();
+			provider.generateIndex(allFiles, out, this.getName(), rootUri, pretty, registry, logService);
+		}
+		finally {
+			IO.close(out);
+		}
+	}
+
+	private void gatherFiles(Set<File> allFiles) throws Exception {
+		if (!storageDir.isDirectory())
+			return;
+		
+		List<String> bsns = storageRepo.list(null);
+		if (bsns != null)
+			for (String bsn : bsns) {
+				File[] files = storageRepo.get(bsn, RANGE_ANY);
+				if (files != null)
+					for (File file : files) {
+						allFiles.add(file.getCanonicalFile());
+					}
+			}
+	}
+
+	@Override
+	public boolean canWrite() {
+		return !readOnly;
+	}
+
+	private synchronized void finishPut() throws Exception {
+		reset();
+		regenerateAllIndexes();
+
+		List<URI> clone = new ArrayList<URI>(newFilesInCoordination);
+		synchronized (newFilesInCoordination) {
+			newFilesInCoordination.clear();
+		}
+		for (URI entry : clone) {
+			File file = new File(entry);
+			fireBundleAdded(file);
+		}
+	}
+
+	public synchronized void ended(Coordination coordination) throws Exception {
+		finishPut();
+	}
+
+	public void failed(Coordination coordination) throws Exception {
+		ArrayList<URI> clone;
+		synchronized (newFilesInCoordination) {
+			clone = new ArrayList<URI>(newFilesInCoordination);
+			newFilesInCoordination.clear();
+		}
+		for (URI entry : clone) {
+			try {
+				new File(entry).delete();
+			}
+			catch (Exception e) {
+				reporter.warning("Failed to remove repository entry %s on coordination rollback: %s", entry, e);
+			}
+		}
+	}
+
+	protected File putArtifact(File tmpFile) throws Exception {
+		assert (tmpFile != null);
+		assert (tmpFile.isFile());
+
+		init();
+
+		Jar jar = new Jar(tmpFile);
+		try {
+			String bsn = jar.getBsn();
+			if (bsn == null || !Verifier.isBsn(bsn))
+				throw new IllegalArgumentException("Jar does not have a Bundle-SymbolicName manifest header");
+
+			File dir = new File(storageDir, bsn);
+			if (dir.exists() && !dir.isDirectory())
+				throw new IllegalArgumentException("Path already exists but is not a directory: "
+						+ dir.getAbsolutePath());
+			if (!dir.exists() && !dir.mkdirs()) {
+				throw new IOException("Could not create directory " + dir);
+			}
+
+			String versionString = jar.getVersion();
+			if (versionString == null)
+				versionString = "0";
+			else if (!Verifier.isVersion(versionString))
+				throw new IllegalArgumentException("Invalid version " + versionString + " in file " + tmpFile);
+
+			Version version = Version.parseVersion(versionString);
+			String fName = bsn + "-" + version.getWithoutQualifier() + ".jar";
+			File file = new File(dir, fName);
+
+			// check overwrite policy
+			if (!overwrite && file.exists())
+				return null;
+
+			// An open jar on file will fail rename on windows
+			jar.close();
+
+			IO.rename(tmpFile, file);
+
+			synchronized (newFilesInCoordination) {
+				newFilesInCoordination.add(file.toURI());
+			}
+
+			Coordinator coordinator = (registry != null) ? registry.getPlugin(Coordinator.class) : null;
+			if (!(coordinator != null && coordinator.addParticipant(this))) {
+				finishPut();
+			}
+			return file;
+		}
+		finally {
+			jar.close();
+		}
+	}
+
+	/* NOTE: this is a straight copy of FileRepo.put */
+	@Override
+	public synchronized PutResult put(InputStream stream, PutOptions options) throws Exception {
+		/* determine if the put is allowed */
+		if (readOnly) {
+			throw new IOException("Repository is read-only");
+		}
+
+		if (options == null)
+			options = DEFAULTOPTIONS;
+
+		/* both parameters are required */
+		if (stream == null)
+			throw new IllegalArgumentException("No stream and/or options specified");
+
+		/* the root directory of the repository has to be a directory */
+		if (!storageDir.isDirectory()) {
+			throw new IOException("Repository directory " + storageDir + " is not a directory");
+		}
+
+		/*
+		 * setup a new stream that encapsulates the stream and calculates (when
+		 * needed) the digest
+		 */
+		DigestInputStream dis = new DigestInputStream(stream, MessageDigest.getInstance("SHA-1"));
+
+		File tmpFile = null;
+		try {
+			/*
+			 * copy the artifact from the (new/digest) stream into a temporary
+			 * file in the root directory of the repository
+			 */
+			tmpFile = IO.createTempFile(storageDir, "put", ".bnd");
+			IO.copy(dis, tmpFile);
+
+			/* beforeGet the digest if available */
+			byte[] disDigest = dis.getMessageDigest().digest();
+
+			if (options.digest != null && !Arrays.equals(options.digest, disDigest))
+				throw new IOException("Retrieved artifact digest doesn't match specified digest");
+
+			/* put the artifact into the repository (from the temporary file) */
+			File file = putArtifact(tmpFile);
+
+			PutResult result = new PutResult();
+			if (file != null) {
+				result.digest = disDigest;
+				result.artifact = file.toURI();
+			}
+
+			return result;
+		}
+		finally {
+			if (tmpFile != null && tmpFile.exists()) {
+				IO.delete(tmpFile);
+			}
+		}
+	}
+
+	public boolean refresh() {
+		reset();
+		return true;
+	}
+
+	public synchronized File getRoot() {
+		return storageDir;
+	}
+
+	protected void fireBundleAdded(File file) {
+		if (registry == null)
+			return;
+		List<RepositoryListenerPlugin> listeners = registry.getPlugins(RepositoryListenerPlugin.class);
+		Jar jar = null;
+		for (RepositoryListenerPlugin listener : listeners) {
+			try {
+				if (jar == null)
+					jar = new Jar(file);
+				listener.bundleAdded(this, jar, file);
+			}
+			catch (Exception e) {
+				if (reporter != null)
+					reporter.warning("Repository listener threw an unexpected exception: %s", e);
+			}
+			finally {
+				if (jar != null)
+					jar.close();
+			}
+		}
+	}
+
+	@Override
+	public synchronized String getLocation() {
+		StringBuilder builder = new StringBuilder();
+		builder.append(storageDir.getAbsolutePath());
+
+		String otherPaths = super.getLocation();
+		if (otherPaths != null && otherPaths.length() > 0)
+			builder.append(", ").append(otherPaths);
+
+		return builder.toString();
+	}
+
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/MapToDictionaryAdapter.java b/biz.aQute.repository/src/aQute/bnd/deployer/repository/MapToDictionaryAdapter.java
new file mode 100644
index 0000000..6b69e13
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/MapToDictionaryAdapter.java
@@ -0,0 +1,64 @@
+package aQute.bnd.deployer.repository;
+
+import java.util.*;
+
+public class MapToDictionaryAdapter extends Dictionary<String,Object> {
+	
+	private final Map<String,Object>	map;
+
+	public MapToDictionaryAdapter(Map<String, Object> map) {
+		this.map = map;
+	}
+
+	@Override
+	public Enumeration<Object> elements() {
+		final Iterator<Object> iter = map.values().iterator();
+		return new Enumeration<Object>() {
+			public boolean hasMoreElements() {
+				return iter.hasNext();
+			}
+			public Object nextElement() {
+				return iter.next();
+			}
+		};
+	}
+
+	@Override
+	public Object get(Object key) {
+		return map.get(key);
+	}
+
+	@Override
+	public boolean isEmpty() {
+		return map.isEmpty();
+	}
+
+	@Override
+	public Enumeration<String> keys() {
+		final Iterator<String> iter = map.keySet().iterator();
+		return new Enumeration<String>() {
+			public boolean hasMoreElements() {
+				return iter.hasNext();
+			}
+			public String nextElement() {
+				return iter.next();
+			}
+		};
+	}
+
+	@Override
+	public Object put(String key, Object value) {
+		return map.put(key, value);
+	}
+
+	@Override
+	public Object remove(Object key) {
+		return map.remove(key);
+	}
+
+	@Override
+	public int size() {
+		return map.size();
+	}
+
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/NullLogService.java b/biz.aQute.repository/src/aQute/bnd/deployer/repository/NullLogService.java
new file mode 100644
index 0000000..a2a073c
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/NullLogService.java
@@ -0,0 +1,16 @@
+package aQute.bnd.deployer.repository;
+
+import org.osgi.framework.*;
+import org.osgi.service.log.*;
+
+public class NullLogService implements LogService {
+
+	public void log(int level, String message) {}
+
+	public void log(int level, String message, Throwable t) {}
+
+	public void log(ServiceReference sr, int level, String message) {}
+
+	public void log(ServiceReference sr, int level, String message, Throwable t) {}
+
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/ProtectedStream.java b/biz.aQute.repository/src/aQute/bnd/deployer/repository/ProtectedStream.java
new file mode 100644
index 0000000..77372a1
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/ProtectedStream.java
@@ -0,0 +1,56 @@
+package aQute.bnd.deployer.repository;
+
+import java.io.*;
+
+/**
+ * This is used to prevent content providers with interfering with the state of
+ * the underlying stream by calling ant of {@link InputStream#close()},
+ * {@link InputStream#mark(int)} or {@link InputStream#reset()}.
+ * 
+ * @author Neil Bartlett
+ */
+class ProtectedStream extends InputStream {
+
+	private InputStream	delegate;
+
+	ProtectedStream(InputStream delegate) {
+		this.delegate = delegate;
+	}
+
+	public int available() throws IOException {
+		return delegate.available();
+	}
+
+	public void close() throws IOException {
+		// ignore!
+	}
+
+	public void mark(int limit) {
+		throw new UnsupportedOperationException("mark is not supported");
+	}
+
+	public boolean markSupported() {
+		return false;
+	}
+
+	public int read() throws IOException {
+		return delegate.read();
+	}
+
+	public int read(byte[] buf) throws IOException {
+		return delegate.read(buf);
+	}
+
+	public int read(byte[] buf, int start, int len) throws IOException {
+		return delegate.read(buf, start, len);
+	}
+
+	public void reset() throws IOException {
+		throw new IOException("Reset not allowed");
+	}
+
+	public long skip(long bytes) throws IOException {
+		return delegate.skip(bytes);
+	}
+
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/ReporterLogService.java b/biz.aQute.repository/src/aQute/bnd/deployer/repository/ReporterLogService.java
new file mode 100644
index 0000000..5779187
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/ReporterLogService.java
@@ -0,0 +1,42 @@
+package aQute.bnd.deployer.repository;
+
+import org.osgi.framework.*;
+import org.osgi.service.log.*;
+
+import aQute.service.reporter.*;
+
+public class ReporterLogService implements LogService {
+
+	private final Reporter	reporter;
+
+	public ReporterLogService(Reporter reporter) {
+		this.reporter = reporter;
+	}
+
+	public void log(int level, String message) {
+		log(null, level, message, null);
+	}
+
+	public void log(int level, String message, Throwable t) {
+		log(null, level, message, t);
+	}
+
+	public void log(ServiceReference sr, int level, String message) {
+		log(sr, level, message, null);
+	}
+
+	public void log(ServiceReference sr, int level, String message, Throwable t) {
+		if (t != null)
+			message += " [" + t + "]";
+
+		if (reporter != null) {
+			if (level <= LOG_ERROR)
+				reporter.error(message);
+			else if (level == LOG_WARNING)
+				reporter.warning(message);
+			else if (level == LOG_INFO || level == LOG_DEBUG)
+				reporter.trace(message);
+		}
+	}
+
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/api/CheckResult.java b/biz.aQute.repository/src/aQute/bnd/deployer/repository/api/CheckResult.java
new file mode 100644
index 0000000..1e890b3
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/api/CheckResult.java
@@ -0,0 +1,51 @@
+package aQute.bnd.deployer.repository.api;
+
+import static aQute.bnd.deployer.repository.api.Decision.*;
+
+public class CheckResult {
+
+	private Decision	decision;
+	private String		message;
+	private Throwable	exception;
+
+	public static CheckResult fromBool(boolean match, String matchMsg, String unmatchedMsg, Throwable exception) {
+		return new CheckResult(match ? accept : reject, match ? matchMsg : unmatchedMsg, exception);
+	}
+
+	public CheckResult(Decision decision, String message, Throwable exception) {
+		assert decision != null;
+		this.decision = decision;
+		this.message = message;
+		this.exception = exception;
+	}
+
+	public Decision getDecision() {
+		return decision;
+	}
+
+	public void setDecision(Decision decision) {
+		this.decision = decision;
+	}
+
+	public String getMessage() {
+		return message;
+	}
+
+	public void setMessage(String message) {
+		this.message = message;
+	}
+
+	public Throwable getException() {
+		return exception;
+	}
+
+	public void setException(Throwable exception) {
+		this.exception = exception;
+	}
+
+	@Override
+	public String toString() {
+		return "CheckResult [decision=" + decision + ", message=" + message + ", exception=" + exception + "]";
+	}
+
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/api/Decision.java b/biz.aQute.repository/src/aQute/bnd/deployer/repository/api/Decision.java
new file mode 100644
index 0000000..970fdc3
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/api/Decision.java
@@ -0,0 +1,5 @@
+package aQute.bnd.deployer.repository.api;
+
+public enum Decision {
+	accept, reject, undecided;
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/api/IRepositoryContentProvider.java b/biz.aQute.repository/src/aQute/bnd/deployer/repository/api/IRepositoryContentProvider.java
new file mode 100644
index 0000000..ae1c773
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/api/IRepositoryContentProvider.java
@@ -0,0 +1,94 @@
+package aQute.bnd.deployer.repository.api;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import org.osgi.service.log.*;
+
+import aQute.bnd.service.*;
+
+public interface IRepositoryContentProvider {
+
+	/**
+	 * Get the name of this provider (keep it short!).
+	 */
+	String getName();
+
+	/**
+	 * Parse the index provided via the input stream.
+	 * 
+	 * @param stream
+	 *            The stream that provides the index data.
+	 * @param baseUri
+	 * @param processor
+	 */
+	void parseIndex(InputStream stream, URI baseUri, IRepositoryIndexProcessor processor, LogService log) throws Exception;
+
+	/**
+	 * <p>
+	 * Check the stream for compatibility with this provider.
+	 * </p>
+	 * </ul>
+	 * 
+	 * @param name
+	 *            The name of the stream, which may be the file name, or
+	 *            {@code null}. Providers can use this as a hint to the nature
+	 *            of the file.
+	 * @param stream
+	 *            An input stream that MUST support mark/reset operations.
+	 * @return Whether the stream can be handled by this provider.
+	 * @throws IOException
+	 */
+	CheckResult checkStream(String name, InputStream stream) throws IOException;
+
+	/**
+	 * Return whether the content provider supports index generation.
+	 * 
+	 * @return
+	 */
+	boolean supportsGeneration();
+
+	/**
+	 * Generate a new repository index to a stream. Clients must not call this
+	 * method if the provider returns {@code false} from
+	 * {@link #supportsGeneration()}.
+	 * 
+	 * @param files
+	 *            The files to be indexed.
+	 * @param output
+	 *            The output stream, on which the index should be written.
+	 * @param repoName
+	 *            The name of the repository, which may be entered into the
+	 *            generated index.
+	 * @param rootUri
+	 *            The URI of the repository.
+	 * @param pretty
+	 *            Hint to request "pretty printing", i.e. uncompressed, indented
+	 *            output.
+	 * @param registry
+	 *            The bnd workspace plug-in registry if available, or
+	 *            {@code null}.
+	 * @param log
+	 *            The OSGi log service if available, or {@code null}.
+	 * @throws Exception
+	 *             If any other error unrecoverable occurs.
+	 */
+	void generateIndex(Set<File> files, OutputStream output, String repoName, URI rootUri, boolean pretty,
+			Registry registry, LogService log) throws Exception;
+
+	/**
+	 * Get the default name for an index file supported by this provider;
+	 * however the actual index file may take a different name if it is
+	 * overridden by the user or build settings.
+	 * 
+	 * @param pretty
+	 *            Whether the pretty-printing option will be used. Providers may
+	 *            return a different default file name depending on this value,
+	 *            e.g. a non-pretty file may be compressed with the {@code .gz}
+	 *            extension.
+	 * @return
+	 */
+	String getDefaultIndexName(boolean pretty);
+
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/api/IRepositoryIndexProcessor.java b/biz.aQute.repository/src/aQute/bnd/deployer/repository/api/IRepositoryIndexProcessor.java
new file mode 100644
index 0000000..7af3ac3
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/api/IRepositoryIndexProcessor.java
@@ -0,0 +1,33 @@
+package aQute.bnd.deployer.repository.api;
+
+import java.net.*;
+
+import org.osgi.resource.*;
+
+public interface IRepositoryIndexProcessor {
+
+	/**
+	 * Process an OBR resource descriptor from the index document, and possibly
+	 * request early termination of the parser.
+	 * 
+	 * @param resource
+	 *            The resource to be processed. The content URI of the resource
+	 *            must be a resolved, absolute URI.
+	 */
+	void processResource(Resource resource);
+
+	/**
+	 * Process an OBR referral
+	 * 
+	 * @param parentUri
+	 *            The URI of the Repository that referred to this Referral
+	 * @param referral
+	 *            The referral to be processed
+	 * @param maxDepth
+	 *            The depth of referrals this repository acknowledges.
+	 * @param currentDepth
+	 *            The current depth
+	 */
+	void processReferral(URI parentUri, Referral referral, int maxDepth, int currentDepth);
+
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/api/Referral.java b/biz.aQute.repository/src/aQute/bnd/deployer/repository/api/Referral.java
new file mode 100644
index 0000000..99477e5
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/api/Referral.java
@@ -0,0 +1,59 @@
+package aQute.bnd.deployer.repository.api;
+
+public class Referral {
+
+	private final String	url;
+	private final int		depth;
+
+	public Referral(String url, int depth) {
+		this.url = url;
+		this.depth = depth;
+	}
+
+	public String getUrl() {
+		return url;
+	}
+
+	public int getDepth() {
+		return depth;
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder builder = new StringBuilder();
+		builder.append("Referral [");
+		if (url != null)
+			builder.append("url=").append(url).append(", ");
+		builder.append("depth=").append(depth).append(", ");
+		return builder.toString();
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((url == null) ? 0 : url.hashCode());
+		result = prime * result + depth;
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		Referral other = (Referral) obj;
+		if (url == null) {
+			if (other.url != null)
+				return false;
+		} else if (!url.equals(other.url))
+			return false;
+		if (depth != other.depth)
+			return false;
+		return true;
+	}
+
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/api/packageinfo b/biz.aQute.repository/src/aQute/bnd/deployer/repository/api/packageinfo
new file mode 100644
index 0000000..7a6a5c0
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/api/packageinfo
@@ -0,0 +1 @@
+version 2.0
\ No newline at end of file
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/packageinfo b/biz.aQute.repository/src/aQute/bnd/deployer/repository/packageinfo
new file mode 100644
index 0000000..ec185a7
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/packageinfo
@@ -0,0 +1 @@
+version 3.1
\ No newline at end of file
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/providers/AttributeType.java b/biz.aQute.repository/src/aQute/bnd/deployer/repository/providers/AttributeType.java
new file mode 100644
index 0000000..49376e3
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/providers/AttributeType.java
@@ -0,0 +1,101 @@
+package aQute.bnd.deployer.repository.providers;
+
+import java.util.*;
+import java.util.regex.*;
+
+public class AttributeType {
+	
+	public static final AttributeType STRING      = new AttributeType(false, ScalarType.String);
+	public static final AttributeType STRINGLIST  = new AttributeType(true, ScalarType.String);
+	public static final AttributeType LONG        = new AttributeType(false, ScalarType.Long);
+	public static final AttributeType LONGLIST    = new AttributeType(true, ScalarType.Long);
+	public static final AttributeType DOUBLE      = new AttributeType(false, ScalarType.Double);
+	public static final AttributeType DOUBLELIST  = new AttributeType(true, ScalarType.Double);
+	public static final AttributeType VERSION      = new AttributeType(false, ScalarType.Version);
+	public static final AttributeType VERSIONLIST = new AttributeType(true, ScalarType.Version);
+	
+	public static final AttributeType DEFAULT = STRING;
+	
+	private static final Pattern LIST_TYPE_PATTERN = Pattern.compile("List<(\\w*)>");
+
+	private final boolean list;
+	private final ScalarType baseType;
+	
+	public static AttributeType parseTypeName(String typeName) throws IllegalArgumentException {
+		if (typeName == null)
+			return DEFAULT;
+
+		Matcher matcher = LIST_TYPE_PATTERN.matcher(typeName);
+		if (matcher.matches()) {
+			String scalarTypeName = matcher.group(1);
+			ScalarType scalarType = ScalarType.valueOf(scalarTypeName);
+			return new AttributeType(true, scalarType);
+		}
+
+		ScalarType scalarType = ScalarType.valueOf(typeName.trim());
+		return new AttributeType(false, scalarType);
+	}
+	
+	public AttributeType(boolean list, ScalarType baseType) {
+		this.list = list;
+		this.baseType = baseType;
+	}
+	
+	public boolean isList() {
+		return list;
+	}
+	
+	public ScalarType getBaseType() {
+		return baseType;
+	}
+	
+	public Object parseString(String input) {
+		if (list) {
+			LinkedList<Object> list = new LinkedList<Object>();
+			StringTokenizer tokenizer = new StringTokenizer(input, ",");
+			while (tokenizer.hasMoreTokens())
+				list.add(baseType.parseString(tokenizer.nextToken()));
+			return list;
+		}
+		
+		return baseType.parseString(input);
+	}
+	
+	@Override
+	public String toString() {
+		String output;
+		if (list) {
+			output = "List<" + baseType.toString() + ">";
+		} else {
+			output = baseType.toString();
+		}
+		return output;
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result
+				+ ((baseType == null) ? 0 : baseType.hashCode());
+		result = prime * result + (list ? 1231 : 1237);
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		AttributeType other = (AttributeType) obj;
+		if (baseType != other.baseType)
+			return false;
+		if (list != other.list)
+			return false;
+		return true;
+	}
+	
+}
\ No newline at end of file
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/providers/KnownBundleAnalyzerPlugin.java b/biz.aQute.repository/src/aQute/bnd/deployer/repository/providers/KnownBundleAnalyzerPlugin.java
new file mode 100644
index 0000000..f77c157
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/providers/KnownBundleAnalyzerPlugin.java
@@ -0,0 +1,47 @@
+package aQute.bnd.deployer.repository.providers;
+
+import java.io.*;
+import java.util.*;
+
+import org.osgi.service.indexer.*;
+import org.osgi.service.indexer.impl.*;
+
+import aQute.bnd.service.*;
+import aQute.service.reporter.*;
+
+public class KnownBundleAnalyzerPlugin extends KnownBundleAnalyzer implements ResourceAnalyzer, Plugin {
+	
+	private static final String	PROP_DATA	= "data";
+
+	private Reporter	reporter;
+
+	public KnownBundleAnalyzerPlugin() {
+		super(new Properties());
+	}
+
+	public void setProperties(Map<String,String> config) {
+		String fileName = config.get(PROP_DATA);
+		if (fileName == null)
+			throw new IllegalArgumentException(String.format("Property name '%s' must be set on KnownBundleAnalyzerPlugin", PROP_DATA));
+		File file = new File(fileName);
+		if (!file.isFile())
+			throw new IllegalArgumentException(String.format("Data file does not exist, or is not a plain file: %s", file));
+
+		FileInputStream stream = null;
+		try {
+			stream = new FileInputStream(file);
+			Properties props = new Properties();
+			props.load(stream);
+			setKnownBundlesExtra(props);
+		} catch (IOException e) {
+			throw new IllegalArgumentException(String.format("Unable to read data file: %s", file), e);
+		} finally {
+			try { if (stream != null) stream.close(); } catch (IOException e) {}
+		}
+	}
+
+	public void setReporter(Reporter reporter) {
+		this.reporter = reporter;
+	}
+
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/providers/ObrContentProvider.java b/biz.aQute.repository/src/aQute/bnd/deployer/repository/providers/ObrContentProvider.java
new file mode 100644
index 0000000..f41eb83
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/providers/ObrContentProvider.java
@@ -0,0 +1,366 @@
+package aQute.bnd.deployer.repository.providers;
+
+import static aQute.bnd.deployer.repository.api.Decision.*;
+import static javax.xml.stream.XMLStreamConstants.*;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import javax.xml.stream.*;
+import javax.xml.transform.stream.*;
+
+import org.osgi.framework.*;
+import org.osgi.framework.namespace.*;
+import org.osgi.namespace.service.*;
+import org.osgi.resource.*;
+import org.osgi.service.bindex.*;
+import org.osgi.service.log.*;
+import org.osgi.service.repository.*;
+
+import aQute.bnd.deployer.repository.api.*;
+import aQute.bnd.osgi.resource.*;
+import aQute.bnd.service.*;
+import aQute.lib.io.*;
+
+public class ObrContentProvider implements IRepositoryContentProvider {
+
+	private static final String	NULL_CONTENT	= "[null]";
+
+	public static final String	NAME						= "OBR";
+
+	private static final String	INDEX_NAME					= "repository.xml";
+	private static final String	EMPTY_REPO_TEMPLATE			= "<?xml version='1.0' encoding='UTF-8'?>%n<repository name='%s' lastmodified='0' xmlns='http://www.osgi.org/xmlns/obr/v1.0.0'/>";
+
+	private static final String	NS_URI						= "http://www.osgi.org/xmlns/obr/v1.0.0";
+	private static final String	PI_DATA_STYLESHEET			= "type='text/xsl' href='http://www2.osgi.org/www/obr2html.xsl'";
+	private static final String	PI_TARGET_STYLESHEET		= "xml-stylesheet";
+
+	private static final String	TAG_REPOSITORY				= "repository";
+
+	private static final String	TAG_RESOURCE				= "resource";
+	private static final String	ATTR_RESOURCE_SYMBOLIC_NAME	= "symbolicname";
+	private static final String	ATTR_RESOURCE_URI			= "uri";
+	private static final String	ATTR_RESOURCE_VERSION		= "version";
+
+	private static final String	TAG_REFERRAL				= "referral";
+	private static final String	ATTR_REFERRAL_URL			= "url";
+	private static final String	ATTR_REFERRAL_DEPTH			= "depth";
+
+	private static final String	TAG_CAPABILITY				= "capability";
+	private static final String TAG_REQUIRE 				= "require";
+	private static final String ATTR_NAME					= "name";
+	private static final String ATTR_EXTEND					= "extend";
+	private static final String ATTR_OPTIONAL				= "optional";
+	private static final String ATTR_FILTER					= "filter";
+	
+	private static final String	TAG_PROPERTY				= "p";
+	private static final String ATTR_PROPERTY_NAME			= "n";
+	private static final String ATTR_PROPERTY_TYPE			= "t";
+	private static final String ATTR_PROPERTY_VALUE			= "v";
+	
+	private static final String PROPERTY_USES				= "uses";
+	private static final String TYPE_VERSION				= "version";
+
+	private BundleIndexer		indexer;
+
+	private static enum ParserState {
+		beforeRoot, inRoot, inResource, inCapability
+	}
+	
+	public ObrContentProvider(BundleIndexer indexer) {
+		this.indexer = indexer;
+	}
+
+	public String getName() {
+		return NAME;
+	}
+
+	public String getDefaultIndexName(boolean pretty) {
+		return INDEX_NAME;
+	}
+
+	public void parseIndex(InputStream stream, URI baseUri, IRepositoryIndexProcessor listener, LogService log) throws Exception {
+		XMLInputFactory inputFactory = XMLInputFactory.newInstance();
+		inputFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
+		inputFactory.setProperty(XMLInputFactory.IS_VALIDATING, false);
+		inputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
+
+		StreamSource source = new StreamSource(stream, baseUri.toString());
+		XMLStreamReader reader = inputFactory.createXMLStreamReader(source);
+		
+		ResourceBuilder resourceBuilder = null;
+		CapReqBuilder capReqBuilder = null;
+
+		while (reader.hasNext()) {
+			int type = reader.next();
+			String localName;
+
+			switch (type) {
+				case START_ELEMENT :
+					localName = reader.getLocalName();
+					if (TAG_REFERRAL.equals(localName)) {
+						Referral referral = new Referral(reader.getAttributeValue(null, ATTR_REFERRAL_URL),
+								parseInt(reader.getAttributeValue(null, ATTR_REFERRAL_DEPTH)));
+						listener.processReferral(baseUri, referral, referral.getDepth(), 1);
+					} else if (TAG_RESOURCE.equals(localName)) {
+						resourceBuilder = new ResourceBuilder();
+						
+						
+						String bsn = reader.getAttributeValue(null, ATTR_RESOURCE_SYMBOLIC_NAME);
+						String versionStr = reader.getAttributeValue(null, ATTR_RESOURCE_VERSION);
+						Version version = Version.parseVersion(versionStr);
+						String uri = reader.getAttributeValue(null, ATTR_RESOURCE_URI);
+						URI resolvedUri = resolveUri(uri, baseUri);
+						addBasicCapabilities(resourceBuilder, bsn, version, resolvedUri);
+					} else if (TAG_CAPABILITY.equals(localName)) {
+						String obrName = reader.getAttributeValue(null, ATTR_NAME);
+						String namespace = mapObrNameToR5Namespace(obrName, false);
+						capReqBuilder = new CapReqBuilder(namespace);
+					} else if (TAG_REQUIRE.equals(localName)) {
+						String obrName = reader.getAttributeValue(null, ATTR_NAME);
+						boolean extend = "true".equalsIgnoreCase(reader.getAttributeValue(null,  ATTR_EXTEND));
+						String namespace = mapObrNameToR5Namespace(obrName, extend);
+						boolean optional = "true".equalsIgnoreCase(reader.getAttributeValue(null, ATTR_OPTIONAL));
+						
+						capReqBuilder = new CapReqBuilder(namespace);
+						if (optional)
+							capReqBuilder.addDirective(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE, Namespace.RESOLUTION_OPTIONAL);
+						String filter = translateObrFilter(namespace, reader.getAttributeValue(null, ATTR_FILTER), log);
+						capReqBuilder.addDirective(Namespace.REQUIREMENT_FILTER_DIRECTIVE, filter);
+					} else if (TAG_PROPERTY.equals(localName)) {
+						String name = reader.getAttributeValue(null, ATTR_PROPERTY_NAME);
+						String typeStr = reader.getAttributeValue(null, ATTR_PROPERTY_TYPE);
+						String valueStr = reader.getAttributeValue(null, ATTR_PROPERTY_VALUE);
+						if (capReqBuilder != null) {
+							name = mapObrPropertyToR5(capReqBuilder.getNamespace(), name);
+							if (PROPERTY_USES.equals(name))
+								capReqBuilder.addDirective(PROPERTY_USES, valueStr);
+							else {
+								Object value = convertProperty(valueStr, typeStr);
+								capReqBuilder.addAttribute(name, value);
+							}
+						}
+					}
+					break;
+				case END_ELEMENT:
+					localName = reader.getLocalName();
+					if (TAG_RESOURCE.equals(localName)) {
+						if (resourceBuilder != null) {
+							Resource resource = resourceBuilder.build();
+							listener.processResource(resource);
+						}
+					} else if (TAG_CAPABILITY.equals(localName)) {
+						if (resourceBuilder != null && capReqBuilder != null)
+							resourceBuilder.addCapability(capReqBuilder);
+						capReqBuilder = null;
+					} else if (TAG_REQUIRE.equals(localName)) {
+						if (resourceBuilder != null && capReqBuilder != null)
+							resourceBuilder.addRequirement(capReqBuilder);
+						capReqBuilder = null;
+					}
+			}
+		}
+	}
+	
+	private static Object convertProperty(String value, String typeName) {
+		final Object result;
+		if (TYPE_VERSION.equals(typeName))
+			result = Version.parseVersion(value);
+		else
+			result = value;
+		return result;
+	}
+	
+	private static String mapObrNameToR5Namespace(String obrName, boolean extend) {
+		if ("bundle".equals(obrName))
+			return extend ? HostNamespace.HOST_NAMESPACE : BundleNamespace.BUNDLE_NAMESPACE;
+		if ("package".equals(obrName))
+			return PackageNamespace.PACKAGE_NAMESPACE;
+		if ("service".equals(obrName))
+			return ServiceNamespace.SERVICE_NAMESPACE;
+		if ("ee".equals(obrName))
+			return ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE;
+		
+		return obrName;
+	}
+	
+	private static String translateObrFilter(String namespace, String filter, LogService log) {
+		filter = ObrUtil.processFilter(filter, log);
+		
+		if (PackageNamespace.PACKAGE_NAMESPACE.equals(namespace))
+			return filter.replaceAll("\\(package", "(" + PackageNamespace.PACKAGE_NAMESPACE);
+		
+		if (ServiceNamespace.SERVICE_NAMESPACE.equals(namespace))
+			return filter.replaceAll("\\(service", "(" + ServiceNamespace.SERVICE_NAMESPACE);
+		
+		if (BundleNamespace.BUNDLE_NAMESPACE.equals(namespace)) {
+			filter = filter.replaceAll("\\(symbolicname", "(" + BundleNamespace.BUNDLE_NAMESPACE);
+			return filter.replaceAll("\\(version", "(" + BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
+		}
+		
+		if (ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE.equals(namespace))
+			return filter.replaceAll("\\(ee", "(" + ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE);
+		
+		return filter;
+	}
+	
+	private static String mapObrPropertyToR5(String namespace, String propName) {
+		if (BundleNamespace.BUNDLE_NAMESPACE.equals(namespace)) {
+			if ("symbolicname".equals(propName))
+				return BundleNamespace.BUNDLE_NAMESPACE;
+			if ("version".equals(propName))
+				return BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE;
+		}
+		
+		if (PackageNamespace.PACKAGE_NAMESPACE.equals(namespace)) {
+			if ("package".equals(propName))
+				return PackageNamespace.PACKAGE_NAMESPACE;
+		}
+		
+		if (ServiceNamespace.SERVICE_NAMESPACE.equals(namespace)) {
+			if ("service".equals(propName))
+				return ServiceNamespace.SERVICE_NAMESPACE;
+		}
+		
+		return propName;
+	}
+
+	private static URI resolveUri(String uriStr, URI baseUri) throws URISyntaxException {
+		URI resolved;
+		
+		URI resourceUri = new URI(uriStr);
+		if (resourceUri.isAbsolute())
+			resolved = resourceUri;
+		else
+			resolved = baseUri.resolve(resourceUri);
+		
+		return resolved;
+	}
+
+	private static void addBasicCapabilities(ResourceBuilder builder, String bsn, Version version, URI resolvedUri) {
+		CapReqBuilder identity = new CapReqBuilder(IdentityNamespace.IDENTITY_NAMESPACE)
+			.addAttribute(IdentityNamespace.IDENTITY_NAMESPACE, bsn)
+			.addAttribute(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, IdentityNamespace.TYPE_BUNDLE)
+			.addAttribute(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, version);
+		
+		CapReqBuilder content = new CapReqBuilder(ContentNamespace.CONTENT_NAMESPACE)
+			.addAttribute(ContentNamespace.CONTENT_NAMESPACE, null)
+			.addAttribute(ContentNamespace.CAPABILITY_URL_ATTRIBUTE, resolvedUri);
+		
+		CapReqBuilder host = new CapReqBuilder(HostNamespace.HOST_NAMESPACE)
+			.addAttribute(HostNamespace.HOST_NAMESPACE, bsn)
+			.addAttribute(HostNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE, version);
+		
+		builder.addCapability(identity)
+			.addCapability(content)
+			.addCapability(host);
+	}
+	
+	private static int parseInt(String value) {
+		if (value == null || "".equals(value))
+			return 0;
+		return Integer.parseInt(value);
+	}
+
+	public CheckResult checkStream(String name, InputStream stream) throws IOException {
+		XMLStreamReader reader = null;
+		try {
+			XMLInputFactory inputFactory = XMLInputFactory.newInstance();
+
+			inputFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
+			inputFactory.setProperty(XMLInputFactory.IS_VALIDATING, false);
+			inputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
+
+			reader = inputFactory.createXMLStreamReader(stream);
+			ParserState state = ParserState.beforeRoot;
+
+			while (reader.hasNext()) {
+				int type = reader.next();
+				String localName;
+
+				switch (type) {
+					case PROCESSING_INSTRUCTION :
+						if (PI_TARGET_STYLESHEET.equals(reader.getPITarget())
+								&& PI_DATA_STYLESHEET.equals(reader.getPIData()))
+							return new CheckResult(accept, "Recognised stylesheet", null);
+						break;
+					case START_ELEMENT :
+						localName = reader.getLocalName();
+						switch (state) {
+							case beforeRoot :
+								String nsUri = reader.getNamespaceURI();
+								if (nsUri != null)
+									return CheckResult.fromBool(NS_URI.equals(nsUri),
+											"Correct namespace on root element",
+											"Incorrect namespace on root element: " + nsUri, null);
+								if (!TAG_REPOSITORY.equals(localName))
+									return new CheckResult(reject, "Incorrect root element name", null);
+								state = ParserState.inRoot;
+								break;
+							case inRoot :
+								if (TAG_RESOURCE.equals(localName)) {
+									state = ParserState.inResource;
+								} else if (!TAG_REFERRAL.equals(localName)) {
+									return new CheckResult(reject, String.format(
+											"Incorrect element '%s', expected '%s' or '%s'.", localName, TAG_RESOURCE,
+											TAG_REFERRAL), null);
+								}
+								break;
+							case inResource :
+								if (TAG_CAPABILITY.equals(localName)) {
+									state = ParserState.inCapability;
+								}
+								break;
+							case inCapability :
+								return CheckResult.fromBool(TAG_PROPERTY.equals(localName),
+										"Found 'p' tag inside 'capability'", String.format(
+												"Incorrect element '%s' inside '%s'; expected '%s'.", localName,
+												TAG_CAPABILITY, TAG_PROPERTY), null);
+						}
+						break;
+					case END_ELEMENT :
+						localName = reader.getLocalName();
+						if (state == ParserState.inResource && TAG_RESOURCE.equals(localName))
+							state = ParserState.inRoot;
+						if (state == ParserState.inCapability && TAG_CAPABILITY.equals(localName))
+							state = ParserState.inResource;
+						break;
+				}
+			}
+			return new CheckResult(undecided, "Reached end of stream", null);
+		}
+		catch (XMLStreamException e) {
+			return new CheckResult(reject, "Invalid XML", e);
+		}
+		finally {
+			if (reader != null)
+				try {
+					reader.close();
+				}
+				catch (XMLStreamException e) {}
+		}
+	}
+
+	public boolean supportsGeneration() {
+		return true;
+	}
+
+	public void generateIndex(Set<File> files, OutputStream output, String repoName, URI rootUri, boolean pretty, Registry registry, LogService log) throws Exception {
+		if (!files.isEmpty()) {
+			if (indexer == null)
+				throw new IllegalStateException("Cannot index repository: no Bundle Indexer provided.");
+
+			Map<String,String> config = new HashMap<String,String>();
+
+			config.put(BundleIndexer.REPOSITORY_NAME, repoName);
+			config.put(BundleIndexer.ROOT_URL, rootUri.toString());
+
+			indexer.index(files, output, config);
+		} else {
+			String content = String.format(EMPTY_REPO_TEMPLATE, repoName);
+			IO.copy(IO.stream(content), output);
+		}
+	}
+
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/providers/ObrUtil.java b/biz.aQute.repository/src/aQute/bnd/deployer/repository/providers/ObrUtil.java
new file mode 100644
index 0000000..443e522
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/providers/ObrUtil.java
@@ -0,0 +1,44 @@
+package aQute.bnd.deployer.repository.providers;
+
+import java.util.regex.*;
+
+import org.osgi.service.log.*;
+
+public class ObrUtil {
+
+	// Pattern to remove naked less-than operators and replace with not-greater-or-equal
+	private static final Pattern REMOVE_LT = Pattern.compile("\\(([^<>=~()]*)<([^*=]([^\\\\\\*\\(\\)]|\\\\|\\*|\\(|\\))*)\\)");
+	private static final String	NOT_GREATER_THAN_OR_EQUAL	= "(!($1>=$2))";
+
+	// Pattern to remove naked greater-than operators and replace with not-less-than-or-equal
+	private static final Pattern REMOVE_GT = Pattern.compile("\\(([^<>=~()]*)>([^*=]([^\\\\\\*\\(\\)]|\\\\|\\*|\\(|\\))*)\\)");
+	private static final String	NOT_LESS_THAN_OR_EQUAL	= "(!($1<=$2))";
+	
+	// Patterns to search for OBR's extension "Set Arithmetic" operations
+	private static final Pattern REMOVE_SUBSET = Pattern.compile("\\([^<>=~()]*<\\*[^)]*\\)");
+	private static final Pattern REMOVE_SUPERSET = Pattern.compile("\\([^<>=~()]*\\*>[^)]*\\)");
+
+	public static final String processFilter(String filter, LogService log) {
+		filter = removeMatches(filter, REMOVE_SUBSET, log, "Removed unsupported subset clause: %s");
+		filter = removeMatches(filter, REMOVE_SUPERSET, log, "Removed unsupported superset clause: %s");
+		
+		filter = REMOVE_LT.matcher(filter).replaceAll(NOT_GREATER_THAN_OR_EQUAL);
+		filter = REMOVE_GT.matcher(filter).replaceAll(NOT_LESS_THAN_OR_EQUAL);
+		
+		return filter;
+	}
+	
+	private static final String removeMatches(String string, Pattern pattern, LogService log, String messageTemplate) {
+		Matcher matcher = pattern.matcher(string);
+		while (matcher.find()) {
+			String offending = matcher.group();
+			String before = string.substring(0, matcher.start());
+			String after = matcher.end() < string.length() ? string.substring(matcher.end()) : "";
+			string = before + after;
+			if (log != null)
+				log.log(LogService.LOG_INFO, String.format(messageTemplate, offending), null);
+			matcher.reset(string);
+		}
+		return string;
+	}
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/providers/R5RepoContentProvider.java b/biz.aQute.repository/src/aQute/bnd/deployer/repository/providers/R5RepoContentProvider.java
new file mode 100644
index 0000000..d0ff313
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/providers/R5RepoContentProvider.java
@@ -0,0 +1,269 @@
+package aQute.bnd.deployer.repository.providers;
+
+import static aQute.bnd.deployer.repository.api.Decision.*;
+import static javax.xml.stream.XMLStreamConstants.*;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import javax.xml.stream.*;
+
+import org.osgi.framework.*;
+import org.osgi.resource.Resource;
+import org.osgi.service.indexer.*;
+import org.osgi.service.indexer.impl.*;
+import org.osgi.service.log.*;
+import org.osgi.service.repository.*;
+
+import aQute.bnd.deployer.repository.api.*;
+import aQute.bnd.osgi.resource.*;
+import aQute.bnd.service.*;
+
+public class R5RepoContentProvider implements IRepositoryContentProvider {
+
+	public static final String	NAME					= "R5";
+
+	private static final String	NS_URI					= "http://www.osgi.org/xmlns/repository/v1.0.0";
+
+	private static final String	INDEX_NAME_COMPRESSED	= "index.xml.gz";
+	private static final String	INDEX_NAME_PRETTY		= "index.xml";
+
+	private static final String	TAG_REPOSITORY			= "repository";
+	private static final String	TAG_REFERRAL			= "referral";
+	private static final String	TAG_RESOURCE			= "resource";
+	private static final String	TAG_CAPABILITY			= "capability";
+	private static final String	TAG_REQUIREMENT			= "requirement";
+	private static final String	TAG_ATTRIBUTE			= "attribute";
+	private static final String	TAG_DIRECTIVE			= "directive";
+
+	private static final String	ATTR_REFERRAL_URL		= "url";
+	private static final String	ATTR_REFERRAL_DEPTH		= "depth";
+
+	private static final String	ATTR_NAMESPACE			= "namespace";
+
+	private static final String	ATTR_NAME				= "name";
+	private static final String	ATTR_VALUE				= "value";
+	private static final String	ATTR_TYPE				= "type";
+	
+	public String getName() {
+		return NAME;
+	}
+
+	public String getDefaultIndexName(boolean pretty) {
+		return pretty ? INDEX_NAME_PRETTY : INDEX_NAME_COMPRESSED;
+	}
+
+	private static enum ParserState {
+		beforeRoot, inRoot, inResource, inCapability
+	}
+
+	public CheckResult checkStream(String name, InputStream stream) throws IOException {
+		XMLStreamReader reader = null;
+		try {
+			XMLInputFactory inputFactory = XMLInputFactory.newInstance();
+
+			inputFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
+			inputFactory.setProperty(XMLInputFactory.IS_VALIDATING, false);
+			inputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
+
+			reader = inputFactory.createXMLStreamReader(stream);
+			ParserState state = ParserState.beforeRoot;
+
+			while (reader.hasNext()) {
+				int type = reader.next();
+				String localName;
+
+				switch (type) {
+					case START_ELEMENT :
+						localName = reader.getLocalName();
+						switch (state) {
+							case beforeRoot :
+								String nsUri = reader.getNamespaceURI();
+								if (nsUri != null)
+									return CheckResult.fromBool(NS_URI.equals(nsUri), "Corrent namespace",
+											"Incorrect namespace: " + nsUri, null);
+								if (!TAG_REPOSITORY.equals(localName))
+									return new CheckResult(reject, "Incorrect root element name", null);
+								state = ParserState.inRoot;
+								break;
+							case inRoot :
+								if (TAG_RESOURCE.equals(localName)) {
+									state = ParserState.inResource;
+								}
+								break;
+							case inResource :
+								if (TAG_REQUIREMENT.equals(localName))
+									return new CheckResult(accept, "Recognised element 'requirement' in 'resource'",
+											null);
+								if (TAG_CAPABILITY.equals(localName))
+									state = ParserState.inCapability;
+								break;
+							case inCapability :
+								if (TAG_ATTRIBUTE.equals(localName) || TAG_DIRECTIVE.equals(localName)) {
+									return new CheckResult(accept, "Recognised element '%s' in 'capability'", null);
+								}
+								break;
+						}
+						break;
+					case END_ELEMENT :
+						localName = reader.getLocalName();
+						if (state == ParserState.inResource && TAG_RESOURCE.equals(localName))
+							state = ParserState.inRoot;
+						if (state == ParserState.inCapability && TAG_CAPABILITY.equals(localName))
+							state = ParserState.inResource;
+						break;
+					default :
+						break;
+				}
+
+			}
+			return new CheckResult(undecided, "Reached end of stream", null);
+		}
+		catch (XMLStreamException e) {
+			return new CheckResult(reject, "Invalid XML", e);
+		}
+		finally {
+			if (reader != null)
+				try {
+					reader.close();
+				}
+				catch (XMLStreamException e) {}
+		}
+	}
+
+	public void parseIndex(InputStream stream, URI baseUri, IRepositoryIndexProcessor listener, LogService log)
+			throws Exception {
+		XMLStreamReader reader = null;
+		try {
+			XMLInputFactory inputFactory = XMLInputFactory.newInstance();
+
+			inputFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
+			inputFactory.setProperty(XMLInputFactory.IS_VALIDATING, false);
+			inputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
+
+			reader = inputFactory.createXMLStreamReader(stream);
+
+			ResourceBuilder resourceBuilder = null;
+			CapReqBuilder capReqBuilder = null;
+
+			while (reader.hasNext()) {
+				int type = reader.next();
+				String localName;
+
+				switch (type) {
+					case START_ELEMENT :
+						localName = reader.getLocalName();
+						if (TAG_REFERRAL.equals(localName)) {
+							String url = reader.getAttributeValue(null, ATTR_REFERRAL_URL);
+							String depth = reader.getAttributeValue(null, ATTR_REFERRAL_DEPTH);
+							Referral referral = new Referral(url, parseInt(depth));
+							listener.processReferral(baseUri, referral, 0, 0);
+						} else if (TAG_RESOURCE.equals(localName)) {
+							resourceBuilder = new ResourceBuilder();
+						} else if (TAG_CAPABILITY.equals(localName) || TAG_REQUIREMENT.equals(localName)) {
+							String namespace = reader.getAttributeValue(null, ATTR_NAMESPACE);
+							capReqBuilder = new CapReqBuilder(namespace);
+						} else if (TAG_ATTRIBUTE.equals(localName)) {
+							String name = reader.getAttributeValue(null, ATTR_NAME);
+							String valueStr = reader.getAttributeValue(null, ATTR_VALUE);
+							String typeAttr = reader.getAttributeValue(null, ATTR_TYPE);
+							if (capReqBuilder != null) {
+								// If the attribute is 'url' on the osgi.content namespace then resolve it relative to the base URI.
+								if (ContentNamespace.CONTENT_NAMESPACE.equals(capReqBuilder.getNamespace()) && ContentNamespace.CAPABILITY_URL_ATTRIBUTE.equals(name)) {
+									URI resolvedUri = resolveUri(valueStr, baseUri);
+									capReqBuilder.addAttribute(name, resolvedUri);
+								} else {
+									Object convertedAttr = convertAttribute(valueStr, typeAttr);
+									capReqBuilder.addAttribute(name, convertedAttr);
+								}
+							}
+						} else if (TAG_DIRECTIVE.equals(localName)) {
+							String name = reader.getAttributeValue(null, ATTR_NAME);
+							String valueStr = reader.getAttributeValue(null, ATTR_VALUE);
+							if (capReqBuilder != null)
+								capReqBuilder.addDirective(name, valueStr);
+						}
+						break;
+					case END_ELEMENT :
+						localName = reader.getLocalName();
+						if (TAG_CAPABILITY.equals(localName)) {
+							if (resourceBuilder != null && capReqBuilder != null)
+								resourceBuilder.addCapability(capReqBuilder);
+							capReqBuilder = null;
+						} else if (TAG_REQUIREMENT.equals(localName)) {
+							if (resourceBuilder != null && capReqBuilder != null)
+								resourceBuilder.addRequirement(capReqBuilder);
+							capReqBuilder = null;
+						} else if (TAG_RESOURCE.equals(localName)) {
+							if (resourceBuilder != null) {
+								Resource resource = resourceBuilder.build();
+								listener.processResource(resource);
+								resourceBuilder = null;
+							}
+						}
+						break;
+				}
+			}
+		}
+		finally {
+			if (reader != null) {
+				try {
+					reader.close();
+				}
+				catch (Exception e) {}
+			}
+		}
+	}
+
+	private static URI resolveUri(String uriStr, URI baseUri) throws URISyntaxException {
+		URI resolved;
+		
+		URI resourceUri = new URI(uriStr);
+		if (resourceUri.isAbsolute())
+			resolved = resourceUri;
+		else
+			resolved = baseUri.resolve(resourceUri);
+		
+		return resolved;
+	}
+
+	private static int parseInt(String value) {
+		if (value == null || "".equals(value))
+			return 0;
+		return Integer.parseInt(value);
+	}
+
+	private static Object convertAttribute(String value, String type) {
+		AttributeType attType = AttributeType.parseTypeName(type);
+		return attType.parseString(value);
+	}
+
+	public boolean supportsGeneration() {
+		return true;
+	}
+
+	public void generateIndex(Set<File> files, OutputStream output, String repoName, URI baseUri, boolean pretty, Registry registry, LogService log) throws Exception {
+		RepoIndex indexer;
+		if (log != null)
+			indexer = new RepoIndex(log);
+		else
+			indexer = new RepoIndex();
+		indexer.addAnalyzer(new KnownBundleAnalyzer(), FrameworkUtil.createFilter("(name=*)"));
+
+		if (registry != null) {
+			List<ResourceAnalyzer> analyzers = registry.getPlugins(ResourceAnalyzer.class);
+			for (ResourceAnalyzer analyzer : analyzers) {
+				// TODO: where to get the filter property??
+				indexer.addAnalyzer(analyzer, null);
+			}
+		}
+
+		Map<String,String> config = new HashMap<String,String>();
+		config.put(ResourceIndexer.REPOSITORY_NAME, repoName);
+		config.put(ResourceIndexer.ROOT_URL, baseUri.toString());
+		config.put(ResourceIndexer.PRETTY, Boolean.toString(pretty));
+
+		indexer.index(files, output, config);
+	}
+}
diff --git a/biz.aQute.repository/src/aQute/bnd/deployer/repository/providers/ScalarType.java b/biz.aQute.repository/src/aQute/bnd/deployer/repository/providers/ScalarType.java
new file mode 100644
index 0000000..7acceed
--- /dev/null
+++ b/biz.aQute.repository/src/aQute/bnd/deployer/repository/providers/ScalarType.java
@@ -0,0 +1,28 @@
+package aQute.bnd.deployer.repository.providers;
+
+public enum ScalarType {
+	String, Version, Long, Double;
+
+	public Object parseString(String input) {
+		Object result;
+
+		switch (this) {
+			case String :
+				result = input;
+				break;
+			case Long :
+				result = java.lang.Long.parseLong(input.trim());
+				break;
+			case Double :
+				result = java.lang.Double.parseDouble(input.trim());
+				break;
+			case Version :
+				result = org.osgi.framework.Version.parseVersion(input.trim());
+				break;
+			default :
+				throw new IllegalArgumentException("Cannot parse input for unknown attribute type '" + name() + "'");
+		}
+
+		return result;
+	}
+}
\ No newline at end of file
diff --git a/biz.aQute.repository/src/test/AllTests.java b/biz.aQute.repository/src/test/AllTests.java
new file mode 100644
index 0000000..bc988a6
--- /dev/null
+++ b/biz.aQute.repository/src/test/AllTests.java
@@ -0,0 +1,32 @@
+package test;
+
+import junit.framework.*;
+import test.http.*;
+import test.obr.*;
+import test.r5repository.*;
+import test.repository.*;
+
+public class AllTests {
+
+	public static Test suite() {
+		TestSuite suite = new TestSuite(AllTests.class.getName());
+		// $JUnit-BEGIN$
+		suite.addTestSuite(CachingUriResourceHandlerTest.class);
+		suite.addTestSuite(HttpConnectorTest.class);
+		suite.addTestSuite(OBRTest.class);
+		suite.addTestSuite(TestFixedIndexedRepo.class);
+		suite.addTestSuite(TestLocalIndexedRepo.class);
+		suite.addTestSuite(TestCompressedObrRepo.class);
+		suite.addTestSuite(TestLocalIndexGeneration.class);
+		suite.addTestSuite(TestLocalObrGeneration.class);
+		suite.addTestSuite(TestObrRepo.class);
+		suite.addTestSuite(TestMultipleLocalIndexGeneration.class);
+		suite.addTestSuite(TestObrCapReqParsing.class);
+		suite.addTestSuite(TestObrRecognition.class);
+		suite.addTestSuite(TestR5Recognition.class);
+		suite.addTestSuite(FindProvidersTest.class);
+		// $JUnit-END$
+		return suite;
+	}
+
+}
diff --git a/biz.aQute.repository/src/test/helpers/Sed.java b/biz.aQute.repository/src/test/helpers/Sed.java
new file mode 100644
index 0000000..a5de9f2
--- /dev/null
+++ b/biz.aQute.repository/src/test/helpers/Sed.java
@@ -0,0 +1,48 @@
+package test.helpers;
+
+import java.io.*;
+import java.util.zip.*;
+
+public class Sed {
+	private static void processObrFileInternal(BufferedReader reader, String searchPattern, String replacementPattern,
+			OutputStream out) throws Exception {
+		try {
+			String line;
+			while ((line = reader.readLine()) != null) {
+				String newline = line.replaceAll(searchPattern, replacementPattern);
+				out.write(newline.getBytes());
+				out.write("\n".getBytes());
+			}
+		}
+		finally {
+			reader.close();
+			out.close();
+		}
+	}
+
+	public static void file2File(String filenameIn, String searchPattern, String replacementPattern, String filenameOut)
+			throws Exception {
+		BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filenameIn)));
+		BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(filenameOut));
+
+		processObrFileInternal(reader, searchPattern, replacementPattern, out);
+
+	}
+
+	public static void file2GzFile(String filenameIn, String searchPattern, String replacementPattern,
+			String filenameOut) throws Exception {
+		BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filenameIn)));
+		BufferedOutputStream out = new BufferedOutputStream(new GZIPOutputStream(new FileOutputStream(filenameOut)));
+
+		processObrFileInternal(reader, searchPattern, replacementPattern, out);
+	}
+
+	public static void gzFile2GzFile(String filenameIn, String searchPattern, String replacementPattern,
+			String filenameOut) throws Exception {
+		BufferedReader reader = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(
+				filenameIn))));
+		BufferedOutputStream out = new BufferedOutputStream(new GZIPOutputStream(new FileOutputStream(filenameOut)));
+
+		processObrFileInternal(reader, searchPattern, replacementPattern, out);
+	}
+}
diff --git a/biz.aQute.repository/src/test/http/CachingUriResourceHandlerTest.java b/biz.aQute.repository/src/test/http/CachingUriResourceHandlerTest.java
new file mode 100644
index 0000000..8f9847f
--- /dev/null
+++ b/biz.aQute.repository/src/test/http/CachingUriResourceHandlerTest.java
@@ -0,0 +1,141 @@
+package test.http;
+
+import java.io.*;
+import java.net.*;
+
+import junit.framework.*;
+import test.lib.*;
+import aQute.bnd.deployer.http.*;
+import aQute.bnd.deployer.repository.*;
+import aQute.bnd.deployer.repository.CachingUriResourceHandle.CachingMode;
+import aQute.lib.io.*;
+
+public class CachingUriResourceHandlerTest extends TestCase {
+
+	private static final String EXPECTED_SHA = "d0002141a722ef03ecd8fd2e0d3e4d3bc680ba91483cb4962f68a41a12dd01ab".toUpperCase();
+
+	static File						currentDir		= new File(System.getProperty("user.dir"));
+
+	public static void testLoadFromCache() throws Exception {
+		CachingUriResourceHandle handle = new CachingUriResourceHandle(
+				new URI("http://localhost:18083/bundles/dummybundle.jar"), new File(
+						"testdata/httpcache/1"), new DefaultURLConnector(), (String) null);
+		File result = handle.request();
+
+		assertEquals(
+				new File("testdata/httpcache/1/http%3A%2F%2Flocalhost%3A18083%2Fbundles/dummybundle.jar")
+						.getAbsolutePath(),
+				result.getAbsolutePath());
+	}
+
+	public static void testFailedLoadFromRemote() throws Exception {
+		CachingUriResourceHandle handle = new CachingUriResourceHandle(
+				new URI("http://localhost:18083/bundles/dummybundle.jar"), new File(
+						"testdata/httpcache/2"), new DefaultURLConnector(), (String) null);
+
+		try {
+			handle.request();
+			fail("Should throw IOException");
+		}
+		catch (IOException e) {
+			// expected
+		}
+	}
+
+	public static void testLoadFromRemote() throws Exception {
+		CachingUriResourceHandle handle = new CachingUriResourceHandle(
+				new URI("http://localhost:18083/bundles/dummybundle.jar"), new File(
+						"testdata/httpcache/3"), new DefaultURLConnector(), (String) null);
+
+		NanoHTTPD httpd = new NanoHTTPD(18083, new File("testdata/http"));
+		try {
+			File result = handle.request();
+			assertEquals(
+					new File("testdata/httpcache/3/http%3A%2F%2Flocalhost%3A18083%2Fbundles/dummybundle.jar")
+							.getAbsolutePath(),
+					result.getAbsolutePath());
+
+			File shaFile = new File(result.getAbsolutePath() + ".sha");
+			assertEquals(EXPECTED_SHA, IO.collect(shaFile));
+
+			result.delete();
+			shaFile.delete();
+		}
+		finally {
+			httpd.stop();
+		}
+	}
+
+	public static void testUseCached() throws Exception {
+		File cached = new File("testdata/httpcache/4/http%3A%2F%2Flocalhost%3A18083%2Fbundles/dummybundle.jar");
+		long cacheTimestamp = cached.lastModified();
+
+		CachingUriResourceHandle handle = new CachingUriResourceHandle(
+				new URI("http://localhost:18083/bundles/dummybundle.jar"), new File("testdata/httpcache/4"), new DefaultURLConnector(), EXPECTED_SHA);
+
+		NanoHTTPD httpd = new NanoHTTPD(18083, new File("testdata/http"));
+		try {
+			File result = handle.request();
+			assertEquals(cached, result);
+			assertEquals("File timestamp should NOT change", cacheTimestamp, result.lastModified());
+		}
+		finally {
+			httpd.stop();
+		}
+	}
+
+	public static void testReplaceCache() throws Exception {
+		File cached = new File("testdata/httpcache/5/http%3A%2F%2Flocalhost%3A18083%2Fbundles/dummybundle.jar");
+		long cacheTimestamp = cached.lastModified();
+
+		// Clear the SHA so the file appears modified
+		File shaFile = new File(cached.getAbsolutePath() + ".sha");
+		IO.copy(IO.stream("00000000"), shaFile);
+
+		CachingUriResourceHandle handle = new CachingUriResourceHandle(
+				new URI("http://localhost:18083/bundles/dummybundle.jar"), new File("testdata/httpcache/5"), new DefaultURLConnector(), EXPECTED_SHA);
+
+		NanoHTTPD httpd = new NanoHTTPD(18083, new File("testdata/http"));
+		try {
+			File result = handle.request();
+			assertEquals(cached, result);
+			assertNotSame("File timestamp SHOULD change", cacheTimestamp, result.lastModified());
+
+			assertEquals(EXPECTED_SHA, IO.collect(shaFile));
+		}
+		finally {
+			httpd.stop();
+		}
+	}
+
+	public static void testEmptyCache() throws Exception {
+		File cached = new File("testdata/httpcache/6/http%3A%2F%2Flocalhost%3A18083%2Fbundles/dummybundle.jar");
+		cached.delete();
+
+		File shaFile = new File(cached.getAbsolutePath() + ".sha");
+		shaFile.delete();
+
+		CachingUriResourceHandle handle = new CachingUriResourceHandle(
+				new URI("http://localhost:18083/bundles/dummybundle.jar"), new File("testdata/httpcache/6"), new DefaultURLConnector(), EXPECTED_SHA);
+		NanoHTTPD httpd = new NanoHTTPD(18083, new File("testdata/http"));
+		try {
+			File result = handle.request();
+			assertEquals(cached, result);
+			assertEquals(EXPECTED_SHA, IO.collect(shaFile));
+		}
+		finally {
+			httpd.stop();
+		}
+	}
+	
+	public static void testUseCacheWhenRemoteUnavailable() throws Exception {
+		File cached = new File("testdata/httpcache/7/http%3A%2F%2Flocalhost%3A18083%2Fbundles/dummybundle.jar");
+		CachingUriResourceHandle handle = new CachingUriResourceHandle(new URI("http://localhost:18083/bundles/dummybundle.jar"), new File("testdata/httpcache/7"), new DefaultURLConnector(), (String) null);
+
+		// whoops where's the server...
+
+		File result = handle.request();
+		assertEquals(cached, result);
+	}
+
+}
diff --git a/biz.aQute.repository/src/test/http/ETaggingResourceHandler.java b/biz.aQute.repository/src/test/http/ETaggingResourceHandler.java
new file mode 100644
index 0000000..9592b7f
--- /dev/null
+++ b/biz.aQute.repository/src/test/http/ETaggingResourceHandler.java
@@ -0,0 +1,94 @@
+package test.http;
+
+import java.io.*;
+
+import javax.servlet.*;
+import javax.servlet.http.*;
+
+import org.eclipse.jetty.http.*;
+import org.eclipse.jetty.io.*;
+import org.eclipse.jetty.server.*;
+import org.eclipse.jetty.server.handler.*;
+import org.eclipse.jetty.util.resource.*;
+
+public class ETaggingResourceHandler extends ResourceHandler {
+
+	MimeTypes	_mimeTypes	= new MimeTypes();
+
+	public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
+			throws IOException, ServletException {
+		if (baseRequest.isHandled())
+			return;
+
+		boolean skipContentBody = false;
+
+		if (!HttpMethods.GET.equals(request.getMethod())) {
+			if (!HttpMethods.HEAD.equals(request.getMethod())) {
+				// try another handler
+				super.handle(target, baseRequest, request, response);
+				return;
+			}
+			skipContentBody = true;
+		}
+
+		Resource resource = getResource(request);
+
+		if (resource == null || !resource.exists()) {
+			// no resource - try other handlers
+			super.handle(target, baseRequest, request, response);
+			return;
+		}
+
+		// We are going to serve something
+		baseRequest.setHandled(true);
+
+		if (resource.isDirectory()) {
+			response.sendError(HttpStatus.FORBIDDEN_403);
+		}
+
+		// set some headers
+		long last_modified = resource.lastModified();
+		if (last_modified > 0) {
+			long if_modified = request.getDateHeader(HttpHeaders.IF_MODIFIED_SINCE);
+			if (if_modified > 0 && last_modified / 1000 <= if_modified / 1000) {
+				response.setStatus(HttpStatus.NOT_MODIFIED_304);
+				return;
+			}
+		}
+
+		String etag = calculateETag(resource);
+		String incomingETag = request.getHeader(HttpHeaders.IF_NONE_MATCH);
+		if (incomingETag != null) {
+			if (incomingETag.equals(etag)) {
+				response.setStatus(HttpStatus.NOT_MODIFIED_304);
+				return;
+			}
+		}
+		response.setHeader(HttpHeaders.ETAG, etag);
+
+		Buffer mime = _mimeTypes.getMimeByExtension(resource.toString());
+		if (mime == null)
+			mime = _mimeTypes.getMimeByExtension(request.getPathInfo());
+
+		// set the headers
+		doResponseHeaders(response, resource, mime != null ? mime.toString() : null);
+		response.setDateHeader(HttpHeaders.LAST_MODIFIED, last_modified);
+		if (skipContentBody)
+			return;
+
+		// Send the content
+		OutputStream out = null;
+		try {
+			out = response.getOutputStream();
+		}
+		catch (IllegalStateException e) {
+			out = new WriterOutputStream(response.getWriter());
+		}
+		resource.writeTo(out, 0, resource.length());
+	}
+
+	protected static String calculateETag(Resource resource) {
+		return Integer.toHexString(Long.toString(resource.length()).hashCode());
+	}
+
+}
diff --git a/biz.aQute.repository/src/test/http/HttpConnectorTest.java b/biz.aQute.repository/src/test/http/HttpConnectorTest.java
new file mode 100644
index 0000000..50ba007
--- /dev/null
+++ b/biz.aQute.repository/src/test/http/HttpConnectorTest.java
@@ -0,0 +1,316 @@
+package test.http;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import javax.net.ssl.*;
+
+import junit.framework.*;
+
+import org.eclipse.jetty.security.*;
+import org.eclipse.jetty.server.*;
+import org.eclipse.jetty.server.handler.*;
+import org.eclipse.jetty.server.nio.*;
+import org.eclipse.jetty.server.ssl.*;
+import org.eclipse.jetty.util.security.*;
+import org.eclipse.jetty.util.ssl.*;
+
+import aQute.bnd.deployer.http.*;
+import aQute.bnd.service.url.*;
+import aQute.lib.io.*;
+
+public class HttpConnectorTest extends TestCase {
+
+	private static final String	LOCALHOST		= "127.0.0.1";
+
+	private static int			HTTP_PORT		= 0;
+	private static int			HTTPS_PORT		= 0;
+
+	private static final String	RESOURCE_BASE	= "testdata/http";
+	private static final String	SECURED_PATH	= "/securebundles/*";
+
+	private static final String	USER_ROLE_FILE	= "testdata/jetty-users.properties";
+	private static final String	KEYSTORE_PATH	= "testdata/example.keystore";
+	private static final String	KEYSTORE_PASS	= "opensesame";
+
+	private static final String	EXPECTED_ETAG	= "64035a95";
+
+	private static Server				jetty;
+
+	private static String getUrl(boolean http) {
+		if (http) {
+			return "http://127.0.0.1:" + HTTP_PORT + "/";
+		}
+		return "https://127.0.0.1:" + HTTPS_PORT + "/";
+	}
+
+	@Override
+	protected void setUp() throws Exception {
+		File tmpFile = File.createTempFile("cache", ".tmp");
+		tmpFile.deleteOnExit();
+
+		jetty = startJetty();
+	}
+
+	@Override
+	protected void tearDown() throws Exception {
+		jetty.stop();
+	}
+
+	private static Server startJetty() throws Exception {
+		Server server = new Server();
+
+		// Create the login service
+		String REQUIRED_ROLE = "users";
+		HashLoginService loginSvc = new HashLoginService(REQUIRED_ROLE, USER_ROLE_FILE);
+		server.addBean(loginSvc);
+
+		// Start HTTP and HTTPS connectors
+		SelectChannelConnector httpConnector = new SelectChannelConnector();
+		httpConnector.setPort(0);
+		httpConnector.setHost(LOCALHOST);
+		server.addConnector(httpConnector);
+
+		SslSelectChannelConnector sslConnector = new SslSelectChannelConnector();
+		sslConnector.setPort(0);
+		sslConnector.setHost(LOCALHOST);
+		SslContextFactory contextFactory = sslConnector.getSslContextFactory();
+		contextFactory.setKeyStorePath(KEYSTORE_PATH);
+		contextFactory.setKeyStorePassword(KEYSTORE_PASS);
+		server.addConnector(sslConnector);
+
+		// Create the resource handler to serve files
+		ResourceHandler resourceHandler = new ETaggingResourceHandler();
+		resourceHandler.setResourceBase(RESOURCE_BASE);
+		resourceHandler.setDirectoriesListed(true);
+
+		// Setup user role constraints
+		Constraint constraint = new Constraint();
+		constraint.setName(Constraint.__BASIC_AUTH);
+		constraint.setRoles(new String[] {
+			REQUIRED_ROLE
+		});
+		constraint.setAuthenticate(true);
+
+		// Map constraints to the secured directory
+		ConstraintMapping cm = new ConstraintMapping();
+		cm.setConstraint(constraint);
+		cm.setPathSpec(SECURED_PATH);
+
+		// Setup the constraint handler
+		ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
+		securityHandler.setAuthMethod("BASIC");
+		securityHandler.setHandler(resourceHandler);
+		securityHandler.setLoginService(loginSvc);
+		securityHandler.setConstraintMappings(new ConstraintMapping[] {
+			cm
+		});
+
+		// Finally!! Start the server
+		server.setHandler(securityHandler);
+		server.start();
+
+		while (!server.isRunning()) {
+			Thread.sleep(10);
+		}
+		
+		HTTP_PORT = httpConnector.getLocalPort();
+		HTTPS_PORT = sslConnector.getLocalPort();
+		assertNotSame(new Integer(0), new Integer(HTTP_PORT));
+		assertNotSame(new Integer(-1), new Integer(HTTP_PORT));
+		assertNotSame(new Integer(0), new Integer(HTTPS_PORT));
+		assertNotSame(new Integer(-1), new Integer(HTTPS_PORT));
+		assertNotSame(new Integer(HTTP_PORT), new Integer(HTTPS_PORT));
+
+		return server;
+	}
+
+	public static void testConnectTagged() throws Exception {
+		DefaultURLConnector connector = new DefaultURLConnector();
+
+		TaggedData data = connector.connectTagged(new URL(getUrl(true) + "bundles/dummybundle.jar"));
+		assertNotNull("Data should be non-null because ETag not provided", data);
+		data.getInputStream().close();
+		assertEquals("ETag is incorrect", EXPECTED_ETAG, data.getTag());
+	}
+
+	public static void testConnectKnownTag() throws Exception {
+		DefaultURLConnector connector = new DefaultURLConnector();
+
+		TaggedData data = connector.connectTagged(new URL(getUrl(true) + "bundles/dummybundle.jar"), EXPECTED_ETAG);
+		assertNull("Data should be null since ETag not modified.", data);
+	}
+
+	public static void testConnectTagModified() throws Exception {
+		DefaultURLConnector connector = new DefaultURLConnector();
+
+		TaggedData data = connector.connectTagged(new URL(getUrl(true) + "bundles/dummybundle.jar"), "00000000");
+		assertNotNull("Data should be non-null because ETag was different", data);
+		data.getInputStream().close();
+		assertEquals("ETag is incorrect", EXPECTED_ETAG, data.getTag());
+	}
+
+	public static void testConnectHTTPS() throws Exception {
+		DefaultURLConnector connector = new DefaultURLConnector();
+		Map<String,String> config = new HashMap<String,String>();
+		config.put(HttpsUtil.PROP_DISABLE_SERVER_CERT_VERIFY, "true");
+		connector.setProperties(config);
+
+		InputStream stream = connector.connect(new URL(getUrl(false) + "bundles/dummybundle.jar"));
+		assertNotNull(stream);
+		stream.close();
+	}
+
+	public static void testConnectHTTPSBadCerficate() throws Exception {
+		DefaultURLConnector connector = new DefaultURLConnector();
+
+		InputStream stream = null;
+		try {
+			stream = connector.connect(new URL(getUrl(false) + "bundles/dummybundle.jar"));
+			fail("Expected SSLHandsakeException");
+		}
+		catch (SSLHandshakeException e) {
+			// expected
+		}
+		finally {
+			if (stream != null)
+				IO.close(stream);
+		}
+	}
+
+	public static void testConnectTaggedHTTPS() throws Exception {
+		DefaultURLConnector connector = new DefaultURLConnector();
+		Map<String,String> config = new HashMap<String,String>();
+		config.put(HttpsUtil.PROP_DISABLE_SERVER_CERT_VERIFY, "true");
+		connector.setProperties(config);
+
+		TaggedData data = connector.connectTagged(new URL(getUrl(false) + "bundles/dummybundle.jar"));
+		assertNotNull(data);
+		data.getInputStream().close();
+	}
+
+	public static void testConnectTaggedHTTPSBadCerficate() throws Exception {
+		DefaultURLConnector connector = new DefaultURLConnector();
+
+		InputStream stream = null;
+		try {
+			connector.connectTagged(new URL(getUrl(false) + "bundles/dummybundle.jar"));
+			fail("Expected SSLHandsakeException");
+		}
+		catch (SSLHandshakeException e) {
+			// expected
+		}
+		finally {
+			if (stream != null)
+				IO.close(stream);
+		}
+	}
+
+	public static void testConnectNoUserPass() throws Exception {
+		HttpBasicAuthURLConnector connector = new HttpBasicAuthURLConnector();
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("configs", "");
+		connector.setProperties(config);
+
+		try {
+			connector.connect(new URL(getUrl(true) + "securebundles/dummybundle.jar"));
+			fail("Should have thrown IOException due to missing auth");
+		}
+		catch (IOException e) {
+			// expected
+			assertTrue(e.getMessage().startsWith("Server returned HTTP response code: 401"));
+		}
+	}
+
+	public static void testConnectWithUserPass() throws Exception {
+		HttpBasicAuthURLConnector connector = new HttpBasicAuthURLConnector();
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("configs", "testdata/http_auth.properties");
+		connector.setProperties(config);
+
+		InputStream stream = connector.connect(new URL(getUrl(true) + "securebundles/dummybundle.jar"));
+		assertNotNull(stream);
+	}
+
+	public static void testConnectHTTPSBadCertificate() throws Exception {
+		HttpBasicAuthURLConnector connector = new HttpBasicAuthURLConnector();
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("configs", "testdata/http_auth.properties");
+		connector.setProperties(config);
+
+		try {
+			connector.connect(new URL(getUrl(false) + "securebundles/dummybundle.jar"));
+			fail("Should have thrown error: invalid server certificate");
+		}
+		catch (IOException e) {
+			// expected
+			assertTrue(e instanceof SSLHandshakeException);
+		}
+	}
+	
+	// FIXME
+	// run stand-alone this test passes within 0.5 seconds.
+	// run right after testConnectHTTPSBadCertificate it times out, but claims to succeed
+	public static void testConnectWithUserPassHTTPS() throws Exception {
+		HttpBasicAuthURLConnector connector = new HttpBasicAuthURLConnector();
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("configs", "testdata/http_auth.properties");
+		config.put(HttpsUtil.PROP_DISABLE_SERVER_CERT_VERIFY, "true");
+		connector.setProperties(config);
+
+		try {
+			InputStream stream = connector.connect(new URL(getUrl(false) + "securebundles/dummybundle.jar"));
+			assertNotNull(stream);
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+			throw e;
+		}
+	}
+
+	public static void testConnectWithWrongUserPass() throws Exception {
+		HttpBasicAuthURLConnector connector = new HttpBasicAuthURLConnector();
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("configs", "testdata/http_auth_wrong.properties");
+		connector.setProperties(config);
+
+		try {
+			connector.connect(new URL(getUrl(true) + "securebundles/dummybundle.jar"));
+			fail("Should have thrown IOException due to incorrect auth");
+		}
+		catch (IOException e) {
+			// expected
+			assertTrue(e.getMessage().startsWith("Server returned HTTP response code: 401"));
+		}
+	}
+
+	public static void testConnectWithWrongUserPassHTTPS() throws Exception {
+		HttpBasicAuthURLConnector connector = new HttpBasicAuthURLConnector();
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("configs", "testdata/http_auth_wrong.properties");
+		config.put(HttpsUtil.PROP_DISABLE_SERVER_CERT_VERIFY, "true");
+		connector.setProperties(config);
+
+		try {
+			connector.connect(new URL(getUrl(false) + "securebundles/dummybundle.jar"));
+			fail("Should have thrown IOException due to incorrect auth");
+		}
+		catch (IOException e) {
+			// expected
+			assertTrue(e.getMessage().startsWith("Server returned HTTP response code: 401"));
+		}
+	}
+
+	public static void testConnectWithUserPassAndTag() throws Exception {
+		HttpBasicAuthURLConnector connector = new HttpBasicAuthURLConnector();
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("configs", "testdata/http_auth.properties");
+		connector.setProperties(config);
+
+		TaggedData data = connector.connectTagged(new URL(getUrl(true) + "securebundles/dummybundle.jar"),
+				EXPECTED_ETAG);
+		assertNull("Data should be null because resource not modified", data);
+	}
+
+}
diff --git a/biz.aQute.repository/src/test/lib/MockRegistry.java b/biz.aQute.repository/src/test/lib/MockRegistry.java
new file mode 100644
index 0000000..23f3dae
--- /dev/null
+++ b/biz.aQute.repository/src/test/lib/MockRegistry.java
@@ -0,0 +1,32 @@
+package test.lib;
+
+import java.util.*;
+
+import aQute.bnd.service.*;
+
+public class MockRegistry implements Registry {
+
+	private final Set<Object>	plugins	= new HashSet<Object>();
+
+	public void addPlugin(Object plugin) {
+		plugins.add(plugin);
+	}
+
+	public <T> List<T> getPlugins(Class<T> clazz) {
+		List<T> l = new ArrayList<T>();
+		for (Object plugin : plugins) {
+			if (clazz.isInstance(plugin))
+				l.add(clazz.cast(plugin));
+		}
+		return l;
+	}
+
+	public <T> T getPlugin(Class<T> clazz) {
+		for (Object plugin : plugins) {
+			if (clazz.isInstance(plugin))
+				return clazz.cast(plugin);
+		}
+		return null;
+	}
+
+}
diff --git a/biz.aQute.repository/src/test/lib/NanoHTTPD.java b/biz.aQute.repository/src/test/lib/NanoHTTPD.java
new file mode 100644
index 0000000..c5ec481
--- /dev/null
+++ b/biz.aQute.repository/src/test/lib/NanoHTTPD.java
@@ -0,0 +1,1058 @@
+package test.lib;
+
+import java.io.*;
+import java.net.*;
+import java.security.*;
+import java.util.*;
+
+import javax.net.ssl.*;
+
+import aQute.lib.io.*;
+
+/**
+ * A simple, tiny, nicely embeddable HTTP 1.0 (partially 1.1) server in Java
+ * <p>
+ * <b>Modified from the original NanoHTTPD!</b> ETags are calculated based
+ * solely on file size, rather than absolute path and last-modified timestamp.
+ * This allows them to be used in location-independent unit tests.
+ * </p>
+ * <p>
+ * NanoHTTPD version 1.25, Copyright © 2001,2005-2012 Jarno Elonen
+ * (elonen at iki.fi, http://iki.fi/elonen/) and Copyright © 2010 Konstantinos
+ * Togias (info at ktogias.gr, http://ktogias.gr)
+ * <p>
+ * <b>Features + limitations: </b>
+ * <ul>
+ * <li>Only one Java file</li>
+ * <li>Java 1.1 compatible</li>
+ * <li>Released as open source, Modified BSD licence</li>
+ * <li>No fixed config files, logging, authorization etc. (Implement yourself if
+ * you need them.)</li>
+ * <li>Supports parameter parsing of GET and POST methods (+ rudimentary PUT
+ * support in 1.25)</li>
+ * <li>Supports both dynamic content and file serving</li>
+ * <li>Supports file upload (since version 1.2, 2010)</li>
+ * <li>Supports partial content (streaming)</li>
+ * <li>Supports ETags</li>
+ * <li>Never caches anything</li>
+ * <li>Doesn't limit bandwidth, request time or simultaneous connections</li>
+ * <li>Default code serves files and shows all HTTP parameters and headers</li>
+ * <li>File server supports directory listing, index.html and index.htm</li>
+ * <li>File server supports partial content (streaming)</li>
+ * <li>File server supports ETags</li>
+ * <li>File server does the 301 redirection trick for directories without '/'</li>
+ * <li>File server supports simple skipping for files (continue download)</li>
+ * <li>File server serves also very long files without memory overhead</li>
+ * <li>Contains a built-in list of most common mime types</li>
+ * <li>All header names are converted lowercase so they don't vary between
+ * browsers/clients</li>
+ * </ul>
+ * <p>
+ * <b>Ways to use: </b>
+ * <ul>
+ * <li>Run as a standalone app, serves files and shows requests</li>
+ * <li>Subclass serve() and embed to your own program</li>
+ * <li>Call serveFile() from serve() with your own base directory</li>
+ * </ul>
+ * See the end of the source file for distribution license (Modified BSD
+ * licence)
+ */
+ at SuppressWarnings("synthetic-access")
+public class NanoHTTPD {
+	// ==================================================
+	// API parts
+	// ==================================================
+
+	/**
+	 * Override this to customize the server.
+	 * <p>
+	 * (By default, this delegates to serveFile() and allows directory listing.)
+	 * 
+	 * @param uri
+	 *            Percent-decoded URI without parameters, for example
+	 *            "/index.cgi"
+	 * @param method
+	 *            "GET", "POST" etc.
+	 * @param parms
+	 *            Parsed, percent decoded parameters from URI and, in case of
+	 *            POST, data.
+	 * @param header
+	 *            Header entries, percent decoded
+	 * @return HTTP response, see class Response for details
+	 */
+	public Response serve(String uri, String method, Properties header, Properties parms, Properties files) {
+		myOut.println(method + " '" + uri + "' ");
+
+		Enumeration< ? > e = header.propertyNames();
+		while (e.hasMoreElements()) {
+			String value = (String) e.nextElement();
+			myOut.println("  HDR: '" + value + "' = '" + header.getProperty(value) + "'");
+		}
+		e = parms.propertyNames();
+		while (e.hasMoreElements()) {
+			String value = (String) e.nextElement();
+			myOut.println("  PRM: '" + value + "' = '" + parms.getProperty(value) + "'");
+		}
+		e = files.propertyNames();
+		while (e.hasMoreElements()) {
+			String value = (String) e.nextElement();
+			myOut.println("  UPLOADED: '" + value + "' = '" + files.getProperty(value) + "'");
+		}
+
+		return serveFile(uri, header, myRootDir, true);
+	}
+
+	/**
+	 * HTTP response. Return one of these from serve().
+	 */
+	public class Response {
+		/**
+		 * Default constructor: response = HTTP_OK, data = mime = 'null'
+		 */
+		public Response() {
+			this.status = HTTP_OK;
+		}
+
+		/**
+		 * Basic constructor.
+		 */
+		public Response(String status, String mimeType, InputStream data) {
+			this.status = status;
+			this.mimeType = mimeType;
+			this.data = data;
+		}
+
+		/**
+		 * Convenience method that makes an InputStream out of given text.
+		 */
+		public Response(String status, String mimeType, String txt) {
+			this.status = status;
+			this.mimeType = mimeType;
+			try {
+				this.data = new ByteArrayInputStream(txt.getBytes("UTF-8"));
+			}
+			catch (java.io.UnsupportedEncodingException uee) {
+				uee.printStackTrace();
+			}
+		}
+
+		/**
+		 * Adds given line to the header.
+		 */
+		public void addHeader(String name, String value) {
+			header.put(name, value);
+		}
+
+		/**
+		 * HTTP status code after processing, e.g. "200 OK", HTTP_OK
+		 */
+		public String		status;
+
+		/**
+		 * MIME type of content, e.g. "text/html"
+		 */
+		public String		mimeType;
+
+		/**
+		 * Data of the response, may be null.
+		 */
+		public InputStream	data;
+
+		/**
+		 * Headers for the HTTP response. Use addHeader() to add lines.
+		 */
+		public Properties	header	= new Properties();
+	}
+
+	/**
+	 * Some HTTP response status codes
+	 */
+	public static final String	HTTP_OK	= "200 OK", HTTP_PARTIALCONTENT = "206 Partial Content",
+			HTTP_RANGE_NOT_SATISFIABLE = "416 Requested Range Not Satisfiable",
+			HTTP_REDIRECT = "301 Moved Permanently", HTTP_NOTMODIFIED = "304 Not Modified",
+			HTTP_FORBIDDEN = "403 Forbidden", HTTP_NOTFOUND = "404 Not Found", HTTP_BADREQUEST = "400 Bad Request",
+			HTTP_INTERNALERROR = "500 Internal Server Error", HTTP_NOTIMPLEMENTED = "501 Not Implemented";
+
+	/**
+	 * Common mime types for dynamic content
+	 */
+	public static final String	MIME_PLAINTEXT	= "text/plain", MIME_HTML = "text/html",
+			MIME_DEFAULT_BINARY = "application/octet-stream", MIME_XML = "text/xml";
+
+	// ==================================================
+	// Socket & server code
+	// ==================================================
+
+	public NanoHTTPD(int port, File wwwroot) throws Exception {
+		this(port, wwwroot, false, null, null);
+	}
+
+	/**
+	 * Starts a HTTP server to given port.
+	 * <p>
+	 * Throws an IOException if the socket is already in use
+	 */
+	public NanoHTTPD(int port, File wwwroot, boolean ssl, File keyStoreFile, String keyStorePwd) throws Exception {
+		myTcpPort = port;
+		this.myRootDir = wwwroot;
+		if (ssl) {
+			System.out.println("Using SSL");
+
+			KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+			keyStore.load(new FileInputStream(keyStoreFile), null);
+
+			KeyManagerFactory keyManagerFactory = KeyManagerFactory
+					.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+			keyManagerFactory.init(keyStore, keyStorePwd.toCharArray());
+
+			TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory
+					.getDefaultAlgorithm());
+			trustManagerFactory.init(keyStore);
+
+			SSLContext sslContext = SSLContext.getInstance("TLSv1");
+			sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(),
+					new SecureRandom());
+			SSLServerSocketFactory serverSocketFactory = sslContext.getServerSocketFactory();
+
+			SSLServerSocket sslSock = (SSLServerSocket) serverSocketFactory.createServerSocket(myTcpPort);
+			sslSock.setEnableSessionCreation(true);
+			sslSock.setWantClientAuth(true);
+			String[] protocols = sslSock.getEnabledProtocols();
+			System.out.printf("Enabled protocols: %s\n", Arrays.toString(protocols));
+
+			myServerSocket = sslSock;
+		} else {
+			myServerSocket = new ServerSocket(myTcpPort);
+			myTcpPort = myServerSocket.getLocalPort();
+		}
+		myThread = new Thread(new Runnable() {
+			@SuppressWarnings("unused")
+			public void run() {
+				try {
+					while (true)
+						new HTTPSession(myServerSocket.accept());
+				}
+				catch (IOException ioe) {}
+			}
+		});
+		myThread.setDaemon(true);
+		myThread.start();
+	}
+
+	/**
+	 * Stops the server.
+	 */
+	public void stop() {
+		try {
+			myServerSocket.close();
+			myThread.join();
+		}
+		catch (IOException ioe) {}
+		catch (InterruptedException e) {}
+	}
+
+	/**
+	 * Starts as a standalone file server and waits for Enter.
+	 */
+	@SuppressWarnings("unused")
+	public static void main(String[] args) {
+		myOut.println("NanoHTTPD 1.25 (C) 2001,2005-2011 Jarno Elonen and (C) 2010 Konstantinos Togias\n"
+				+ "(Command line options: [-p port] [-d root-dir] [--ssl] [--keyStore file] [--keyStorePass password] [--licence])\n");
+
+		// Defaults
+		int port = -1;
+		File wwwroot = new File(".").getAbsoluteFile();
+		File authFile = null;
+		boolean ssl = false;
+		File keyStoreFile = null;
+		String keyStorePass = null;
+
+		// Show licence if requested
+		for (int i = 0; i < args.length; ++i)
+			if (args[i].equalsIgnoreCase("-p"))
+				port = Integer.parseInt(args[i + 1]);
+			else if (args[i].equalsIgnoreCase("-d"))
+				wwwroot = new File(args[i + 1]).getAbsoluteFile();
+			else if (args[i].equalsIgnoreCase("--auth"))
+				authFile = new File(args[i + 1]).getAbsoluteFile();
+			else if (args[i].equalsIgnoreCase("--ssl"))
+				ssl = true;
+			else if (args[i].equalsIgnoreCase("--keyStore"))
+				keyStoreFile = new File(args[i + 1]).getAbsoluteFile();
+			else if (args[i].equalsIgnoreCase("--keyStorePass"))
+				keyStorePass = args[i + 1];
+			else if (args[i].toLowerCase().endsWith("licence")) {
+				myOut.println(LICENCE + "\n");
+				break;
+			}
+
+		if (port == -1)
+			port = ssl ? 443 : 80;
+
+		try {
+			new NanoHTTPD(port, wwwroot, ssl, keyStoreFile, keyStorePass);
+		}
+		catch (Exception ioe) {
+			System.err.printf("Couldn't start server:%n" + ioe + "%n");
+			System.exit(-1);
+		}
+
+		myOut.println("Now serving files in port " + port + " from \"" + wwwroot + "\"");
+		myOut.printf("Hit Enter to stop.%n");
+
+		try {
+			System.in.read();
+		}
+		catch (Throwable t) {}
+	}
+
+	/**
+	 * Handles one session, i.e. parses the HTTP request and returns the
+	 * response.
+	 */
+	private class HTTPSession implements Runnable {
+		public HTTPSession(Socket s) {
+			mySocket = s;
+			Thread t = new Thread(this);
+			t.setDaemon(true);
+			t.start();
+		}
+
+		public void run() {
+			try {
+				InputStream is = mySocket.getInputStream();
+				if (is == null)
+					return;
+
+				// Read the first 8192 bytes.
+				// The full header should fit in here.
+				// Apache's default header limit is 8KB.
+				int bufsize = 8192;
+				byte[] buf = new byte[bufsize];
+				int rlen = is.read(buf, 0, bufsize);
+				if (rlen <= 0)
+					return;
+
+				// Create a BufferedReader for parsing the header.
+				ByteArrayInputStream hbis = new ByteArrayInputStream(buf, 0, rlen);
+				BufferedReader hin = new BufferedReader(new InputStreamReader(hbis));
+				dumpInput(hin);
+				Properties pre = new Properties();
+				Properties parms = new Properties();
+				Properties header = new Properties();
+				Properties files = new Properties();
+
+				// Decode the header into parms and header java properties
+				decodeHeader(hin, pre, parms, header);
+				String method = pre.getProperty("method");
+				String uri = pre.getProperty("uri");
+
+				long size = 0x7FFFFFFFFFFFFFFFl;
+				String contentLength = header.getProperty("content-length");
+				if (contentLength != null) {
+					try {
+						size = Integer.parseInt(contentLength);
+					}
+					catch (NumberFormatException ex) {}
+				}
+
+				// We are looking for the byte separating header from body.
+				// It must be the last byte of the first two sequential new
+				// lines.
+				int splitbyte = 0;
+				boolean sbfound = false;
+				while (splitbyte < rlen) {
+					if (buf[splitbyte] == '\r' && buf[++splitbyte] == '\n' && buf[++splitbyte] == '\r'
+							&& buf[++splitbyte] == '\n') {
+						sbfound = true;
+						break;
+					}
+					splitbyte++;
+				}
+				splitbyte++;
+
+				// Write the part of body already read to ByteArrayOutputStream
+				// f
+				ByteArrayOutputStream f = new ByteArrayOutputStream();
+				if (splitbyte < rlen)
+					f.write(buf, splitbyte, rlen - splitbyte);
+
+				// While Firefox sends on the first read all the data fitting
+				// our buffer, Chrome and Opera sends only the headers even if
+				// there is data for the body. So we do some magic here to find
+				// out whether we have already consumed part of body, if we
+				// have reached the end of the data to be sent or we should
+				// expect the first byte of the body at the next read.
+				if (splitbyte < rlen)
+					size -= rlen - splitbyte + 1;
+				else if (!sbfound || size == 0x7FFFFFFFFFFFFFFFl)
+					size = 0;
+
+				// Now read all the body and write it to f
+				buf = new byte[512];
+				while (rlen >= 0 && size > 0) {
+					rlen = is.read(buf, 0, 512);
+					size -= rlen;
+					if (rlen > 0)
+						f.write(buf, 0, rlen);
+				}
+
+				// Get the raw body as a byte []
+				byte[] fbuf = f.toByteArray();
+
+				// Create a BufferedReader for easily reading it as string.
+				ByteArrayInputStream bin = new ByteArrayInputStream(fbuf);
+				BufferedReader in = new BufferedReader(new InputStreamReader(bin));
+
+				// If the method is POST, there may be parameters
+				// in data section, too, read it:
+				if (method.equalsIgnoreCase("POST")) {
+					String contentType = "";
+					String contentTypeHeader = header.getProperty("content-type");
+					StringTokenizer st = new StringTokenizer(contentTypeHeader, "; ");
+					if (st.hasMoreTokens()) {
+						contentType = st.nextToken();
+					}
+
+					if (contentType.equalsIgnoreCase("multipart/form-data")) {
+						// Handle multipart/form-data
+						if (!st.hasMoreTokens())
+							sendError(HTTP_BADREQUEST,
+									"BAD REQUEST: Content type is multipart/form-data but boundary missing. Usage: GET /example/file.html");
+						String boundaryExp = st.nextToken();
+						st = new StringTokenizer(boundaryExp, "=");
+						if (st.countTokens() != 2)
+							sendError(HTTP_BADREQUEST,
+									"BAD REQUEST: Content type is multipart/form-data but boundary syntax error. Usage: GET /example/file.html");
+						st.nextToken();
+						String boundary = st.nextToken();
+
+						decodeMultipartData(boundary, fbuf, in, parms, files);
+					} else {
+						// Handle application/x-www-form-urlencoded
+						String postLine = "";
+						char pbuf[] = new char[512];
+						int read = in.read(pbuf);
+						while (read >= 0 && !postLine.endsWith("\r\n")) {
+							postLine += String.valueOf(pbuf, 0, read);
+							read = in.read(pbuf);
+						}
+						postLine = postLine.trim();
+						decodeParms(postLine, parms);
+					}
+				}
+
+				if (method.equalsIgnoreCase("PUT"))
+					files.put("content", saveTmpFile(fbuf, 0, f.size()));
+
+				// Ok, now do the serve()
+				Response r = serve(uri, method, header, parms, files);
+				if (r == null)
+					sendError(HTTP_INTERNALERROR, "SERVER INTERNAL ERROR: Serve() returned a null response.");
+				else
+					sendResponse(r.status, r.mimeType, r.header, r.data);
+
+				in.close();
+				is.close();
+			}
+			catch (IOException ioe) {
+				try {
+					sendError(HTTP_INTERNALERROR, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage());
+				}
+				catch (Throwable t) {}
+			}
+			catch (InterruptedException ie) {
+				// Thrown by sendError, ignore and exit the thread.
+			}
+		}
+
+		private void dumpInput(Reader in) throws IOException {
+			in.mark(2024);
+			try {
+				String data = IO.collect(in);
+				System.out.println("READ DATA: " + data);
+			}
+			finally {
+				in.reset();
+			}
+		}
+
+		/**
+		 * Decodes the sent headers and loads the data into java Properties' key
+		 * - value pairs
+		 **/
+		private void decodeHeader(BufferedReader in, Properties pre, Properties parms, Properties header)
+				throws InterruptedException {
+			try {
+				// Read the request line
+				String inLine = in.readLine();
+				if (inLine == null)
+					return;
+				StringTokenizer st = new StringTokenizer(inLine);
+				if (!st.hasMoreTokens())
+					sendError(HTTP_BADREQUEST, "BAD REQUEST: Syntax error. Usage: GET /example/file.html");
+
+				String method = st.nextToken();
+				pre.put("method", method);
+
+				if (!st.hasMoreTokens())
+					sendError(HTTP_BADREQUEST, "BAD REQUEST: Missing URI. Usage: GET /example/file.html");
+
+				String uri = st.nextToken();
+
+				// Decode parameters from the URI
+				int qmi = uri.indexOf('?');
+				if (qmi >= 0) {
+					decodeParms(uri.substring(qmi + 1), parms);
+					uri = decodePercent(uri.substring(0, qmi));
+				} else
+					uri = decodePercent(uri);
+
+				// If there's another token, it's protocol version,
+				// followed by HTTP headers. Ignore version but parse headers.
+				// NOTE: this now forces header names lowercase since they are
+				// case insensitive and vary by client.
+				if (st.hasMoreTokens()) {
+					String line = in.readLine();
+					while (line != null && line.trim().length() > 0) {
+						int p = line.indexOf(':');
+						if (p >= 0)
+							header.put(line.substring(0, p).trim().toLowerCase(), line.substring(p + 1).trim());
+						line = in.readLine();
+					}
+				}
+
+				pre.put("uri", uri);
+			}
+			catch (IOException ioe) {
+				sendError(HTTP_INTERNALERROR, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage());
+			}
+		}
+
+		/**
+		 * Decodes the Multipart Body data and put it into java Properties' key
+		 * - value pairs.
+		 **/
+		private void decodeMultipartData(String boundary, byte[] fbuf, BufferedReader in, Properties parms,
+				Properties files) throws InterruptedException {
+			try {
+				int[] bpositions = getBoundaryPositions(fbuf, boundary.getBytes());
+				int boundarycount = 1;
+				String mpline = in.readLine();
+				while (mpline != null) {
+					if (mpline.indexOf(boundary) == -1)
+						sendError(
+								HTTP_BADREQUEST,
+								"BAD REQUEST: Content type is multipart/form-data but next chunk does not start with boundary. Usage: GET /example/file.html");
+					boundarycount++;
+					Properties item = new Properties();
+					mpline = in.readLine();
+					while (mpline != null && mpline.trim().length() > 0) {
+						int p = mpline.indexOf(':');
+						if (p != -1)
+							item.put(mpline.substring(0, p).trim().toLowerCase(), mpline.substring(p + 1).trim());
+						mpline = in.readLine();
+					}
+					if (mpline != null) {
+						String contentDisposition = item.getProperty("content-disposition");
+						if (contentDisposition == null) {
+							sendError(HTTP_BADREQUEST,
+									"BAD REQUEST: Content type is multipart/form-data but no content-disposition info found. Usage: GET /example/file.html");
+						}
+						StringTokenizer st = new StringTokenizer(contentDisposition, "; ");
+						Properties disposition = new Properties();
+						while (st.hasMoreTokens()) {
+							String token = st.nextToken();
+							int p = token.indexOf('=');
+							if (p != -1)
+								disposition.put(token.substring(0, p).trim().toLowerCase(), token.substring(p + 1)
+										.trim());
+						}
+						String pname = disposition.getProperty("name");
+						pname = pname.substring(1, pname.length() - 1);
+
+						String value = "";
+						if (item.getProperty("content-type") == null) {
+							while (mpline != null && mpline.indexOf(boundary) == -1) {
+								mpline = in.readLine();
+								if (mpline != null) {
+									int d = mpline.indexOf(boundary);
+									if (d == -1)
+										value += mpline;
+									else
+										value += mpline.substring(0, d - 2);
+								}
+							}
+						} else {
+							if (boundarycount > bpositions.length)
+								sendError(HTTP_INTERNALERROR, "Error processing request");
+							int offset = stripMultipartHeaders(fbuf, bpositions[boundarycount - 2]);
+							String path = saveTmpFile(fbuf, offset, bpositions[boundarycount - 1] - offset - 4);
+							files.put(pname, path);
+							value = disposition.getProperty("filename");
+							value = value.substring(1, value.length() - 1);
+							do {
+								mpline = in.readLine();
+							} while (mpline != null && mpline.indexOf(boundary) == -1);
+						}
+						parms.put(pname, value);
+					}
+				}
+			}
+			catch (IOException ioe) {
+				sendError(HTTP_INTERNALERROR, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage());
+			}
+		}
+
+		/**
+		 * Find the byte positions where multipart boundaries start.
+		 **/
+		public int[] getBoundaryPositions(byte[] b, byte[] boundary) {
+			int matchcount = 0;
+			int matchbyte = -1;
+			Vector<Object> matchbytes = new Vector<Object>();
+			for (int i = 0; i < b.length; i++) {
+				if (b[i] == boundary[matchcount]) {
+					if (matchcount == 0)
+						matchbyte = i;
+					matchcount++;
+					if (matchcount == boundary.length) {
+						matchbytes.addElement(new Integer(matchbyte));
+						matchcount = 0;
+						matchbyte = -1;
+					}
+				} else {
+					i -= matchcount;
+					matchcount = 0;
+					matchbyte = -1;
+				}
+			}
+			int[] ret = new int[matchbytes.size()];
+			for (int i = 0; i < ret.length; i++) {
+				ret[i] = ((Integer) matchbytes.elementAt(i)).intValue();
+			}
+			return ret;
+		}
+
+		/**
+		 * Retrieves the content of a sent file and saves it to a temporary
+		 * file. The full path to the saved file is returned.
+		 **/
+		private String saveTmpFile(byte[] b, int offset, int len) {
+			String path = "";
+			if (len > 0) {
+				String tmpdir = System.getProperty("java.io.tmpdir");
+				try {
+					File temp = File.createTempFile("NanoHTTPD", "", new File(tmpdir));
+					OutputStream fstream = new FileOutputStream(temp);
+					fstream.write(b, offset, len);
+					fstream.close();
+					path = temp.getAbsolutePath();
+				}
+				catch (Exception e) { // Catch exception if any
+					System.err.println("Error: " + e.getMessage());
+				}
+			}
+			return path;
+		}
+
+		/**
+		 * It returns the offset separating multipart file headers from the
+		 * file's data.
+		 **/
+		private int stripMultipartHeaders(byte[] b, int offset) {
+			int i = 0;
+			for (i = offset; i < b.length; i++) {
+				if (b[i] == '\r' && b[++i] == '\n' && b[++i] == '\r' && b[++i] == '\n')
+					break;
+			}
+			return i + 1;
+		}
+
+		/**
+		 * Decodes the percent encoding scheme. <br/>
+		 * For example: "an+example%20string" -> "an example string"
+		 */
+		private String decodePercent(String str) throws InterruptedException {
+			try {
+				StringBuffer sb = new StringBuffer();
+				for (int i = 0; i < str.length(); i++) {
+					char c = str.charAt(i);
+					switch (c) {
+						case '+' :
+							sb.append(' ');
+							break;
+						case '%' :
+							sb.append((char) Integer.parseInt(str.substring(i + 1, i + 3), 16));
+							i += 2;
+							break;
+						default :
+							sb.append(c);
+							break;
+					}
+				}
+				return sb.toString();
+			}
+			catch (Exception e) {
+				sendError(HTTP_BADREQUEST, "BAD REQUEST: Bad percent-encoding.");
+				return null;
+			}
+		}
+
+		/**
+		 * Decodes parameters in percent-encoded URI-format ( e.g.
+		 * "name=Jack%20Daniels&pass=Single%20Malt" ) and adds them to given
+		 * Properties. NOTE: this doesn't support multiple identical keys due to
+		 * the simplicity of Properties -- if you need multiples, you might want
+		 * to replace the Properties with a Hashtable of Vectors or such.
+		 */
+		private void decodeParms(String parms, Properties p) throws InterruptedException {
+			if (parms == null)
+				return;
+
+			StringTokenizer st = new StringTokenizer(parms, "&");
+			while (st.hasMoreTokens()) {
+				String e = st.nextToken();
+				int sep = e.indexOf('=');
+				if (sep >= 0)
+					p.put(decodePercent(e.substring(0, sep)).trim(), decodePercent(e.substring(sep + 1)));
+			}
+		}
+
+		/**
+		 * Returns an error message as a HTTP response and throws
+		 * InterruptedException to stop further request processing.
+		 */
+		private void sendError(String status, String msg) throws InterruptedException {
+			sendResponse(status, MIME_PLAINTEXT, null, new ByteArrayInputStream(msg.getBytes()));
+			throw new InterruptedException();
+		}
+
+		/**
+		 * Sends given response to the socket.
+		 */
+		private void sendResponse(String status, String mime, Properties header, InputStream data) {
+			try {
+				if (status == null)
+					throw new Error("sendResponse(): Status can't be null.");
+
+				OutputStream out = mySocket.getOutputStream();
+				PrintWriter pw = new PrintWriter(out);
+				pw.print("HTTP/1.0 " + status + " \r\n");
+
+				if (mime != null)
+					pw.print("Content-Type: " + mime + "\r\n");
+
+				if (header == null || header.getProperty("Date") == null)
+					pw.print("Date: " + gmtFrmt.format(new Date()) + "\r\n");
+
+				if (header != null) {
+					Enumeration< ? > e = header.keys();
+					while (e.hasMoreElements()) {
+						String key = (String) e.nextElement();
+						String value = header.getProperty(key);
+						pw.print(key + ": " + value + "\r\n");
+					}
+				}
+
+				pw.print("\r\n");
+				pw.flush();
+
+				if (data != null) {
+					int pending = data.available(); // This is to support
+													// partial sends, see
+													// serveFile()
+					byte[] buff = new byte[theBufferSize];
+					while (pending > 0) {
+						int read = data.read(buff, 0, ((pending > theBufferSize) ? theBufferSize : pending));
+						if (read <= 0)
+							break;
+						out.write(buff, 0, read);
+						pending -= read;
+					}
+				}
+				out.flush();
+				out.close();
+				if (data != null)
+					data.close();
+			}
+			catch (IOException ioe) {
+				// Couldn't write? No can do.
+				try {
+					mySocket.close();
+				}
+				catch (Throwable t) {}
+			}
+		}
+
+		private Socket	mySocket;
+	}
+
+	/**
+	 * URL-encodes everything between "/"-characters. Encodes spaces as '%20'
+	 * instead of '+'.
+	 */
+	private static String encodeUri(String uri) {
+		String newUri = "";
+		StringTokenizer st = new StringTokenizer(uri, "/ ", true);
+		while (st.hasMoreTokens()) {
+			String tok = st.nextToken();
+			if (tok.equals("/"))
+				newUri += "/";
+			else if (tok.equals(" "))
+				newUri += "%20";
+			else {
+				try {
+					newUri += URLEncoder.encode(tok, "UTF-8");
+				}
+				catch (java.io.UnsupportedEncodingException uee) {}
+			}
+		}
+		return newUri;
+	}
+
+	private int					myTcpPort;
+	private final ServerSocket	myServerSocket;
+	private Thread				myThread;
+	private File				myRootDir;
+
+	public int getPort() {
+		return myTcpPort;
+	}
+
+	// ==================================================
+	// File server code
+	// ==================================================
+
+	/**
+	 * Serves file from homeDir and its' subdirectories (only). Uses only URI,
+	 * ignores all headers and HTTP parameters.
+	 */
+	public Response serveFile(String uri, Properties header, File homeDir, boolean allowDirectoryListing) {
+		Response res = null;
+
+		// Make sure we won't die of an exception later
+		if (!homeDir.isDirectory())
+			res = new Response(HTTP_INTERNALERROR, MIME_PLAINTEXT,
+					"INTERNAL ERRROR: serveFile(): given homeDir is not a directory.");
+
+		if (res == null) {
+			// Remove URL arguments
+			uri = uri.trim().replace(File.separatorChar, '/');
+			if (uri.indexOf('?') >= 0)
+				uri = uri.substring(0, uri.indexOf('?'));
+
+			// Prohibit getting out of current directory
+			if (uri.startsWith("..") || uri.endsWith("..") || uri.indexOf("../") >= 0)
+				res = new Response(HTTP_FORBIDDEN, MIME_PLAINTEXT, "FORBIDDEN: Won't serve ../ for security reasons.");
+		}
+
+		File f = new File(homeDir, uri);
+		if (res == null && !f.exists())
+			res = new Response(HTTP_NOTFOUND, MIME_PLAINTEXT, "Error 404, file not found.");
+
+		// List the directory, if necessary
+		if (res == null && f.isDirectory()) {
+			// Browsers get confused without '/' after the
+			// directory, send a redirect.
+			if (!uri.endsWith("/")) {
+				uri += "/";
+				res = new Response(HTTP_REDIRECT, MIME_HTML, "<html><body>Redirected: <a href=\"" + uri + "\">" + uri
+						+ "</a></body></html>");
+				res.addHeader("Location", uri);
+			}
+
+			if (res == null) {
+				// First try index.html and index.htm
+				if (new File(f, "index.html").exists())
+					f = new File(homeDir, uri + "/index.html");
+				else if (new File(f, "index.htm").exists())
+					f = new File(homeDir, uri + "/index.htm");
+				// No index file, list the directory if it is readable
+				else if (allowDirectoryListing && f.canRead()) {
+					String[] files = f.list();
+					String msg = "<html><body><h1>Directory " + uri + "</h1><br/>";
+
+					if (uri.length() > 1) {
+						String u = uri.substring(0, uri.length() - 1);
+						int slash = u.lastIndexOf('/');
+						if (slash >= 0 && slash < u.length())
+							msg += "<b><a href=\"" + uri.substring(0, slash + 1) + "\">..</a></b><br/>";
+					}
+
+					if (files != null) {
+						for (int i = 0; i < files.length; ++i) {
+							File curFile = new File(f, files[i]);
+							boolean dir = curFile.isDirectory();
+							if (dir) {
+								msg += "<b>";
+								files[i] += "/";
+							}
+
+							msg += "<a href=\"" + encodeUri(uri + files[i]) + "\">" + files[i] + "</a>";
+
+							// Show file size
+							if (curFile.isFile()) {
+								long len = curFile.length();
+								msg += "  <font size=2>(";
+								if (len < 1024)
+									msg += len + " bytes";
+								else if (len < 1024 * 1024)
+									msg += len / 1024 + "." + (len % 1024 / 10 % 100) + " KB";
+								else
+									msg += len / (1024 * 1024) + "." + len % (1024 * 1024) / 10 % 100 + " MB";
+
+								msg += ")</font>";
+							}
+							msg += "<br/>";
+							if (dir)
+								msg += "</b>";
+						}
+					}
+					msg += "</body></html>";
+					res = new Response(HTTP_OK, MIME_HTML, msg);
+				} else {
+					res = new Response(HTTP_FORBIDDEN, MIME_PLAINTEXT, "FORBIDDEN: No directory listing.");
+				}
+			}
+		}
+
+		try {
+			if (res == null) {
+				// Get MIME type from file name extension, if possible
+				String mime = null;
+				int dot = f.getCanonicalPath().lastIndexOf('.');
+				if (dot >= 0)
+					mime = (String) theMimeTypes.get(f.getCanonicalPath().substring(dot + 1).toLowerCase());
+				if (mime == null)
+					mime = MIME_DEFAULT_BINARY;
+
+				// Calculate etag
+				String etag = Integer.toHexString(Long.toString(f.length()).hashCode());
+
+				// Support (simple) skipping:
+				long startFrom = 0;
+				long endAt = -1;
+				String range = header.getProperty("range");
+				if (range != null) {
+					if (range.startsWith("bytes=")) {
+						range = range.substring("bytes=".length());
+						int minus = range.indexOf('-');
+						try {
+							if (minus > 0) {
+								startFrom = Long.parseLong(range.substring(0, minus));
+								endAt = Long.parseLong(range.substring(minus + 1));
+							}
+						}
+						catch (NumberFormatException nfe) {}
+					}
+				}
+
+				// Change return code and add Content-Range header when skipping
+				// is requested
+				long fileLen = f.length();
+				if (range != null && startFrom >= 0) {
+					if (startFrom >= fileLen) {
+						res = new Response(HTTP_RANGE_NOT_SATISFIABLE, MIME_PLAINTEXT, "");
+						res.addHeader("Content-Range", "bytes 0-0/" + fileLen);
+						res.addHeader("ETag", etag);
+					} else {
+						if (endAt < 0)
+							endAt = fileLen - 1;
+						long newLen = endAt - startFrom + 1;
+						if (newLen < 0)
+							newLen = 0;
+
+						final long dataLen = newLen;
+						FileInputStream fis = new FileInputStream(f) {
+							public int available() throws IOException {
+								return (int) dataLen;
+							}
+						};
+						fis.skip(startFrom);
+
+						res = new Response(HTTP_PARTIALCONTENT, mime, fis);
+						res.addHeader("Content-Length", "" + dataLen);
+						res.addHeader("Content-Range", "bytes " + startFrom + "-" + endAt + "/" + fileLen);
+						res.addHeader("ETag", etag);
+					}
+				} else {
+					if (etag.equals(header.getProperty("if-none-match")))
+						res = new Response(HTTP_NOTMODIFIED, mime, "");
+					else {
+						res = new Response(HTTP_OK, mime, new FileInputStream(f));
+						res.addHeader("Content-Length", "" + fileLen);
+						res.addHeader("ETag", etag);
+					}
+				}
+			}
+		}
+		catch (IOException ioe) {
+			res = new Response(HTTP_FORBIDDEN, MIME_PLAINTEXT, "FORBIDDEN: Reading file failed.");
+		}
+
+		res.addHeader("Accept-Ranges", "bytes"); // Announce that the file
+													// server accepts partial
+													// content requestes
+		return res;
+	}
+
+	/**
+	 * Hashtable mapping (String)FILENAME_EXTENSION -> (String)MIME_TYPE
+	 */
+	private static Hashtable<String,String>		theMimeTypes	= new Hashtable<String,String>();
+	static {
+		StringTokenizer st = new StringTokenizer("css		text/css " + "htm		text/html " + "html		text/html "
+				+ "xml		text/xml " + "txt		text/plain " + "asc		text/plain " + "gif		image/gif " + "jpg		image/jpeg "
+				+ "jpeg		image/jpeg " + "png		image/png " + "mp3		audio/mpeg " + "m3u		audio/mpeg-url "
+				+ "mp4		video/mp4 " + "ogv		video/ogg " + "flv		video/x-flv " + "mov		video/quicktime "
+				+ "swf		application/x-shockwave-flash " + "js			application/javascript " + "pdf		application/pdf "
+				+ "doc		application/msword " + "ogg		application/x-ogg " + "zip		application/octet-stream "
+				+ "exe		application/octet-stream " + "class		application/octet-stream ");
+		while (st.hasMoreTokens())
+			theMimeTypes.put(st.nextToken(), st.nextToken());
+	}
+
+	private static int							theBufferSize	= 16 * 1024;
+
+	// Change this if you want to log to somewhere else than stdout
+	protected static PrintStream				myOut			= System.out;
+
+	/**
+	 * GMT date formatter
+	 */
+	private static java.text.SimpleDateFormat	gmtFrmt;
+	static {
+		gmtFrmt = new java.text.SimpleDateFormat("E, d MMM yyyy HH:mm:ss 'GMT'", Locale.US);
+		gmtFrmt.setTimeZone(TimeZone.getTimeZone("GMT"));
+	}
+
+	/**
+	 * The distribution licence
+	 */
+	private static final String					LICENCE			= "Copyright (C) 2001,2005-2011 by Jarno Elonen <elonen at iki.fi>\n"
+																		+ "and Copyright (C) 2010 by Konstantinos Togias <info at ktogias.gr>\n"
+																		+ "\n"
+																		+ "Redistribution and use in source and binary forms, with or without\n"
+																		+ "modification, are permitted provided that the following conditions\n"
+																		+ "are met:\n"
+																		+ "\n"
+																		+ "Redistributions of source code must retain the above copyright notice,\n"
+																		+ "this list of conditions and the following disclaimer. Redistributions in\n"
+																		+ "binary form must reproduce the above copyright notice, this list of\n"
+																		+ "conditions and the following disclaimer in the documentation and/or other\n"
+																		+ "materials provided with the distribution. The name of the author may not\n"
+																		+ "be used to endorse or promote products derived from this software without\n"
+																		+ "specific prior written permission. \n"
+																		+ " \n"
+																		+ "THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n"
+																		+ "IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n"
+																		+ "OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n"
+																		+ "IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n"
+																		+ "INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n"
+																		+ "NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
+																		+ "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
+																		+ "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
+																		+ "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
+																		+ "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.";
+}
diff --git a/biz.aQute.repository/src/test/obr/OBRTest.java b/biz.aQute.repository/src/test/obr/OBRTest.java
new file mode 100644
index 0000000..0410e22
--- /dev/null
+++ b/biz.aQute.repository/src/test/obr/OBRTest.java
@@ -0,0 +1,215 @@
+package test.obr;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import junit.framework.*;
+import test.helpers.*;
+import test.lib.*;
+import aQute.bnd.deployer.obr.*;
+import aQute.bnd.deployer.repository.*;
+import aQute.bnd.deployer.repository.providers.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.*;
+import aQute.bnd.version.*;
+
+public class OBRTest extends TestCase {
+
+	private static final String obrSrc = "testdata/fullobr.xml";
+	private static final String obrDst = "testdata/fullobr.tmp.xml";
+	private static OBR			obr;
+	private static NanoHTTPD	httpd;
+	private static int			httpdPort;
+	private static Processor reporter;
+
+	@Override
+	protected void setUp() throws Exception {
+		httpd = new NanoHTTPD(0, new File("testdata/http"));
+		httpdPort = httpd.getPort();
+
+		Sed.file2File(obrSrc, "__httpdPort__", Integer.toString(httpdPort), obrDst);
+
+		obr = new OBR();
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("location", new File(obrDst).getAbsoluteFile().toURI().toString());
+
+		File tmpFile = File.createTempFile("cache", ".tmp");
+		tmpFile.deleteOnExit();
+		File cacheDir = new File(tmpFile.getAbsolutePath() + ".dir");
+
+		obr.setProperties(config);
+		obr.setCacheDirectory(cacheDir);
+		
+		reporter = new Processor();
+		obr.setReporter(reporter);
+
+	}
+
+	@Override
+	protected void tearDown() throws Exception {
+		httpd.stop();
+
+		File[] cachedFiles = obr.getCacheDirectory().listFiles();
+		if (cachedFiles != null) {
+			for (File file : cachedFiles) {
+				file.delete();
+			}
+		}
+		obr.getCacheDirectory().delete();
+		new File(obrDst).delete();
+	}
+
+	public static void testSetProperties() throws Exception {
+		OBR obr2 = new OBR();
+
+		Map<String,String> props = new HashMap<String,String>();
+		props.put("location", new File("testdata/fullobr.xml").toURI().toString());
+		obr2.setProperties(props);
+		obr2.setCacheDirectory(obr.getCacheDirectory());
+
+		Collection<URI> indexes = obr2.getIndexLocations();
+		assertEquals(1, indexes.size());
+		assertEquals(new File("testdata/fullobr.xml").toURI().toString(), indexes.iterator().next().toString());
+
+		assertEquals(obr.getCacheDirectory(), obr2.getCacheDirectory());
+	}
+
+	public static void testCacheDirectoryNotSpecified() {
+		OBR obr2 = new OBR();
+
+		Map<String,String> props = new HashMap<String,String>();
+		props.put("location", new File("testdata/fullobr.xml").toURI().toString());
+		obr2.setProperties(props);
+	}
+
+	public static void testGetLatest() throws Exception {
+		File[] files = obr.get("name.njbartlett.osgi.emf.minimal", "latest");
+		assertTrue(reporter.getErrors().isEmpty());
+
+		assertNotNull(files);
+		assertEquals(1, files.length);
+
+		assertEquals("name.njbartlett.osgi.emf.minimal-2.7.0.jar", files[0].getName());
+	}
+
+	public static void testGetAll() throws Exception {
+		File[] files = obr.get("name.njbartlett.osgi.emf.xmi", null);
+
+		assertNotNull(files);
+		assertEquals(2, files.length);
+
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.5.0.jar", files[0].getName());
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.7.0.jar", files[1].getName());
+	}
+
+	public static void testGetHttp() throws Exception {
+		File[] files = obr.get("org.example.dummy", "latest");
+
+		assertNotNull(files);
+		assertEquals(1, files.length);
+
+		assertNotNull(files[0]);
+		assertEquals("dummybundle.jar", files[0].getName());
+	}
+
+	public static void testGetBsnLowest() throws Exception {
+		File result = obr.get("name.njbartlett.osgi.emf.xmi", null, Strategy.LOWEST, null);
+		assertNotNull(result);
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.5.0.jar", result.getName());
+	}
+
+	public static void testGetBsnHighest() throws Exception {
+		File result = obr.get("name.njbartlett.osgi.emf.xmi", null, Strategy.HIGHEST, null);
+		assertNotNull(result);
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.7.0.jar", result.getName());
+	}
+
+	public static void testGetBsnLowestWithRange() throws Exception {
+		File result = obr.get("name.njbartlett.osgi.emf.xmi", "2.5.1", Strategy.LOWEST, null);
+		assertNotNull(result);
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.7.0.jar", result.getName());
+	}
+
+	public static void testGetBsnHighestWithRange() throws Exception {
+		File result = obr.get("name.njbartlett.osgi.emf.xmi", "[2.5,2.7)", Strategy.HIGHEST, null);
+		assertNotNull(result);
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.5.0.jar", result.getName());
+	}
+
+	/*
+	 * public void testGetPackageLowest() throws Exception { Map<String, String>
+	 * props = new HashMap<String, String>(); props.put("package",
+	 * "org.eclipse.emf.common"); File result = obr.get(null, null,
+	 * Strategy.LOWEST, props); assertNotNull(result);
+	 * assertEquals("name.njbartlett.osgi.emf.minimal-2.6.1.jar",
+	 * result.getName()); } public void testGetPackageLowestWithRange() throws
+	 * Exception { Map<String, String> props = new HashMap<String, String>();
+	 * props.put("package", "org.eclipse.emf.common"); File result =
+	 * obr.get(null, "2.6.2", Strategy.LOWEST, props); assertNotNull(result);
+	 * assertEquals("name.njbartlett.osgi.emf.minimal-2.7.0.jar",
+	 * result.getName()); } public void testGetPackageHighest() throws Exception
+	 * { Map<String, String> props = new HashMap<String, String>();
+	 * props.put("package", "org.eclipse.emf.common"); File result =
+	 * obr.get(null, null, Strategy.HIGHEST, props); assertNotNull(result);
+	 * assertEquals("name.njbartlett.osgi.emf.minimal-2.7.0.jar",
+	 * result.getName()); } public void testGetPackageHighestWithRange() throws
+	 * Exception { Map<String, String> props = new HashMap<String, String>();
+	 * props.put("package", "org.eclipse.emf.common"); File result =
+	 * obr.get(null, "[2.6,2.7)", Strategy.HIGHEST, props);
+	 * assertNotNull(result);
+	 * assertEquals("name.njbartlett.osgi.emf.minimal-2.6.1.jar",
+	 * result.getName()); }
+	 */
+
+	public static void testList() throws Exception {
+		List<String> result = obr.list("name.njbart*");
+		assertNotNull(result);
+		assertEquals(2, result.size());
+	}
+
+	public static void testVersions() throws Exception {
+		SortedSet<Version> result = obr.versions("name.njbartlett.osgi.emf.minimal");
+		assertEquals(2, result.size());
+
+		assertEquals(new Version("2.6.1.v20100914-1218"), result.first());
+		assertEquals(new Version("2.7.0.201104130744"), result.last());
+	}
+
+	public static void testName() throws MalformedURLException {
+		assertEquals(new File(obrDst).getAbsoluteFile().toURI().toString(), obr.getName());
+
+		OBR obr2 = new OBR();
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("location", "http://www.example.com/bundles/dummybundle.jar,file:/Users/neil/bundles/dummy.jar");
+		obr2.setProperties(config);
+
+		assertEquals("http://www.example.com/bundles/dummybundle.jar,file:/Users/neil/bundles/dummy.jar",
+				obr2.getName());
+	}
+	
+	public static void testProcessFilter1() {
+		String filter = "(&(name=foo)(version<1.0.0))";
+		String expected = "(&(name=foo)(!(version>=1.0.0)))";
+		assertEquals(expected, ObrUtil.processFilter(filter, null));
+	}
+
+	public static void testProcessFilter2() {
+		String filter = "(&(name=foo)(version>1.0.0))";
+		String expected = "(&(name=foo)(!(version<=1.0.0)))";
+		assertEquals(expected, ObrUtil.processFilter(filter, null));
+	}
+	
+	public static void testProcessFilter3() {
+		String filter = "(name=foo)(mandatory:<*hello)(version>=1.0.0)(foo<*bar)";
+		String expected = "(name=foo)(version>=1.0.0)";
+		assertEquals(expected, ObrUtil.processFilter(filter, null));
+	}
+
+	public static void testProcessFilter4() {
+		String filter = "(name=foo)(mandatory:<*hello)(mandatory:*>goodbye)(version>=1.0.0)(foo<*bar)";
+		String expected = "(name=foo)(version>=1.0.0)";
+		assertEquals(expected, ObrUtil.processFilter(filter, null));
+	}
+
+}
diff --git a/biz.aQute.repository/src/test/r5repository/FindProvidersTest.java b/biz.aQute.repository/src/test/r5repository/FindProvidersTest.java
new file mode 100644
index 0000000..b15d855
--- /dev/null
+++ b/biz.aQute.repository/src/test/r5repository/FindProvidersTest.java
@@ -0,0 +1,90 @@
+package test.r5repository;
+
+import java.io.*;
+import java.util.*;
+
+import junit.framework.*;
+
+import org.osgi.framework.*;
+import org.osgi.resource.*;
+
+import aQute.bnd.deployer.repository.*;
+import aQute.bnd.osgi.resource.*;
+
+public class FindProvidersTest extends TestCase {
+
+	public static void testPackageQuery() throws Exception {
+		FixedIndexedRepo repo = new FixedIndexedRepo();
+		Map<String,String> props = new HashMap<String,String>();
+		props.put("locations", new File("testdata/minir5.xml").toURI().toString());
+		repo.setProperties(props);
+		
+		Requirement req = CapReqBuilder.createPackageRequirement("org.example.a", "[1,2)").buildSyntheticRequirement();
+		Map<Requirement,Collection<Capability>> result = repo.findProviders(Collections.singleton(req));
+		
+		assertNotNull(result);
+		assertTrue(result.containsKey(req));
+		Collection<Capability> caps = result.get(req);
+		Capability[] capsArray = new Capability[1];
+		capsArray = caps.toArray(capsArray );
+		Capability identityCap = capsArray[0].getResource().getCapabilities("osgi.identity").get(0);
+		Object identityAttrValue = identityCap.getAttributes().get("osgi.identity");
+		assertEquals("dummybundle", identityAttrValue);
+	}
+	
+	public static void testTypedCapabilityAttribute() {
+		FixedIndexedRepo repo = new FixedIndexedRepo();
+		Map<String,String> props = new HashMap<String,String>();
+		props.put("locations", new File("testdata/minir5.xml").toURI().toString());
+		repo.setProperties(props);
+		
+		Requirement req = CapReqBuilder.createPackageRequirement("org.example.a", "[1,2)").buildSyntheticRequirement();
+		Map<Requirement,Collection<Capability>> result = repo.findProviders(Collections.singleton(req));
+		Capability id = result.get(req).iterator().next().getResource().getCapabilities("osgi.identity").get(0);
+		assertEquals(Version.class, id.getAttributes().get("version").getClass());
+	}
+
+	public static void testReadGZippedStream() throws Exception {
+		FixedIndexedRepo repo = new FixedIndexedRepo();
+		Map<String,String> props = new HashMap<String,String>();
+		props.put("locations", new File("testdata/big_index.xml.gz").toURI().toString());
+		repo.setProperties(props);
+		
+		Requirement req = new CapReqBuilder("osgi.identity").addDirective("filter", "(&(osgi.identity=osgi.cmpn)(version>=4.2.0)(!(version>=4.2.1)))").buildSyntheticRequirement();
+		Map<Requirement,Collection<Capability>> result = repo.findProviders(Collections.singleton(req));
+		
+		assertNotNull(result);
+		assertTrue(result.containsKey(req));
+		
+		Collection<Capability> caps = result.get(req);
+		assertEquals(1, caps.size());
+		Capability identityCap = caps.iterator().next();
+		
+		List<Capability> contentCaps = identityCap.getResource().getCapabilities("osgi.content");
+		assertNotNull(contentCaps);
+		assertEquals(1, contentCaps.size());
+		Capability contentCap = contentCaps.iterator().next();
+		assertEquals(new File("testdata/osgi.cmpn/osgi.cmpn-4.2.0.jar").getAbsoluteFile().toURI(), contentCap.getAttributes().get("url"));
+	}
+
+	public static void testMultipleMatches() throws Exception {
+		FixedIndexedRepo repo = new FixedIndexedRepo();
+		Map<String,String> props = new HashMap<String,String>();
+		props.put("locations", new File("testdata/big_index.xml").toURI().toString());
+		repo.setProperties(props);
+		
+		Requirement req = CapReqBuilder.createPackageRequirement("aQute.bnd.annotation", "[1.43,2)").buildSyntheticRequirement();
+		Map<Requirement,Collection<Capability>> result = repo.findProviders(Collections.singleton(req));
+		Collection<Capability> matchingCaps = result.get(req);
+		
+		// 16 versions of biz.aQute.bndlib plus 8 versions of biz.aQute.bnd.annotation!
+		assertEquals(24, matchingCaps.size());
+		
+		for (Capability cap : matchingCaps) {
+			Capability identityCap = cap.getResource().getCapabilities("osgi.identity").iterator().next();
+			String bsn = (String) identityCap.getAttributes().get("osgi.identity");
+			assertTrue("biz.aQute.bndlib".equals(bsn) || "biz.aQute.bnd.annotation".equals(bsn));
+		}
+	}
+
+}
diff --git a/biz.aQute.repository/src/test/repository/FailingGeneratingProvider.java b/biz.aQute.repository/src/test/repository/FailingGeneratingProvider.java
new file mode 100644
index 0000000..2816add
--- /dev/null
+++ b/biz.aQute.repository/src/test/repository/FailingGeneratingProvider.java
@@ -0,0 +1,38 @@
+package test.repository;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import org.osgi.service.log.*;
+
+import aQute.bnd.deployer.repository.api.*;
+import aQute.bnd.service.*;
+
+class FailingGeneratingProvider implements IRepositoryContentProvider {
+
+	public String getName() {
+		return "Fail";
+	}
+
+	public void parseIndex(InputStream stream, URI baseUrl, IRepositoryIndexProcessor listener, LogService log)
+			throws Exception {}
+
+	public CheckResult checkStream(String name, InputStream stream) throws IOException {
+		return new CheckResult(Decision.accept, "I accept anything but create nothing!", null);
+	}
+
+	public boolean supportsGeneration() {
+		return true;
+	}
+
+	public void generateIndex(Set<File> files, OutputStream output, String repoName, URI rootUrl, boolean pretty,
+			Registry registry, LogService log) throws Exception {
+		throw new UnsupportedOperationException("This always breaks");
+	}
+
+	public String getDefaultIndexName(boolean pretty) {
+		return "neverhappens.xml";
+	}
+
+}
diff --git a/biz.aQute.repository/src/test/repository/NonGeneratingProvider.java b/biz.aQute.repository/src/test/repository/NonGeneratingProvider.java
new file mode 100644
index 0000000..2713e2a
--- /dev/null
+++ b/biz.aQute.repository/src/test/repository/NonGeneratingProvider.java
@@ -0,0 +1,38 @@
+package test.repository;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import org.osgi.service.log.*;
+
+import aQute.bnd.deployer.repository.api.*;
+import aQute.bnd.service.*;
+
+class NonGeneratingProvider implements IRepositoryContentProvider {
+
+	public String getName() {
+		return "Nongenerating";
+	}
+
+	public void parseIndex(InputStream stream, URI baseUrl, IRepositoryIndexProcessor listener, LogService log)
+			throws Exception {}
+
+	public CheckResult checkStream(String name, InputStream stream) throws IOException {
+		return new CheckResult(Decision.accept, "I accept anything but create nothing!", null);
+	}
+
+	public boolean supportsGeneration() {
+		return false;
+	}
+
+	public void generateIndex(Set<File> files, OutputStream output, String repoName, URI rootUrl, boolean pretty,
+			Registry registry, LogService log) throws Exception {
+		throw new UnsupportedOperationException("I told you I don't support this!");
+	}
+
+	public String getDefaultIndexName(boolean pretty) {
+		return "neverhappens.xml";
+	}
+
+}
diff --git a/biz.aQute.repository/src/test/repository/TestAttributeTypeParsing.java b/biz.aQute.repository/src/test/repository/TestAttributeTypeParsing.java
new file mode 100644
index 0000000..6d2dbf2
--- /dev/null
+++ b/biz.aQute.repository/src/test/repository/TestAttributeTypeParsing.java
@@ -0,0 +1,23 @@
+package test.repository;
+
+import junit.framework.*;
+import aQute.bnd.deployer.repository.providers.*;
+
+public class TestAttributeTypeParsing extends TestCase {
+
+	public static void testScalarTypeNames() {
+		assertEquals(AttributeType.STRING, AttributeType.parseTypeName(null));
+		assertEquals(AttributeType.STRING, AttributeType.parseTypeName("String"));
+		assertEquals(AttributeType.LONG, AttributeType.parseTypeName("Long"));
+		assertEquals(AttributeType.DOUBLE, AttributeType.parseTypeName("Double"));
+		assertEquals(AttributeType.VERSION, AttributeType.parseTypeName("Version"));
+	}
+
+	public static void testListTypeNames() {
+		assertEquals(AttributeType.STRINGLIST, AttributeType.parseTypeName("List<String>"));
+		assertEquals(AttributeType.LONGLIST, AttributeType.parseTypeName("List<Long>"));
+		assertEquals(AttributeType.DOUBLELIST, AttributeType.parseTypeName("List<Double>"));
+		assertEquals(AttributeType.VERSIONLIST, AttributeType.parseTypeName("List<Version>"));
+	}
+
+}
diff --git a/biz.aQute.repository/src/test/repository/TestCompressedObrRepo.java b/biz.aQute.repository/src/test/repository/TestCompressedObrRepo.java
new file mode 100644
index 0000000..9eb60c9
--- /dev/null
+++ b/biz.aQute.repository/src/test/repository/TestCompressedObrRepo.java
@@ -0,0 +1,128 @@
+package test.repository;
+
+import java.io.*;
+import java.util.*;
+
+import junit.framework.*;
+import test.helpers.*;
+import test.lib.*;
+import aQute.bnd.deployer.repository.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.*;
+import aQute.bnd.version.*;
+
+public class TestCompressedObrRepo extends TestCase {
+
+	private static final String obrSrc = "testdata/fullobr.xml";
+	private static final String obrDst = "testdata/fullobr.xml.gz";
+	private static FixedIndexedRepo	obr;
+	private static NanoHTTPD			httpd;
+	private static int					httpdPort;
+	private static Processor			reporter;
+
+	@Override
+	protected void setUp() throws Exception {
+		httpd = new NanoHTTPD(0, new File("testdata/http"));
+		httpdPort = httpd .getPort();
+
+		Sed.file2GzFile(obrSrc, "__httpdPort__", Integer.toString(httpdPort), obrDst);
+
+		reporter = new Processor();
+		obr = new FixedIndexedRepo();
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("name", "obr");
+		config.put("locations", new File(obrDst).toURI().toString());
+		config.put("type", "OBR");
+		obr.setProperties(config);
+		obr.setReporter(reporter);
+
+		File tmpFile = File.createTempFile("cache", ".tmp");
+		tmpFile.deleteOnExit();
+		obr.setCacheDirectory(new File(tmpFile.getAbsolutePath() + ".dir"));
+	}
+
+	@Override
+	protected void tearDown() throws Exception {
+		httpd.stop();
+
+		File[] cachedFiles = obr.getCacheDirectory().listFiles();
+		if (cachedFiles != null) {
+			for (File file : cachedFiles) {
+				file.delete();
+			}
+		}
+		obr.getCacheDirectory().delete();
+		new File(obrDst).delete();
+
+		assertEquals(0, reporter.getErrors().size());
+		assertEquals(0, reporter.getWarnings().size());
+	}
+
+	public static void testGetLatest() throws Exception {
+		File[] files = obr.get("name.njbartlett.osgi.emf.minimal", "latest");
+
+		assertNotNull(files);
+		assertEquals(1, files.length);
+
+		assertEquals("name.njbartlett.osgi.emf.minimal-2.7.0.jar", files[0].getName());
+	}
+
+	public static void testGetAll() throws Exception {
+		File[] files = obr.get("name.njbartlett.osgi.emf.xmi", null);
+
+		assertNotNull(files);
+		assertEquals(2, files.length);
+
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.5.0.jar", files[0].getName());
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.7.0.jar", files[1].getName());
+	}
+
+	public static void testGetHttp() throws Exception {
+		File[] files = obr.get("org.example.dummy", "latest");
+
+		assertNotNull(files);
+		assertEquals(1, files.length);
+
+		assertNotNull(files[0]);
+		assertEquals("dummybundle.jar", files[0].getName());
+	}
+
+	public static void testGetBsnLowest() throws Exception {
+		File result = obr.get("name.njbartlett.osgi.emf.xmi", null, Strategy.LOWEST, null);
+		assertNotNull(result);
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.5.0.jar", result.getName());
+	}
+
+	public static void testGetBsnHighest() throws Exception {
+		File result = obr.get("name.njbartlett.osgi.emf.xmi", null, Strategy.HIGHEST, null);
+		assertNotNull(result);
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.7.0.jar", result.getName());
+	}
+
+	public static void testGetBsnLowestWithRange() throws Exception {
+		File result = obr.get("name.njbartlett.osgi.emf.xmi", "2.5.1", Strategy.LOWEST, null);
+		assertNotNull(result);
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.7.0.jar", result.getName());
+	}
+
+	public static void testGetBsnHighestWithRange() throws Exception {
+		File result = obr.get("name.njbartlett.osgi.emf.xmi", "[2.5,2.7)", Strategy.HIGHEST, null);
+		assertNotNull(result);
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.5.0.jar", result.getName());
+	}
+
+	public static void testList() throws Exception {
+		List<String> result = obr.list("name.njbart*");
+		assertNotNull(result);
+		assertEquals(2, result.size());
+	}
+
+	public static void testVersions() throws Exception {
+		SortedSet<Version> result = obr.versions("name.njbartlett.osgi.emf.minimal");
+		assertEquals(2, result.size());
+
+		assertEquals(new Version("2.6.1.v20100914-1218"), result.first());
+		assertEquals(new Version("2.7.0.201104130744"), result.last());
+	}
+
+}
diff --git a/biz.aQute.repository/src/test/repository/TestFixedIndexedRepo.java b/biz.aQute.repository/src/test/repository/TestFixedIndexedRepo.java
new file mode 100644
index 0000000..36921a3
--- /dev/null
+++ b/biz.aQute.repository/src/test/repository/TestFixedIndexedRepo.java
@@ -0,0 +1,152 @@
+package test.repository;
+
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.atomic.*;
+
+import junit.framework.*;
+import test.lib.*;
+import aQute.bnd.deployer.repository.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.*;
+import aQute.bnd.version.*;
+
+public class TestFixedIndexedRepo extends TestCase {
+
+	private static int countBundles(RepositoryPlugin repo) throws Exception {
+		int count = 0;
+
+		List<String> list = repo.list(null);
+		if (list != null)
+			for (String bsn : list) {
+				SortedSet<Version> versions = repo.versions(bsn);
+				if (versions != null)
+					count += versions.size();
+			}
+
+		return count;
+	}
+
+	public static void testIndex1() throws Exception {
+		Processor reporter = new Processor();
+		FixedIndexedRepo repo = new FixedIndexedRepo();
+		Map<String,String> props = new HashMap<String,String>();
+		props.put("name", "index1");
+		props.put("locations", new File("testdata/index1.xml").toURI().toString());
+		repo.setProperties(props);
+		repo.setReporter(reporter);
+
+		List<String> bsns = repo.list(null);
+		assertEquals(2, bsns.size());
+		assertEquals("org.example.c", bsns.get(0));
+		assertEquals("org.example.f", bsns.get(1));
+
+		assertEquals(0, reporter.getErrors().size());
+		assertEquals(0, reporter.getWarnings().size());
+	}
+
+	public static void testIndex2() throws Exception {
+		Processor reporter = new Processor();
+
+		FixedIndexedRepo repo = new FixedIndexedRepo();
+		Map<String,String> props = new HashMap<String,String>();
+		props.put("name", "index2");
+		props.put("locations", new File("testdata/index2.xml").toURI().toString());
+		repo.setProperties(props);
+		repo.setReporter(reporter);
+
+		assertEquals(56, countBundles(repo));
+		assertEquals(0, reporter.getErrors().size());
+		assertEquals(0, reporter.getWarnings().size());
+	}
+
+	public static void testIndex2Compressed() throws Exception {
+		Processor reporter = new Processor();
+		FixedIndexedRepo repo = new FixedIndexedRepo();
+		Map<String,String> props = new HashMap<String,String>();
+		props.put("name", "index2");
+		props.put("locations", new File("testdata/index2.xml.gz").toURI().toString());
+		repo.setProperties(props);
+		repo.setReporter(reporter);
+
+		assertEquals(56, countBundles(repo));
+		assertEquals(0, reporter.getErrors().size());
+		assertEquals(0, reporter.getWarnings().size());
+	}
+
+	public static void testObr() throws Exception {
+		Processor reporter = new Processor();
+		FixedIndexedRepo repo = new FixedIndexedRepo();
+
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("name", "obr");
+		config.put("locations", new File("testdata/fullobr.xml").toURI().toString());
+		config.put("type", "OBR");
+		repo.setProperties(config);
+		repo.setReporter(reporter);
+
+		File[] files = repo.get("name.njbartlett.osgi.emf.xmi", null);
+		assertNotNull(files);
+		assertEquals(2, files.length);
+
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.5.0.jar", files[0].getName());
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.7.0.jar", files[1].getName());
+
+		assertEquals(0, reporter.getErrors().size());
+		assertEquals(0, reporter.getWarnings().size());
+	}
+
+	public static void testAmbiguous() throws Exception {
+		Processor reporter = new Processor();
+		FixedIndexedRepo repo = new FixedIndexedRepo();
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("locations", new File("testdata/ambiguous.xml").toURI().toString());
+		repo.setProperties(config);
+		repo.setReporter(reporter);
+
+		List<String> bsns = repo.list(null);
+
+		assertEquals("Should not be any errors", 0, reporter.getErrors().size());
+		assertTrue("Should be some ambiguity warnings", reporter.getWarnings().size() > 0);
+
+		assertEquals(0, bsns.size());
+	}
+
+	public static void testExternalEntitiesNotFetched() throws Exception {
+		final AtomicInteger accessCount = new AtomicInteger(0);
+
+		FixedIndexedRepo repo;
+		Map<String,String> config;
+		Processor reporter = new Processor();
+
+		repo = new FixedIndexedRepo() {
+			// A bit of a hack, this makes sure that only OBR can be selected
+			protected synchronized void loadAllContentProviders() {
+				super.loadAllContentProviders();
+				allContentProviders.remove("R5");
+			}
+		};
+		config = new HashMap<String,String>();
+		config.put("locations", new File("testdata/xmlWithDtdRef.xml").toURI().toString());
+		repo.setProperties(config);
+		repo.setReporter(reporter);
+		repo.list(null);
+
+		repo = new FixedIndexedRepo() {
+			protected synchronized void loadAllContentProviders() {
+				super.loadAllContentProviders();
+				allContentProviders.remove("OBR");
+			}
+		};
+		config = new HashMap<String,String>();
+		config.put("locations", new File("testdata/xmlWithDtdRef.xml").toURI().toString());
+		repo.setProperties(config);
+		repo.setReporter(reporter);
+		repo.list(null);
+
+		assertEquals("Should not make any HTTP connection.", 0, accessCount.get());
+		assertEquals("Should not be any errors", 0, reporter.getErrors().size());
+		assertTrue("Should be some ambiguity warnings", reporter.getWarnings().size() > 0);
+	}
+
+}
diff --git a/biz.aQute.repository/src/test/repository/TestLocalIndexGeneration.java b/biz.aQute.repository/src/test/repository/TestLocalIndexGeneration.java
new file mode 100644
index 0000000..8b17f75
--- /dev/null
+++ b/biz.aQute.repository/src/test/repository/TestLocalIndexGeneration.java
@@ -0,0 +1,153 @@
+package test.repository;
+
+import java.io.*;
+import java.util.*;
+
+import junit.framework.*;
+import test.lib.*;
+import aQute.bnd.deployer.repository.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.*;
+import aQute.bnd.service.RepositoryPlugin.PutResult;
+import aQute.lib.io.*;
+
+public class TestLocalIndexGeneration extends TestCase {
+
+	private static Processor				reporter;
+	private static LocalIndexedRepo		repo;
+	private static File					outputDir;
+	private static HashMap<String,String>	config;
+
+	protected void setUp() throws Exception {
+		// Ensure output directory exists and is empty
+		outputDir = new File("generated/testoutput");
+		IO.delete(outputDir);
+		if (!outputDir.exists() && !outputDir.mkdirs()) {
+			throw new IOException("Could not create directory " + outputDir);
+		}
+
+		// Setup the repo
+		reporter = new Processor();
+		repo = new LocalIndexedRepo();
+		config = new HashMap<String,String>();
+		config.put("local", outputDir.getAbsolutePath());
+		config.put("type", "R5");
+		repo.setProperties(config);
+		repo.setReporter(reporter);
+	}
+
+	@Override
+	protected void tearDown() throws Exception {
+		IO.delete(outputDir);
+		assertEquals(0, reporter.getErrors().size());
+		assertEquals(0, reporter.getWarnings().size());
+	}
+
+	public static void testInitiallyEmpty() throws Exception {
+		List<String> list = repo.list(".*");
+		assertNotNull(list);
+		assertEquals(0, list.size());
+	}
+
+	public static void testDeployBundle() throws Exception {
+		PutResult r = repo.put(new BufferedInputStream(new FileInputStream("testdata/bundles/name.njbartlett.osgi.emf.minimal-2.6.1.jar")), new RepositoryPlugin.PutOptions());
+		File deployedFile = new File(r.artifact);
+
+		assertEquals(IO.getFile("generated/testoutput/name.njbartlett.osgi.emf.minimal/name.njbartlett.osgi.emf.minimal-2.6.1.jar")
+			.getAbsolutePath(), deployedFile.getAbsolutePath());
+
+		File indexFile = IO.getFile("generated/testoutput/index.xml.gz");
+		assertTrue(indexFile.exists());
+
+		AbstractIndexedRepo repo2 = createRepoForIndex(indexFile);
+		File[] files = repo2.get("name.njbartlett.osgi.emf.minimal", null);
+		assertNotNull(files);
+		assertEquals(1, files.length);
+		assertEquals(deployedFile.getAbsoluteFile(), files[0]);
+	}
+	
+	public static void testOverwrite() throws Exception {
+		config.put("overwrite", "false");
+		repo.setProperties(config);
+		
+		PutResult r = repo.put(new BufferedInputStream(new FileInputStream("testdata/bundles/name.njbartlett.osgi.emf.minimal-2.6.1.jar")), new RepositoryPlugin.PutOptions());
+		File originalFile = new File(r.artifact);
+		assertEquals(IO.getFile("generated/testoutput/name.njbartlett.osgi.emf.minimal/name.njbartlett.osgi.emf.minimal-2.6.1.jar")
+				.getAbsolutePath(), originalFile.getAbsolutePath());
+		
+		Jar newJar = new Jar(IO.getFile("testdata/bundles/name.njbartlett.osgi.emf.minimal-2.6.1.jar"));
+		Jar dummyJar = new Jar(IO.getFile("testdata/bundles/dummybundle.jar"));
+		newJar.putResource("testOverwrite/dummybundle.jar", new JarResource(dummyJar));
+		newJar.write("testdata/bundles/name.njbartlett.osgi.emf.minimal-2.6.1-testOverwrite.jar");
+		r = repo.put(new BufferedInputStream(new FileInputStream("testdata/bundles/name.njbartlett.osgi.emf.minimal-2.6.1-testOverwrite.jar")), new RepositoryPlugin.PutOptions());
+		IO.delete(new File("testdata/bundles/name.njbartlett.osgi.emf.minimal-2.6.1-testOverwrite.jar"));
+		assertNull(r.artifact);
+	}
+
+	public static void testInvalidContentProvider() throws Exception {
+		LocalIndexedRepo repo = new LocalIndexedRepo();
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("local", outputDir.getAbsolutePath());
+		config.put("type", "Rubbish");
+		repo.setProperties(config);
+		repo.setReporter(reporter);
+
+		repo.put(new BufferedInputStream(new FileInputStream("testdata/bundles/name.njbartlett.osgi.emf.minimal-2.6.1.jar")), new RepositoryPlugin.PutOptions());
+
+		assertEquals(0, reporter.getErrors().size());
+		assertTrue(reporter.getWarnings().size() > 0);
+		reporter.clear();
+	}
+
+	public static void testNonGeneratingProvider() throws Exception {
+		MockRegistry registry = new MockRegistry();
+		registry.addPlugin(new NonGeneratingProvider());
+
+		LocalIndexedRepo repo = new LocalIndexedRepo();
+		repo.setRegistry(registry);
+		repo.setReporter(reporter);
+
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("local", outputDir.getAbsolutePath());
+		config.put("type", "Nongenerating");
+		repo.setProperties(config);
+
+		repo.put(new BufferedInputStream(new FileInputStream("testdata/bundles/name.njbartlett.osgi.emf.minimal-2.6.1.jar")), new RepositoryPlugin.PutOptions());
+
+		assertEquals(0, reporter.getErrors().size());
+		assertTrue(reporter.getWarnings().size() > 0);
+		reporter.clear();
+	}
+
+	public static void testFailToGenerate() throws Exception {
+		MockRegistry registry = new MockRegistry();
+		registry.addPlugin(new FailingGeneratingProvider());
+
+		LocalIndexedRepo repo = new LocalIndexedRepo();
+		repo.setRegistry(registry);
+		repo.setReporter(reporter);
+
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("local", outputDir.getAbsolutePath());
+		config.put("type", "Fail");
+		repo.setProperties(config);
+
+		repo.put(new BufferedInputStream(new FileInputStream("testdata/bundles/name.njbartlett.osgi.emf.minimal-2.6.1.jar")), new RepositoryPlugin.PutOptions());
+
+		assertTrue(reporter.getErrors().size() > 0);
+		assertEquals(0, reporter.getWarnings().size());
+		reporter.clear();
+	}
+
+	// UTILS
+
+	private static AbstractIndexedRepo createRepoForIndex(File index) {
+		FixedIndexedRepo newRepo = new FixedIndexedRepo();
+
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("locations", index.getAbsoluteFile().toURI().toString());
+		newRepo.setProperties(config);
+
+		return newRepo;
+	}
+}
diff --git a/biz.aQute.repository/src/test/repository/TestLocalIndexedRepo.java b/biz.aQute.repository/src/test/repository/TestLocalIndexedRepo.java
new file mode 100644
index 0000000..3b0d310
--- /dev/null
+++ b/biz.aQute.repository/src/test/repository/TestLocalIndexedRepo.java
@@ -0,0 +1,67 @@
+package test.repository;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import junit.framework.*;
+import test.lib.*;
+import aQute.bnd.deployer.repository.*;
+import aQute.bnd.osgi.*;
+import aQute.lib.io.*;
+
+public class TestLocalIndexedRepo extends TestCase {
+
+	private static File		outputDir;
+	private static NanoHTTPD	httpd;
+	private static int			httpdPort;
+
+	protected void setUp() throws Exception {
+		// Ensure output directory exists and is empty
+		outputDir = new File("generated" + File.separator + "testoutput");
+		IO.deleteWithException(outputDir);
+		if (!outputDir.exists() && !outputDir.mkdirs()) {
+			throw new IOException("Could not create directory " + outputDir);
+		}
+
+		httpd = new NanoHTTPD(0, new File("testdata"));
+		httpdPort = httpd.getPort();
+	}
+
+	@Override
+	protected void tearDown() throws Exception {
+		httpd.stop();
+	}
+
+	public static void testLocalIndexLocation() throws Exception {
+		Processor reporter = new Processor();
+		LocalIndexedRepo repo = new LocalIndexedRepo();
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("local", outputDir.getAbsolutePath());
+		repo.setProperties(config);
+		repo.setReporter(reporter);
+
+		assertEquals(1, repo.getIndexLocations().size());
+		assertEquals(new File(outputDir, "index.xml.gz").toURI(), repo.getIndexLocations().get(0));
+		assertEquals(0, reporter.getErrors().size());
+		assertEquals(0, reporter.getWarnings().size());
+	}
+
+	public static void testLocalAndRemoteIndexLocations() throws Exception {
+		Processor reporter = new Processor();
+		LocalIndexedRepo repo = new LocalIndexedRepo();
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("local", outputDir.getAbsolutePath());
+		config.put("locations", "http://localhost:" + httpdPort + "/index1.xml,http://localhost:" + httpdPort + "/index2.xml");
+		repo.setProperties(config);
+		repo.setReporter(reporter);
+
+		assertEquals(3, repo.getIndexLocations().size());
+		assertEquals(new File(outputDir, "index.xml.gz").toURI(), repo.getIndexLocations().get(0));
+		assertEquals(new URI("http://localhost:" + httpdPort + "/index1.xml"), repo.getIndexLocations().get(1));
+		assertEquals(new URI("http://localhost:" + httpdPort + "/index2.xml"), repo.getIndexLocations().get(2));
+
+		assertEquals(0, reporter.getErrors().size());
+		assertEquals(0, reporter.getWarnings().size());
+	}
+}
diff --git a/biz.aQute.repository/src/test/repository/TestLocalObrGeneration.java b/biz.aQute.repository/src/test/repository/TestLocalObrGeneration.java
new file mode 100644
index 0000000..6354e75
--- /dev/null
+++ b/biz.aQute.repository/src/test/repository/TestLocalObrGeneration.java
@@ -0,0 +1,81 @@
+package test.repository;
+
+import java.io.*;
+import java.util.*;
+
+import junit.framework.*;
+import aQute.bnd.deployer.repository.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.*;
+import aQute.bnd.service.RepositoryPlugin.PutResult;
+import aQute.lib.io.*;
+
+public class TestLocalObrGeneration extends TestCase {
+
+	private static LocalIndexedRepo	repo;
+	private static File				outputDir;
+	private static Processor			reporter;
+
+	protected void setUp() throws Exception {
+		// Ensure output directory exists and is empty
+		outputDir = new File("generated/testoutput");
+		IO.delete(outputDir);
+		if (!outputDir.exists() && !outputDir.mkdirs()) {
+			throw new IOException("Could not create directory " + outputDir);
+		}
+
+		// Setup the repo
+		reporter = new Processor();
+		repo = new LocalIndexedRepo();
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("local", outputDir.getAbsolutePath());
+		config.put("type", "OBR");
+		repo.setProperties(config);
+		repo.setReporter(reporter);
+	}
+
+	@Override
+	protected void tearDown() throws Exception {
+		IO.deleteWithException(outputDir);
+
+		assertEquals(0, reporter.getErrors().size());
+		assertEquals(0, reporter.getWarnings().size());
+	}
+
+	public static void testInitiallyEmpty() throws Exception {
+		List<String> list = repo.list(".*");
+		assertNotNull(list);
+		assertEquals(0, list.size());
+	}
+
+	public static void testDeployBundle() throws Exception {
+		PutResult r = repo.put(new BufferedInputStream(new FileInputStream("testdata/bundles/name.njbartlett.osgi.emf.minimal-2.6.1.jar")), new RepositoryPlugin.PutOptions());
+		File deployedFile = new File(r.artifact);
+
+		assertEquals(IO.getFile("generated/testoutput/name.njbartlett.osgi.emf.minimal/name.njbartlett.osgi.emf.minimal-2.6.1.jar")
+			.getAbsolutePath(), deployedFile.getAbsolutePath());
+		
+		File indexFile = IO.getFile("generated/testoutput/repository.xml");
+		assertTrue(indexFile.exists());
+		assertTrue(IO.collect(indexFile).length() > 0);
+
+		AbstractIndexedRepo repo2 = createRepoForIndex(indexFile);
+		File[] files = repo2.get("name.njbartlett.osgi.emf.minimal", null);
+		assertNotNull(files);
+		assertEquals(1, files.length);
+		assertEquals(deployedFile.getAbsoluteFile(), files[0]);
+	}
+
+	// UTILS
+
+	private static AbstractIndexedRepo createRepoForIndex(File index) {
+		FixedIndexedRepo newRepo = new FixedIndexedRepo();
+
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("locations", index.getAbsoluteFile().toURI().toString());
+		config.put("type", "OBR");
+		newRepo.setProperties(config);
+
+		return newRepo;
+	}
+}
diff --git a/biz.aQute.repository/src/test/repository/TestMultipleLocalIndexGeneration.java b/biz.aQute.repository/src/test/repository/TestMultipleLocalIndexGeneration.java
new file mode 100644
index 0000000..1651994
--- /dev/null
+++ b/biz.aQute.repository/src/test/repository/TestMultipleLocalIndexGeneration.java
@@ -0,0 +1,124 @@
+package test.repository;
+
+import java.io.*;
+import java.util.*;
+
+import junit.framework.*;
+
+import org.osgi.impl.bundle.bindex.*;
+
+import test.lib.*;
+import aQute.bnd.deployer.repository.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.*;
+import aQute.bnd.service.RepositoryPlugin.PutResult;
+import aQute.lib.io.*;
+
+public class TestMultipleLocalIndexGeneration extends TestCase {
+
+	private static Processor			reporter;
+	private static LocalIndexedRepo	repo;
+	private static File				outputDir;
+	private static MockRegistry		registry;
+
+	protected void setUp() throws Exception {
+		// Ensure output directory exists and is empty
+		outputDir = new File("generated/testoutput");
+		IO.deleteWithException(outputDir);
+		if (!outputDir.exists() && !outputDir.mkdirs()) {
+			throw new IOException("Could not create directory " + outputDir);
+		}
+
+		// Setup the repo
+		reporter = new Processor();
+		repo = new LocalIndexedRepo();
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("local", outputDir.getAbsolutePath());
+		config.put("type", "OBR|R5");
+		repo.setProperties(config);
+
+		// Add the BundleIndexer plugin
+		registry = new MockRegistry();
+		BundleIndexerImpl obrIndexer = new BundleIndexerImpl();
+		registry.addPlugin(obrIndexer);
+		repo.setRegistry(registry);
+
+		repo.setReporter(reporter);
+	}
+
+	@Override
+	protected void tearDown() throws Exception {
+		IO.deleteWithException(outputDir);
+
+		assertEquals(0, reporter.getErrors().size());
+		assertEquals(0, reporter.getWarnings().size());
+	}
+
+	public static void testInitiallyEmpty() throws Exception {
+		List<String> list = repo.list(".*");
+		assertNotNull(list);
+		assertEquals(0, list.size());
+	}
+
+	public static void testDeployBundle() throws Exception {
+		PutResult r = repo.put(new BufferedInputStream(new FileInputStream("testdata/bundles/name.njbartlett.osgi.emf.minimal-2.6.1.jar")), new RepositoryPlugin.PutOptions());
+		File deployedFile = new File(r.artifact);
+
+		assertEquals(
+				new File(
+						"generated/testoutput/name.njbartlett.osgi.emf.minimal/name.njbartlett.osgi.emf.minimal-2.6.1.jar")
+						.getAbsolutePath(), deployedFile.getAbsolutePath());
+
+		File r5IndexFile = new File("generated/testoutput/index.xml.gz");
+		assertTrue(r5IndexFile.exists());
+
+		File obrIndexFile = new File("generated/testoutput/repository.xml");
+		assertTrue(obrIndexFile.exists());
+
+		AbstractIndexedRepo checkRepo;
+		File[] files;
+
+		checkRepo = createRepoForIndex(r5IndexFile);
+		files = checkRepo.get("name.njbartlett.osgi.emf.minimal", null);
+		assertNotNull(files);
+		assertEquals(1, files.length);
+		assertEquals(deployedFile.getAbsoluteFile(), files[0]);
+
+		checkRepo = createRepoForIndex(obrIndexFile);
+		files = checkRepo.get("name.njbartlett.osgi.emf.minimal", null);
+		assertNotNull(files);
+		assertEquals(1, files.length);
+		assertEquals(deployedFile.getAbsoluteFile(), files[0]);
+	}
+
+	public static void testReadMixedRepoTypes() throws Exception {
+		FixedIndexedRepo repo = new FixedIndexedRepo();
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("locations",
+				new File("testdata/fullobr.xml").toURI() + "," + new File("testdata/minir5.xml").toURI());
+		repo.setProperties(config);
+
+		File[] files;
+
+		files = repo.get("name.njbartlett.osgi.emf.minimal", "[2.6,2.7)");
+		assertEquals(1, files.length);
+		assertEquals(new File("testdata/bundles/name.njbartlett.osgi.emf.minimal-2.6.1.jar").getAbsoluteFile(),
+				files[0]);
+
+		files = repo.get("dummybundle", null);
+		assertEquals(1, files.length);
+		assertEquals(new File("testdata/bundles/dummybundle.jar").getAbsoluteFile(), files[0]);
+	}
+
+	// UTILS
+
+	private static AbstractIndexedRepo createRepoForIndex(File index) {
+		FixedIndexedRepo newRepo = new FixedIndexedRepo();
+
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("locations", index.getAbsoluteFile().toURI().toString());
+		newRepo.setProperties(config);
+
+		return newRepo;
+	}
+}
diff --git a/biz.aQute.repository/src/test/repository/TestObrCapReqParsing.java b/biz.aQute.repository/src/test/repository/TestObrCapReqParsing.java
new file mode 100644
index 0000000..c796817
--- /dev/null
+++ b/biz.aQute.repository/src/test/repository/TestObrCapReqParsing.java
@@ -0,0 +1,113 @@
+package test.repository;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import junit.framework.*;
+
+import org.osgi.framework.*;
+import org.osgi.impl.bundle.bindex.*;
+import org.osgi.resource.*;
+
+import aQute.bnd.deployer.repository.*;
+import aQute.bnd.deployer.repository.api.*;
+import aQute.bnd.deployer.repository.providers.*;
+
+public class TestObrCapReqParsing extends TestCase {
+
+	private static List<Resource> parseIndex(InputStream stream, URI baseUri) throws Exception {
+		ObrContentProvider parser = new ObrContentProvider(new BundleIndexerImpl());
+		final List<Resource> resources = new LinkedList<Resource>();
+		IRepositoryIndexProcessor processor = new IRepositoryIndexProcessor() {
+			public void processResource(Resource resource) {
+				resources.add(resource);
+			}
+
+			public void processReferral(URI parentUri, Referral referral, int maxDepth, int currentDepth) {}
+		};
+		parser.parseIndex(stream, baseUri, processor, new NullLogService());
+		return resources;
+	}
+
+	public static void testObrContentCaps() throws Exception {
+		FileInputStream stream = new FileInputStream("testdata/fullobr.xml");
+		URI baseUri = new File("testdata").toURI();
+		List<Resource> resources = parseIndex(stream, baseUri);
+
+		assertEquals(7, resources.size());
+		
+		Resource resource = resources.get(0);
+		
+		// Check identity
+		List<Capability> idCaps = resource.getCapabilities("osgi.identity");
+		assertEquals(1, idCaps.size());
+		assertEquals("name.njbartlett.osgi.emf.minimal", idCaps.get(0).getAttributes().get("osgi.identity"));
+		
+		// Check content
+		List<Capability> contentCaps = resource.getCapabilities("osgi.content");
+		assertEquals(1, contentCaps.size());
+		assertEquals(new File("testdata/bundles/name.njbartlett.osgi.emf.minimal-2.7.0.jar").getAbsoluteFile().toURI(), contentCaps.get(0).getAttributes().get("url"));
+		
+		// Check bundle
+		List<Capability> bundleCaps = resource.getCapabilities("osgi.wiring.bundle");
+		assertEquals(1, bundleCaps.size());
+		assertEquals("name.njbartlett.osgi.emf.minimal", bundleCaps.get(0).getAttributes().get("osgi.wiring.bundle"));
+		assertEquals(new Version("2.7.0.201104130744"), bundleCaps.get(0).getAttributes().get("bundle-version"));
+		
+		// Check packages
+		List<Capability> pkgCaps = resource.getCapabilities("osgi.wiring.package");
+		assertNotNull(pkgCaps);
+		assertEquals(14, pkgCaps.size());
+		assertEquals("org.eclipse.emf.common", pkgCaps.get(0).getAttributes().get("osgi.wiring.package"));
+		assertEquals(new Version("2.7.0.201104130744"), pkgCaps.get(0).getAttributes().get("version"));
+		assertEquals("org.eclipse.core.runtime,org.eclipse.emf.common.util,org.osgi.framework", pkgCaps.get(0).getDirectives().get("uses"));
+		
+		
+		// Check service capabilities of felix.shell bundle
+		List<Capability> svcCaps = resources.get(4).getCapabilities("osgi.service");
+		assertNotNull(svcCaps);
+		assertEquals(2, svcCaps.size());
+		assertEquals("org.apache.felix.shell.ShellService", svcCaps.get(0).getAttributes().get("osgi.service"));
+		assertEquals("org.ungoverned.osgi.service.shell.ShellService", svcCaps.get(1).getAttributes().get("osgi.service"));
+	}
+	
+	public static void testObrContentReqs() throws Exception {
+		FileInputStream stream = new FileInputStream("testdata/fullobr.xml");
+		URI baseUri = new File("testdata").toURI();
+		List<Resource> resources = parseIndex(stream, baseUri);
+		assertEquals(7, resources.size());
+
+		// Check package imports of emf.minimal 2.7.0
+		List<Requirement> pkgReqs = resources.get(0).getRequirements("osgi.wiring.package");
+		assertNotNull(pkgReqs);
+		assertEquals(20, pkgReqs.size());
+		
+		// Check mandatory/optional and filters
+		assertNull(pkgReqs.get(0).getDirectives().get("resolution"));
+		assertEquals("optional", pkgReqs.get(5).getDirectives().get("resolution"));
+		assertEquals("(&(osgi.wiring.package=javax.crypto)(version>=0.0.0))", pkgReqs.get(0).getDirectives().get("filter"));
+		
+		// Check service requires of felix.shell
+		List<Requirement> svcReqs = resources.get(4).getRequirements("osgi.service");
+		assertNotNull(svcReqs);
+		assertEquals(2, svcReqs.size());
+		
+		assertEquals("(osgi.service=org.osgi.service.startlevel.StartLevel)", svcReqs.get(0).getDirectives().get("filter"));
+		assertEquals("(osgi.service=org.osgi.service.packageadmin.PackageAdmin)", svcReqs.get(1).getDirectives().get("filter"));
+	}
+	
+	public static void testObrEEReq() throws Exception {
+		FileInputStream stream = new FileInputStream("testdata/bree-obr.xml");
+		URI baseUri = new File("testdata").toURI();
+		List<Resource> resources = parseIndex(stream, baseUri);
+		assertEquals(1, resources.size());
+
+		List<Requirement> eeReqs = resources.get(0).getRequirements("osgi.ee");
+		assertNotNull(eeReqs);
+		assertEquals(1, eeReqs.size());
+		
+		assertEquals("(|(osgi.ee=J2SE-1.4)(osgi.ee=OSGi/Minimum-1.1))", eeReqs.get(0).getDirectives().get("filter"));
+	}
+
+}
diff --git a/biz.aQute.repository/src/test/repository/TestObrRecognition.java b/biz.aQute.repository/src/test/repository/TestObrRecognition.java
new file mode 100644
index 0000000..9a80459
--- /dev/null
+++ b/biz.aQute.repository/src/test/repository/TestObrRecognition.java
@@ -0,0 +1,125 @@
+package test.repository;
+
+import static aQute.bnd.deployer.repository.api.Decision.*;
+
+import java.io.*;
+
+import javax.xml.stream.*;
+
+import junit.framework.*;
+
+import org.osgi.impl.bundle.bindex.*;
+import org.osgi.service.bindex.*;
+
+import aQute.bnd.deployer.repository.api.*;
+import aQute.bnd.deployer.repository.providers.*;
+
+public class TestObrRecognition extends TestCase {
+
+	private static BundleIndexer indexer = new BundleIndexerImpl();
+
+	public static void testRejectNamespace() throws Exception {
+		String testdata = "<?xml version='1.0' encoding='utf-8'?>"
+				+ "<repository increment='0' name='index1' xmlns='http://www.osgi.org/xmlns/repository/v1.0.0'>"
+				+ "<resource>";
+		ByteArrayInputStream stream = new ByteArrayInputStream(testdata.getBytes());
+		assertEquals(reject, new ObrContentProvider(indexer).checkStream("xxx", stream).getDecision());
+	}
+
+	public static void testAcceptNamespace() throws Exception {
+		String testdata = "<?xml version='1.0'?>" + "<repository xmlns='http://www.osgi.org/xmlns/obr/v1.0.0'>";
+		ByteArrayInputStream stream = new ByteArrayInputStream(testdata.getBytes());
+		assertEquals(accept, new ObrContentProvider(indexer).checkStream("xxx", stream).getDecision());
+	}
+
+	public static void testRejectRootElementName() throws Exception {
+		String testdata = "<?xml version='1.0' encoding='utf-8'?>" + "<repo name='index1'/>";
+		ByteArrayInputStream stream = new ByteArrayInputStream(testdata.getBytes());
+		assertEquals(reject, new ObrContentProvider(indexer).checkStream("xxx", stream).getDecision());
+	}
+
+	public static void testUndecidable() throws Exception {
+		String testdata = "<?xml version='1.0' encoding='utf-8'?>" + "<repository name='index1'/>";
+		ByteArrayInputStream stream = new ByteArrayInputStream(testdata.getBytes());
+		assertEquals(undecided, new ObrContentProvider(indexer).checkStream("xxx", stream).getDecision());
+	}
+
+	public static void testUnparseable() throws Exception {
+		String testdata = "<?xml version='1.0' encoding='utf-8'?>" + "<repository name='index1'>";
+		ByteArrayInputStream stream = new ByteArrayInputStream(testdata.getBytes());
+		CheckResult result = new ObrContentProvider(indexer).checkStream("xxx", stream);
+		assertEquals(reject, result.getDecision());
+		assertTrue(result.getException() != null && result.getException() instanceof XMLStreamException);
+	}
+
+	public static void testAcceptStylesheet() throws Exception {
+		String testdata = "<?xml version='1.0' encoding='utf-8'?>"
+				+ "<?xml-stylesheet type='text/xsl' href='http://www2.osgi.org/www/obr2html.xsl'?>" + "<repository...";
+		ByteArrayInputStream stream = new ByteArrayInputStream(testdata.getBytes());
+		CheckResult result = new ObrContentProvider(indexer).checkStream("xxx", stream);
+		assertEquals(accept, result.getDecision());
+	}
+
+	public static void testRejectOnRepositoryChildElementName() throws Exception {
+		String testdata;
+		ByteArrayInputStream stream;
+		CheckResult result;
+
+		// Definitely wrong
+		testdata = "<repository><XXX/><repo...";
+		stream = new ByteArrayInputStream(testdata.getBytes());
+		result = new ObrContentProvider(indexer).checkStream("xxx", stream);
+		assertEquals(reject, result.getDecision());
+		assertNull(result.getException());
+
+		// Okay but not enough to decide for sure
+		testdata = "<repository><resource/></repository>";
+		stream = new ByteArrayInputStream(testdata.getBytes());
+		result = new ObrContentProvider(indexer).checkStream("xxx", stream);
+		assertEquals(undecided, result.getDecision());
+
+		// Okay but not enough to decide for sure
+		testdata = "<repository><referral/></repository>";
+		stream = new ByteArrayInputStream(testdata.getBytes());
+		result = new ObrContentProvider(indexer).checkStream("xxx", stream);
+		assertEquals(undecided, result.getDecision());
+	}
+
+	public static void testRejectOnCapabilityChildElementName() throws Exception {
+		String testdata;
+		ByteArrayInputStream stream;
+		CheckResult result;
+
+		// Definitely wrong
+		testdata = "<repository><resource><capability><XXX/></capability></resource><repo...";
+		stream = new ByteArrayInputStream(testdata.getBytes());
+		result = new ObrContentProvider(indexer).checkStream("xxx", stream);
+		assertEquals(reject, result.getDecision());
+		assertNull(result.getException());
+
+		// Definitely right
+		testdata = "<repository><resource><capability><p/></capability></resource><repo...";
+		stream = new ByteArrayInputStream(testdata.getBytes());
+		result = new ObrContentProvider(indexer).checkStream("xxx", stream);
+		assertEquals(accept, result.getDecision());
+
+		// Arbitrary elements under resource are allowed
+		testdata = "<repository><resource><XXX/><YYY/><capability><p/></capability><ZZZ/></resource><repo...";
+		stream = new ByteArrayInputStream(testdata.getBytes());
+		result = new ObrContentProvider(indexer).checkStream("xxx", stream);
+		assertEquals(accept, result.getDecision());
+	}
+
+	public static void testAcceptExtensionElementOtherNamespace() throws Exception {
+		String testdata;
+		ByteArrayInputStream stream;
+		CheckResult result;
+
+		// Arbitrary elements under resource are allowed
+		testdata = "<?xml version='1.0'?>"
+				+ "<repository><resource><foo:XXX xmlns:foo='http://org.example/ns'/><YYY/><capability><p/></capability><ZZZ/></resource><repo...";
+		stream = new ByteArrayInputStream(testdata.getBytes());
+		result = new ObrContentProvider(indexer).checkStream("xxx", stream);
+		assertEquals(accept, result.getDecision());
+	}
+}
diff --git a/biz.aQute.repository/src/test/repository/TestObrRepo.java b/biz.aQute.repository/src/test/repository/TestObrRepo.java
new file mode 100644
index 0000000..4f1ef9c
--- /dev/null
+++ b/biz.aQute.repository/src/test/repository/TestObrRepo.java
@@ -0,0 +1,149 @@
+package test.repository;
+
+import java.io.*;
+import java.util.*;
+
+import junit.framework.*;
+import test.helpers.*;
+import test.lib.*;
+import aQute.bnd.deployer.repository.*;
+import aQute.bnd.osgi.*;
+import aQute.bnd.service.*;
+import aQute.bnd.version.*;
+
+public class TestObrRepo extends TestCase {
+
+	private static final String obrSrc = "testdata/fullobr.xml";
+	private static final String obrDst = "testdata/fullobr.tmp.xml";
+	private static FixedIndexedRepo	obr;
+	private static NanoHTTPD			httpd;
+	private static int					httpdPort;
+	private static Processor			reporter;
+
+	@Override
+	protected void setUp() throws Exception {
+		httpd = new NanoHTTPD(0, new File("testdata/http"));
+		httpdPort = httpd.getPort();
+
+		Sed.file2File(obrSrc, "__httpdPort__", Integer.toString(httpdPort), obrDst);
+
+		reporter = new Processor();
+		obr = new FixedIndexedRepo();
+		Map<String,String> config = new HashMap<String,String>();
+		config.put("name", "obr");
+		config.put("locations", new File(obrDst).toURI().toString());
+		config.put("type", "OBR");
+		obr.setProperties(config);
+		obr.setReporter(reporter);
+
+		File tmpFile = File.createTempFile("cache", ".tmp");
+		tmpFile.deleteOnExit();
+		obr.setCacheDirectory(new File(tmpFile.getAbsolutePath() + ".dir"));
+	}
+
+	@Override
+	protected void tearDown() throws Exception {
+		httpd.stop();
+
+		File[] cachedFiles = obr.getCacheDirectory().listFiles();
+		if (cachedFiles != null) {
+			for (File file : cachedFiles) {
+				file.delete();
+			}
+		}
+		obr.getCacheDirectory().delete();
+		new File(obrDst).delete();
+
+		assertEquals(0, reporter.getErrors().size());
+		assertEquals(0, reporter.getWarnings().size());
+	}
+
+	public static void testGetLatest() throws Exception {
+		File[] files = obr.get("name.njbartlett.osgi.emf.minimal", "latest");
+
+		assertNotNull(files);
+		assertEquals(1, files.length);
+
+		assertEquals("name.njbartlett.osgi.emf.minimal-2.7.0.jar", files[0].getName());
+	}
+
+	public static void testGetAll() throws Exception {
+		File[] files = obr.get("name.njbartlett.osgi.emf.xmi", null);
+
+		assertNotNull(files);
+		assertEquals(2, files.length);
+
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.5.0.jar", files[0].getName());
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.7.0.jar", files[1].getName());
+	}
+
+	public static void testGetHttp() throws Exception {
+		File[] files = obr.get("org.example.dummy", "latest");
+
+		assertNotNull(files);
+		assertEquals(1, files.length);
+
+		assertNotNull(files[0]);
+		assertEquals("dummybundle.jar", files[0].getName());
+	}
+
+	public static void testGetBsnLowest() throws Exception {
+		File result = obr.get("name.njbartlett.osgi.emf.xmi", null, Strategy.LOWEST, null);
+		assertNotNull(result);
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.5.0.jar", result.getName());
+	}
+
+	public static void testGetBsnHighest() throws Exception {
+		File result = obr.get("name.njbartlett.osgi.emf.xmi", null, Strategy.HIGHEST, null);
+		assertNotNull(result);
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.7.0.jar", result.getName());
+	}
+
+	public static void testGetBsnExcactNoMatch() throws Exception {
+		File result = obr.get("name.njbartlett.osgi.emf.xmi", "2.4.0", Strategy.EXACT, null);
+		assertNull(result);
+	}
+
+	public static void testGetBsnExcactWithQualifier() throws Exception {
+		File result = obr.get("name.njbartlett.osgi.emf.xmi", "2.7.0.201104130744", Strategy.EXACT, null);
+		assertNotNull(result);
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.7.0.jar", result.getName());
+	}
+
+	public static void testGetBsnExcact() throws Exception {
+		File result = obr.get("name.njbartlett.osgi.emf.xmi", "2.7.0", Strategy.EXACT, null);
+		assertNotNull(result);
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.7.0.jar", result.getName());
+
+		result = obr.get("name.njbartlett.osgi.emf.xmi", "2.5.0", Strategy.EXACT, null);
+		assertNotNull(result);
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.5.0.jar", result.getName());
+	}
+
+	public static void testGetBsnLowestWithRange() throws Exception {
+		File result = obr.get("name.njbartlett.osgi.emf.xmi", "2.5.1", Strategy.LOWEST, null);
+		assertNotNull(result);
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.7.0.jar", result.getName());
+	}
+
+	public static void testGetBsnHighestWithRange() throws Exception {
+		File result = obr.get("name.njbartlett.osgi.emf.xmi", "[2.5,2.7)", Strategy.HIGHEST, null);
+		assertNotNull(result);
+		assertEquals("name.njbartlett.osgi.emf.xmi-2.5.0.jar", result.getName());
+	}
+
+	public static void testList() throws Exception {
+		List<String> result = obr.list("name.njbart*");
+		assertNotNull(result);
+		assertEquals(2, result.size());
+	}
+
+	public static void testVersions() throws Exception {
+		SortedSet<Version> result = obr.versions("name.njbartlett.osgi.emf.minimal");
+		assertEquals(2, result.size());
+
+		assertEquals(new Version("2.6.1.v20100914-1218"), result.first());
+		assertEquals(new Version("2.7.0.201104130744"), result.last());
+	}
+
+}
diff --git a/biz.aQute.repository/src/test/repository/TestR5Recognition.java b/biz.aQute.repository/src/test/repository/TestR5Recognition.java
new file mode 100644
index 0000000..a6ff0dd
--- /dev/null
+++ b/biz.aQute.repository/src/test/repository/TestR5Recognition.java
@@ -0,0 +1,98 @@
+package test.repository;
+
+import static aQute.bnd.deployer.repository.api.Decision.*;
+
+import java.io.*;
+
+import javax.xml.stream.*;
+
+import junit.framework.*;
+import aQute.bnd.deployer.repository.api.*;
+import aQute.bnd.deployer.repository.providers.*;
+
+public class TestR5Recognition extends TestCase {
+
+	public static void testRejectNamespace() throws Exception {
+		String testdata = "<?xml version='1.0' encoding='utf-8'?>"
+				+ "<repository increment='0' name='index1' xmlns='http://www2.osgi.org/www/obr2html.xsl'>"
+				+ "<resource>";
+		ByteArrayInputStream stream = new ByteArrayInputStream(testdata.getBytes());
+		assertEquals(reject, new R5RepoContentProvider().checkStream("xxx", stream).getDecision());
+	}
+
+	public static void testAcceptNamespace() throws Exception {
+		String testdata = "<?xml version='1.0'?>" + "<repository xmlns='http://www.osgi.org/xmlns/repository/v1.0.0'>";
+		ByteArrayInputStream stream = new ByteArrayInputStream(testdata.getBytes());
+		assertEquals(accept, new R5RepoContentProvider().checkStream("xxx", stream).getDecision());
+	}
+
+	public static void testRejectRootElementName() throws Exception {
+		String testdata = "<?xml version='1.0' encoding='utf-8'?>" + "<repo name='index1'/>";
+		ByteArrayInputStream stream = new ByteArrayInputStream(testdata.getBytes());
+		assertEquals(reject, new R5RepoContentProvider().checkStream("xxx", stream).getDecision());
+	}
+
+	public static void testUndecidable() throws Exception {
+		String testdata;
+		ByteArrayInputStream stream;
+		CheckResult result;
+
+		testdata = "<?xml version='1.0' encoding='utf-8'?><repository name='index1'/>";
+		stream = new ByteArrayInputStream(testdata.getBytes());
+		assertEquals(undecided, new R5RepoContentProvider().checkStream("xxx", stream).getDecision());
+
+		testdata = "<repository><resource/></repository>";
+		stream = new ByteArrayInputStream(testdata.getBytes());
+		result = new R5RepoContentProvider().checkStream("xxx", stream);
+		assertEquals(undecided, result.getDecision());
+
+		testdata = "<repository><referral/></repository>";
+		stream = new ByteArrayInputStream(testdata.getBytes());
+		result = new R5RepoContentProvider().checkStream("xxx", stream);
+		assertEquals(undecided, result.getDecision());
+	}
+
+	public static void testUnparseable() throws Exception {
+		String testdata = "<?xml version='1.0' encoding='utf-8'?>" + "<repository name='index1'>";
+		ByteArrayInputStream stream = new ByteArrayInputStream(testdata.getBytes());
+		CheckResult result = new R5RepoContentProvider().checkStream("xxx", stream);
+		assertEquals(reject, result.getDecision());
+		assertTrue(result.getException() != null && result.getException() instanceof XMLStreamException);
+	}
+
+	public static void testAcceptOnCapabilityChildElementNames() throws Exception {
+		String testdata;
+		ByteArrayInputStream stream;
+		CheckResult result;
+
+		// Must be R5
+		testdata = "<repository><resource><capability><attribute/>...";
+		stream = new ByteArrayInputStream(testdata.getBytes());
+		result = new R5RepoContentProvider().checkStream("xxx", stream);
+		assertEquals(accept, result.getDecision());
+
+		// Must be R5
+		testdata = "<repository><resource><capability><directive/>...";
+		stream = new ByteArrayInputStream(testdata.getBytes());
+		result = new R5RepoContentProvider().checkStream("xxx", stream);
+		assertEquals(accept, result.getDecision());
+
+		// Arbitrary elements under repo, resource and capability are allowed
+		testdata = "<repository><XXX/><resource><YYY/><capability><ZZZ/><attribute/>...";
+		stream = new ByteArrayInputStream(testdata.getBytes());
+		result = new R5RepoContentProvider().checkStream("xxx", stream);
+		assertEquals(accept, result.getDecision());
+	}
+
+	public static void testAcceptExtensionElementOtherNamespace() throws Exception {
+		String testdata;
+		ByteArrayInputStream stream;
+		CheckResult result;
+
+		// Arbitrary elements under resource are allowed
+		testdata = "<repository><resource><foo:XXX xmlns:foo='http://org.example/ns'/><YYY/><capability><attribute/></capability><ZZZ/></resource><repo...";
+		stream = new ByteArrayInputStream(testdata.getBytes());
+		result = new R5RepoContentProvider().checkStream("xxx", stream);
+		assertEquals(accept, result.getDecision());
+	}
+}
diff --git a/biz.aQute.repository/testdata/ambiguous.xml b/biz.aQute.repository/testdata/ambiguous.xml
new file mode 100644
index 0000000..caba5e4
--- /dev/null
+++ b/biz.aQute.repository/testdata/ambiguous.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<repository name="ambiguous"/>
\ No newline at end of file
diff --git a/biz.aQute.repository/testdata/big_index.xml b/biz.aQute.repository/testdata/big_index.xml
new file mode 100644
index 0000000..049aa59
--- /dev/null
+++ b/biz.aQute.repository/testdata/big_index.xml
@@ -0,0 +1,7186 @@
+<?xml version="1.0" encoding="utf-8"?>
+<repository xmlns="http://www.osgi.org/xmlns/repository/v1.0.0" increment="1339935779016" name="Bundle-Hub">
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="osgi.cmpn"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="4.2.1.201001051203"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="254c16624d02cd6f168fb7cae458ef0276b170e36062619cc9ac6aae5b082169"/>
+      <attribute name="url" value="osgi.cmpn/osgi.cmpn-4.2.1.jar"/>
+      <attribute name="size" type="Long" value="659655"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="osgi.cmpn"/>
+      <attribute name="bundle-version" type="Version" value="4.2.1.201001051203"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="osgi.cmpn"/>
+      <attribute name="bundle-version" type="Version" value="4.2.1.201001051203"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="info.dmtree"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="info.dmtree.spi"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="info.dmtree"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="info.dmtree.registry"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.framework,info.dmtree,info.dmtree.notification"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="info.dmtree.notification.spi"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="info.dmtree.notification"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="info.dmtree.security"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="info.dmtree"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="info.dmtree.notification"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="info.dmtree"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.application"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.application"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.blueprint.container"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+      <directive name="uses" value="org.osgi.service.blueprint.reflect,org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.blueprint.reflect"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.cm"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.component"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.deploymentadmin.spi"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+      <directive name="uses" value="org.osgi.service.deploymentadmin,org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.deploymentadmin"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.device"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.event"/>
+      <attribute name="version" type="Version" value="1.2.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.http"/>
+      <attribute name="version" type="Version" value="1.2.1"/>
+      <directive name="uses" value="javax.servlet.http,javax.servlet"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.io"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="javax.microedition.io"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.log"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.metatype"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.monitor"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.prefs"/>
+      <attribute name="version" type="Version" value="1.1.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.provisioning"/>
+      <attribute name="version" type="Version" value="1.2.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.remoteserviceadmin"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.upnp"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.useradmin"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.wireadmin"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.util.measurement"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.util.position"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+      <directive name="uses" value="org.osgi.util.measurement"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.util.cdma"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.framework,org.osgi.service.condpermadmin"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.util.gsm"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+      <directive name="uses" value="org.osgi.framework,org.osgi.service.condpermadmin"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.util.mobile"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.framework,org.osgi.service.condpermadmin"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.util.tracker"/>
+      <attribute name="version" type="Version" value="1.4.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.util.xml"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+      <directive name="uses" value="javax.xml.parsers,org.osgi.framework"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=info.dmtree)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=info.dmtree.notification)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=info.dmtree.notification.spi)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=info.dmtree.registry)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=info.dmtree.security)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=info.dmtree.spi)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.microedition.io)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.servlet)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.servlet.http)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.application)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.application)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.blueprint.container)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.blueprint.reflect)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.cm)(version>=1.3.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.component)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.condpermadmin)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.deploymentadmin)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.deploymentadmin.spi)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.device)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.event)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.http)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.io)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.log)(version>=1.3.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.metatype)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.monitor)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.prefs)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.provisioning)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.remoteserviceadmin)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.upnp)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.useradmin)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.wireadmin)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.util.cdma)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.util.gsm)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.util.measurement)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.util.mobile)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.util.position)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.util.tracker)(version>=1.4.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.util.xml)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bnd"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.50.0"/>
+      <directive name="singleton" value="true"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="ea87f85f5772f2d29a80aa19633fad612ab5652b2fcd1ffce0930217541708fb"/>
+      <attribute name="url" value="biz.aQute.bnd/biz.aQute.bnd-1.50.0.jar"/>
+      <attribute name="size" type="Long" value="1219230"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bnd"/>
+      <attribute name="bundle-version" type="Version" value="1.50.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bnd"/>
+      <attribute name="bundle-version" type="Version" value="1.50.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.url"/>
+      <attribute name="version" type="Version" value="1.50.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.apache.tools.ant)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.apache.tools.ant.types)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.service.component.annotations)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.packageadmin)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui.ide)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jface.text)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui.workbench.texteditor)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui.editors)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.debug.ui)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.core)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.ui)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.core.runtime)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.launching)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.debug.ui)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.junit)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.junit)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.eclipse.osgi.services)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.apache.ant)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.eclipse.ui.console)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="org.apache.felix.scr"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.6.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="a1491c209969495b4f5f1f7f9387194f2d5109b0e768e9788ae98cf82b335c11"/>
+      <attribute name="url" value="org.apache.felix.scr/org.apache.felix.scr-1.6.0.jar"/>
+      <attribute name="size" type="Long" value="192368"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="org.apache.felix.scr"/>
+      <attribute name="bundle-version" type="Version" value="1.6.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="org.apache.felix.scr"/>
+      <attribute name="bundle-version" type="Version" value="1.6.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.apache.felix.scr"/>
+      <attribute name="version" type="Version" value="1.6.0"/>
+      <directive name="uses" value="org.osgi.framework,org.osgi.service.component"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.component"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.apache.felix.shell)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.4.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.cm)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.component)(version>=1.1.0)(!(version>=1.2.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.log)(version>=1.3.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.metatype)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.packageadmin)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="javax.servlet"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="2.5.0.v200910301333"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="c2030131f54c997400a1b245980f609489fd4cded5283ac3fb17bfee6ca8ff49"/>
+      <attribute name="url" value="javax.servlet/javax.servlet-2.5.0.jar"/>
+      <attribute name="size" type="Long" value="118865"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="javax.servlet"/>
+      <attribute name="bundle-version" type="Version" value="2.5.0.v200910301333"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="javax.servlet"/>
+      <attribute name="bundle-version" type="Version" value="2.5.0.v200910301333"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.servlet"/>
+      <attribute name="version" type="Version" value="2.5.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.servlet.http"/>
+      <attribute name="version" type="Version" value="2.5.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.servlet.resources"/>
+      <attribute name="version" type="Version" value="2.5.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=CDC-1.1/Foundation-1.1)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.4)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="org.apache.felix.webconsole"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="3.1.8"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="9e672ffd4a771014de75c0c2015c03c08df134f1da09e401b9d42b214414e7f6"/>
+      <attribute name="url" value="org.apache.felix.webconsole/org.apache.felix.webconsole-3.1.8.jar"/>
+      <attribute name="size" type="Long" value="637792"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="org.apache.felix.webconsole"/>
+      <attribute name="bundle-version" type="Version" value="3.1.8"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="org.apache.felix.webconsole"/>
+      <attribute name="bundle-version" type="Version" value="3.1.8"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.apache.felix.webconsole"/>
+      <attribute name="version" type="Version" value="3.1.2"/>
+      <directive name="uses" value="javax.servlet,org.osgi.framework,javax.servlet.http"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.portlet)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=javax.servlet)(version>=2.4.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=javax.servlet.http)(version>=2.4.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.apache.felix.scr)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.apache.felix.shell)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.apache.felix.webconsole)(version>=3.1.2))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.framework)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.service.cm)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.service.condpermadmin)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.service.deploymentadmin)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.service.http)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.service.log)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.service.metatype)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.service.packageadmin)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.service.permissionadmin)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.service.prefs)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.service.startlevel)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.service.wireadmin)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="org.apache.felix.configadmin"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.2.8"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="fb6e6a9e02566aad593562c59343118af05c153b0be911c219eb5792eaa4f422"/>
+      <attribute name="url" value="org.apache.felix.configadmin/org.apache.felix.configadmin-1.2.8.jar"/>
+      <attribute name="size" type="Long" value="94688"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="org.apache.felix.configadmin"/>
+      <attribute name="bundle-version" type="Version" value="1.2.8"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="org.apache.felix.configadmin"/>
+      <attribute name="bundle-version" type="Version" value="1.2.8"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.apache.felix.cm"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.apache.felix.cm.file"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.apache.felix.cm,org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.cm"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.apache.felix.cm)(version>=1.0.0)(!(version>=1.1.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.apache.felix.cm.file)(version>=1.0.0)(!(version>=1.1.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.3.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.cm)(version>=1.3.0)(!(version>=1.4.0)))"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="javax.xml"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.3.4.v201005080400"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="2dfe6eb515952ed4498b10944f89b44427a38a4ab0c8be29b177ec3d59894f03"/>
+      <attribute name="url" value="javax.xml/javax.xml-1.3.4.jar"/>
+      <attribute name="size" type="Long" value="237988"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="javax.xml"/>
+      <attribute name="bundle-version" type="Version" value="1.3.4.v201005080400"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="javax.xml"/>
+      <attribute name="bundle-version" type="Version" value="1.3.4.v201005080400"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.xml"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.xml.datatype"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.xml.namespace"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.xml.parsers"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.xml.transform"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.xml.transform.dom"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.xml.transform.sax"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.xml.transform.stream"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.xml.validation"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.xml.xpath"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.apache.xmlcommons"/>
+      <attribute name="version" type="Version" value="1.3.4"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.w3c.dom"/>
+      <attribute name="version" type="Version" value="3.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.w3c.dom.bootstrap"/>
+      <attribute name="version" type="Version" value="3.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.w3c.dom.css"/>
+      <attribute name="version" type="Version" value="2.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.w3c.dom.events"/>
+      <attribute name="version" type="Version" value="2.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.w3c.dom.html"/>
+      <attribute name="version" type="Version" value="2.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.w3c.dom.ls"/>
+      <attribute name="version" type="Version" value="2.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.w3c.dom.ranges"/>
+      <attribute name="version" type="Version" value="2.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.w3c.dom.stylesheets"/>
+      <attribute name="version" type="Version" value="2.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.w3c.dom.traversal"/>
+      <attribute name="version" type="Version" value="2.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.w3c.dom.views"/>
+      <attribute name="version" type="Version" value="2.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.w3c.dom.xpath"/>
+      <attribute name="version" type="Version" value="3.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.xml.sax"/>
+      <attribute name="version" type="Version" value="2.0.2"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.xml.sax.ext"/>
+      <attribute name="version" type="Version" value="2.0.2"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.xml.sax.helpers"/>
+      <attribute name="version" type="Version" value="2.0.2"/>
+    </capability>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=system.bundle)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.2)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bnd"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.51.1"/>
+      <directive name="singleton" value="true"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="5ed78bf2430bc41f8fa38a11e34e368ba4049d5a9bf8e8f008e0d843cc55288d"/>
+      <attribute name="url" value="biz.aQute.bnd/biz.aQute.bnd-1.51.1.jar"/>
+      <attribute name="size" type="Long" value="1252727"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bnd"/>
+      <attribute name="bundle-version" type="Version" value="1.51.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bnd"/>
+      <attribute name="bundle-version" type="Version" value="1.51.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.url"/>
+      <attribute name="version" type="Version" value="1.51.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.coordinator"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=aQute.bnd.service.url)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.apache.tools.ant)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.apache.tools.ant.types)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.component.annotations)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.coordinator)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.packageadmin)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui.ide)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jface.text)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui.workbench.texteditor)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui.editors)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.debug.ui)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.core)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.ui)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.core.runtime)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.launching)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.debug.ui)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.junit)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.junit)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.eclipse.osgi.services)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.apache.ant)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.eclipse.ui.console)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bnd"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.47.0"/>
+      <directive name="singleton" value="true"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="10465832c9c51ab60a9f0a60ab4d0ea4c81b7c6c16d0e7e772922bf37c5af344"/>
+      <attribute name="url" value="biz.aQute.bnd/biz.aQute.bnd-1.47.0.jar"/>
+      <attribute name="size" type="Long" value="1194632"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bnd"/>
+      <attribute name="bundle-version" type="Version" value="1.47.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bnd"/>
+      <attribute name="bundle-version" type="Version" value="1.47.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.apache.tools.ant)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.apache.tools.ant.types)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.service.component.annotations)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.packageadmin)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui.ide)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jface.text)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui.workbench.texteditor)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui.editors)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.debug.ui)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.core)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.ui)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.core.runtime)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.launching)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.debug.ui)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.junit)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.junit)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.eclipse.osgi.services)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.apache.ant)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.eclipse.ui.console)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bndlib"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.50.4"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="01962c4a3f5e4ed68b8470c075159f3a5ee9100418b510d6f8fd85245b292ba3"/>
+      <attribute name="url" value="biz.aQute.bndlib/biz.aQute.bndlib-1.50.4.jar"/>
+      <attribute name="size" type="Long" value="926275"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.50.4"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.50.4"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.osgi"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.annotation,aQute.libg.version,aQute.bnd.service,aQute.bnd.header,aQute.bnd.annotation.metatype,aQute.libg.reporter,aQute.libg.sed,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.build"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.service,aQute.bnd.osgi,aQute.libg.reporter,aQute.libg.version,aQute.bnd.help,aQute.bnd.header,aQute.bnd.service.action,aQute.libg.sed,javax.naming"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+      <directive name="uses" value="aQute.bnd.osgi,aQute.libg.reporter,aQute.bnd.build,aQute.libg.version"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.url"/>
+      <attribute name="version" type="Version" value="1.50.4"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.build"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.help"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.bnd.osgi"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.reporter"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.version"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sed"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.header"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.libg.reporter,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.qtokens"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sax"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.xml.sax,javax.xml.transform,javax.xml.parsers,javax.xml.transform.sax"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.coordinator"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=aQute.libg.sax)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="org.apache.felix.bundlerepository"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.6.7.SNAPSHOT"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="ad562877b1724a8f6064711ffc96319ee35363c5ad21d787c24e597c456aa0ca"/>
+      <attribute name="url" value="org.apache.felix.bundlerepository/org.apache.felix.bundlerepository-1.6.7.jar"/>
+      <attribute name="size" type="Long" value="173372"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="org.apache.felix.bundlerepository"/>
+      <attribute name="bundle-version" type="Version" value="1.6.7.SNAPSHOT"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="org.apache.felix.bundlerepository"/>
+      <attribute name="bundle-version" type="Version" value="1.6.7.SNAPSHOT"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.apache.felix.bundlerepository"/>
+      <attribute name="version" type="Version" value="2.0.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.service">
+      <attribute name="osgi.wiring.service" value="org.apache.felix.bundlerepository.RepositoryAdmin"/>
+    </capability>
+    <capability namespace="osgi.wiring.service">
+      <attribute name="osgi.wiring.service" value="org.osgi.service.obr.RepositoryAdmin"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.apache.felix.bundlerepository)(version>=2.0.0)(!(version>=3.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.4.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.log)(version>=1.3.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.obr)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.url)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bnd"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+      <directive name="singleton" value="true"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="d8c21734231e5262568b94400a1c0c0ae778b5fa5fea5cbdecc2eb4ec4017427"/>
+      <attribute name="url" value="biz.aQute.bnd/biz.aQute.bnd-1.44.0.jar"/>
+      <attribute name="size" type="Long" value="1149013"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bnd"/>
+      <attribute name="bundle-version" type="Version" value="1.44.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bnd"/>
+      <attribute name="bundle-version" type="Version" value="1.44.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.apache.tools.ant)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.apache.tools.ant.types)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.packageadmin)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui.ide)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jface.text)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui.workbench.texteditor)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui.editors)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.debug.ui)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.core)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.ui)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.core.runtime)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.launching)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.debug.ui)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.junit)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.junit)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.eclipse.osgi.services)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.apache.ant)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.eclipse.ui.console)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="org.apache.felix.shell.tui"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.4.1"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="915f7d3ace47dcbcdea1e4b465404b59db1a2823f1ca8f5b263a9aa628fffaa2"/>
+      <attribute name="url" value="org.apache.felix.shell.tui/org.apache.felix.shell.tui-1.4.1.jar"/>
+      <attribute name="size" type="Long" value="12748"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="org.apache.felix.shell.tui"/>
+      <attribute name="bundle-version" type="Version" value="1.4.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="org.apache.felix.shell.tui"/>
+      <attribute name="bundle-version" type="Version" value="1.4.1"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.apache.felix.shell)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.3.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.service">
+      <directive name="filter" value="(osgi.wiring.service=org.apache.felix.shell.ShellService)"/>
+      <directive name="effective" value="active"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bnd.annotation"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="b2759b3028d7e6aa1699f542169ee1780a8252cdebc526cf30b29926ecfd9894"/>
+      <attribute name="url" value="biz.aQute.bnd.annotation/biz.aQute.bnd.annotation-1.44.0.jar"/>
+      <attribute name="size" type="Long" value="29118"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bnd.annotation"/>
+      <attribute name="bundle-version" type="Version" value="1.44.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bnd.annotation"/>
+      <attribute name="bundle-version" type="Version" value="1.44.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="osgi.cmpn"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="4.2.0.200908310645"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="b707c3d23618f6f1e83dade8c2686e0b08f488e86885e25312fb68499165aa92"/>
+      <attribute name="url" value="osgi.cmpn/osgi.cmpn-4.2.0.jar"/>
+      <attribute name="size" type="Long" value="614264"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="osgi.cmpn"/>
+      <attribute name="bundle-version" type="Version" value="4.2.0.200908310645"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="osgi.cmpn"/>
+      <attribute name="bundle-version" type="Version" value="4.2.0.200908310645"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="info.dmtree"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="info.dmtree.spi"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="info.dmtree"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="info.dmtree.registry"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.framework,info.dmtree,info.dmtree.notification"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="info.dmtree.notification.spi"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="info.dmtree.notification"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="info.dmtree.security"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="info.dmtree"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="info.dmtree.notification"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="info.dmtree"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.application"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.application"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.blueprint.container"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.service.blueprint.reflect,org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.blueprint.reflect"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.cm"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.component"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.deploymentadmin.spi"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+      <directive name="uses" value="org.osgi.service.deploymentadmin,org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.deploymentadmin"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.device"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.event"/>
+      <attribute name="version" type="Version" value="1.2.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.http"/>
+      <attribute name="version" type="Version" value="1.2.1"/>
+      <directive name="uses" value="javax.servlet.http,javax.servlet"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.io"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="javax.microedition.io"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.log"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.metatype"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.monitor"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.prefs"/>
+      <attribute name="version" type="Version" value="1.1.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.provisioning"/>
+      <attribute name="version" type="Version" value="1.2.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.upnp"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.useradmin"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.wireadmin"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.util.measurement"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.util.position"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+      <directive name="uses" value="org.osgi.util.measurement"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.util.cdma"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.framework,org.osgi.service.condpermadmin"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.util.gsm"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+      <directive name="uses" value="org.osgi.framework,org.osgi.service.condpermadmin"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.util.mobile"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.framework,org.osgi.service.condpermadmin"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.util.tracker"/>
+      <attribute name="version" type="Version" value="1.4.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.util.xml"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+      <directive name="uses" value="javax.xml.parsers,org.osgi.framework"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=info.dmtree)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=info.dmtree.notification)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=info.dmtree.notification.spi)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=info.dmtree.registry)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=info.dmtree.security)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=info.dmtree.spi)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.microedition.io)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.servlet)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.servlet.http)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.application)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.application)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.blueprint.container)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.blueprint.reflect)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.cm)(version>=1.3.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.component)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.condpermadmin)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.deploymentadmin)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.deploymentadmin.spi)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.device)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.event)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.http)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.io)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.log)(version>=1.3.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.metatype)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.monitor)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.prefs)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.provisioning)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.upnp)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.useradmin)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.wireadmin)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.util.cdma)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.util.gsm)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.util.measurement)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.util.mobile)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.util.position)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.util.tracker)(version>=1.4.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.util.xml)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bndlib"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.48.3"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="9c0bfb0eb55a4c2b3d7882401ec1a41bfd1b33b4f6d048e8aaf72da5ab80c04d"/>
+      <attribute name="url" value="biz.aQute.bndlib/biz.aQute.bndlib-1.48.3.jar"/>
+      <attribute name="size" type="Long" value="893406"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.48.3"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.48.3"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.osgi"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.annotation,aQute.libg.version,aQute.bnd.service,aQute.bnd.header,aQute.bnd.annotation.metatype,aQute.libg.reporter,aQute.libg.sed,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.build"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.service,aQute.bnd.osgi,aQute.libg.reporter,aQute.libg.version,aQute.bnd.help,aQute.bnd.header,aQute.bnd.service.action,aQute.libg.sed,javax.naming"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+      <directive name="uses" value="aQute.bnd.osgi,aQute.libg.reporter,aQute.bnd.build,aQute.libg.version"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.url"/>
+      <attribute name="version" type="Version" value="1.48.3"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.build"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.help"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.bnd.osgi"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.reporter"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.version"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sed"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.header"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.libg.reporter,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.qtokens"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sax"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.xml.sax,javax.xml.transform,javax.xml.parsers,javax.xml.transform.sax"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="com.jcraft.jsch"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="0.1.41.v201101211617"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="14b188dbb6dbe38264a67a092edb76b9a13e55e628653b375376366aa3eeb45d"/>
+      <attribute name="url" value="com.jcraft.jsch/com.jcraft.jsch-0.1.41.jar"/>
+      <attribute name="size" type="Long" value="226770"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="com.jcraft.jsch"/>
+      <attribute name="bundle-version" type="Version" value="0.1.41.v201101211617"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="com.jcraft.jsch"/>
+      <attribute name="bundle-version" type="Version" value="0.1.41.v201101211617"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="com.jcraft.jsch"/>
+      <attribute name="version" type="Version" value="0.1.41"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="com.jcraft.jsch.jce"/>
+      <attribute name="version" type="Version" value="0.1.41"/>
+      <directive name="x-internal" value="true"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="com.jcraft.jsch.jcraft"/>
+      <attribute name="version" type="Version" value="0.1.41"/>
+      <directive name="x-internal" value="true"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="com.jcraft.jsch.jgss"/>
+      <attribute name="version" type="Version" value="0.1.41"/>
+      <directive name="x-internal" value="true"/>
+    </capability>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.4)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bndlib"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.50.3"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="5216ed3f766ec5812bd48f0f9003ff99c984a546fa2717626537a80dabdc23d8"/>
+      <attribute name="url" value="biz.aQute.bndlib/biz.aQute.bndlib-1.50.3.jar"/>
+      <attribute name="size" type="Long" value="926832"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.50.3"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.50.3"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.osgi"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.annotation,aQute.libg.version,aQute.bnd.service,aQute.bnd.header,aQute.bnd.annotation.metatype,aQute.libg.reporter,aQute.libg.sed,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.build"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.service,aQute.bnd.osgi,aQute.libg.reporter,aQute.libg.version,aQute.bnd.help,aQute.bnd.header,aQute.bnd.service.action,aQute.libg.sed,javax.naming"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+      <directive name="uses" value="aQute.bnd.osgi,aQute.libg.reporter,aQute.bnd.build,aQute.libg.version"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.url"/>
+      <attribute name="version" type="Version" value="1.50.3"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.build"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.help"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.bnd.osgi"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.reporter"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.version"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sed"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.header"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.libg.reporter,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.qtokens"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sax"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.xml.sax,javax.xml.transform,javax.xml.parsers,javax.xml.transform.sax"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.coordinator"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=aQute.libg.sax)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="org.apache.felix.gogo.shell"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="0.10.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="95e85d53c1683d01d456275ac5eb20fe9e37f03e2ac5a1fd11e204aaedbb803c"/>
+      <attribute name="url" value="org.apache.felix.gogo.shell/org.apache.felix.gogo.shell-0.10.0.jar"/>
+      <attribute name="size" type="Long" value="49004"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="org.apache.felix.gogo.shell"/>
+      <attribute name="bundle-version" type="Version" value="0.10.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="org.apache.felix.gogo.shell"/>
+      <attribute name="bundle-version" type="Version" value="0.10.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <attribute name="status" value="provisional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.apache.felix.service.command)(version>=0.10.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.framework)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.service.startlevel)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.util.tracker)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bndlib"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.48.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="5c6d76bc87c1dfe32830b07f619455e386a3c4a4c9845710fa264ef339eb53c5"/>
+      <attribute name="url" value="biz.aQute.bndlib/biz.aQute.bndlib-1.48.0.jar"/>
+      <attribute name="size" type="Long" value="866019"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.48.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.48.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.osgi"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.annotation,aQute.libg.version,aQute.bnd.service,aQute.bnd.header,aQute.bnd.annotation.metatype,aQute.libg.reporter,aQute.libg.sed,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.build"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.service,aQute.bnd.osgi,aQute.libg.reporter,aQute.libg.version,aQute.bnd.header,aQute.bnd.service.action,aQute.libg.sed,javax.naming"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+      <directive name="uses" value="aQute.bnd.osgi,aQute.libg.reporter,aQute.bnd.build,aQute.libg.version"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.build"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.reporter"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.version"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sed"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.header"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.libg.reporter,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.qtokens"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sax"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.xml.sax,javax.xml.transform,javax.xml.parsers,javax.xml.transform.sax"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bnd"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.45.0"/>
+      <directive name="singleton" value="true"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="292ecca5d8fdb881f0273c1166b9c20925be063d3baf3824515983f76b73fffb"/>
+      <attribute name="url" value="biz.aQute.bnd/biz.aQute.bnd-1.45.0.jar"/>
+      <attribute name="size" type="Long" value="1163919"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bnd"/>
+      <attribute name="bundle-version" type="Version" value="1.45.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bnd"/>
+      <attribute name="bundle-version" type="Version" value="1.45.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.apache.tools.ant)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.apache.tools.ant.types)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.packageadmin)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui.ide)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jface.text)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui.workbench.texteditor)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui.editors)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.debug.ui)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.core)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.ui)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.core.runtime)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.launching)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.debug.ui)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.junit)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.junit)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.eclipse.osgi.services)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.apache.ant)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.eclipse.ui.console)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bndlib"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.51.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="a2b831780c4416bcd48e0d3330e23eafa1fc6540263f51e7420662c5fb038a98"/>
+      <attribute name="url" value="biz.aQute.bndlib/biz.aQute.bndlib-1.51.0.jar"/>
+      <attribute name="size" type="Long" value="931471"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.51.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.51.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.osgi"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.annotation,aQute.libg.version,aQute.bnd.service,aQute.bnd.header,aQute.bnd.annotation.metatype,aQute.libg.reporter,aQute.libg.sed,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.build"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.service,aQute.bnd.osgi,aQute.libg.reporter,aQute.libg.version,aQute.bnd.help,aQute.bnd.header,aQute.bnd.service.action,aQute.libg.sed,javax.naming"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+      <directive name="uses" value="aQute.bnd.osgi,aQute.libg.reporter,aQute.bnd.build,aQute.libg.version"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.url"/>
+      <attribute name="version" type="Version" value="1.51.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.build"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.help"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.bnd.osgi"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.reporter"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.version"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sed"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.header"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.libg.reporter,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.qtokens"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sax"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.xml.sax,javax.xml.transform,javax.xml.parsers,javax.xml.transform.sax"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.coordinator"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=aQute.libg.sax)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="osgi.enterprise"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="4.2.0.201003190513"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="2a7270d14f3eb80fc8814ff95ceeace0ce64f7908b5b89bf8d36fe0098c49db6"/>
+      <attribute name="url" value="osgi.enterprise/osgi.enterprise-4.2.0.jar"/>
+      <attribute name="size" type="Long" value="354544"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="osgi.enterprise"/>
+      <attribute name="bundle-version" type="Version" value="4.2.0.201003190513"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="osgi.enterprise"/>
+      <attribute name="bundle-version" type="Version" value="4.2.0.201003190513"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.jmx.service.cm"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+      <directive name="uses" value="javax.management.openmbean"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.jmx.framework"/>
+      <attribute name="version" type="Version" value="1.5.0"/>
+      <directive name="uses" value="org.osgi.jmx,javax.management.openmbean"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.jmx.service.permissionadmin"/>
+      <attribute name="version" type="Version" value="1.2.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.jmx.service.provisioning"/>
+      <attribute name="version" type="Version" value="1.2.0"/>
+      <directive name="uses" value="javax.management.openmbean"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.jmx.service.useradmin"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+      <directive name="uses" value="org.osgi.jmx,javax.management.openmbean"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.jmx"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="javax.management.openmbean"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.blueprint.reflect"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.blueprint.container"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+      <directive name="uses" value="org.osgi.service.blueprint.reflect,org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.cm"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.component"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.event"/>
+      <attribute name="version" type="Version" value="1.2.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.http"/>
+      <attribute name="version" type="Version" value="1.2.1"/>
+      <directive name="uses" value="javax.servlet.http,javax.servlet"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.provisioning"/>
+      <attribute name="version" type="Version" value="1.2.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.remoteserviceadmin"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.jdbc"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="javax.sql"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.jndi"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="javax.naming.directory,javax.naming"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.jpa"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="javax.persistence"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.log"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.metatype"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.useradmin"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.util.tracker"/>
+      <attribute name="version" type="Version" value="1.4.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.util.xml"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+      <directive name="uses" value="org.osgi.framework,javax.xml.parsers"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.management.openmbean)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.naming.directory)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.persistence)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.servlet)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.servlet.http)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.sql)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.jmx)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.jmx.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.jmx.service.cm)(version>=1.3.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.jmx.service.permissionadmin)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.jmx.service.provisioning)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.jmx.service.useradmin)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.blueprint.container)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.blueprint.reflect)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.cm)(version>=1.3.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.component)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.event)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.http)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.jdbc)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.jndi)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.jpa)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.log)(version>=1.3.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.metatype)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.provisioning)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.remoteserviceadmin)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.useradmin)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.util.tracker)(version>=1.4.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.util.xml)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bnd.annotation"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.52.3"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="d5e5ae19715457f10eab807c8be63fd39cf30fb061ca51d2e975c444437afce0"/>
+      <attribute name="url" value="biz.aQute.bnd.annotation/biz.aQute.bnd.annotation-1.52.3.jar"/>
+      <attribute name="size" type="Long" value="29505"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bnd.annotation"/>
+      <attribute name="bundle-version" type="Version" value="1.52.3"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bnd.annotation"/>
+      <attribute name="bundle-version" type="Version" value="1.52.3"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bnd.annotation"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.47.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="0bec95dcea1ef17fd9d9180bdbfd357c803c8f7a3d80cbf78cabfbc7031787d5"/>
+      <attribute name="url" value="biz.aQute.bnd.annotation/biz.aQute.bnd.annotation-1.47.0.jar"/>
+      <attribute name="size" type="Long" value="35599"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bnd.annotation"/>
+      <attribute name="bundle-version" type="Version" value="1.47.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bnd.annotation"/>
+      <attribute name="bundle-version" type="Version" value="1.47.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.test"/>
+      <attribute name="version" type="Version" value="1.47.0"/>
+      <directive name="uses" value="aQute.libg.reporter,junit.framework,javax.xml.namespace,javax.xml.xpath,javax.xml.parsers,org.w3c.dom"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=aQute.libg.reporter)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="org.apache.felix.fileinstall"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="3.1.4"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="d71a3a19d5af5ab2ff384df3d521fb15f61ae3652db1b75c9abb0a34ad8c03cf"/>
+      <attribute name="url" value="org.apache.felix.fileinstall/org.apache.felix.fileinstall-3.1.4.jar"/>
+      <attribute name="size" type="Long" value="71899"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="org.apache.felix.fileinstall"/>
+      <attribute name="bundle-version" type="Version" value="3.1.4"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="org.apache.felix.fileinstall"/>
+      <attribute name="bundle-version" type="Version" value="3.1.4"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.apache.felix.fileinstall"/>
+      <attribute name="version" type="Version" value="3.1.4"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.apache.felix.fileinstall)(version>=3.1.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.4.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.cm)(version>=1.3.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.log)(version>=1.3.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.packageadmin)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.startlevel)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.url)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.util.tracker)(version>=1.4.0)(!(version>=2.0.0)))"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="slf4j.api"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.6.2"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="0a4f0379d165984cb62a68c6c3d66fd668b9be2f0e51ae6326e4712b535c05e6"/>
+      <attribute name="url" value="slf4j.api/slf4j.api-1.6.2.jar"/>
+      <attribute name="size" type="Long" value="26249"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="slf4j.api"/>
+      <attribute name="bundle-version" type="Version" value="1.6.2"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="slf4j.api"/>
+      <attribute name="bundle-version" type="Version" value="1.6.2"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.slf4j"/>
+      <attribute name="version" type="Version" value="1.6.2"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.slf4j.spi"/>
+      <attribute name="version" type="Version" value="1.6.2"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.slf4j.helpers"/>
+      <attribute name="version" type="Version" value="1.6.2"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.slf4j.impl)(version>=1.6.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.3)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bndlib"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.45.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="d7c4c987fea94e15a52e3bb311084f180300548c5d361e45a38e04559a695bc8"/>
+      <attribute name="url" value="biz.aQute.bndlib/biz.aQute.bndlib-1.45.0.jar"/>
+      <attribute name="size" type="Long" value="849152"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.45.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.45.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.osgi"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.annotation,aQute.libg.version,aQute.bnd.service,aQute.bnd.header,aQute.bnd.annotation.metatype,aQute.libg.reporter,aQute.libg.sed,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.build"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.service,aQute.bnd.osgi,aQute.libg.reporter,aQute.bnd.header,aQute.bnd.service.action,aQute.libg.sed,javax.naming"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+      <directive name="uses" value="aQute.bnd.osgi,aQute.libg.reporter,aQute.bnd.build,aQute.libg.version"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.build"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.reporter"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.version"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sed"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.header"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.libg.reporter,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.qtokens"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sax"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.xml.sax,javax.xml.transform,javax.xml.parsers,javax.xml.transform.sax"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.component.annotations)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bnd.annotation"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.50.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="918e298558f6bbd3b5cc08f5deef814fb29a8e003b9a91c85216f64118580bb5"/>
+      <attribute name="url" value="biz.aQute.bnd.annotation/biz.aQute.bnd.annotation-1.50.0.jar"/>
+      <attribute name="size" type="Long" value="35639"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bnd.annotation"/>
+      <attribute name="bundle-version" type="Version" value="1.50.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bnd.annotation"/>
+      <attribute name="bundle-version" type="Version" value="1.50.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.test"/>
+      <attribute name="version" type="Version" value="1.50.0"/>
+      <directive name="uses" value="aQute.libg.reporter,junit.framework,javax.xml.namespace,javax.xml.xpath,javax.xml.parsers,org.w3c.dom"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=aQute.libg.reporter)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="org.apache.felix.http.jetty"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="2.2.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="200b06287951050faf436723eab9d7a5dc582fa98b99824319da8b9eebe70a0a"/>
+      <attribute name="url" value="org.apache.felix.http.jetty/org.apache.felix.http.jetty-2.2.0.jar"/>
+      <attribute name="size" type="Long" value="941716"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="org.apache.felix.http.jetty"/>
+      <attribute name="bundle-version" type="Version" value="2.2.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="org.apache.felix.http.jetty"/>
+      <attribute name="bundle-version" type="Version" value="2.2.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.apache.felix.http.api"/>
+      <attribute name="version" type="Version" value="2.0.4"/>
+      <directive name="uses" value="javax.servlet,org.osgi.service.http"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.http"/>
+      <attribute name="version" type="Version" value="1.2.0"/>
+      <directive name="uses" value="javax.servlet.http,javax.servlet"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.servlet.resources"/>
+      <attribute name="version" type="Version" value="2.5.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.servlet"/>
+      <attribute name="version" type="Version" value="2.5.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.servlet.jsp.resources"/>
+      <attribute name="version" type="Version" value="2.5.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.servlet.http"/>
+      <attribute name="version" type="Version" value="2.5.0"/>
+      <directive name="uses" value="javax.servlet"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.net.ssl)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.security.cert)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=javax.servlet)(version>=2.5.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=javax.servlet.http)(version>=2.5.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=javax.servlet.jsp.resources)(version>=2.5.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=javax.servlet.resources)(version>=2.5.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.apache.felix.http.api)(version>=2.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.3.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.http)(version>=1.2.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.log)(version>=1.3.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.util.tracker)(version>=1.3.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.slf4j)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="org.apache.felix.gogo.command"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="0.12.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="17f1f6455b82208a71a49a26780083f4791d14e701a083e577d8b9893adb2528"/>
+      <attribute name="url" value="org.apache.felix.gogo.command/org.apache.felix.gogo.command-0.12.0.jar"/>
+      <attribute name="size" type="Long" value="51746"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="org.apache.felix.gogo.command"/>
+      <attribute name="bundle-version" type="Version" value="0.12.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="org.apache.felix.gogo.command"/>
+      <attribute name="bundle-version" type="Version" value="0.12.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.log"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <attribute name="status" value="provisional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.apache.felix.service.command)(version>=0.10.0)(!(version>=1.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework.wiring)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.log)(version>=1.3.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.packageadmin)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.startlevel)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.util.tracker)(version>=1.3.0)(!(version>=2.0.0)))"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="com.springsource.org.objectweb.asm"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="3.1.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="45c483ae220faaf06c709e58e01ce89ad046c60e14c20a6398d9d0a4a40eb839"/>
+      <attribute name="url" value="com.springsource.org.objectweb.asm/com.springsource.org.objectweb.asm-3.1.0.jar"/>
+      <attribute name="size" type="Long" value="44173"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="com.springsource.org.objectweb.asm"/>
+      <attribute name="bundle-version" type="Version" value="3.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="com.springsource.org.objectweb.asm"/>
+      <attribute name="bundle-version" type="Version" value="3.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.objectweb.asm"/>
+      <attribute name="version" type="Version" value="3.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.objectweb.asm.signature"/>
+      <attribute name="version" type="Version" value="3.1.0"/>
+    </capability>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bndlib"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.48.2"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="8319dc475dc2966dca5963e0688e5092fb357a983e660777ced6b56b1e56e3f6"/>
+      <attribute name="url" value="biz.aQute.bndlib/biz.aQute.bndlib-1.48.2.jar"/>
+      <attribute name="size" type="Long" value="888120"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.48.2"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.48.2"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.osgi"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.annotation,aQute.libg.version,aQute.bnd.service,aQute.bnd.header,aQute.bnd.annotation.metatype,aQute.libg.reporter,aQute.libg.sed,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.build"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.service,aQute.bnd.osgi,aQute.libg.reporter,aQute.libg.version,aQute.bnd.header,aQute.bnd.service.action,aQute.libg.sed,javax.naming"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+      <directive name="uses" value="aQute.bnd.osgi,aQute.libg.reporter,aQute.bnd.build,aQute.libg.version"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.url"/>
+      <attribute name="version" type="Version" value="1.48.2"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.build"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.reporter"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.version"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sed"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.header"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.libg.reporter,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.qtokens"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sax"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.xml.sax,javax.xml.transform,javax.xml.parsers,javax.xml.transform.sax"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="org.mockito.mockito-all"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.8.5"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="48625a64a612635bd1ecbe2eb05b622be8830cf2a3e56ebfb12be180b4384890"/>
+      <attribute name="url" value="org.mockito.mockito-all/org.mockito.mockito-all-1.8.5.jar"/>
+      <attribute name="size" type="Long" value="1439455"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="org.mockito.mockito-all"/>
+      <attribute name="bundle-version" type="Version" value="1.8.5"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="org.mockito.mockito-all"/>
+      <attribute name="bundle-version" type="Version" value="1.8.5"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.mockito.exceptions.base"/>
+      <attribute name="version" type="Version" value="1.8.5"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.mockito.stubbing"/>
+      <attribute name="version" type="Version" value="1.8.5"/>
+      <directive name="uses" value="org.mockito.invocation"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.mockito.exceptions.verification.junit"/>
+      <attribute name="version" type="Version" value="1.8.5"/>
+      <directive name="uses" value="junit.framework,org.mockito.exceptions.verification"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.mockito.exceptions.misusing"/>
+      <attribute name="version" type="Version" value="1.8.5"/>
+      <directive name="uses" value="org.mockito.exceptions.base"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.mockito.invocation"/>
+      <attribute name="version" type="Version" value="1.8.5"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.mockito.runners"/>
+      <attribute name="version" type="Version" value="1.8.5"/>
+      <directive name="uses" value="org.junit.runner,org.junit.runner.notification,org.junit.runner.manipulation"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.mockito.verification"/>
+      <attribute name="version" type="Version" value="1.8.5"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.mockito"/>
+      <attribute name="version" type="Version" value="1.8.5"/>
+      <directive name="uses" value="org.hamcrest,org.mockito.stubbing,org.mockito.verification,org.mockito.exceptions.base,org.mockito.exceptions,org.mockito.configuration,org.mockito.invocation"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.mockito.exceptions"/>
+      <attribute name="version" type="Version" value="1.8.5"/>
+      <directive name="uses" value="org.mockito.exceptions.verification.junit,org.mockito.exceptions.base,org.mockito.exceptions.verification,org.mockito.exceptions.misusing"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.mockito.configuration"/>
+      <attribute name="version" type="Version" value="1.8.5"/>
+      <directive name="uses" value="org.mockito,org.mockito.stubbing"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.mockito.stubbing.answers"/>
+      <attribute name="version" type="Version" value="1.8.5"/>
+      <directive name="uses" value="org.mockito.exceptions.base,org.mockito.stubbing,org.mockito.invocation"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.mockito.exceptions.verification"/>
+      <attribute name="version" type="Version" value="1.8.5"/>
+      <directive name="uses" value="org.mockito.exceptions.base"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.hamcrest"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+      <directive name="uses" value="org.hamcrest.core"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.hamcrest.core"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+      <directive name="uses" value="org.hamcrest"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.objenesis"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=COM.jrockit.reflect)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=jrockit.vm)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=junit.framework)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.apache.tools.ant)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.apache.tools.ant.types)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.hamcrest)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.junit)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.junit.internal.runners)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.junit.runner)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.junit.runner.manipulation)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.junit.runner.notification)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.junit.runners)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.junit.runners.model)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.mockito)(version>=1.8.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.mockito.configuration)(version>=1.8.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.mockito.exceptions)(version>=1.8.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.mockito.exceptions.base)(version>=1.8.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.mockito.exceptions.misusing)(version>=1.8.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.mockito.exceptions.verification)(version>=1.8.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.mockito.exceptions.verification.junit)(version>=1.8.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.mockito.invocation)(version>=1.8.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.mockito.runners)(version>=1.8.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.mockito.stubbing)(version>=1.8.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.mockito.stubbing.answers)(version>=1.8.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.mockito.verification)(version>=1.8.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.objenesis)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=sun.reflect)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bndlib"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.48.1"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="30e5e5059a035bbe33dab96d9b88f518e92c0c1e3f2208dcd8081b7034f14b84"/>
+      <attribute name="url" value="biz.aQute.bndlib/biz.aQute.bndlib-1.48.1.jar"/>
+      <attribute name="size" type="Long" value="878962"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.48.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.48.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.osgi"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.annotation,aQute.libg.version,aQute.bnd.service,aQute.bnd.header,aQute.bnd.annotation.metatype,aQute.libg.reporter,aQute.libg.sed,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.build"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.service,aQute.bnd.osgi,aQute.libg.reporter,aQute.libg.version,aQute.bnd.header,aQute.bnd.service.action,aQute.libg.sed,javax.naming"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+      <directive name="uses" value="aQute.bnd.osgi,aQute.libg.reporter,aQute.bnd.build,aQute.libg.version"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.build"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.reporter"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.version"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sed"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.header"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.libg.reporter,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.qtokens"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sax"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.xml.sax,javax.xml.transform,javax.xml.parsers,javax.xml.transform.sax"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="org.apache.felix.metatype"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.0.4"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="3eba0039242a2bd3c26609648d50c0850b3f11cdebbca94acb45b555ddddef10"/>
+      <attribute name="url" value="org.apache.felix.metatype/org.apache.felix.metatype-1.0.4.jar"/>
+      <attribute name="size" type="Long" value="93990"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="org.apache.felix.metatype"/>
+      <attribute name="bundle-version" type="Version" value="1.0.4"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="org.apache.felix.metatype"/>
+      <attribute name="bundle-version" type="Version" value="1.0.4"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.apache.felix.metatype"/>
+      <attribute name="version" type="Version" value="1.0.4"/>
+      <directive name="uses" value="org.osgi.service.metatype,org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.metatype"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.apache.felix.metatype)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.3.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.log)(version>=1.3.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.metatype)(version>=1.1.0))"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bnd"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.48.0"/>
+      <directive name="singleton" value="true"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="6c02d4ac3e51c515a91cffc80765d4942da8c131a34c1519786ab026fac4edff"/>
+      <attribute name="url" value="biz.aQute.bnd/biz.aQute.bnd-1.48.0.jar"/>
+      <attribute name="size" type="Long" value="1216987"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bnd"/>
+      <attribute name="bundle-version" type="Version" value="1.48.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bnd"/>
+      <attribute name="bundle-version" type="Version" value="1.48.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.url"/>
+      <attribute name="version" type="Version" value="1.48.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.apache.tools.ant)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.apache.tools.ant.types)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.service.component.annotations)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.packageadmin)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui.ide)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jface.text)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui.workbench.texteditor)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui.editors)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.debug.ui)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.core)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.ui)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.core.runtime)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.launching)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.debug.ui)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.junit)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.junit)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.eclipse.osgi.services)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.apache.ant)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.eclipse.ui.console)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bnd.annotation"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.51.1"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="003d4f597431c3b22823e8161a3fbc7d9a0516afcdf996993eadc02ed3fcc7d0"/>
+      <attribute name="url" value="biz.aQute.bnd.annotation/biz.aQute.bnd.annotation-1.51.1.jar"/>
+      <attribute name="size" type="Long" value="35646"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bnd.annotation"/>
+      <attribute name="bundle-version" type="Version" value="1.51.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bnd.annotation"/>
+      <attribute name="bundle-version" type="Version" value="1.51.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.test"/>
+      <attribute name="version" type="Version" value="1.51.1"/>
+      <directive name="uses" value="aQute.libg.reporter,junit.framework,javax.xml.namespace,javax.xml.xpath,javax.xml.parsers,org.w3c.dom"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=aQute.libg.reporter)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="org.eclipse.equinox.supplement"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.3.0.v20100503"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="95b64f733c90ef1a456e19a8eaa58d7cd2868914e917b0335be2dace0ce3df15"/>
+      <attribute name="url" value="org.eclipse.equinox.supplement/org.eclipse.equinox.supplement-1.3.0.jar"/>
+      <attribute name="size" type="Long" value="113255"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="org.eclipse.equinox.supplement"/>
+      <attribute name="bundle-version" type="Version" value="1.3.0.v20100503"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="org.eclipse.equinox.supplement"/>
+      <attribute name="bundle-version" type="Version" value="1.3.0.v20100503"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.osgi.framework.log"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.osgi.service.datalocation"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.osgi.service.debug"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.osgi.service.environment"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.osgi.service.localization"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.osgi.service.runnable"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.osgi.service.urlconversion"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.osgi.storagemanager"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.osgi.util"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.osgi.framework.debug"/>
+      <attribute name="version" type="Version" value="0.0.0"/>
+      <directive name="x-internal" value="true"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.osgi.framework.util"/>
+      <attribute name="version" type="Version" value="0.0.0"/>
+      <directive name="x-internal" value="true"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.osgi.framework.internal.core"/>
+      <attribute name="version" type="Version" value="0.0.0"/>
+      <directive name="x-internal" value="true"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.osgi.framework.internal.reliablefile"/>
+      <attribute name="version" type="Version" value="0.0.0"/>
+      <directive name="x-internal" value="true"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.core.runtime.internal.adaptor"/>
+      <attribute name="version" type="Version" value="0.0.0"/>
+      <directive name="x-internal" value="true"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.framework)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.util.tracker)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.osgi.framework.log)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.osgi.service.datalocation)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.osgi.service.debug)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.osgi.service.environment)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.osgi.service.localization)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.osgi.service.runnable)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.osgi.service.urlconversion)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.osgi.storagemanager)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.osgi.util)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.4)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=CDC-1.0/Foundation-1.0)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.3)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bnd.annotation"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.50.1"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="1c8763381afd7fc73f9963761c5dd68194aa81eba5040900c8f6bee4eab8894e"/>
+      <attribute name="url" value="biz.aQute.bnd.annotation/biz.aQute.bnd.annotation-1.50.1.jar"/>
+      <attribute name="size" type="Long" value="35644"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bnd.annotation"/>
+      <attribute name="bundle-version" type="Version" value="1.50.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bnd.annotation"/>
+      <attribute name="bundle-version" type="Version" value="1.50.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.test"/>
+      <attribute name="version" type="Version" value="1.50.1"/>
+      <directive name="uses" value="aQute.libg.reporter,junit.framework,javax.xml.namespace,javax.xml.xpath,javax.xml.parsers,org.w3c.dom"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=aQute.libg.reporter)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="org.apache.felix.bundlerepository"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.6.2"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="d2326d2f171a9f6ae0207c9e11f6db65dba3f7d4b8ad15cab9cb908ccbc62cfd"/>
+      <attribute name="url" value="org.apache.felix.bundlerepository/org.apache.felix.bundlerepository-1.6.2.jar"/>
+      <attribute name="size" type="Long" value="230135"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="org.apache.felix.bundlerepository"/>
+      <attribute name="bundle-version" type="Version" value="1.6.2"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="org.apache.felix.bundlerepository"/>
+      <attribute name="bundle-version" type="Version" value="1.6.2"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.apache.felix.bundlerepository"/>
+      <attribute name="version" type="Version" value="2.0.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.service">
+      <attribute name="osgi.wiring.service" value="org.apache.felix.bundlerepository.RepositoryAdmin"/>
+    </capability>
+    <capability namespace="osgi.wiring.service">
+      <attribute name="osgi.wiring.service" value="org.osgi.service.obr.RepositoryAdmin"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.apache.felix.bundlerepository)(version>=2.0.0)(!(version>=3.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.3.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.log)(version>=1.3.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.obr)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.url)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="org.osgi.impl.bundle.bindex"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="2.2.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="356a194750baa693bfc43638bdc5febd4f0143ca3400e3a69702b1c97aa098b5"/>
+      <attribute name="url" value="org.osgi.impl.bundle.bindex/org.osgi.impl.bundle.bindex-2.2.0.jar"/>
+      <attribute name="size" type="Long" value="154617"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="org.osgi.impl.bundle.bindex"/>
+      <attribute name="bundle-version" type="Version" value="2.2.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="org.osgi.impl.bundle.bindex"/>
+      <attribute name="bundle-version" type="Version" value="2.2.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.apache.tools.ant)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.apache.tools.ant.types)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bndlib"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.44.19"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="339a3121a4abe279441c311c7713bd24264a282e7beaf76aa4a90e1e8b4e3c28"/>
+      <attribute name="url" value="biz.aQute.bndlib/biz.aQute.bndlib-1.44.19.jar"/>
+      <attribute name="size" type="Long" value="823149"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.44.19"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.44.19"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.osgi"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.annotation,aQute.libg.version,aQute.bnd.service,aQute.bnd.header,aQute.bnd.annotation.metatype,aQute.libg.reporter,aQute.libg.sed,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.build"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.service,aQute.bnd.osgi,aQute.libg.reporter,aQute.bnd.header,aQute.bnd.service.action,aQute.libg.sed,javax.naming"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+      <directive name="uses" value="aQute.bnd.osgi,aQute.bnd.build,aQute.libg.reporter,aQute.libg.version"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.build"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.reporter"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.version"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sed"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.header"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.libg.reporter,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.qtokens"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sax"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.xml.sax,javax.xml.transform,javax.xml.parsers,javax.xml.transform.sax"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="name.njbartlett.osgi.emf.xmi"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="2.7.0.v20110520-1406"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="e09b6e672c769f23c796b2bcfe97cf068d7518d2239635b6d1bd4cd371091fcf"/>
+      <attribute name="url" value="name.njbartlett.osgi.emf.xmi/name.njbartlett.osgi.emf.xmi-2.7.0.jar"/>
+      <attribute name="size" type="Long" value="208921"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="name.njbartlett.osgi.emf.xmi"/>
+      <attribute name="bundle-version" type="Version" value="2.7.0.v20110520-1406"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="name.njbartlett.osgi.emf.xmi"/>
+      <attribute name="bundle-version" type="Version" value="2.7.0.v20110520-1406"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.emf.ecore.xmi"/>
+      <attribute name="version" type="Version" value="2.7.0.v20110520-1406"/>
+      <directive name="uses" value="org.eclipse.emf.ecore,org.w3c.dom,org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.util,org.eclipse.emf.common.util,org.eclipse.emf.common,org.xml.sax.ext,org.xml.sax,javax.xml.parsers,org.eclipse.emf.ecore.xml.type"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.emf.ecore.xmi.impl"/>
+      <attribute name="version" type="Version" value="2.7.0.v20110520-1406"/>
+      <directive name="uses" value="org.eclipse.emf.ecore.xmi,org.eclipse.emf.ecore,org.eclipse.emf.ecore.util,org.w3c.dom,org.eclipse.emf.common.util,org.xml.sax,org.xml.sax.helpers,org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.ecore.xml.type,org.eclipse.emf.common,org.eclipse.emf.ecore.impl,org.eclipse.emf.ecore.xml.type.util,org.eclipse.emf.ecore.xmi.util,org.eclipse.emf.ecore.xml.type.internal,javax.xml.namespace,org.xml.sax.ext,javax.xml.parsers, [...]
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.emf.ecore.xmi.util"/>
+      <attribute name="version" type="Version" value="2.7.0.v20110520-1406"/>
+      <directive name="uses" value="org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.util,org.eclipse.emf.ecore.xmi,org.eclipse.emf.common.util,org.eclipse.emf.common,org.eclipse.emf.ecore.xmi.impl,org.eclipse.emf.ecore.resource.impl,org.w3c.dom,org.xml.sax,org.eclipse.emf.ecore,org.eclipse.emf.ecore.impl"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.emf.common)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.emf.common.notify)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.emf.common.util)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.emf.ecore)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.emf.ecore.impl)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.emf.ecore.resource)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.emf.ecore.resource.impl)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.emf.ecore.util)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.emf.ecore.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.emf.ecore.xml.type)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.emf.ecore.xml.type.internal)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.emf.ecore.xml.type.util)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.ext)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="org.apache.felix.gogo.runtime"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="0.10.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="5de2ea1d61f35a8931719355a9771756fd60735f687e9db81413f89ee6fa6bd6"/>
+      <attribute name="url" value="org.apache.felix.gogo.runtime/org.apache.felix.gogo.runtime-0.10.0.jar"/>
+      <attribute name="size" type="Long" value="66965"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="org.apache.felix.gogo.runtime"/>
+      <attribute name="bundle-version" type="Version" value="0.10.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="org.apache.felix.gogo.runtime"/>
+      <attribute name="bundle-version" type="Version" value="0.10.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="status" value="provisional"/>
+      <attribute name="osgi.wiring.package" value="org.apache.felix.service.command"/>
+      <attribute name="version" type="Version" value="0.10.0"/>
+      <directive name="mandatory" value="status"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.apache.felix.gogo.api"/>
+      <attribute name="version" type="Version" value="0.10.0"/>
+      <directive name="uses" value="org.apache.felix.service.command"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="status" value="provisional"/>
+      <attribute name="osgi.wiring.package" value="org.apache.felix.service.threadio"/>
+      <attribute name="version" type="Version" value="0.10.0"/>
+      <directive name="mandatory" value="status"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.apache.felix.gogo.api)(version>=0.10.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <attribute name="status" value="provisional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.apache.felix.service.command)(version>=0.10.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <attribute name="status" value="provisional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.apache.felix.service.threadio)(version>=0.10.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.framework)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.service.event)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.osgi.util.tracker)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.junit"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="0b2dd50393fdd7801e6c764d54365b65726235bacb6cb7f73a47b8a93f8cd605"/>
+      <attribute name="url" value="biz.aQute.junit/biz.aQute.junit-1.0.0.jar"/>
+      <attribute name="size" type="Long" value="66752"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.junit"/>
+      <attribute name="bundle-version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.junit"/>
+      <attribute name="bundle-version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="junit.framework"/>
+      <attribute name="version" type="Version" value="3.8.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.util.tracker)(version>=1.4.0)(!(version>=2.0.0)))"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="com.google.guava"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="11.0.1"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="5162e3281e5130cfad5d8c336eea19e412555ecc852928a3914e30725c4d7244"/>
+      <attribute name="url" value="com.google.guava/com.google.guava-11.0.1.jar"/>
+      <attribute name="size" type="Long" value="1675518"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="com.google.guava"/>
+      <attribute name="bundle-version" type="Version" value="11.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="com.google.guava"/>
+      <attribute name="bundle-version" type="Version" value="11.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="com.google.common.annotations"/>
+      <attribute name="version" type="Version" value="11.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="com.google.common.base"/>
+      <attribute name="version" type="Version" value="11.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="com.google.common.cache"/>
+      <attribute name="version" type="Version" value="11.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="com.google.common.collect"/>
+      <attribute name="version" type="Version" value="11.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="com.google.common.eventbus"/>
+      <attribute name="version" type="Version" value="11.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="com.google.common.hash"/>
+      <attribute name="version" type="Version" value="11.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="com.google.common.io"/>
+      <attribute name="version" type="Version" value="11.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="com.google.common.math"/>
+      <attribute name="version" type="Version" value="11.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="com.google.common.net"/>
+      <attribute name="version" type="Version" value="11.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="com.google.common.primitives"/>
+      <attribute name="version" type="Version" value="11.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="com.google.common.util.concurrent"/>
+      <attribute name="version" type="Version" value="11.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="com.google.common.base.internal"/>
+      <attribute name="version" type="Version" value="11.0.1"/>
+      <directive name="x-internal" value="true"/>
+    </capability>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bndlib"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.50.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="5d504f9568f0bc9b3745591752123ddc03c015ecc66fc7d6c155229a1ad08ca1"/>
+      <attribute name="url" value="biz.aQute.bndlib/biz.aQute.bndlib-1.50.0.jar"/>
+      <attribute name="size" type="Long" value="894917"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.50.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.50.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.osgi"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.annotation,aQute.libg.version,aQute.bnd.service,aQute.bnd.header,aQute.bnd.annotation.metatype,aQute.libg.reporter,aQute.libg.sed,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.build"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.service,aQute.bnd.osgi,aQute.libg.reporter,aQute.libg.version,aQute.bnd.help,aQute.bnd.header,aQute.bnd.service.action,aQute.libg.sed,javax.naming"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+      <directive name="uses" value="aQute.bnd.osgi,aQute.libg.reporter,aQute.bnd.build,aQute.libg.version"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.url"/>
+      <attribute name="version" type="Version" value="1.50.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.build"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.help"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.bnd.osgi"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.reporter"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.version"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sed"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.header"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.libg.reporter,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.qtokens"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sax"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.xml.sax,javax.xml.transform,javax.xml.parsers,javax.xml.transform.sax"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bnd.annotation"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.48.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="5f89f9683d069bb93dcadd845e8bd2e22df14eaefe70d36aff97b217f570ac9b"/>
+      <attribute name="url" value="biz.aQute.bnd.annotation/biz.aQute.bnd.annotation-1.48.0.jar"/>
+      <attribute name="size" type="Long" value="35591"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bnd.annotation"/>
+      <attribute name="bundle-version" type="Version" value="1.48.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bnd.annotation"/>
+      <attribute name="bundle-version" type="Version" value="1.48.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.test"/>
+      <attribute name="version" type="Version" value="1.48.0"/>
+      <directive name="uses" value="aQute.libg.reporter,junit.framework,javax.xml.namespace,javax.xml.xpath,javax.xml.parsers,org.w3c.dom"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=aQute.libg.reporter)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="bndtools.runtime.eclipse.applaunch"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="0.1.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="513f91c21d7a080b0e97ec95dbe9c937fb94470dcdc5998235b5363275d16cd8"/>
+      <attribute name="url" value="bndtools.runtime.eclipse.applaunch/bndtools.runtime.eclipse.applaunch-0.1.0.jar"/>
+      <attribute name="size" type="Long" value="14079"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="bndtools.runtime.eclipse.applaunch"/>
+      <attribute name="bundle-version" type="Version" value="0.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="bndtools.runtime.eclipse.applaunch"/>
+      <attribute name="bundle-version" type="Version" value="0.1.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.eclipse.osgi.service.runnable)(version>=1.1.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.util.tracker)(version>=1.4.0)(!(version>=2.0.0)))"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bnd.annotation"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.45.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="f2f458856f1ffc05a851a6c9794ba06ab45b54ce777a4e54e23e8a94fd1e7b0f"/>
+      <attribute name="url" value="biz.aQute.bnd.annotation/biz.aQute.bnd.annotation-1.45.0.jar"/>
+      <attribute name="size" type="Long" value="29123"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bnd.annotation"/>
+      <attribute name="bundle-version" type="Version" value="1.45.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bnd.annotation"/>
+      <attribute name="bundle-version" type="Version" value="1.45.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="name.njbartlett.osgi.emf.minimal"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="2.7.0.v20110912-0920"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="7438d400ed6fcb87eef1b1e3294a5598164283dbe8381fd469b895cde29653c2"/>
+      <attribute name="url" value="name.njbartlett.osgi.emf.minimal/name.njbartlett.osgi.emf.minimal-2.7.0.jar"/>
+      <attribute name="size" type="Long" value="1192662"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="name.njbartlett.osgi.emf.minimal"/>
+      <attribute name="bundle-version" type="Version" value="2.7.0.v20110912-0920"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="name.njbartlett.osgi.emf.minimal"/>
+      <attribute name="bundle-version" type="Version" value="2.7.0.v20110912-0920"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.emf.common"/>
+      <attribute name="version" type="Version" value="2.7.0.v20110912-0920"/>
+      <directive name="uses" value="org.eclipse.core.runtime,org.eclipse.emf.common.util,org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.emf.common.notify"/>
+      <attribute name="version" type="Version" value="2.7.0.v20110912-0920"/>
+      <directive name="uses" value="org.eclipse.emf.common.util"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.emf.common.notify.impl"/>
+      <attribute name="version" type="Version" value="2.7.0.v20110912-0920"/>
+      <directive name="uses" value="org.eclipse.emf.common.util,org.eclipse.emf.common.notify"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.emf.common.util"/>
+      <attribute name="version" type="Version" value="2.7.0.v20110912-0920"/>
+      <directive name="uses" value="org.eclipse.core.runtime,org.eclipse.emf.common"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.emf.ecore"/>
+      <attribute name="version" type="Version" value="2.7.0.v20110912-0920"/>
+      <directive name="uses" value="org.eclipse.emf.common.util,org.eclipse.emf.ecore.resource,org.eclipse.emf.common.notify,org.eclipse.emf.ecore.impl,org.eclipse.emf.ecore.util"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.emf.ecore.impl"/>
+      <attribute name="version" type="Version" value="2.7.0.v20110912-0920"/>
+      <directive name="uses" value="org.eclipse.emf.ecore.util,org.eclipse.emf.ecore,org.eclipse.emf.common.util,org.eclipse.emf.ecore.resource,org.eclipse.emf.common.notify.impl,org.eclipse.emf.common.notify,org.eclipse.emf.ecore.xml.type.util,org.eclipse.emf.common,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.ecore.plugin,org.eclipse.emf.ecore.xml.type"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.emf.ecore.plugin"/>
+      <attribute name="version" type="Version" value="2.7.0.v20110912-0920"/>
+      <directive name="uses" value="org.eclipse.emf.ecore.resource,org.eclipse.core.runtime,org.osgi.framework,org.eclipse.emf.ecore,org.xml.sax.helpers,org.xml.sax,org.eclipse.emf.ecore.impl,org.eclipse.core.resources,org.eclipse.emf.common,org.eclipse.emf.common.util,javax.xml.parsers,org.eclipse.emf.ecore.util,org.eclipse.emf.ecore.resource.impl"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.emf.ecore.resource"/>
+      <attribute name="version" type="Version" value="2.7.0.v20110912-0920"/>
+      <directive name="uses" value="org.eclipse.core.runtime.content,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.common.util,org.eclipse.emf.ecore,org.eclipse.emf.common.notify"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.emf.ecore.resource.impl"/>
+      <attribute name="version" type="Version" value="2.7.0.v20110912-0920"/>
+      <directive name="uses" value="org.eclipse.emf.ecore.resource,javax.crypto.spec,javax.crypto,org.eclipse.emf.common.util,org.eclipse.emf.ecore,org.eclipse.emf.ecore.util,org.eclipse.core.runtime,org.eclipse.core.runtime.content,org.eclipse.emf.common,org.eclipse.emf.ecore.plugin,org.eclipse.core.resources,org.eclipse.emf.common.notify.impl,org.eclipse.emf.common.notify,org.eclipse.emf.ecore.impl"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.emf.ecore.xml.namespace"/>
+      <attribute name="version" type="Version" value="2.7.0.v20110912-0920"/>
+      <directive name="uses" value="org.eclipse.emf.common.util,org.eclipse.emf.ecore.util,org.eclipse.emf.ecore"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.emf.ecore.xml.type"/>
+      <attribute name="version" type="Version" value="2.7.0.v20110912-0920"/>
+      <directive name="uses" value="org.eclipse.emf.ecore.util,org.eclipse.emf.ecore,org.eclipse.emf.common.util,javax.xml.datatype,javax.xml.namespace"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.emf.ecore.xml.type.internal"/>
+      <attribute name="version" type="Version" value="2.7.0.v20110912-0920"/>
+      <directive name="uses" value="org.eclipse.emf.ecore.xml.type,javax.xml.namespace,org.eclipse.emf.ecore.plugin,org.eclipse.emf.common.util,org.eclipse.emf.ecore.xml.type.util,javax.xml.datatype"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.emf.ecore.xml.type.util"/>
+      <attribute name="version" type="Version" value="2.7.0.v20110912-0920"/>
+      <directive name="uses" value="org.xml.sax,org.eclipse.emf.ecore.xml.type,javax.xml.datatype,javax.xml.namespace,org.xml.sax.helpers,org.eclipse.emf.common.util,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.ecore,org.eclipse.emf.ecore.xml.type.internal,org.eclipse.emf.ecore.plugin,org.eclipse.emf.ecore.util"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.emf.ecore.util"/>
+      <attribute name="version" type="Version" value="2.7.0.v20110912-0920"/>
+      <directive name="uses" value="org.eclipse.emf.common.notify,org.eclipse.emf.ecore,org.eclipse.emf.common.util,org.eclipse.emf.ecore.xml.type,org.eclipse.emf.ecore.xml.type.util,org.eclipse.emf.ecore.impl,org.eclipse.emf.common.notify.impl,org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.plugin,org.eclipse.emf.ecore.xml.namespace"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.crypto)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.crypto.spec)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.datatype)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.core.resources)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.core.runtime)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.core.runtime.content)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.emf.common.notify)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.emf.common.util)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.emf.ecore)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.emf.ecore.impl)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.emf.ecore.plugin)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.emf.ecore.resource)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.emf.ecore.util)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.emf.ecore.xml.type.internal)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.eclipse.emf.ecore.xml.type.util)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.6.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="org.eclipse.jgit"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.1.0.201109151100-r"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="c785e18b04a7e08649067c0705efbf51fefd29abcc554dffca4e41b43092a9fe"/>
+      <attribute name="url" value="org.eclipse.jgit/org.eclipse.jgit-1.1.0.jar"/>
+      <attribute name="size" type="Long" value="1394520"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="org.eclipse.jgit"/>
+      <attribute name="bundle-version" type="Version" value="1.1.0.201109151100-r"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="org.eclipse.jgit"/>
+      <attribute name="bundle-version" type="Version" value="1.1.0.201109151100-r"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.api"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.api.errors"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.blame"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.diff"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.dircache"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.errors"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.events"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.fnmatch"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.ignore"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.lib"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.merge"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.nls"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.notes"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.patch"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.revplot"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.revwalk"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.revwalk.filter"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.storage.file"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.storage.pack"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.transport"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.transport.resolver"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.treewalk"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.treewalk.filter"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.util"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.eclipse.jgit.util.io"/>
+      <attribute name="version" type="Version" value="1.1.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=com.jcraft.jsch)(bundle-version>=0.1.37)(!(bundle-version>=0.2.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bnd"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.50.1"/>
+      <directive name="singleton" value="true"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="28933ff004f006e1de7f682aa9e8253bf2121be66c239c4d43768c520beb7657"/>
+      <attribute name="url" value="biz.aQute.bnd/biz.aQute.bnd-1.50.1.jar"/>
+      <attribute name="size" type="Long" value="1250653"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bnd"/>
+      <attribute name="bundle-version" type="Version" value="1.50.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bnd"/>
+      <attribute name="bundle-version" type="Version" value="1.50.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.url"/>
+      <attribute name="version" type="Version" value="1.50.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.coordinator"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=aQute.bnd.service.url)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.apache.tools.ant)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.apache.tools.ant.types)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.component.annotations)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.coordinator)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.packageadmin)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui.ide)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jface.text)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui.workbench.texteditor)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui.editors)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.ui)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.debug.ui)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.core)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.ui)(bundle-version>=3.3.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.core.runtime)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.launching)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.debug.ui)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(&(osgi.wiring.bundle=org.eclipse.jdt.junit)(bundle-version>=3.2.0)(!(bundle-version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.junit)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.eclipse.osgi.services)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.apache.ant)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=org.eclipse.ui.console)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="com.springsource.org.objectweb.asm.tree"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="3.1.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="672ff952419ef61f243bdaf70c1c9d56b2765181584f92bb7d7c7a1177722365"/>
+      <attribute name="url" value="com.springsource.org.objectweb.asm.tree/com.springsource.org.objectweb.asm.tree-3.1.0.jar"/>
+      <attribute name="size" type="Long" value="23108"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="com.springsource.org.objectweb.asm.tree"/>
+      <attribute name="bundle-version" type="Version" value="3.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="com.springsource.org.objectweb.asm.tree"/>
+      <attribute name="bundle-version" type="Version" value="3.1.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.objectweb.asm.tree"/>
+      <attribute name="version" type="Version" value="3.1.0"/>
+      <directive name="uses" value="org.objectweb.asm"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.objectweb.asm)(version>=3.1.0)(version<=3.1.0))"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="org.easymock"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="3.0.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="42f578620708e68c16518d305d15e071c782b310da17e0617f6b068d7c41aab5"/>
+      <attribute name="url" value="org.easymock/org.easymock-3.0.0.jar"/>
+      <attribute name="size" type="Long" value="210829"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="org.easymock"/>
+      <attribute name="bundle-version" type="Version" value="3.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="org.easymock"/>
+      <attribute name="bundle-version" type="Version" value="3.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="poweruser" value="true"/>
+      <attribute name="osgi.wiring.package" value="org.easymock.internal"/>
+      <attribute name="version" type="Version" value="3.0.0"/>
+      <directive name="mandatory" value="poweruser"/>
+      <directive name="uses" value="org.easymock,net.sf.cglib.proxy,net.sf.cglib.core,org.easymock.internal.matchers,org.objenesis"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="poweruser" value="true"/>
+      <attribute name="osgi.wiring.package" value="org.easymock.internal.matchers"/>
+      <attribute name="version" type="Version" value="3.0.0"/>
+      <directive name="mandatory" value="poweruser"/>
+      <directive name="uses" value="org.easymock,org.easymock.internal"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.easymock"/>
+      <attribute name="version" type="Version" value="3.0.0"/>
+      <directive name="uses" value="org.easymock.internal,org.easymock.internal.matchers"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=net.sf.cglib.core)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=net.sf.cglib.proxy)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=net.sf.cglib.reflect)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.easymock)(version>=3.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <attribute name="poweruser" value="true"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.easymock.internal)(version>=3.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.objenesis)(version>=1.2.0))"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bndlib"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.49.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="9fcfd9bcd6de6b0847a14bd7450e925d3f1f7fa3f2b59f556ed41d09294f25ac"/>
+      <attribute name="url" value="biz.aQute.bndlib/biz.aQute.bndlib-1.49.0.jar"/>
+      <attribute name="size" type="Long" value="893098"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.49.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.49.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.osgi"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.annotation,aQute.libg.version,aQute.bnd.service,aQute.bnd.header,aQute.bnd.annotation.metatype,aQute.libg.reporter,aQute.libg.sed,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.build"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.service,aQute.bnd.osgi,aQute.libg.reporter,aQute.libg.version,aQute.bnd.header,aQute.bnd.service.action,aQute.libg.sed,javax.naming"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+      <directive name="uses" value="aQute.bnd.osgi,aQute.libg.reporter,aQute.bnd.build,aQute.libg.version"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.url"/>
+      <attribute name="version" type="Version" value="1.49.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.build"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.reporter"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.version"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sed"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.header"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.libg.reporter,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.qtokens"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sax"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.xml.sax,javax.xml.transform,javax.xml.parsers,javax.xml.transform.sax"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bndlib"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.46.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="01c279a065d4b309dfec84a92ac05c71260aa7722fbcbb5e50e62df228b85797"/>
+      <attribute name="url" value="biz.aQute.bndlib/biz.aQute.bndlib-1.46.0.jar"/>
+      <attribute name="size" type="Long" value="877110"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.46.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.46.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.osgi"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.annotation,aQute.libg.version,aQute.bnd.service,aQute.bnd.header,aQute.bnd.annotation.metatype,aQute.libg.reporter,aQute.libg.sed,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.build"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.service,aQute.bnd.osgi,aQute.libg.reporter,aQute.bnd.header,aQute.bnd.service.action,aQute.libg.sed,javax.naming"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+      <directive name="uses" value="aQute.bnd.osgi,aQute.bnd.build,aQute.libg.reporter,aQute.libg.version"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.build"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.reporter"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.version"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sed"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.header"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.libg.reporter,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.qtokens"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sax"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.xml.sax,javax.xml.transform,javax.xml.parsers,javax.xml.transform.sax"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bndlib"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.50.1"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="1efae5fb766287e8a148508e1c2dcb4d7d78bc4bf92b082d2ed3a1cc6f3437b4"/>
+      <attribute name="url" value="biz.aQute.bndlib/biz.aQute.bndlib-1.50.1.jar"/>
+      <attribute name="size" type="Long" value="925162"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.50.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.50.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.osgi"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.annotation,aQute.libg.version,aQute.bnd.service,aQute.bnd.header,aQute.bnd.annotation.metatype,aQute.libg.reporter,aQute.libg.sed,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.build"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.service,aQute.bnd.osgi,aQute.libg.reporter,aQute.libg.version,aQute.bnd.help,aQute.bnd.header,aQute.bnd.service.action,aQute.libg.sed,javax.naming"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+      <directive name="uses" value="aQute.bnd.osgi,aQute.libg.reporter,aQute.bnd.build,aQute.libg.version"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.url"/>
+      <attribute name="version" type="Version" value="1.50.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.build"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.help"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.bnd.osgi"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.reporter"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.version"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sed"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.header"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.libg.reporter,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.qtokens"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sax"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.xml.sax,javax.xml.transform,javax.xml.parsers,javax.xml.transform.sax"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.coordinator"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=aQute.libg.sax)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bndlib"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.50.2"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="3c2c3d30eee59b5ff80f13290d1bf719b9d4f76b461d5b4b9d633b9298577f76"/>
+      <attribute name="url" value="biz.aQute.bndlib/biz.aQute.bndlib-1.50.2.jar"/>
+      <attribute name="size" type="Long" value="926279"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.50.2"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.50.2"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.osgi"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.annotation,aQute.libg.version,aQute.bnd.service,aQute.bnd.header,aQute.bnd.annotation.metatype,aQute.libg.reporter,aQute.libg.sed,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.build"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.service,aQute.bnd.osgi,aQute.libg.reporter,aQute.libg.version,aQute.bnd.help,aQute.bnd.header,aQute.bnd.service.action,aQute.libg.sed,javax.naming"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+      <directive name="uses" value="aQute.bnd.osgi,aQute.libg.reporter,aQute.bnd.build,aQute.libg.version"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.url"/>
+      <attribute name="version" type="Version" value="1.50.2"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.build"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.help"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.bnd.osgi"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.reporter"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.version"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sed"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.header"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.libg.reporter,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.qtokens"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sax"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.xml.sax,javax.xml.transform,javax.xml.parsers,javax.xml.transform.sax"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.coordinator"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=aQute.libg.sax)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.launcher"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="f7917bc6cd12e1d1d05ce1c332970c4270d790300e10c8078e1f0ada92e52029"/>
+      <attribute name="url" value="biz.aQute.launcher/biz.aQute.launcher-1.0.0.jar"/>
+      <attribute name="size" type="Long" value="56027"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.launcher"/>
+      <attribute name="bundle-version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.launcher"/>
+      <attribute name="bundle-version" type="Version" value="1.0.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=aQute.bnd.build)(version>=1.43.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=aQute.bnd.service)(version>=1.44.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=aQute.lib.io)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=aQute.bnd.osgi)(version>=1.43.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=aQute.libg.generics)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework.launch)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.packageadmin)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.permissionadmin)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bndlib"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.47.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="566df2fbcac58a36ccf961a9f0915f865d615cfc24982291ec9485f77f91bb8f"/>
+      <attribute name="url" value="biz.aQute.bndlib/biz.aQute.bndlib-1.47.jar"/>
+      <attribute name="size" type="Long" value="877121"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.47.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.47.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.osgi"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.annotation,aQute.libg.version,aQute.bnd.service,aQute.bnd.header,aQute.bnd.annotation.metatype,aQute.libg.reporter,aQute.libg.sed,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.build"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.service,aQute.bnd.osgi,aQute.libg.reporter,aQute.bnd.header,aQute.bnd.service.action,aQute.libg.sed,javax.naming"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+      <directive name="uses" value="aQute.bnd.osgi,aQute.bnd.build,aQute.libg.reporter,aQute.libg.version"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.build"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.reporter"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.version"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sed"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.header"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.libg.reporter,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.qtokens"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sax"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.xml.sax,javax.xml.transform,javax.xml.parsers,javax.xml.transform.sax"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="org.apache.felix.shell"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.4.2"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="d16d2a360fe52f4cb4c2ccae9bb3e0cbd433749664d36db578ad4667b5fa185d"/>
+      <attribute name="url" value="org.apache.felix.shell/org.apache.felix.shell-1.4.2.jar"/>
+      <attribute name="size" type="Long" value="62727"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="org.apache.felix.shell"/>
+      <attribute name="bundle-version" type="Version" value="1.4.2"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="org.apache.felix.shell"/>
+      <attribute name="bundle-version" type="Version" value="1.4.2"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.ungoverned.osgi.service.shell"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.log"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.apache.felix.shell"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.service">
+      <attribute name="osgi.wiring.service" value="org.apache.felix.shell.ShellService"/>
+    </capability>
+    <capability namespace="osgi.wiring.service">
+      <attribute name="osgi.wiring.service" value="org.ungoverned.osgi.service.shell.ShellService"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.apache.felix.shell)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.4.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.log)(version>=1.3.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.packageadmin)(version>=1.2.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.startlevel)(version>=1.1.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.ungoverned.osgi.service.shell)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.service">
+      <directive name="filter" value="(osgi.wiring.service=org.osgi.service.startlevel.StartLevel)"/>
+      <directive name="effective" value="active"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.service">
+      <directive name="filter" value="(osgi.wiring.service=org.osgi.service.packageadmin.PackageAdmin)"/>
+      <directive name="effective" value="active"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="javax.xml.stream"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.0.1.v201004272200"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="baa081764f4ac60043e9a19aafa504149b84c9bd12cd657b1f8f6c5689bb9f94"/>
+      <attribute name="url" value="javax.xml.stream/javax.xml.stream-1.0.1.jar"/>
+      <attribute name="size" type="Long" value="39698"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="javax.xml.stream"/>
+      <attribute name="bundle-version" type="Version" value="1.0.1.v201004272200"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="javax.xml.stream"/>
+      <attribute name="bundle-version" type="Version" value="1.0.1.v201004272200"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.xml"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.xml.namespace"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.xml.stream"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.xml.stream.events"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="javax.xml.stream.util"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+    </capability>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=javax.xml)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.bundle">
+      <directive name="filter" value="(osgi.wiring.bundle=system.bundle)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.4)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.launcher"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="6e1e33d7747e3037966771e8d69c8e5ea0d9d65c66af2afffcb3dd2e9b17cd98"/>
+      <attribute name="url" value="biz.aQute.launcher/biz.aQute.launcher-1.0.1.jar"/>
+      <attribute name="size" type="Long" value="56678"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.launcher"/>
+      <attribute name="bundle-version" type="Version" value="1.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.launcher"/>
+      <attribute name="bundle-version" type="Version" value="1.0.1"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=aQute.bnd.build)(version>=1.43.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=aQute.bnd.service)(version>=1.44.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=aQute.lib.io)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=aQute.bnd.osgi)(version>=1.43.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=aQute.libg.generics)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework.launch)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.packageadmin)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.permissionadmin)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="org.apache.felix.log"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.0.1"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="88c4038729ab8dc4dddb018aeb41811443db0516b87d20cd60e55cd0593b85b1"/>
+      <attribute name="url" value="org.apache.felix.log/org.apache.felix.log-1.0.1.jar"/>
+      <attribute name="size" type="Long" value="22243"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="org.apache.felix.log"/>
+      <attribute name="bundle-version" type="Version" value="1.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="org.apache.felix.log"/>
+      <attribute name="bundle-version" type="Version" value="1.0.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.log"/>
+      <attribute name="version" type="Version" value="1.3.0"/>
+      <directive name="uses" value="org.osgi.framework"/>
+    </capability>
+    <capability namespace="osgi.wiring.service">
+      <attribute name="osgi.wiring.service" value="org.osgi.service.log.LogService"/>
+    </capability>
+    <capability namespace="osgi.wiring.service">
+      <attribute name="osgi.wiring.service" value="org.osgi.service.log.LogReaderService"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.4.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.log)(version>=1.3.0)(!(version>=2.0.0)))"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bndlib"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.47.1"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="ada77c7a30b73544942f5e1b6738ff80b3ce3f4c93705ad83bdbf8b70a8e3d9c"/>
+      <attribute name="url" value="biz.aQute.bndlib/biz.aQute.bndlib-1.47.1.jar"/>
+      <attribute name="size" type="Long" value="870648"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.47.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bndlib"/>
+      <attribute name="bundle-version" type="Version" value="1.47.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.metatype"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.annotation.component"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.osgi"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.annotation,aQute.libg.version,aQute.bnd.service,aQute.bnd.header,aQute.bnd.annotation.metatype,aQute.libg.reporter,aQute.libg.sed,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.build"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.service,aQute.bnd.osgi,aQute.libg.reporter,aQute.bnd.header,aQute.bnd.service.action,aQute.libg.sed,javax.naming"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+      <directive name="uses" value="aQute.bnd.osgi,aQute.libg.reporter,aQute.bnd.build,aQute.libg.version"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+      <directive name="uses" value="aQute.bnd.build"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.reporter"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.version"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sed"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.header"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="aQute.libg.reporter,aQute.libg.qtokens"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.qtokens"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.libg.sax"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.xml.sax,javax.xml.transform,javax.xml.parsers,javax.xml.transform.sax"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.bindex)(version>=1.0.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="biz.aQute.bnd"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.52.3"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="5cab3de85fb65f1c637e2bdce6b1e98e8a3964bed92258b75263c6b2e602b73c"/>
+      <attribute name="url" value="biz.aQute.bnd/biz.aQute.bnd-1.52.3.jar"/>
+      <attribute name="size" type="Long" value="1133121"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="biz.aQute.bnd"/>
+      <attribute name="bundle-version" type="Version" value="1.52.3"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="biz.aQute.bnd"/>
+      <attribute name="bundle-version" type="Version" value="1.52.3"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.osgi.service.bindex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service"/>
+      <attribute name="version" type="Version" value="1.44.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.action"/>
+      <attribute name="version" type="Version" value="1.43.1"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.url"/>
+      <attribute name="version" type="Version" value="1.52.3"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="aQute.bnd.service.diff"/>
+      <attribute name="version" type="Version" value="1.52.3"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.apache.tools.ant)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.stream)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=junit.framework)(version>=3.8.0)(!(version>=4.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.transform.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.service.component.annotations)(version>=1.2.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.apache.tools.ant.types)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.namespace)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=org.w3c.dom)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.xpath)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="ch.qos.logback.classic"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="971f35a106bc4852075a518da73ba03ca878c76f33d60f28b8bfb5443fcaaee4"/>
+      <attribute name="url" value="ch.qos.logback.classic/ch.qos.logback.classic-1.0.0.jar"/>
+      <attribute name="size" type="Long" value="249827"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="ch.qos.logback.classic"/>
+      <attribute name="bundle-version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="ch.qos.logback.classic"/>
+      <attribute name="bundle-version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic.turbo"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.spi,ch.qos.logback.classic,org.slf4j,ch.qos.logback.core.status,ch.qos.logback.classic.util,ch.qos.logback.core,ch.qos.logback.classic.gaffer,ch.qos.logback.core.joran.spi,ch.qos.logback.classic.joran,ch.qos.logback.core.joran.event,ch.qos.logback.core.joran.util"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic.db.names"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic.util"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.status,ch.qos.logback.classic,ch.qos.logback.core,ch.qos.logback.classic.gaffer,ch.qos.logback.core.joran.spi,ch.qos.logback.core.util,ch.qos.logback.classic.joran,ch.qos.logback.classic.selector,ch.qos.logback.core.filter,ch.qos.logback.classic.boolex,ch.qos.logback.classic.encoder,javax.naming,ch.qos.logback.classic.spi,org.slf4j.spi"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic.jmx"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.spi,ch.qos.logback.core.status,ch.qos.logback.classic.util,ch.qos.logback.classic,ch.qos.logback.core,javax.management,ch.qos.logback.core.joran.spi,ch.qos.logback.classic.joran,ch.qos.logback.core.util,ch.qos.logback.classic.spi"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic.jul"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.classic,ch.qos.logback.core.spi,ch.qos.logback.core,ch.qos.logback.classic.spi"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic.joran.action"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.classic.turbo,ch.qos.logback.classic,ch.qos.logback.core,ch.qos.logback.core.joran.spi,ch.qos.logback.core.joran.action,ch.qos.logback.core.util,org.xml.sax,ch.qos.logback.classic.net,ch.qos.logback.classic.boolex,ch.qos.logback.classic.util,javax.naming,ch.qos.logback.classic.jmx,javax.management,ch.qos.logback.core.spi,ch.qos.logback.classic.spi"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic.html"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.html,ch.qos.logback.core,ch.qos.logback.core.helpers,ch.qos.logback.classic.spi,ch.qos.logback.classic,ch.qos.logback.core.pattern,ch.qos.logback.classic.pattern"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.status,ch.qos.logback.core,ch.qos.logback.core.encoder,ch.qos.logback.classic.encoder,org.slf4j,org.slf4j.spi,ch.qos.logback.core.spi,ch.qos.logback.classic.spi,ch.qos.logback.classic.turbo,ch.qos.logback.classic.joran.action,ch.qos.logback.core.pattern,ch.qos.logback.core.pattern.parser,ch.qos.logback.classic.pattern,javax.servlet.http"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic.selector"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.status,javax.naming,ch.qos.logback.classic.util,ch.qos.logback.classic,ch.qos.logback.core,ch.qos.logback.core.joran.spi,ch.qos.logback.core.util,ch.qos.logback.classic.joran"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic.helpers"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="javax.servlet,org.slf4j,javax.servlet.http"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic.gaffer"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.status,ch.qos.logback.core.spi,groovy.lang,org.codehaus.groovy.reflection,org.codehaus.groovy.runtime,ch.qos.logback.core,org.codehaus.groovy.runtime.callsite,org.codehaus.groovy.runtime.typehandling,ch.qos.logback.classic,ch.qos.logback.classic.turbo,ch.qos.logback.core.util"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic.boolex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="groovy.lang,org.codehaus.groovy.runtime.typehandling,org.codehaus.groovy.reflection,org.codehaus.groovy.runtime,ch.qos.logback.classic.spi,org.codehaus.groovy.runtime.callsite,ch.qos.logback.core.spi,ch.qos.logback.core.boolex,ch.qos.logback.core.util,org.codehaus.groovy.control,ch.qos.logback.classic,ch.qos.logback.core,org.slf4j"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic.pattern"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.status,ch.qos.logback.core,ch.qos.logback.core.boolex,ch.qos.logback.classic.spi,ch.qos.logback.core.pattern,ch.qos.logback.core.util,ch.qos.logback.classic,org.slf4j,ch.qos.logback.classic.util,ch.qos.logback.core.net"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic.filter"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.spi,ch.qos.logback.core.filter,ch.qos.logback.classic,ch.qos.logback.classic.spi"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic.encoder"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.classic,ch.qos.logback.core.pattern,ch.qos.logback.core"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic.joran"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.joran.conditional,ch.qos.logback.classic.util,ch.qos.logback.classic.sift,ch.qos.logback.classic.joran.action,ch.qos.logback.core.joran,ch.qos.logback.core.joran.spi,ch.qos.logback.core.joran.action,ch.qos.logback.classic.spi"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic.net"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.spi,javax.naming,javax.jms,ch.qos.logback.core.net,ch.qos.logback.classic.spi,ch.qos.logback.classic.util,ch.qos.logback.classic,org.slf4j,ch.qos.logback.core.helpers,ch.qos.logback.core.pattern,ch.qos.logback.core,ch.qos.logback.core.boolex,ch.qos.logback.classic.boolex,ch.qos.logback.core.joran.spi,ch.qos.logback.classic.joran,ch.qos.logback.classic.pattern"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic.db"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.classic.db.names,ch.qos.logback.core.db,ch.qos.logback.classic,ch.qos.logback.classic.spi"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic.log4j"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.helpers,ch.qos.logback.classic,ch.qos.logback.core,ch.qos.logback.classic.spi"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic.selector.servlet"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="javax.servlet,javax.naming,ch.qos.logback.classic.util,ch.qos.logback.classic,ch.qos.logback.classic.selector,org.slf4j"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic.sift"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.joran.event,ch.qos.logback.core.sift,ch.qos.logback.classic.spi,ch.qos.logback.core.spi,ch.qos.logback.core.status,org.codehaus.groovy.reflection,ch.qos.logback.core,ch.qos.logback.classic.gaffer,org.codehaus.groovy.runtime.callsite,ch.qos.logback.core.helpers,ch.qos.logback.core.filter,groovy.lang,org.codehaus.groovy.runtime.typehandling,org.codehaus.groovy.runtime,ch.qos.logback.classic.util,ch.qos.logback.classic,ch.qos.logback.c [...]
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.classic.spi"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core,ch.qos.logback.core.spi,ch.qos.logback.classic,org.slf4j,org.slf4j.spi,ch.qos.logback.classic.util,org.slf4j.helpers,sun.reflect,ch.qos.logback.classic.turbo"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="org.slf4j.impl"/>
+      <attribute name="version" type="Version" value="1.6.4"/>
+      <directive name="uses" value="org.slf4j.spi,ch.qos.logback.classic.util,org.slf4j.helpers,ch.qos.logback.classic,ch.qos.logback.core,ch.qos.logback.classic.selector,ch.qos.logback.core.joran.spi,org.slf4j,ch.qos.logback.core.util"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic.boolex)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic.db)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic.db.names)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic.encoder)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic.filter)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic.gaffer)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic.helpers)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic.html)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic.jmx)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic.joran)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic.joran.action)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic.jul)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic.log4j)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic.net)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic.pattern)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic.selector)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic.selector.servlet)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic.sift)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic.spi)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic.turbo)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.classic.util)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.boolex)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.db)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.encoder)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.filter)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.helpers)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.html)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.joran)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.joran.action)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.joran.conditional)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.joran.event)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.joran.spi)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.joran.util)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.net)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.pattern)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.pattern.parser)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.read)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.rolling)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.rolling.helper)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.sift)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.spi)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.status)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.util)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=groovy.lang)(version>=1.7.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.jms)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.management)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.servlet)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.servlet.http)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.codehaus.groovy.control)(version>=1.7.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.codehaus.groovy.reflection)(version>=1.7.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.codehaus.groovy.runtime)(version>=1.7.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.codehaus.groovy.runtime.callsite)(version>=1.7.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(&(osgi.wiring.package=org.codehaus.groovy.runtime.typehandling)(version>=1.7.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.slf4j)(version>=1.6.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.slf4j.helpers)(version>=1.6.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.slf4j.impl)(version>=1.6.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=org.slf4j.spi)(version>=1.6.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=sun.reflect)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace="osgi.identity">
+      <attribute name="osgi.identity" value="ch.qos.logback.core"/>
+      <attribute name="type" value="osgi.bundle"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.content">
+      <attribute name="osgi.content" value="44d390d4225369f1b9da619901ecca416941642dce207467b9ae8ebf84f0d497"/>
+      <attribute name="url" value="ch.qos.logback.core/ch.qos.logback.core-1.0.0.jar"/>
+      <attribute name="size" type="Long" value="332750"/>
+    </capability>
+    <capability namespace="osgi.wiring.bundle">
+      <attribute name="osgi.wiring.bundle" value="ch.qos.logback.core"/>
+      <attribute name="bundle-version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.host">
+      <attribute name="osgi.wiring.host" value="ch.qos.logback.core"/>
+      <attribute name="bundle-version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.spi"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core,ch.qos.logback.core.status,ch.qos.logback.core.helpers,ch.qos.logback.core.filter"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.status"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.spi,ch.qos.logback.core,ch.qos.logback.core.util,ch.qos.logback.core.helpers,javax.servlet,javax.servlet.http"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.db.dialect"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.spi"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.property"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.spi,ch.qos.logback.core.status,ch.qos.logback.core.filter,ch.qos.logback.core.helpers,ch.qos.logback.core.joran.spi,ch.qos.logback.core.recovery,ch.qos.logback.core.util,ch.qos.logback.core.encoder"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.encoder"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core,ch.qos.logback.core.spi"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.joran.action"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.spi,ch.qos.logback.core.boolex,ch.qos.logback.core,ch.qos.logback.core.joran.spi,ch.qos.logback.core.util,org.xml.sax,ch.qos.logback.core.joran.util,ch.qos.logback.core.joran.event,ch.qos.logback.core.pattern.util,ch.qos.logback.core.status"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.joran.spi"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.spi,org.xml.sax,ch.qos.logback.core.joran.event,ch.qos.logback.core,ch.qos.logback.core.util,ch.qos.logback.core.joran.action,ch.qos.logback.core.status"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.joran.event"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="org.xml.sax,org.xml.sax.helpers,ch.qos.logback.core.status,ch.qos.logback.core.spi,javax.xml.parsers,ch.qos.logback.core,ch.qos.logback.core.joran.spi"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.net"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="javax.naming,ch.qos.logback.core,javax.mail,ch.qos.logback.core.helpers,ch.qos.logback.core.spi,ch.qos.logback.core.sift,javax.mail.internet,ch.qos.logback.core.pattern,ch.qos.logback.core.boolex,ch.qos.logback.core.util"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.joran"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.status,ch.qos.logback.core.spi,ch.qos.logback.core.joran.event,ch.qos.logback.core,ch.qos.logback.core.joran.util,ch.qos.logback.core.joran.spi,org.xml.sax,ch.qos.logback.core.joran.action"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.boolex"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.spi,org.codehaus.janino,ch.qos.logback.core"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.rolling"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core,ch.qos.logback.core.rolling.helper,ch.qos.logback.core.spi,ch.qos.logback.core.joran.spi,ch.qos.logback.core.util"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.recovery"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.status,ch.qos.logback.core,ch.qos.logback.core.net"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.sift"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.joran.event,ch.qos.logback.core,ch.qos.logback.core.joran.spi,ch.qos.logback.core.spi,ch.qos.logback.core.helpers,ch.qos.logback.core.joran,ch.qos.logback.core.joran.action"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.db"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="javax.naming,javax.sql,ch.qos.logback.core,ch.qos.logback.core.joran.spi,ch.qos.logback.core.joran.util,ch.qos.logback.core.joran.action,ch.qos.logback.core.util,org.xml.sax,ch.qos.logback.core.spi,ch.qos.logback.core.db.dialect"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.read"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.helpers,ch.qos.logback.core"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.pattern"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.status,ch.qos.logback.core.spi,ch.qos.logback.core,ch.qos.logback.core.pattern.parser,ch.qos.logback.core.encoder"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.pattern.parser"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.status,ch.qos.logback.core.spi,ch.qos.logback.core.pattern,ch.qos.logback.core,ch.qos.logback.core.util,ch.qos.logback.core.pattern.util"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.html"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.pattern,ch.qos.logback.core,ch.qos.logback.core.pattern.parser"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.joran.conditional"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.joran.event,ch.qos.logback.core.spi,ch.qos.logback.core,ch.qos.logback.core.joran.spi,ch.qos.logback.core.joran.action,ch.qos.logback.core.util,org.xml.sax,org.codehaus.janino"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.helpers"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.filter"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.spi,ch.qos.logback.core.boolex"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.layout"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.pattern.util"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.joran.util"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.status,ch.qos.logback.core,ch.qos.logback.core.joran.spi,ch.qos.logback.core.util,ch.qos.logback.core.spi"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.util"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.spi,ch.qos.logback.core,ch.qos.logback.core.status,ch.qos.logback.core.helpers"/>
+    </capability>
+    <capability namespace="osgi.wiring.package">
+      <attribute name="osgi.wiring.package" value="ch.qos.logback.core.rolling.helper"/>
+      <attribute name="version" type="Version" value="1.0.0"/>
+      <directive name="uses" value="ch.qos.logback.core.spi,ch.qos.logback.core.status,ch.qos.logback.core.pattern,ch.qos.logback.core.util,ch.qos.logback.core.pattern.util,ch.qos.logback.core,ch.qos.logback.core.pattern.parser,ch.qos.logback.core.rolling"/>
+    </capability>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.boolex)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.db)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.db.dialect)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.encoder)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.filter)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.helpers)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.html)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.joran)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.joran.action)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.joran.conditional)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.joran.event)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.joran.spi)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.joran.util)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.layout)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.net)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.pattern)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.pattern.parser)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.pattern.util)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.property)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.read)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.recovery)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.rolling)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.rolling.helper)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.sift)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.spi)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.status)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="filter" value="(&(osgi.wiring.package=ch.qos.logback.core.util)(version>=1.0.0))"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.mail)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.mail.internet)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.naming)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.servlet)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.servlet.http)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.sql)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=javax.xml.parsers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.codehaus.janino)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.package">
+      <directive name="resolution" value="optional"/>
+      <directive name="filter" value="(osgi.wiring.package=org.xml.sax.helpers)"/>
+    </requirement>
+    <requirement namespace="osgi.wiring.ee">
+      <directive name="filter" value="(ee=J2SE-1.5)"/>
+    </requirement>
+  </resource>
+</repository>
diff --git a/biz.aQute.repository/testdata/big_index.xml.gz b/biz.aQute.repository/testdata/big_index.xml.gz
new file mode 100644
index 0000000..9da4ad1
Binary files /dev/null and b/biz.aQute.repository/testdata/big_index.xml.gz differ
diff --git a/biz.aQute.repository/testdata/bree-obr.xml b/biz.aQute.repository/testdata/bree-obr.xml
new file mode 100644
index 0000000..ab82c47
--- /dev/null
+++ b/biz.aQute.repository/testdata/bree-obr.xml
@@ -0,0 +1,19 @@
+<?xml version='1.0' encoding='utf-8'?>
+<?xml-stylesheet type='text/xsl' href='http://www2.osgi.org/www/obr2html.xsl'?>
+
+<repository lastmodified='20120708085553.753' name='Untitled'>
+  <resource id='org.example.m/0.0.0' presentationname='org.example.m' symbolicname='org.example.m' uri='13-bree.jar' version='0.0.0'>
+    <size>
+      1144
+    </size>
+    <capability name='bundle'>
+      <p n='manifestversion' v='2'/>
+      <p n='presentationname' v='org.example.m'/>
+      <p n='symbolicname' v='org.example.m'/>
+      <p n='version' t='version' v='0.0.0'/>
+    </capability>
+    <require extend='false' filter='(|(ee=J2SE-1.4)(ee=OSGi/Minimum-1.1))' multiple='false' name='ee' optional='false'>
+      Execution Environment (|(ee=J2SE-1.4)(ee=OSGi/Minimum-1.1))
+    </require>
+  </resource>
+</repository>
\ No newline at end of file
diff --git a/biz.aQute.repository/testdata/dummy.dtd b/biz.aQute.repository/testdata/dummy.dtd
new file mode 100644
index 0000000..b419747
--- /dev/null
+++ b/biz.aQute.repository/testdata/dummy.dtd
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!ELEMENT root (#PCDATA)>
\ No newline at end of file
diff --git a/biz.aQute.repository/testdata/example.keystore b/biz.aQute.repository/testdata/example.keystore
new file mode 100644
index 0000000..bb63ec9
Binary files /dev/null and b/biz.aQute.repository/testdata/example.keystore differ
diff --git a/biz.aQute.repository/testdata/fullobr.xml b/biz.aQute.repository/testdata/fullobr.xml
new file mode 100644
index 0000000..e1ad020
--- /dev/null
+++ b/biz.aQute.repository/testdata/fullobr.xml
@@ -0,0 +1,553 @@
+<?xml version='1.0' encoding='utf-8'?>
+<?xml-stylesheet type='text/xsl' href='http://www2.osgi.org/www/obr2html.xsl'?>
+
+<repository lastmodified='20110425120125.066' name='Untitled'>
+  <resource id='name.njbartlett.osgi.emf.minimal/2.7.0.201104130744' presentationname='name.njbartlett.osgi.emf.minimal' symbolicname='name.njbartlett.osgi.emf.minimal' uri='bundles/name.njbartlett.osgi.emf.minimal-2.7.0.jar' version='2.7.0.201104130744'>
+    <size>
+      2005961
+    </size>
+    <capability name='bundle'>
+      <p n='manifestversion' v='2'/>
+      <p n='presentationname' v='name.njbartlett.osgi.emf.minimal'/>
+      <p n='symbolicname' v='name.njbartlett.osgi.emf.minimal'/>
+      <p n='version' t='version' v='2.7.0.201104130744'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.common'/>
+      <p n='uses' v='org.eclipse.core.runtime,org.eclipse.emf.common.util,org.osgi.framework'/>
+      <p n='version' t='version' v='2.7.0.201104130744'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.common.notify'/>
+      <p n='uses' v='org.eclipse.emf.common.util'/>
+      <p n='version' t='version' v='2.7.0.201104130744'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.common.notify.impl'/>
+      <p n='uses' v='org.eclipse.emf.common.util,org.eclipse.emf.common.notify'/>
+      <p n='version' t='version' v='2.7.0.201104130744'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.common.util'/>
+      <p n='uses' v='org.eclipse.core.runtime,org.eclipse.emf.common'/>
+      <p n='version' t='version' v='2.7.0.201104130744'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore'/>
+      <p n='uses' v='org.eclipse.emf.common.util,org.eclipse.emf.ecore.resource,org.eclipse.emf.common.notify,org.eclipse.emf.ecore.impl,org.eclipse.emf.ecore.util'/>
+      <p n='version' t='version' v='2.7.0.201104130744'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.impl'/>
+      <p n='uses' v='org.eclipse.emf.ecore.util,org.eclipse.emf.ecore,org.eclipse.emf.common.util,org.eclipse.emf.ecore.resource,org.eclipse.emf.common.notify.impl,org.eclipse.emf.common.notify,org.eclipse.emf.ecore.xml.type.util,org.eclipse.emf.common,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.ecore.plugin,org.eclipse.emf.ecore.xml.type'/>
+      <p n='version' t='version' v='2.7.0.201104130744'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.plugin'/>
+      <p n='uses' v='org.eclipse.emf.ecore.resource,org.eclipse.core.runtime,org.osgi.framework,org.eclipse.emf.ecore,org.xml.sax.helpers,org.xml.sax,org.eclipse.emf.ecore.impl,org.eclipse.core.resources,org.eclipse.emf.common,org.eclipse.emf.common.util,javax.xml.parsers,org.eclipse.emf.ecore.util,org.eclipse.emf.ecore.resource.impl'/>
+      <p n='version' t='version' v='2.7.0.201104130744'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.resource'/>
+      <p n='uses' v='org.eclipse.core.runtime.content,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.common.util,org.eclipse.emf.ecore,org.eclipse.emf.common.notify'/>
+      <p n='version' t='version' v='2.7.0.201104130744'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.resource.impl'/>
+      <p n='uses' v='org.eclipse.emf.ecore.resource,javax.crypto.spec,javax.crypto,org.eclipse.emf.common.util,org.eclipse.emf.ecore,org.eclipse.emf.ecore.util,org.eclipse.core.runtime,org.eclipse.core.runtime.content,org.eclipse.emf.common,org.eclipse.emf.ecore.plugin,org.eclipse.core.resources,org.eclipse.emf.common.notify.impl,org.eclipse.emf.common.notify,org.eclipse.emf.ecore.impl'/>
+      <p n='version' t='version' v='2.7.0.201104130744'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.xml.namespace'/>
+      <p n='uses' v='org.eclipse.emf.common.util,org.eclipse.emf.ecore.util,org.eclipse.emf.ecore'/>
+      <p n='version' t='version' v='2.7.0.201104130744'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.xml.type'/>
+      <p n='uses' v='org.eclipse.emf.ecore.util,org.eclipse.emf.ecore,org.eclipse.emf.common.util,javax.xml.datatype,javax.xml.namespace'/>
+      <p n='version' t='version' v='2.7.0.201104130744'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.xml.type.internal'/>
+      <p n='uses' v='org.eclipse.emf.ecore.xml.type,javax.xml.namespace,org.eclipse.emf.ecore.plugin,org.eclipse.emf.common.util,org.eclipse.emf.ecore.xml.type.util,javax.xml.datatype'/>
+      <p n='version' t='version' v='2.7.0.201104130744'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.xml.type.util'/>
+      <p n='uses' v='org.xml.sax,org.eclipse.emf.ecore.xml.type,javax.xml.namespace,javax.xml.datatype,org.xml.sax.helpers,org.eclipse.emf.common.util,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.ecore,org.eclipse.emf.ecore.xml.type.internal,org.eclipse.emf.ecore.plugin,org.eclipse.emf.ecore.util'/>
+      <p n='version' t='version' v='2.7.0.201104130744'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.util'/>
+      <p n='uses' v='org.eclipse.emf.common.notify,org.eclipse.emf.ecore,org.eclipse.emf.common.util,org.eclipse.emf.ecore.xml.type,org.eclipse.emf.ecore.xml.type.util,org.eclipse.emf.ecore.impl,org.eclipse.emf.common.notify.impl,org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.plugin,org.eclipse.emf.ecore.xml.namespace'/>
+      <p n='version' t='version' v='2.7.0.201104130744'/>
+    </capability>
+    <require extend='false' filter='(&(package=javax.crypto)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package javax.crypto
+    </require>
+    <require extend='false' filter='(&(package=javax.crypto.spec)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package javax.crypto.spec
+    </require>
+    <require extend='false' filter='(&(package=javax.xml.datatype)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package javax.xml.datatype
+    </require>
+    <require extend='false' filter='(&(package=javax.xml.namespace)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package javax.xml.namespace
+    </require>
+    <require extend='false' filter='(&(package=javax.xml.parsers)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package javax.xml.parsers
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.core.resources)(version>=0.0.0))' multiple='false' name='package' optional='true'>
+      Import package org.eclipse.core.resources
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.core.runtime)(version>=0.0.0))' multiple='false' name='package' optional='true'>
+      Import package org.eclipse.core.runtime
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.core.runtime.content)(version>=0.0.0))' multiple='false' name='package' optional='true'>
+      Import package org.eclipse.core.runtime.content
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.common.notify)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.common.notify
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.common.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.common.util
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.impl)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.impl
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.plugin)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.plugin
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.resource)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.resource
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.util
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.type.internal)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.xml.type.internal
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.type.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.xml.type.util
+    </require>
+    <require extend='false' filter='(&(package=org.osgi.framework)(version>=1.6.0)(!(version>=2.0.0)))' multiple='false' name='package' optional='false'>
+      Import package org.osgi.framework ;version=[1.6.0,2.0.0)
+    </require>
+    <require extend='false' filter='(&(package=org.xml.sax)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.xml.sax
+    </require>
+    <require extend='false' filter='(&(package=org.xml.sax.helpers)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.xml.sax.helpers
+    </require>
+  </resource>
+  <resource id='name.njbartlett.osgi.emf.minimal/2.6.1.v20100914-1218' presentationname='name.njbartlett.osgi.emf.minimal' symbolicname='name.njbartlett.osgi.emf.minimal' uri='bundles/name.njbartlett.osgi.emf.minimal-2.6.1.jar' version='2.6.1.v20100914-1218'>
+    <size>
+      2029922
+    </size>
+    <capability name='bundle'>
+      <p n='manifestversion' v='2'/>
+      <p n='presentationname' v='name.njbartlett.osgi.emf.minimal'/>
+      <p n='symbolicname' v='name.njbartlett.osgi.emf.minimal'/>
+      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.common'/>
+      <p n='uses' v='org.eclipse.core.runtime,org.eclipse.emf.common.util,org.osgi.framework'/>
+      <p n='version' t='version' v='2.6.0.v20100914-1218'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.common.notify'/>
+      <p n='uses' v='org.eclipse.emf.common.util'/>
+      <p n='version' t='version' v='2.6.0.v20100914-1218'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.common.notify.impl'/>
+      <p n='uses' v='org.eclipse.emf.common.util,org.eclipse.emf.common.notify'/>
+      <p n='version' t='version' v='2.6.0.v20100914-1218'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.common.util'/>
+      <p n='uses' v='org.eclipse.core.runtime,org.eclipse.emf.common'/>
+      <p n='version' t='version' v='2.6.0.v20100914-1218'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore'/>
+      <p n='uses' v='org.eclipse.emf.common.util,org.eclipse.emf.ecore.resource,org.eclipse.emf.common.notify,org.eclipse.emf.ecore.impl,org.eclipse.emf.ecore.util'/>
+      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.impl'/>
+      <p n='uses' v='org.eclipse.emf.ecore.util,org.eclipse.emf.ecore,org.eclipse.emf.common.util,org.eclipse.emf.ecore.resource,org.eclipse.emf.common.notify.impl,org.eclipse.emf.common.notify,org.eclipse.emf.ecore.xml.type.util,org.eclipse.emf.common,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.ecore.plugin,org.eclipse.emf.ecore.xml.type'/>
+      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.plugin'/>
+      <p n='uses' v='org.eclipse.emf.ecore.resource,org.eclipse.core.runtime,org.osgi.framework,org.eclipse.emf.ecore,org.xml.sax.helpers,org.xml.sax,org.eclipse.emf.ecore.impl,org.eclipse.core.resources,org.eclipse.emf.common,org.eclipse.emf.common.util,javax.xml.parsers,org.eclipse.emf.ecore.resource.impl'/>
+      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.resource'/>
+      <p n='uses' v='org.eclipse.core.runtime.content,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.common.util,org.eclipse.emf.ecore,org.eclipse.emf.common.notify'/>
+      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.resource.impl'/>
+      <p n='uses' v='org.eclipse.emf.ecore.resource,javax.crypto.spec,javax.crypto,org.eclipse.emf.common.util,org.eclipse.emf.ecore,org.eclipse.emf.ecore.util,org.eclipse.core.runtime,org.eclipse.core.runtime.content,org.eclipse.emf.common,org.eclipse.emf.ecore.plugin,org.eclipse.core.resources,org.eclipse.emf.common.notify.impl,org.eclipse.emf.common.notify,org.eclipse.emf.ecore.impl'/>
+      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.xml.namespace'/>
+      <p n='uses' v='org.eclipse.emf.common.util,org.eclipse.emf.ecore.util,org.eclipse.emf.ecore'/>
+      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.xml.type'/>
+      <p n='uses' v='org.eclipse.emf.ecore.util,org.eclipse.emf.ecore,org.eclipse.emf.common.util,javax.xml.datatype,javax.xml.namespace'/>
+      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.xml.type.internal'/>
+      <p n='uses' v='org.eclipse.emf.ecore.xml.type,javax.xml.namespace,org.eclipse.emf.ecore.plugin,org.eclipse.emf.common.util,org.eclipse.emf.ecore.xml.type.util,javax.xml.datatype'/>
+      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.xml.type.util'/>
+      <p n='uses' v='org.xml.sax,org.eclipse.emf.ecore.xml.type,javax.xml.datatype,javax.xml.namespace,org.xml.sax.helpers,org.eclipse.emf.common.util,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.ecore,org.eclipse.emf.ecore.xml.type.internal,org.eclipse.emf.ecore.plugin,org.eclipse.emf.ecore.util'/>
+      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.util'/>
+      <p n='uses' v='org.eclipse.emf.common.notify,org.eclipse.emf.ecore,org.eclipse.emf.common.util,org.eclipse.emf.ecore.xml.type,org.eclipse.emf.ecore.xml.type.util,org.eclipse.emf.ecore.impl,org.eclipse.emf.common.notify.impl,org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.plugin,org.eclipse.emf.ecore.xml.namespace'/>
+      <p n='version' t='version' v='2.6.1.v20100914-1218'/>
+    </capability>
+    <require extend='false' filter='(&(package=javax.crypto)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package javax.crypto
+    </require>
+    <require extend='false' filter='(&(package=javax.crypto.spec)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package javax.crypto.spec
+    </require>
+    <require extend='false' filter='(&(package=javax.xml.datatype)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package javax.xml.datatype
+    </require>
+    <require extend='false' filter='(&(package=javax.xml.namespace)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package javax.xml.namespace
+    </require>
+    <require extend='false' filter='(&(package=javax.xml.parsers)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package javax.xml.parsers
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.core.resources)(version>=0.0.0))' multiple='false' name='package' optional='true'>
+      Import package org.eclipse.core.resources
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.core.runtime)(version>=0.0.0))' multiple='false' name='package' optional='true'>
+      Import package org.eclipse.core.runtime
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.core.runtime.content)(version>=0.0.0))' multiple='false' name='package' optional='true'>
+      Import package org.eclipse.core.runtime.content
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.common.notify)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.common.notify
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.common.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.common.util
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.impl)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.impl
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.plugin)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.plugin
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.resource)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.resource
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.util
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.type.internal)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.xml.type.internal
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.type.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.xml.type.util
+    </require>
+    <require extend='false' filter='(&(package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))' multiple='false' name='package' optional='false'>
+      Import package org.osgi.framework ;version=[1.5.0,2.0.0)
+    </require>
+    <require extend='false' filter='(&(package=org.xml.sax)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.xml.sax
+    </require>
+    <require extend='false' filter='(&(package=org.xml.sax.helpers)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.xml.sax.helpers
+    </require>
+  </resource>
+  <resource id='name.njbartlett.osgi.emf.xmi/2.5.0.v20100521-1846' presentationname='name.njbartlett.osgi.emf.xmi' symbolicname='name.njbartlett.osgi.emf.xmi' uri='bundles/name.njbartlett.osgi.emf.xmi-2.5.0.jar' version='2.5.0.v20100521-1846'>
+    <size>
+      357938
+    </size>
+    <capability name='bundle'>
+      <p n='manifestversion' v='2'/>
+      <p n='presentationname' v='name.njbartlett.osgi.emf.xmi'/>
+      <p n='symbolicname' v='name.njbartlett.osgi.emf.xmi'/>
+      <p n='version' t='version' v='2.5.0.v20100521-1846'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.xmi'/>
+      <p n='uses' v='org.eclipse.emf.ecore,org.w3c.dom,org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.util,org.eclipse.emf.common.util,org.eclipse.emf.common,org.xml.sax.ext,org.xml.sax,javax.xml.parsers,org.eclipse.emf.ecore.xml.type'/>
+      <p n='version' t='version' v='2.5.0.v20100521-1846'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.xmi.impl'/>
+      <p n='uses' v='org.eclipse.emf.ecore.xmi,org.eclipse.emf.ecore,org.eclipse.emf.ecore.util,org.w3c.dom,org.eclipse.emf.common.util,org.xml.sax,org.xml.sax.helpers,org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.ecore.xml.type,org.eclipse.emf.common,org.eclipse.emf.ecore.impl,org.eclipse.emf.ecore.xml.type.util,org.eclipse.emf.ecore.xmi.util,org.eclipse.emf.ecore.xml.type.internal,javax.xml.namespace,org.xml.sax.ext,javax.xml.parsers,org.eclipse.emf [...]
+      <p n='version' t='version' v='2.5.0.v20100521-1846'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.xmi.util'/>
+      <p n='uses' v='org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.util,org.eclipse.emf.ecore.xmi,org.eclipse.emf.common.util,org.eclipse.emf.common,org.eclipse.emf.ecore.xmi.impl,org.eclipse.emf.ecore.resource.impl,org.w3c.dom,org.xml.sax,org.eclipse.emf.ecore,org.eclipse.emf.ecore.impl'/>
+      <p n='version' t='version' v='2.5.0.v20100521-1846'/>
+    </capability>
+    <require extend='false' filter='(&(package=javax.xml.namespace)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package javax.xml.namespace
+    </require>
+    <require extend='false' filter='(&(package=javax.xml.parsers)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package javax.xml.parsers
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.common)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.common
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.common.notify)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.common.notify
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.common.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.common.util
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.impl)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.impl
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.resource)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.resource
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.resource.impl)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.resource.impl
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.util
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.namespace)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.xml.namespace
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.type)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.xml.type
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.type.internal)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.xml.type.internal
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.type.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.xml.type.util
+    </require>
+    <require extend='false' filter='(&(package=org.w3c.dom)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.w3c.dom
+    </require>
+    <require extend='false' filter='(&(package=org.xml.sax)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.xml.sax
+    </require>
+    <require extend='false' filter='(&(package=org.xml.sax.ext)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.xml.sax.ext
+    </require>
+    <require extend='false' filter='(&(package=org.xml.sax.helpers)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.xml.sax.helpers
+    </require>
+  </resource>
+  <resource id='name.njbartlett.osgi.emf.xmi/2.7.0.201104130744' presentationname='name.njbartlett.osgi.emf.xmi' symbolicname='name.njbartlett.osgi.emf.xmi' uri='bundles/name.njbartlett.osgi.emf.xmi-2.7.0.jar' version='2.7.0.201104130744'>
+    <size>
+      362154
+    </size>
+    <capability name='bundle'>
+      <p n='manifestversion' v='2'/>
+      <p n='presentationname' v='name.njbartlett.osgi.emf.xmi'/>
+      <p n='symbolicname' v='name.njbartlett.osgi.emf.xmi'/>
+      <p n='version' t='version' v='2.7.0.201104130744'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.xmi'/>
+      <p n='uses' v='org.eclipse.emf.ecore,org.w3c.dom,org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.util,org.eclipse.emf.common.util,org.eclipse.emf.common,org.xml.sax.ext,org.xml.sax,javax.xml.parsers,org.eclipse.emf.ecore.xml.type'/>
+      <p n='version' t='version' v='2.7.0.201104130744'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.xmi.impl'/>
+      <p n='uses' v='org.eclipse.emf.ecore.xmi,org.eclipse.emf.ecore,org.eclipse.emf.ecore.util,org.w3c.dom,org.eclipse.emf.common.util,org.xml.sax,org.xml.sax.helpers,org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.ecore.xml.type,org.eclipse.emf.common,org.eclipse.emf.ecore.impl,org.eclipse.emf.ecore.xml.type.util,org.eclipse.emf.ecore.xmi.util,org.eclipse.emf.ecore.xml.type.internal,javax.xml.namespace,org.xml.sax.ext,javax.xml.parsers,org.eclipse.emf [...]
+      <p n='version' t='version' v='2.7.0.201104130744'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.eclipse.emf.ecore.xmi.util'/>
+      <p n='uses' v='org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.util,org.eclipse.emf.ecore.xmi,org.eclipse.emf.common.util,org.eclipse.emf.common,org.eclipse.emf.ecore.xmi.impl,org.eclipse.emf.ecore.resource.impl,org.w3c.dom,org.xml.sax,org.eclipse.emf.ecore,org.eclipse.emf.ecore.impl'/>
+      <p n='version' t='version' v='2.7.0.201104130744'/>
+    </capability>
+    <require extend='false' filter='(&(package=javax.xml.namespace)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package javax.xml.namespace
+    </require>
+    <require extend='false' filter='(&(package=javax.xml.parsers)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package javax.xml.parsers
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.common)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.common
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.common.notify)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.common.notify
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.common.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.common.util
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.impl)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.impl
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.resource)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.resource
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.resource.impl)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.resource.impl
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.util
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.namespace)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.xml.namespace
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.type)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.xml.type
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.type.internal)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.xml.type.internal
+    </require>
+    <require extend='false' filter='(&(package=org.eclipse.emf.ecore.xml.type.util)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.eclipse.emf.ecore.xml.type.util
+    </require>
+    <require extend='false' filter='(&(package=org.w3c.dom)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.w3c.dom
+    </require>
+    <require extend='false' filter='(&(package=org.xml.sax)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.xml.sax
+    </require>
+    <require extend='false' filter='(&(package=org.xml.sax.ext)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.xml.sax.ext
+    </require>
+    <require extend='false' filter='(&(package=org.xml.sax.helpers)(version>=0.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.xml.sax.helpers
+    </require>
+  </resource>
+  <resource id='org.apache.felix.shell/1.4.2' presentationname='Apache Felix Shell Service' symbolicname='org.apache.felix.shell' uri='bundles/org.apache.felix.shell-1.4.2.jar' version='1.4.2'>
+    <description>
+      A simple OSGi command shell service.
+    </description>
+    <size>
+      62719
+    </size>
+    <license>
+      http://www.apache.org/licenses/LICENSE-2.0.txt
+    </license>
+    <documentation>
+      http://www.apache.org/
+    </documentation>
+    <capability name='service'>
+      <p n='service' v='org.apache.felix.shell.ShellService'/>
+    </capability>
+    <capability name='service'>
+      <p n='service' v='org.ungoverned.osgi.service.shell.ShellService'/>
+    </capability>
+    <capability name='bundle'>
+      <p n='manifestversion' v='2'/>
+      <p n='presentationname' v='Apache Felix Shell Service'/>
+      <p n='symbolicname' v='org.apache.felix.shell'/>
+      <p n='version' t='version' v='1.4.2'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.ungoverned.osgi.service.shell'/>
+      <p n='uses' v='org.osgi.framework'/>
+      <p n='version' t='version' v='1.0.0'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.osgi.service.log'/>
+      <p n='uses' v='org.osgi.framework'/>
+      <p n='version' t='version' v='1.3.0'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.apache.felix.shell'/>
+      <p n='uses' v='org.osgi.framework'/>
+      <p n='version' t='version' v='1.0.0'/>
+    </capability>
+    <require extend='false' filter='(service=org.osgi.service.startlevel.StartLevel)' multiple='true' name='service' optional='false'>
+      Import Service org.osgi.service.startlevel.StartLevel
+    </require>
+    <require extend='false' filter='(service=org.osgi.service.packageadmin.PackageAdmin)' multiple='true' name='service' optional='false'>
+      Import Service org.osgi.service.packageadmin.PackageAdmin
+    </require>
+    <require extend='false' filter='(&(package=org.apache.felix.shell)(version>=1.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.apache.felix.shell ;version=1.0.0
+    </require>
+    <require extend='false' filter='(&(package=org.osgi.framework)(version>=1.4.0))' multiple='false' name='package' optional='false'>
+      Import package org.osgi.framework ;version=1.4.0
+    </require>
+    <require extend='false' filter='(&(package=org.osgi.service.log)(version>=1.3.0))' multiple='false' name='package' optional='false'>
+      Import package org.osgi.service.log ;version=1.3.0
+    </require>
+    <require extend='false' filter='(&(package=org.osgi.service.packageadmin)(version>=1.2.0))' multiple='false' name='package' optional='false'>
+      Import package org.osgi.service.packageadmin ;version=1.2.0
+    </require>
+    <require extend='false' filter='(&(package=org.osgi.service.startlevel)(version>=1.1.0))' multiple='false' name='package' optional='false'>
+      Import package org.osgi.service.startlevel ;version=1.1.0
+    </require>
+    <require extend='false' filter='(&(package=org.ungoverned.osgi.service.shell)(version>=1.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.ungoverned.osgi.service.shell ;version=1.0.0
+    </require>
+  </resource>
+  <resource id='org.apache.felix.shell.tui/1.4.1' presentationname='Apache Felix Shell TUI' symbolicname='org.apache.felix.shell.tui' uri='bundles/org.apache.felix.shell.tui-1.4.1.jar' version='1.4.1'>
+    <description>
+      A simple textual user interface for Felix' shell service.
+    </description>
+    <size>
+      12740
+    </size>
+    <license>
+      http://www.apache.org/licenses/LICENSE-2.0.txt
+    </license>
+    <documentation>
+      http://felix.apache.org/site/apache-felix-shell-tui.html
+    </documentation>
+    <capability name='bundle'>
+      <p n='manifestversion' v='2'/>
+      <p n='presentationname' v='Apache Felix Shell TUI'/>
+      <p n='symbolicname' v='org.apache.felix.shell.tui'/>
+      <p n='version' t='version' v='1.4.1'/>
+    </capability>
+    <require extend='false' filter='(service=org.apache.felix.shell.ShellService)' multiple='true' name='service' optional='false'>
+      Import Service org.apache.felix.shell.ShellService
+    </require>
+    <require extend='false' filter='(&(package=org.apache.felix.shell)(version>=1.0.0))' multiple='false' name='package' optional='false'>
+      Import package org.apache.felix.shell ;version=1.0.0
+    </require>
+    <require extend='false' filter='(&(package=org.osgi.framework)(version>=1.3.0))' multiple='false' name='package' optional='false'>
+      Import package org.osgi.framework ;version=1.3.0
+    </require>
+  </resource>
+  <resource id='org.example.dummy/1.0.0' presentationname='Dummy' symbolicname='org.example.dummy' uri='http://127.0.0.1:__httpdPort__/bundles/dummybundle.jar' version='1.0.0'>
+    <capability name='bundle'>
+      <p n='manifestversion' v='2'/>
+      <p n='presentationname' v='Dummy'/>
+      <p n='symbolicname' v='org.example.dummy'/>
+      <p n='version' t='version' v='1.0.0'/>
+    </capability>
+    <capability name='package'>
+      <p n='package' v='org.example.dummy'/>
+      <p n='version' t='version' v='1.0.0'/>
+    </capability>
+  </resource>
+</repository>
\ No newline at end of file
diff --git a/biz.aQute.repository/testdata/http_auth.properties b/biz.aQute.repository/testdata/http_auth.properties
new file mode 100644
index 0000000..618428f
--- /dev/null
+++ b/biz.aQute.repository/testdata/http_auth.properties
@@ -0,0 +1,3 @@
+pattern.foo: .*dummybundle.jar
+uid.foo: AliBaba
+pwd.foo: OpenSesame
\ No newline at end of file
diff --git a/biz.aQute.repository/testdata/http_auth_wrong.properties b/biz.aQute.repository/testdata/http_auth_wrong.properties
new file mode 100644
index 0000000..a7c2596
--- /dev/null
+++ b/biz.aQute.repository/testdata/http_auth_wrong.properties
@@ -0,0 +1,4 @@
+# Contains the WRONG password for this user
+pattern.foo: .*dummybundle.jar
+uid.foo: AliBaba
+pwd.foo: Let Me In
\ No newline at end of file
diff --git a/biz.aQute.repository/testdata/httpcache/4/http%3A%2F%2Flocalhost%3A18083%2Fbundles/dummybundle.jar.etag b/biz.aQute.repository/testdata/httpcache/4/http%3A%2F%2Flocalhost%3A18083%2Fbundles/dummybundle.jar.etag
new file mode 100644
index 0000000..3098183
--- /dev/null
+++ b/biz.aQute.repository/testdata/httpcache/4/http%3A%2F%2Flocalhost%3A18083%2Fbundles/dummybundle.jar.etag
@@ -0,0 +1 @@
+64035a95
\ No newline at end of file
diff --git a/biz.aQute.repository/testdata/httpcache/4/http%3A%2F%2Flocalhost%3A18083%2Fbundles/dummybundle.jar.sha b/biz.aQute.repository/testdata/httpcache/4/http%3A%2F%2Flocalhost%3A18083%2Fbundles/dummybundle.jar.sha
new file mode 100644
index 0000000..6e73431
--- /dev/null
+++ b/biz.aQute.repository/testdata/httpcache/4/http%3A%2F%2Flocalhost%3A18083%2Fbundles/dummybundle.jar.sha
@@ -0,0 +1 @@
+D0002141A722EF03ECD8FD2E0D3E4D3BC680BA91483CB4962F68A41A12DD01AB
\ No newline at end of file
diff --git a/biz.aQute.repository/testdata/httpcache/5/http%3A%2F%2Flocalhost%3A18083%2Fbundles/dummybundle.jar.etag b/biz.aQute.repository/testdata/httpcache/5/http%3A%2F%2Flocalhost%3A18083%2Fbundles/dummybundle.jar.etag
new file mode 100644
index 0000000..c43d093
--- /dev/null
+++ b/biz.aQute.repository/testdata/httpcache/5/http%3A%2F%2Flocalhost%3A18083%2Fbundles/dummybundle.jar.etag
@@ -0,0 +1 @@
+00000000
\ No newline at end of file
diff --git a/biz.aQute.repository/testdata/httpcache/5/http%3A%2F%2Flocalhost%3A18083%2Fbundles/dummybundle.jar.sha b/biz.aQute.repository/testdata/httpcache/5/http%3A%2F%2Flocalhost%3A18083%2Fbundles/dummybundle.jar.sha
new file mode 100644
index 0000000..6e73431
--- /dev/null
+++ b/biz.aQute.repository/testdata/httpcache/5/http%3A%2F%2Flocalhost%3A18083%2Fbundles/dummybundle.jar.sha
@@ -0,0 +1 @@
+D0002141A722EF03ECD8FD2E0D3E4D3BC680BA91483CB4962F68A41A12DD01AB
\ No newline at end of file
diff --git a/biz.aQute.repository/testdata/index1.xml b/biz.aQute.repository/testdata/index1.xml
new file mode 100644
index 0000000..bb9b667
--- /dev/null
+++ b/biz.aQute.repository/testdata/index1.xml
@@ -0,0 +1,50 @@
+<?xml version='1.0' encoding='utf-8'?>
+<repository increment='0' name='index1' xmlns='http://www.osgi.org/xmlns/repository/v1.0.0'>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.example.c'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='testdata/03-export.jar'/>
+      <attribute name='description' value='org.example.c'/>
+      <attribute name='size' type='Long' value='1100'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.example.c'/>
+      <attribute name='bundle-version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.example.c'/>
+      <attribute name='bundle-version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.example.a'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+    </capability>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.example.f'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='testdata/06-requirebundle.jar'/>
+      <attribute name='description' value='org.example.f'/>
+      <attribute name='size' type='Long' value='1128'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.example.f'/>
+      <attribute name='bundle-version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.example.f'/>
+      <attribute name='bundle-version' type='Version' value='0.0.0'/>
+    </capability>
+    <requirement namespace='osgi.wiring.bundle'>
+      <directive name='filter' value='(&(osgi.wiring.bundle=org.example.a)(bundle-version>=3.0.0)(!(bundle-version>=4.0.0)))'/>
+    </requirement>
+  </resource>
+</repository>
\ No newline at end of file
diff --git a/biz.aQute.repository/testdata/index2.xml b/biz.aQute.repository/testdata/index2.xml
new file mode 100644
index 0000000..6423796
--- /dev/null
+++ b/biz.aQute.repository/testdata/index2.xml
@@ -0,0 +1,7655 @@
+<?xml version='1.0' encoding='utf-8'?>
+<repository increment='1331339515287' name='Untitled' xmlns='http://www.osgi.org/xmlns/repository/v1.0.0'>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.springframework.asm'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.springframework.asm/org.springframework.asm-3.1.0.jar'/>
+      <attribute name='description' value='Spring ASM'/>
+      <attribute name='size' type='Long' value='53121'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.springframework.asm'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.springframework.asm'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.asm'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.asm.commons'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.asm'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.asm.signature'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='jcl.over.slf4j'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='1.6.2'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='jcl.over.slf4j/jcl.over.slf4j-1.6.2.jar'/>
+      <attribute name='description' value='jcl-over-slf4j'/>
+      <attribute name='size' type='Long' value='17698'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='jcl.over.slf4j'/>
+      <attribute name='bundle-version' type='Version' value='1.6.2'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='jcl.over.slf4j'/>
+      <attribute name='bundle-version' type='Version' value='1.6.2'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.commons.logging'/>
+      <attribute name='version' type='Version' value='1.1.1'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.commons.logging.impl'/>
+      <attribute name='version' type='Version' value='1.1.1'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j)(version>=1.6.2))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j.spi)(version>=1.6.2))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.ee'>
+      <directive name='filter' value='(ee=J2SE-1.3)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.aries.proxy'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.4.1.SNAPSHOT'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.apache.aries.proxy/org.apache.aries.proxy-0.4.1.jar'/>
+      <attribute name='description' value='Apache Aries Proxy Bundle'/>
+      <attribute name='size' type='Long' value='84942'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.aries.proxy'/>
+      <attribute name='bundle-version' type='Version' value='0.4.1.SNAPSHOT'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.aries.proxy'/>
+      <attribute name='bundle-version' type='Version' value='0.4.1.SNAPSHOT'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.proxy'/>
+      <attribute name='version' type='Version' value='0.4.0'/>
+      <directive name='uses' value='org.apache.aries.util.nls,org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.proxy.weaving'/>
+      <attribute name='version' type='Version' value='0.4.0'/>
+      <directive name='uses' value='org.apache.aries.proxy'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.proxy)(version>=0.4.0)(!(version>=0.5.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.util)(version>=0.4.0)(!(version>=0.5.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.util.nls)(version>=0.3.0)(!(version>=0.4.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.objectweb.asm)(version>=3.2.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.objectweb.asm.commons)(version>=3.2.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework.hooks.weaving)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework.wiring)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.slf4j)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.felix.scr'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='1.6.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.apache.felix.scr/org.apache.felix.scr-1.6.0.jar'/>
+      <attribute name='description' value='Apache Felix Declarative Services'/>
+      <attribute name='size' type='Long' value='192368'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.felix.scr'/>
+      <attribute name='bundle-version' type='Version' value='1.6.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.felix.scr'/>
+      <attribute name='bundle-version' type='Version' value='1.6.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.felix.scr'/>
+      <attribute name='version' type='Version' value='1.6.0'/>
+      <directive name='uses' value='org.osgi.framework,org.osgi.service.component'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.component'/>
+      <attribute name='version' type='Version' value='1.1.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.shell)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.4.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.cm)(version>=1.2.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.component)(version>=1.1.0)(!(version>=1.2.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.log)(version>=1.3.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.metatype)(version>=1.1.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.packageadmin)(version>=1.2.0)(!(version>=2.0.0)))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='javax.servlet'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='2.5.0.v200910301333'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='javax.servlet/javax.servlet-2.5.0.jar'/>
+      <attribute name='description' value='Servlet API Bundle'/>
+      <attribute name='size' type='Long' value='118865'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='javax.servlet'/>
+      <attribute name='bundle-version' type='Version' value='2.5.0.v200910301333'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='javax.servlet'/>
+      <attribute name='bundle-version' type='Version' value='2.5.0.v200910301333'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='javax.servlet'/>
+      <attribute name='version' type='Version' value='2.5.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='javax.servlet.http'/>
+      <attribute name='version' type='Version' value='2.5.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='javax.servlet.resources'/>
+      <attribute name='version' type='Version' value='2.5.0'/>
+    </capability>
+    <requirement namespace='osgi.wiring.ee'>
+      <directive name='filter' value='(ee=CDC-1.1/Foundation-1.1)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.ee'>
+      <directive name='filter' value='(ee=J2SE-1.4)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.springframework.expression'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.springframework.expression/org.springframework.expression-3.1.0.jar'/>
+      <attribute name='description' value='Spring Expression Language'/>
+      <attribute name='size' type='Long' value='178311'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.springframework.expression'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.springframework.expression'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.expression'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core.convert'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.expression.common'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core.convert,org.springframework.expression'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.expression.spel'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core.convert,org.springframework.expression'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.expression.spel.ast'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.expression,org.springframework.expression.spel,org.springframework.expression.spel.support'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.expression.spel.generated'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.expression.spel.standard'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core.convert,org.springframework.expression,org.springframework.expression.common,org.springframework.expression.spel,org.springframework.expression.spel.ast'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.expression.spel.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core.convert,org.springframework.expression,org.springframework.expression.spel'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.convert)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.convert.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.util)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.springframework.context.support'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.springframework.context.support/org.springframework.context.support-3.1.0.jar'/>
+      <attribute name='description' value='Spring Context Support'/>
+      <attribute name='size' type='Long' value='107925'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.springframework.context.support'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.springframework.context.support'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.mail'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.mail.javamail'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.activation,javax.mail,javax.mail.internet,org.springframework.beans.factory,org.springframework.core.io,org.springframework.mail'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.scheduling.commonj'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='commonj.timers,commonj.work,javax.naming,org.springframework.beans.factory,org.springframework.context,org.springframework.jndi,org.springframework.scheduling,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.scheduling.quartz'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.sql,org.quartz,org.quartz.impl.jdbcjobstore,org.quartz.simpl,org.quartz.spi,org.quartz.utils,org.springframework.beans.factory,org.springframework.beans.support,org.springframework.context,org.springframework.core,org.springframework.core.io,org.springframework.scheduling,org.springframework.transaction,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.ui.freemarker'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='freemarker.cache,freemarker.template,org.springframework.beans.factory,org.springframework.context,org.springframework.core.io'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.ui.jasperreports'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='net.sf.jasperreports.engine'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.ui.velocity'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.apache.commons.collections,org.apache.velocity.app,org.apache.velocity.exception,org.apache.velocity.runtime,org.apache.velocity.runtime.log,org.apache.velocity.runtime.resource,org.apache.velocity.runtime.resource.loader,org.springframework.beans.factory,org.springframework.context,org.springframework.core.io'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=commonj.timers)(version>=1.1.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=commonj.work)(version>=1.1.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=freemarker.cache)(version>=2.3.14)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=freemarker.template)(version>=2.3.14)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.activation)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.mail)(version>=1.4.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.mail.internet)(version>=1.4.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.naming)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.sql)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=net.sf.jasperreports.engine)(version>=2.0.5)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=net.sf.jasperreports.engine.data)(version>=2.0.5)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=net.sf.jasperreports.engine.export)(version>=2.0.5)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.commons.collections)(version>=3.2.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.commons.logging)(version>=1.1.1)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.velocity)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.velocity.app)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.velocity.context)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.velocity.exception)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.velocity.runtime)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.velocity.runtime.log)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.velocity.runtime.resource)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.velocity.runtime.resource.loader)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.quartz)(version>=1.6.0)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.quartz.impl)(version>=1.6.0)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.quartz.impl.jdbcjobstore)(version>=1.6.0)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.quartz.simpl)(version>=1.6.0)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.quartz.spi)(version>=1.6.0)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.quartz.utils)(version>=1.6.0)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.context)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.io)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.io.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.task)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.jdbc.datasource)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.jdbc.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.jndi)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.scheduling)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.scheduling.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.transaction)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.transaction.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.util)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.springframework.context'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.springframework.context/org.springframework.context-3.1.0.jar'/>
+      <attribute name='description' value='Spring Context'/>
+      <attribute name='size' type='Long' value='841819'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.springframework.context'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.springframework.context'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.cache'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.cache.annotation'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.annotation,org.springframework.beans.factory.annotation,org.springframework.cache,org.springframework.cache.interceptor,org.springframework.context.annotation,org.springframework.core.type'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.cache.concurrent'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans.factory,org.springframework.cache'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.cache.config'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans.factory.config,org.springframework.beans.factory.parsing,org.springframework.beans.factory.support,org.springframework.beans.factory.xml,org.springframework.cache.interceptor,org.w3c.dom'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.cache.ehcache'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='net.sf.ehcache,net.sf.ehcache.bootstrap,net.sf.ehcache.constructs.blocking,net.sf.ehcache.store,org.springframework.beans.factory,org.springframework.cache,org.springframework.cache.support,org.springframework.core.io'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.cache.interceptor'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.aopalliance.intercept,org.springframework.aop,org.springframework.aop.framework,org.springframework.aop.support,org.springframework.beans.factory,org.springframework.cache,org.springframework.core,org.springframework.expression,org.springframework.expression.spel.support'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.cache.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans.factory,org.springframework.cache'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.context'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans,org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.core.env,org.springframework.core.io,org.springframework.core.io.support,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.context.access'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans,org.springframework.beans.factory,org.springframework.beans.factory.access,org.springframework.context,org.springframework.jndi'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.context.annotation'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='net.sf.cglib.proxy,org.apache.commons.logging,org.springframework.beans,org.springframework.beans.factory,org.springframework.beans.factory.annotation,org.springframework.beans.factory.config,org.springframework.beans.factory.parsing,org.springframework.beans.factory.support,org.springframework.beans.factory.xml,org.springframework.context,org.springframework.context.support,org.springframework.core,org.springframework.core.env,org.springframework.core [...]
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.context.config'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans.factory.config,org.springframework.beans.factory.support,org.springframework.beans.factory.xml,org.w3c.dom'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.context.event'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.aopalliance.intercept,org.springframework.beans.factory,org.springframework.context,org.springframework.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.context.expression'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans,org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.expression,org.springframework.expression.spel.support'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.context.i18n'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.context.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.apache.commons.logging,org.springframework.beans,org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.beans.factory.support,org.springframework.beans.factory.xml,org.springframework.context,org.springframework.core,org.springframework.core.convert,org.springframework.core.convert.support,org.springframework.core.env,org.springframework.core.io,org.springframework.core.io.support,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.context.weaving'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans,org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.core,org.springframework.instrument.classloading'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.ejb.access'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.ejb,javax.naming,org.aopalliance.intercept,org.springframework.beans.factory,org.springframework.core,org.springframework.jndi'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.ejb.config'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans.factory.support,org.springframework.beans.factory.xml,org.w3c.dom'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.ejb.interceptor'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.annotation,javax.ejb,javax.interceptor,org.springframework.beans.factory,org.springframework.beans.factory.access,org.springframework.beans.factory.annotation'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.ejb.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.ejb,javax.jms,org.springframework.beans,org.springframework.beans.factory,org.springframework.beans.factory.access,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.format'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core.convert.converter'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.format.annotation'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.format.datetime'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.format'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.format.datetime.joda'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.joda.time,org.joda.time.format,org.springframework.context,org.springframework.core.convert.converter,org.springframework.format,org.springframework.format.annotation,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.format.number'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.context,org.springframework.format,org.springframework.format.annotation,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.format.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans.factory,org.springframework.context,org.springframework.core.convert,org.springframework.core.convert.converter,org.springframework.core.convert.support,org.springframework.format,org.springframework.format.annotation,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.instrument.classloading'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.instrument.classloading.glassfish'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.persistence.spi,org.springframework.instrument.classloading'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.instrument.classloading.jboss'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.instrument.classloading'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.instrument.classloading.oc4j'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.instrument.classloading'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.instrument.classloading.weblogic'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.instrument.classloading'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.instrument.classloading.websphere'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.instrument.classloading'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jmx'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jmx.access'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.management,javax.management.remote,org.aopalliance.intercept,org.springframework.beans.factory,org.springframework.core,org.springframework.jmx,org.springframework.jmx.support'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jmx.export'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.management,javax.management.modelmbean,org.springframework.aop.target,org.springframework.beans.factory,org.springframework.jmx,org.springframework.jmx.export.assembler,org.springframework.jmx.export.naming,org.springframework.jmx.support'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jmx.export.annotation'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.jmx.export,org.springframework.jmx.export.metadata,org.springframework.jmx.support'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jmx.export.assembler'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.management,javax.management.modelmbean,org.springframework.beans.factory,org.springframework.jmx.export.metadata'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jmx.export.metadata'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.management.modelmbean,org.springframework.jmx,org.springframework.jmx.support'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jmx.export.naming'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.management,org.springframework.beans.factory,org.springframework.core.io,org.springframework.jmx.export.metadata'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jmx.export.notification'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.management,javax.management.modelmbean,org.springframework.beans.factory,org.springframework.jmx'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jmx.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.management,javax.management.remote,org.springframework.aop.target,org.springframework.beans.factory,org.springframework.jmx'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jndi'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.naming,org.aopalliance.intercept,org.springframework.aop,org.springframework.beans.factory,org.springframework.core,org.springframework.core.env'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jndi.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans,org.springframework.beans.factory,org.springframework.jndi'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.remoting'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.remoting.rmi'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.naming,org.aopalliance.intercept,org.omg.CORBA,org.springframework.beans.factory,org.springframework.core,org.springframework.jndi,org.springframework.remoting,org.springframework.remoting.support'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.remoting.soap'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.xml.namespace,org.springframework.remoting'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.remoting.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='com.sun.net.httpserver,org.aopalliance.intercept,org.springframework.beans.factory'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.scheduling'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core,org.springframework.core.task'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.scheduling.annotation'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.aopalliance.aop,org.springframework.aop,org.springframework.aop.framework,org.springframework.aop.support,org.springframework.beans.factory,org.springframework.beans.factory.annotation,org.springframework.beans.factory.config,org.springframework.context,org.springframework.context.annotation,org.springframework.context.event,org.springframework.core,org.springframework.core.type,org.springframework.scheduling.config,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.scheduling.backportconcurrent'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='edu.emory.mathcs.backport.java.util.concurrent,org.springframework.beans.factory,org.springframework.scheduling,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.scheduling.concurrent'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans.factory,org.springframework.scheduling,org.springframework.scheduling.support,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.scheduling.config'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.beans.factory.support,org.springframework.beans.factory.xml,org.springframework.core.task,org.springframework.scheduling,org.w3c.dom'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.scheduling.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans.factory,org.springframework.beans.support,org.springframework.scheduling,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.scheduling.timer'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans.factory,org.springframework.scheduling,org.springframework.scheduling.support'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.scripting'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.scripting.bsh'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='bsh,org.springframework.beans.factory,org.springframework.core,org.springframework.scripting'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.scripting.config'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans.factory.config,org.springframework.beans.factory.support,org.springframework.beans.factory.xml,org.w3c.dom'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.scripting.groovy'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='groovy.lang,org.springframework.beans,org.springframework.beans.factory,org.springframework.scripting'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.scripting.jruby'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.jruby,org.jruby.ast,org.jruby.exceptions,org.jruby.runtime.builtin,org.springframework.beans.factory,org.springframework.core,org.springframework.scripting'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.scripting.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.aop,org.springframework.aop.target.dynamic,org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.context,org.springframework.core,org.springframework.core.io,org.springframework.scripting'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.stereotype'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.ui'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.ui.context'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.context'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.ui.context.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.context,org.springframework.ui.context'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.validation'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans,org.springframework.context.support,org.springframework.core,org.springframework.core.convert'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.validation.annotation'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.validation.beanvalidation'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.validation,javax.validation.metadata,org.aopalliance.intercept,org.hibernate.validator.resourceloading,org.springframework.aop.framework,org.springframework.beans,org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.context,org.springframework.core,org.springframework.core.io,org.springframework.validation'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.validation.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.ui'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=bsh)(version>=2.0.0.b4)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=com.ibm.websphere.management)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=com.sun.net.httpserver)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=edu.emory.mathcs.backport.java.util.concurrent)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=groovy.lang)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.annotation)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.ejb)(version>=2.1.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.interceptor)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.jms)(version>=1.1.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.management)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.management.modelmbean)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.management.openmbean)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.management.remote)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.naming)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.persistence)(version>=1.0.0)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.persistence.spi)(version>=1.0.0)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.rmi)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.validation)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.validation.bootstrap)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.validation.metadata)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.xml.namespace)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.xml.ws)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=net.sf.cglib.asm)(version>=2.1.3)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=net.sf.cglib.core)(version>=2.1.3)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=net.sf.cglib.proxy)(version>=2.1.3)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=net.sf.ehcache)(version>=1.3.0)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=net.sf.ehcache.bootstrap)(version>=1.3.0)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=net.sf.ehcache.constructs.blocking)(version>=1.3.0)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=net.sf.ehcache.event)(version>=1.3.0)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=net.sf.ehcache.store)(version>=1.3.0)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aopalliance.aop)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aopalliance.intercept)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.commons.logging)(version>=1.1.1)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.weaver.loadtime)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.codehaus.groovy.control)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.hibernate.validator)(version>=4.0.0)(!(version>=5.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.hibernate.validator.messageinterpolation)(version>=4.0.0)(!(version>=5.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.hibernate.validator.method)(version>=4.0.0)(!(version>=5.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.hibernate.validator.resourceloading)(version>=4.0.0)(!(version>=5.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.joda.time)(version>=1.6.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.joda.time.format)(version>=1.6.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.jruby)(version>=1.1.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.jruby.ast)(version>=1.1.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.jruby.exceptions)(version>=1.1.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.jruby.javasupport)(version>=1.1.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.jruby.runtime)(version>=1.1.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.jruby.runtime.builtin)(version>=1.1.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.omg.CORBA)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.aop)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.aop.config)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.aop.framework)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.aop.framework.adapter)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.aop.interceptor)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.aop.scope)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.aop.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.aop.support.annotation)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.aop.target)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.aop.target.dynamic)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.annotation)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.access)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.annotation)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.config)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.parsing)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.xml)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.propertyeditors)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.annotation)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.convert)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.convert.converter)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.convert.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.env)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.io)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.io.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.task)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.task.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.type)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.type.classreading)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.type.filter)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.expression)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.expression.spel.standard)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.expression.spel.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.instrument)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.orm.jpa.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.util)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.util.xml)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.w3c.dom)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.xml.sax)(version>=0.0.0))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='com.paremus.support.bosch01'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='com.paremus.support.bosch01/com.paremus.support.bosch01-1.0.0.jar'/>
+      <attribute name='description' value='com.paremus.support.bosch01'/>
+      <attribute name='size' type='Long' value='4611'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='com.paremus.support.bosch01'/>
+      <attribute name='bundle-version' type='Version' value='1.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='com.paremus.support.bosch01'/>
+      <attribute name='bundle-version' type='Version' value='1.0.0'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.servlet)(version>=2.5.0)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.servlet.http)(version>=2.5.0)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='com.sun.jersey.jersey-server'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='1.4.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='com.sun.jersey.jersey-server/com.sun.jersey.jersey-server-1.4.0.jar'/>
+      <attribute name='description' value='jersey-server'/>
+      <attribute name='size' type='Long' value='677600'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='com.sun.jersey.jersey-server'/>
+      <attribute name='bundle-version' type='Version' value='1.4.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='com.sun.jersey.jersey-server'/>
+      <attribute name='bundle-version' type='Version' value='1.4.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.container.filter'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,javax.ws.rs,com.sun.jersey.api.container,com.sun.jersey.core.util,javax.annotation.security,com.sun.jersey.spi.container,com.sun.jersey.api.core,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi.scanning'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.spi.scanning,javax.servlet,javax.ws.rs,org.objectweb.asm,com.sun.jersey.core.util,com.sun.jersey.core.reflection,javax.ws.rs.ext'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.wadl'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.research.ws.wadl,javax.ws.rs,com.sun.jersey.core.spi.factory,com.sun.jersey.server.impl.model.method,com.sun.jersey.core.header,com.sun.jersey.api.wadl.config,com.sun.jersey.server.impl.uri,com.sun.jersey.server.wadl,com.sun.jersey.api.core,com.sun.jersey.spi.inject,com.sun.jersey.spi.resource,javax.xml.bind,com.sun.jersey.api.uri,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.model.parameter.multivalued'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.jersey.core.spi.component,javax.ws.rs,com.sun.jersey.impl,com.sun.jersey.api.container,javax.xml.parsers,com.sun.jersey.core.reflection,javax.ws.rs.ext,org.xml.sax,com.sun.jersey.core.header,javax.xml.transform,javax.xml.bind.annotation,com.sun.jersey.spi,com.sun.jersey.spi.inject,javax.xml.transform.sax,javax.xml.bind,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.model.parameter'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.jersey.core.spi.component,javax.ws.rs,com.sun.jersey.server.impl.model.parameter.multivalued,com.sun.jersey.api.representation,com.sun.jersey.core.header,com.sun.jersey.api,com.sun.jersey.api.core,com.sun.jersey.spi.inject,com.sun.jersey.server.impl.inject,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.cdi'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.annotation,javax.ws.rs,org.objectweb.asm,javax.enterprise.util,com.sun.jersey.core.util,javax.enterprise.inject,com.sun.jersey.spi,com.sun.jersey.api.core,com.sun.jersey.spi.container,com.sun.jersey.spi.inject,com.sun.jersey.server.impl,javax.ws.rs.core,javax.naming,com.sun.jersey.api.model,com.sun.jersey.core.spi.component,javax.enterprise.inject.spi,javax.enterprise.event,com.sun.jersey.api.container,com.sun.jersey.core.spi.component.ioc,javax. [...]
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.container.servlet'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs,com.sun.jersey.server.impl.application,javax.servlet,com.sun.jersey.spi.template,com.sun.jersey.spi.container,com.sun.jersey.api.core,javax.servlet.jsp.tagext,com.sun.jersey.spi.inject,com.sun.jersey.server.impl,javax.persistence,javax.ws.rs.core,com.sun.jersey.spi.container.servlet,com.sun.jersey.api.model,com.sun.jersey.core.spi.component,com.sun.jersey.server.spi.component,com.sun.jersey.api.container,com.sun.jersey.core.spi.component.io [...]
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.resource'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.jersey.core.spi.component,javax.ws.rs,com.sun.jersey.server.spi.component,com.sun.jersey.api.container,com.sun.jersey.core.spi.component.ioc,com.sun.jersey.api.core,com.sun.jersey.server.impl.inject,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.modelapi.annotation'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.jersey.core.header,javax.ws.rs,com.sun.jersey.impl,com.sun.jersey.core.reflection,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.container'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.server.impl.application,com.sun.jersey.api.container,com.sun.jersey.spi.container'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi.template'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.view,com.sun.jersey.api.container,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.model.method.dispatch'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,javax.ws.rs,com.sun.jersey.core.spi.component,com.sun.jersey.server.impl.model.parameter.multivalued,com.sun.jersey.core.spi.factory,com.sun.jersey.api.container,com.sun.jersey.api.representation,com.sun.jersey.spi.dispatch,com.sun.jersey.api,com.sun.jersey.api.core,com.sun.jersey.server.impl.inject,com.sun.jersey.spi.inject,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi.container'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs,com.sun.jersey.core.util,com.sun.jersey.core.header,com.sun.jersey.core.header.reader,com.sun.jersey.api.core,com.sun.jersey.spi,com.sun.jersey.server.impl,javax.ws.rs.core,com.sun.jersey.api.model,com.sun.jersey.core.spi.factory,com.sun.jersey.api.container,com.sun.jersey.core.spi.component.ioc,com.sun.jersey.api.representation,com.sun.jersey.core.reflection,javax.ws.rs.ext,com.sun.jersey.server.impl.model,com.sun.jersey.api,com.sun.jersey [...]
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi.resource'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.server.impl.resource,com.sun.jersey.server.spi.component'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.wadl.generators.resourcedoc'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.jersey.server.wadl.generators.resourcedoc.xhtml,com.sun.research.ws.wadl,javax.xml.namespace,com.sun.jersey.server.wadl.generators.resourcedoc.model,com.sun.jersey.server.wadl,javax.xml.bind,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi.container.servlet'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.server.impl.application,com.sun.jersey.core.util,com.sun.jersey.server.impl.cdi,javax.servlet,com.sun.jersey.core.header,com.sun.jersey.server.impl.container.servlet,com.sun.jersey.server.impl.monitoring,com.sun.jersey.spi.container,com.sun.jersey.api.core,com.sun.jersey.spi.inject,com.sun.jersey.server.impl,javax.ws.rs.core,com.sun.jersey.server.impl.managedbeans,javax.naming,com.sun.jersey.server.spi.component,com.sun.jersey.server.pro [...]
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.container.httpserver'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.header,com.sun.net.httpserver,com.sun.jersey.api.core,com.sun.jersey.api.container,com.sun.jersey.spi.container,com.sun.jersey.core.util,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.managedbeans'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.naming,javax.annotation,com.sun.jersey.core.spi.component,com.sun.jersey.api.core,com.sun.jersey.api.container,com.sun.jersey.core.spi.component.ioc,com.sun.jersey.server.impl'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.model'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.spi.container'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.research.ws.wadl'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.xml.bind.annotation,javax.xml.bind.annotation.adapters,javax.xml.bind,javax.xml.namespace'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.container'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.spi.container,com.sun.jersey.api.core,com.sun.jersey.spi.service,com.sun.jersey.core.spi.component.ioc'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.probes'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.modelapi.validation'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,javax.ws.rs,com.sun.jersey.impl,com.sun.jersey.api.core,com.sun.jersey.core.reflection,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.container.httpserver'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.net.httpserver,com.sun.jersey.api.container,com.sun.jersey.api.core,com.sun.jersey.core.spi.component.ioc'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.wadl.config'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.server.wadl,com.sun.jersey.api.core,com.sun.jersey.core.reflection'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.uri'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs.core,com.sun.jersey.api.uri'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi.monitoring'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.header,javax.ws.rs,com.sun.jersey.core.spi.factory,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.application'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.container.filter,javax.ws.rs,com.sun.jersey.server.impl.wadl,com.sun.jersey.server.impl.model.parameter.multivalued,com.sun.jersey.server.impl.model.parameter,com.sun.jersey.core.header,com.sun.jersey.server.impl.modelapi.annotation,com.sun.jersey.spi.template,com.sun.jersey.server.impl.resource,com.sun.jersey.server.impl.model.method.dispatch,com.sun.jersey.spi.container,com.sun.jersey.spi.inject,com.sun.jersey.api.model,com.sun.jer [...]
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.container.grizzly'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.grizzly.tcp.http11,com.sun.grizzly.http.servlet,com.sun.grizzly.standalone,com.sun.jersey.api.container,com.sun.jersey.core.spi.component.ioc,javax.servlet,com.sun.grizzly.tcp,com.sun.jersey.api.core,com.sun.grizzly.http,com.sun.jersey.spi.container.servlet'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.component'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.jersey.core.spi.component,com.sun.jersey.server.spi.component,com.sun.jersey.api.container,com.sun.jersey.core.spi.component.ioc,com.sun.jersey.core.reflection,com.sun.jersey.server.impl.resource,com.sun.jersey.api.core,com.sun.jersey.server.impl.inject,com.sun.jersey.spi.inject'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi.dispatch'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.provider'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.spi.factory,com.sun.jersey.api.core,com.sun.jersey.api.container,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.container.grizzly'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.grizzly.tcp.http11,com.sun.jersey.api.container,com.sun.jersey.core.util,com.sun.grizzly.util.buf,com.sun.jersey.core.header,com.sun.grizzly.tcp,com.sun.jersey.spi.container,com.sun.jersey.api.core,com.sun.jersey.spi.inject,com.sun.jersey.server.impl,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.template'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.spi.component,javax.ws.rs,com.sun.jersey.server.impl.uri.rules,com.sun.jersey.server.probes,com.sun.jersey.core.reflection,javax.ws.rs.ext,com.sun.jersey.server.impl.model.method,com.sun.jersey.core.header,com.sun.jersey.spi.uri.rules,com.sun.jersey.api.view,com.sun.jersey.spi.template,com.sun.jersey.api.core,com.sun.jersey.spi.container,com.sun.jersey.spi.inject,javax.ws.rs.core,com.sun.jersey.api.uri'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.osgi'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.server.impl.provider,org.osgi.framework,javax.ws.rs.ext'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.wadl.generators.resourcedoc.model'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.xml.bind.annotation,javax.xml.namespace'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.monitoring'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.spi.monitoring,com.sun.jersey.spi.service'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.wadl'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.research.ws.wadl,javax.ws.rs,javax.xml.namespace,com.sun.jersey.server.impl.modelapi.annotation,javax.xml.bind,com.sun.jersey.server.impl,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi.uri.rules'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.jersey.spi.container,com.sun.jersey.api.core,com.sun.jersey.api.uri'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.core'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.jersey.spi.scanning,javax.ws.rs,com.sun.jersey.server.impl.application,com.sun.jersey.api.container,com.sun.jersey.core.util,com.sun.jersey.api.representation,javax.ws.rs.ext,com.sun.jersey.core.spi.scanning,javax.servlet,com.sun.jersey.core.header,com.sun.jersey.spi.container,com.sun.jersey.api.uri,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.wadl'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.research.ws.wadl,org.apache.tools.ant,com.sun.jersey.server.impl.modelapi.annotation,com.sun.jersey.server.wadl,org.apache.tools.ant.types,com.sun.jersey.api.core,javax.xml.bind'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.server.impl.model,javax.naming,com.sun.jersey.core.header,com.sun.jersey.api.core,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.wadl.generators.resourcedoc.xhtml'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.xml.bind.annotation,javax.xml.bind,javax.xml.namespace'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.container.filter'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,javax.ws.rs,com.sun.jersey.core.spi.component,com.sun.jersey.server.impl.uri,com.sun.jersey.api.core,com.sun.jersey.spi.container,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.uri.rules'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,javax.ws.rs,com.sun.jersey.api.container,com.sun.jersey.server.probes,com.sun.jersey.core.reflection,com.sun.jersey.server.impl.model.method,com.sun.jersey.spi.dispatch,com.sun.jersey.core.header,com.sun.jersey.server.impl.uri.rules.automata,com.sun.jersey.server.impl.template,com.sun.jersey.spi.uri.rules,com.sun.jersey.api,com.sun.jersey.spi.container,com.sun.jersey.api.core,com.sun.jersey.server.impl.inject,com.sun.jersey.api [...]
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.spi.component'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.jersey.core.spi.component,com.sun.jersey.api.container,com.sun.jersey.core.spi.component.ioc,com.sun.jersey.api.core,com.sun.jersey.spi.inject,com.sun.jersey.server.impl.inject'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.wadl.generators'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.research.ws.wadl,com.sun.jersey.server.wadl,javax.xml.bind.annotation,javax.xml.bind,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.model.method'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.server.impl.container.filter,com.sun.jersey.api.model,com.sun.jersey.server.impl.application,com.sun.jersey.impl,com.sun.jersey.api.container,com.sun.jersey.spi.dispatch,com.sun.jersey.core.header,com.sun.jersey.api.core,com.sun.jersey.spi.inject,javax.ws.rs.core,com.sun.jersey.api.uri'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.model'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs,com.sun.jersey.server.impl.wadl,com.sun.jersey.impl,com.sun.jersey.server.impl.application,com.sun.jersey.core.header,com.sun.jersey.core.header.reader,com.sun.jersey.server.impl.template,com.sun.jersey.spi.uri.rules,com.sun.jersey.api.core,com.sun.jersey.spi.inject,javax.ws.rs.core,com.sun.jersey.server.impl.container.filter,com.sun.jersey.api.model,com.sun.jersey.core.spi.component,com.sun.jersey.server.impl.uri.rules,com.sun.jersey.api.c [...]
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.uri.rules.automata'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.server.impl.uri,com.sun.jersey.spi.uri.rules,com.sun.jersey.server.impl.uri.rules,com.sun.jersey.api.uri'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.view'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.ejb'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.annotation,javax.naming,javax.ejb,com.sun.jersey.core.spi.component,javax.ws.rs,javax.interceptor,com.sun.jersey.api.container,com.sun.jersey.core.spi.component.ioc,javax.ws.rs.ext,com.sun.jersey.api.core,com.sun.jersey.server.impl,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.inject'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.jersey.core.spi.component,javax.ws.rs,com.sun.jersey.core.spi.factory,com.sun.jersey.api.container,com.sun.jersey.api.core,com.sun.jersey.spi.inject'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.grizzly.http)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.grizzly.http.servlet)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.grizzly.standalone)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.grizzly.tcp)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.grizzly.tcp.http11)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.grizzly.util.buf)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.container)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.container.filter)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.container.grizzly)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.container.httpserver)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.core)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.model)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.representation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.uri)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.view)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.wadl)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.wadl.config)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.header)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.header.reader)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.osgi)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.reflection)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.spi.component)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.spi.component.ioc)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.spi.factory)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.spi.scanning)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.util)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.impl)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.application)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.cdi)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.component)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.container)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.container.filter)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.container.grizzly)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.container.httpserver)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.container.servlet)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.ejb)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.inject)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.managedbeans)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.model)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.model.method)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.model.method.dispatch)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.model.parameter)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.model.parameter.multivalued)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.modelapi.annotation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.modelapi.validation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.monitoring)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.provider)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.resource)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.template)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.uri)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.uri.rules)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.uri.rules.automata)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.wadl)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.osgi)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.probes)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.spi.component)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.wadl)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.wadl.generators)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.wadl.generators.resourcedoc)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.wadl.generators.resourcedoc.model)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.wadl.generators.resourcedoc.xhtml)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.container)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.container.servlet)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.dispatch)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.inject)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.monitoring)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.resource)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.scanning)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.service)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.template)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.uri.rules)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.net.httpserver)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.research.ws.wadl)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.annotation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.annotation.security)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.ejb)(version>=3.1.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.enterprise.context)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.enterprise.context.spi)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.enterprise.event)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.enterprise.inject)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.enterprise.inject.spi)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.enterprise.util)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.inject)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.interceptor)(version>=3.1.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.naming)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.persistence)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.servlet)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.servlet.annotation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.servlet.http)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.servlet.jsp)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.servlet.jsp.tagext)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.ws.rs)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.ws.rs.core)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.ws.rs.ext)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.bind)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.bind.annotation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.bind.annotation.adapters)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.namespace)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.parsers)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform.sax)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.apache.tools.ant)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.apache.tools.ant.types)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.objectweb.asm)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.framework)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.xml.sax)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.felix.configadmin'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='1.2.8'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.apache.felix.configadmin/org.apache.felix.configadmin-1.2.8.jar'/>
+      <attribute name='description' value='Apache Felix Configuration Admin Service'/>
+      <attribute name='size' type='Long' value='94680'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.felix.configadmin'/>
+      <attribute name='bundle-version' type='Version' value='1.2.8'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.felix.configadmin'/>
+      <attribute name='bundle-version' type='Version' value='1.2.8'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.felix.cm'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.felix.cm.file'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.apache.felix.cm,org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.cm'/>
+      <attribute name='version' type='Version' value='1.3.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.cm)(version>=1.0.0)(!(version>=1.1.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.cm.file)(version>=1.0.0)(!(version>=1.1.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.3.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.cm)(version>=1.3.0)(!(version>=1.4.0)))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.aries.blueprint.core'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.apache.aries.blueprint.core/org.apache.aries.blueprint.core-0.3.0.jar'/>
+      <attribute name='description' value='Apache Aries Blueprint Core'/>
+      <attribute name='size' type='Long' value='307784'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.aries.blueprint.core'/>
+      <attribute name='bundle-version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.aries.blueprint.core'/>
+      <attribute name='bundle-version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.ext'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.osgi.service.blueprint.reflect,org.apache.aries.blueprint,org.osgi.service.blueprint.container,org.apache.aries.blueprint.mutable,org.slf4j,org.w3c.dom'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.nls'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.container'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.apache.aries.blueprint,org.osgi.service.blueprint.reflect,org.osgi.framework,org.osgi.service.blueprint.container,org.apache.aries.blueprint.utils,org.slf4j,org.apache.aries.blueprint.di,org.apache.aries.proxy,org.apache.aries.blueprint.proxy,org.apache.aries.blueprint.namespace,org.apache.aries.blueprint.reflect,javax.xml.validation,org.osgi.util.tracker,org.osgi.service.event,org.apache.aries.util,org.apache.aries.util.tracker,org.apache.aries.bl [...]
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.osgi.service.blueprint.reflect,org.apache.aries.blueprint.di,org.osgi.framework,org.osgi.service.blueprint.container,org.w3c.dom'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.di'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.apache.aries.blueprint.container,org.osgi.service.blueprint.container,org.apache.aries.blueprint.utils,org.apache.aries.blueprint.ext,org.apache.aries.blueprint,org.osgi.service.blueprint.reflect'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.reflect'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.osgi.service.blueprint.reflect,org.apache.aries.blueprint.mutable,org.apache.aries.blueprint'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.namespace'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.apache.aries.blueprint,org.osgi.service.blueprint.reflect,org.apache.aries.blueprint.reflect,org.apache.aries.blueprint.container,org.osgi.framework,javax.xml.validation,org.slf4j,org.xml.sax,javax.xml.transform,org.osgi.util.tracker,javax.xml.transform.stream'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.mutable'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.osgi.service.blueprint.reflect,org.apache.aries.blueprint'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.proxy'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.apache.aries.blueprint,org.osgi.service.blueprint.reflect,org.apache.aries.proxy,org.slf4j'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.utils'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.osgi.framework,org.apache.aries.blueprint,org.apache.aries.blueprint.container,org.apache.aries.blueprint.di,org.osgi.service.blueprint.container'/>
+    </capability>
+    <capability namespace='osgi.wiring.service'>
+      <attribute name='osgi.wiring.service' value='org.apache.aries.blueprint.NamespaceHandler'/>
+    </capability>
+    <capability namespace='osgi.wiring.service'>
+      <attribute name='osgi.wiring.service' value='org.apache.aries.blueprint.ParserService'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.parsers)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform.dom)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform.stream)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.validation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.blueprint.annotation.service)(version>=0.3.0)(!(version>=1.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.proxy)(version>=0.3.0)(!(version>=1.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.quiesce.manager)(version>=0.2.0)(!(version>=1.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.quiesce.participant)(version>=0.2.0)(!(version>=1.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.util)(version>=0.3.0)(!(version>=1.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.util.tracker)(version>=0.3.0)(!(version>=1.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.blueprint)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.blueprint.container)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.blueprint.reflect)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.event)(version>=1.2.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.framework)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.util.tracker)(version>=1.4.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.w3c.dom)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.xml.sax)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.aries.blueprint.cm'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.apache.aries.blueprint.cm/org.apache.aries.blueprint.cm-0.3.0.jar'/>
+      <attribute name='description' value='Apache Aries Blueprint CM'/>
+      <attribute name='size' type='Long' value='46117'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.aries.blueprint.cm'/>
+      <attribute name='bundle-version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.aries.blueprint.cm'/>
+      <attribute name='bundle-version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.compendium.cm'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.apache.aries.blueprint,org.osgi.service.blueprint.reflect,org.osgi.framework,org.osgi.service.cm,org.osgi.service.blueprint.container,org.apache.aries.blueprint.utils,org.slf4j,org.apache.aries.blueprint.container,org.apache.aries.blueprint.ext,org.w3c.dom,org.apache.aries.blueprint.mutable'/>
+    </capability>
+    <capability namespace='osgi.wiring.service'>
+      <attribute name='osgi.wiring.service' value='org.apache.aries.blueprint.NamespaceHandler'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.blueprint)(version>=0.3.0)(!(version>=0.4.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.blueprint.container)(version>=0.3.0)(!(version>=0.4.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.blueprint.ext)(version>=0.3.0)(!(version>=0.4.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.blueprint.mutable)(version>=0.3.0)(!(version>=0.4.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.blueprint.utils)(version>=0.3.0)(!(version>=0.4.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.blueprint)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.blueprint.container)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.blueprint.reflect)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.cm)(version>=1.3.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.w3c.dom)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.service'>
+      <directive name='filter' value='(osgi.wiring.service=org.osgi.service.cm.ConfigurationAdmin)'/>
+      <directive name='effective' value='active'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.springframework.transaction'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.springframework.transaction/org.springframework.transaction-3.1.0.jar'/>
+      <attribute name='description' value='Spring Transaction'/>
+      <attribute name='size' type='Long' value='250012'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.springframework.transaction'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.springframework.transaction'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.dao'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.dao.annotation'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.aopalliance.aop,org.springframework.aop,org.springframework.aop.framework,org.springframework.aop.support,org.springframework.beans,org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.core,org.springframework.dao.support'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.dao.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.aopalliance.intercept,org.springframework.beans,org.springframework.beans.factory,org.springframework.dao'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jca.cci'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.resource,org.springframework.dao'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jca.cci.connection'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.naming,javax.resource,javax.resource.cci,org.springframework.beans.factory,org.springframework.jca.cci,org.springframework.transaction,org.springframework.transaction.support'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jca.cci.core'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.resource,javax.resource.cci,org.springframework.dao'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jca.cci.core.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.resource.cci,org.springframework.dao.support,org.springframework.jca.cci,org.springframework.jca.cci.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jca.cci.object'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.resource,javax.resource.cci,org.springframework.beans.factory,org.springframework.dao,org.springframework.jca.cci.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jca.context'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.resource,javax.resource.spi,javax.resource.spi.endpoint,javax.resource.spi.work,javax.transaction.xa,org.springframework.beans,org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.beans.factory.support,org.springframework.context,org.springframework.context.support,org.springframework.core.env'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jca.endpoint'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.resource,javax.resource.spi,javax.resource.spi.endpoint,javax.transaction.xa,org.aopalliance.intercept,org.springframework.beans.factory,org.springframework.context,org.springframework.transaction.jta'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jca.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.resource,javax.resource.spi,javax.resource.spi.work,org.springframework.beans.factory'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jca.work'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.naming,javax.resource.spi,javax.resource.spi.work,org.springframework.beans.factory,org.springframework.core.task,org.springframework.jca.context,org.springframework.jndi,org.springframework.scheduling'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jca.work.glassfish'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.resource.spi.work,org.springframework.jca.work'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jca.work.jboss'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.resource.spi.work,org.springframework.jca.work'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.transaction'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.transaction.annotation'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.ejb,org.springframework.beans.factory.annotation,org.springframework.context.annotation,org.springframework.core.type,org.springframework.transaction,org.springframework.transaction.interceptor'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.transaction.config'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans.factory.config,org.springframework.beans.factory.support,org.springframework.beans.factory.xml,org.w3c.dom'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.transaction.interceptor'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.aopalliance.aop,org.aopalliance.intercept,org.springframework.aop,org.springframework.aop.framework,org.springframework.aop.support,org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.transaction,org.springframework.transaction.support'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.transaction.jta'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='com.ibm.wsspi.uow,javax.transaction,javax.transaction.xa,org.apache.commons.logging,org.springframework.beans.factory,org.springframework.jndi,org.springframework.transaction,org.springframework.transaction.support'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.transaction.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans.factory,org.springframework.core,org.springframework.transaction'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=com.ibm.websphere.uow)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=com.ibm.wsspi.uow)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.ejb)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.management)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.naming)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.resource)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.resource.cci)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.resource.spi)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.resource.spi.endpoint)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.resource.spi.work)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.transaction)(version>=1.0.1)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.transaction.xa)(version>=1.0.1)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=oracle.j2ee.transaction)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aopalliance.aop)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aopalliance.intercept)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.commons.logging)(version>=1.1.1)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.jboss.resource.work)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.aop)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.aop.config)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.aop.framework)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.aop.scope)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.aop.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.aop.support.annotation)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.annotation)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.config)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.parsing)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.xml)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.propertyeditors)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.context)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.context.annotation)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.context.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.annotation)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.env)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.task)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.type)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.jndi)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.scheduling)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.stereotype)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.util)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.util.xml)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.w3c.dom)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=weblogic.transaction)(version>=0.0.0))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.felix.bundlerepository'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='1.6.6'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.apache.felix.bundlerepository/org.apache.felix.bundlerepository-1.6.6.jar'/>
+      <attribute name='description' value='Apache Felix Bundle Repository'/>
+      <attribute name='size' type='Long' value='168279'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.felix.bundlerepository'/>
+      <attribute name='bundle-version' type='Version' value='1.6.6'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.felix.bundlerepository'/>
+      <attribute name='bundle-version' type='Version' value='1.6.6'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.felix.bundlerepository'/>
+      <attribute name='version' type='Version' value='2.0.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.service'>
+      <attribute name='osgi.wiring.service' value='org.apache.felix.bundlerepository.RepositoryAdmin'/>
+    </capability>
+    <capability namespace='osgi.wiring.service'>
+      <attribute name='osgi.wiring.service' value='org.osgi.service.obr.RepositoryAdmin'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.stream)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.bundlerepository)(version>=2.0.0)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.4.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.log)(version>=1.3.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.obr)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.url)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.springframework.beans'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.springframework.beans/org.springframework.beans-3.1.0.jar'/>
+      <attribute name='description' value='Spring Beans'/>
+      <attribute name='size' type='Long' value='595647'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.springframework.beans'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.springframework.beans'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.beans'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core,org.springframework.core.convert,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.beans.annotation'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.beans.factory'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.beans.factory.access'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans,org.springframework.beans.factory'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.beans.factory.access.el'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.el,org.springframework.beans.factory'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.beans.factory.annotation'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans,org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.beans.factory.support,org.springframework.beans.factory.wiring,org.springframework.core,org.springframework.core.type'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.beans.factory.config'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.inject,org.apache.commons.logging,org.springframework.beans,org.springframework.beans.factory,org.springframework.beans.support,org.springframework.core,org.springframework.core.convert,org.springframework.core.io.support,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.beans.factory.parsing'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.apache.commons.logging,org.springframework.beans,org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.core.io'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.beans.factory.serviceloader'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans.factory,org.springframework.beans.factory.config'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.beans.factory.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.inject,net.sf.cglib.proxy,org.apache.commons.logging,org.springframework.beans,org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.core,org.springframework.core.convert,org.springframework.core.env,org.springframework.core.io,org.springframework.core.io.support,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.beans.factory.wiring'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans.factory'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.beans.factory.xml'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.xml.parsers,org.springframework.beans,org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.beans.factory.parsing,org.springframework.beans.factory.support,org.springframework.core.env,org.springframework.core.io,org.springframework.core.io.support,org.w3c.dom,org.xml.sax'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.beans.propertyeditors'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core.io'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.beans.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans,org.springframework.core.env,org.springframework.core.io,org.springframework.util'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.el)(version>=1.0.0)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.inject)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.xml.parsers)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=net.sf.cglib.proxy)(version>=2.1.3)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.commons.logging)(version>=1.1.1)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.annotation)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.convert)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.env)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.io)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.io.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.type)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.util)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.util.xml)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.w3c.dom)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.xml.sax)(version>=0.0.0))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.aries.blueprint.api'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.apache.aries.blueprint.api/org.apache.aries.blueprint.api-0.3.0.jar'/>
+      <attribute name='description' value='Apache Aries Blueprint API'/>
+      <attribute name='size' type='Long' value='31787'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.aries.blueprint.api'/>
+      <attribute name='bundle-version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.aries.blueprint.api'/>
+      <attribute name='bundle-version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.blueprint'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.blueprint.reflect'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.blueprint.container'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+      <directive name='uses' value='org.osgi.service.blueprint.reflect,org.osgi.framework'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.aries.proxy.api'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.4.1.SNAPSHOT'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.apache.aries.proxy.api/org.apache.aries.proxy.api-0.4.1.jar'/>
+      <attribute name='description' value='Apache Aries Proxy API'/>
+      <attribute name='size' type='Long' value='12723'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.aries.proxy.api'/>
+      <attribute name='bundle-version' type='Version' value='0.4.1.SNAPSHOT'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.aries.proxy.api'/>
+      <attribute name='bundle-version' type='Version' value='0.4.1.SNAPSHOT'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.proxy'/>
+      <attribute name='version' type='Version' value='0.4.0'/>
+      <directive name='uses' value='org.apache.aries.util.nls,org.osgi.framework'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.util.nls)(version>=0.3.0)(!(version>=0.4.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.springframework.instrument'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.springframework.instrument/org.springframework.instrument-3.1.0.jar'/>
+      <attribute name='description' value='Spring Instrument'/>
+      <attribute name='size' type='Long' value='7711'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.springframework.instrument'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.springframework.instrument'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.instrument'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.springframework.jdbc'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.springframework.jdbc/org.springframework.jdbc-3.1.0.jar'/>
+      <attribute name='description' value='Spring JDBC'/>
+      <attribute name='size' type='Long' value='407156'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.springframework.jdbc'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.springframework.jdbc'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jdbc'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.dao'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jdbc.config'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans.factory.config,org.springframework.beans.factory.support,org.springframework.beans.factory.xml,org.springframework.context,org.springframework.core.io,org.w3c.dom'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jdbc.core'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.sql,javax.sql.rowset,org.apache.commons.logging,org.springframework.beans,org.springframework.dao,org.springframework.jdbc,org.springframework.jdbc.support,org.springframework.jdbc.support.nativejdbc,org.springframework.jdbc.support.rowset'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jdbc.core.metadata'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.sql,org.apache.commons.logging,org.springframework.jdbc.core,org.springframework.jdbc.core.namedparam,org.springframework.jdbc.support,org.springframework.jdbc.support.nativejdbc'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jdbc.core.namedparam'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.sql,org.springframework.dao,org.springframework.jdbc.core,org.springframework.jdbc.core.support,org.springframework.jdbc.support,org.springframework.jdbc.support.rowset'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jdbc.core.simple'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.sql,org.springframework.dao,org.springframework.jdbc.core,org.springframework.jdbc.core.namedparam,org.springframework.jdbc.core.support,org.springframework.jdbc.support,org.springframework.jdbc.support.nativejdbc'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jdbc.core.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.sql,org.springframework.beans.factory.support,org.springframework.dao,org.springframework.dao.support,org.springframework.jdbc,org.springframework.jdbc.core,org.springframework.jdbc.support,org.springframework.jdbc.support.lob'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jdbc.datasource'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.sql,org.apache.commons.logging,org.springframework.beans.factory,org.springframework.jdbc,org.springframework.transaction,org.springframework.transaction.support'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jdbc.datasource.embedded'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.sql,org.springframework.beans.factory,org.springframework.core.io,org.springframework.jdbc.datasource,org.springframework.jdbc.datasource.init'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jdbc.datasource.init'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.sql,org.springframework.beans.factory,org.springframework.core.io,org.springframework.core.io.support'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jdbc.datasource.lookup'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.sql,org.springframework.beans.factory,org.springframework.dao,org.springframework.jdbc.datasource,org.springframework.jndi'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jdbc.object'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.sql,org.springframework.beans.factory,org.springframework.dao,org.springframework.jdbc,org.springframework.jdbc.core,org.springframework.jdbc.core.namedparam,org.springframework.jdbc.support'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jdbc.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.sql,org.springframework.beans.factory,org.springframework.core,org.springframework.core.io,org.springframework.dao'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jdbc.support.incrementer'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.sql,org.springframework.beans.factory,org.springframework.dao'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jdbc.support.lob'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.transaction,org.springframework.jdbc.support.nativejdbc,org.springframework.transaction.support'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jdbc.support.nativejdbc'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jdbc.support.rowset'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.jdbc'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.jdbc.support.xml'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.xml.transform,org.springframework.dao,org.springframework.jdbc.support,org.w3c.dom'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=com.ibm.websphere.rsadapter)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=com.ibm.ws.rsadapter.jdbc)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=com.mchange.v2.c3p0)(version>=0.9.1)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=com.sun.rowset)(version>=1.0.1)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.naming)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.sql)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.sql.rowset)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.transaction)(version>=1.0.1)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.xml.transform)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.xml.transform.dom)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=oracle.jdbc)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=oracle.sql)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.commons.logging)(version>=1.1.1)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.derby.impl.io)(version>=10.5.0)(!(version>=11.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.derby.jdbc)(version>=10.5.0)(!(version>=11.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.h2)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.hsqldb)(version>=1.8.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.jboss.resource.adapter.jdbc)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.config)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.xml)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.context)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.io)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.io.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.dao)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.dao.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.jndi)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.transaction)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.transaction.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.util)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.util.xml)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.w3c.dom)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=weblogic.jdbc.extensions)(version>=0.0.0))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.aries.blueprint'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.apache.aries.blueprint/org.apache.aries.blueprint-0.3.0.jar'/>
+      <attribute name='description' value='Apache Aries Blueprint Bundle'/>
+      <attribute name='size' type='Long' value='370418'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.aries.blueprint'/>
+      <attribute name='bundle-version' type='Version' value='0.3.0'/>
+      <directive name='blueprint.graceperiod' value='false'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.aries.blueprint'/>
+      <attribute name='bundle-version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.blueprint'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+      <directive name='uses' value='org.osgi.service.blueprint.container,org.osgi.service.blueprint.reflect,org.apache.aries.blueprint,org.apache.aries.blueprint.ext,org.apache.aries.blueprint.mutable,org.apache.aries.blueprint.compendium.cm'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.blueprint.container'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+      <directive name='uses' value='org.osgi.service.blueprint.reflect,org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.blueprint.reflect'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.ext'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.osgi.service.blueprint.reflect,org.apache.aries.blueprint,org.osgi.service.blueprint.container,org.apache.aries.blueprint.mutable,org.slf4j,org.w3c.dom'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.compendium.cm'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.apache.aries.blueprint,org.osgi.service.blueprint.reflect,org.osgi.framework,org.osgi.service.cm,org.osgi.service.blueprint.container,org.apache.aries.blueprint.utils,org.slf4j,org.apache.aries.blueprint.container,org.apache.aries.blueprint.ext,org.w3c.dom,org.apache.aries.blueprint.mutable'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.namespace'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.apache.aries.blueprint,org.osgi.service.blueprint.reflect,org.apache.aries.blueprint.reflect,org.apache.aries.blueprint.container,org.osgi.framework,javax.xml.validation,org.slf4j,org.xml.sax,javax.xml.transform,org.osgi.util.tracker,javax.xml.transform.stream'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.utils'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.osgi.framework,org.apache.aries.blueprint,org.apache.aries.blueprint.container,org.apache.aries.blueprint.di,org.osgi.service.blueprint.container'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.nls'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.container'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.apache.aries.blueprint,org.osgi.service.blueprint.reflect,org.osgi.framework,org.osgi.service.blueprint.container,org.apache.aries.blueprint.utils,org.slf4j,org.apache.aries.blueprint.di,org.apache.aries.proxy,org.apache.aries.blueprint.proxy,org.apache.aries.blueprint.namespace,org.apache.aries.blueprint.reflect,javax.xml.validation,org.osgi.util.tracker,org.osgi.service.event,org.apache.aries.util,org.apache.aries.util.tracker,org.apache.aries.bl [...]
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.osgi.service.blueprint.reflect,org.apache.aries.blueprint.di,org.osgi.framework,org.osgi.service.blueprint.container,org.w3c.dom'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.di'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.apache.aries.blueprint.container,org.osgi.service.blueprint.container,org.apache.aries.blueprint.utils,org.apache.aries.blueprint.ext,org.apache.aries.blueprint,org.osgi.service.blueprint.reflect'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.reflect'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.osgi.service.blueprint.reflect,org.apache.aries.blueprint.mutable,org.apache.aries.blueprint'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.mutable'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.osgi.service.blueprint.reflect,org.apache.aries.blueprint'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.proxy'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.apache.aries.blueprint,org.osgi.service.blueprint.reflect,org.apache.aries.proxy,org.slf4j'/>
+    </capability>
+    <capability namespace='osgi.wiring.service'>
+      <attribute name='osgi.wiring.service' value='org.apache.aries.blueprint.NamespaceHandler'/>
+    </capability>
+    <capability namespace='osgi.wiring.service'>
+      <attribute name='osgi.wiring.service' value='org.apache.aries.blueprint.NamespaceHandler'/>
+    </capability>
+    <capability namespace='osgi.wiring.service'>
+      <attribute name='osgi.wiring.service' value='org.apache.aries.blueprint.ParserService'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.parsers)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform.dom)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform.stream)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.validation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.apache.aries.blueprint.annotation.service)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.proxy)(version>=0.3.0)(!(version>=1.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.quiesce.manager)(version>=0.2.0)(!(version>=1.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.quiesce.participant)(version>=0.2.0)(!(version>=1.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.util)(version>=0.3.0)(!(version>=1.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.util.tracker)(version>=0.3.0)(!(version>=1.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.osgi.framework.adaptor)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.osgi.framework.internal.core)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.osgi.internal.loader)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.cm)(version>=1.2.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.event)(version>=1.2.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.framework)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.util.tracker)(version>=1.4.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.w3c.dom)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.xml.sax)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.service'>
+      <directive name='filter' value='(osgi.wiring.service=org.osgi.service.cm.ConfigurationAdmin)'/>
+      <directive name='effective' value='active'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.aries.util'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.5.0.SNAPSHOT'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.apache.aries.util/org.apache.aries.util-0.5.0.jar'/>
+      <attribute name='description' value='Apache Aries Util'/>
+      <attribute name='size' type='Long' value='106412'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.aries.util'/>
+      <attribute name='bundle-version' type='Version' value='0.5.0.SNAPSHOT'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.aries.util'/>
+      <attribute name='bundle-version' type='Version' value='0.5.0.SNAPSHOT'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.util'/>
+      <attribute name='version' type='Version' value='0.4.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.util.tracker'/>
+      <attribute name='version' type='Version' value='0.4.0'/>
+      <directive name='uses' value='org.osgi.util.tracker,org.osgi.framework,org.osgi.framework.launch,org.osgi.service.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.util.nls'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.osgi.framework,org.apache.aries.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.util.io'/>
+      <attribute name='version' type='Version' value='0.1.0'/>
+      <directive name='uses' value='org.apache.aries.util.filesystem'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.util.service.registry'/>
+      <attribute name='version' type='Version' value='0.1.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.util.manifest'/>
+      <attribute name='version' type='Version' value='0.1.0'/>
+      <directive name='uses' value='org.apache.aries.util.io,org.apache.aries.util.filesystem,org.osgi.framework,org.apache.aries.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.util.filesystem'/>
+      <attribute name='version' type='Version' value='0.1.0'/>
+      <directive name='uses' value='org.apache.aries.util.manifest'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.osgi.framework.adaptor)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.osgi.framework.internal.core)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.osgi.internal.loader)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework.hooks.bundle)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework.launch)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework.wiring)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.framework)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.util.tracker)(version>=1.4.0)(!(version>=2.0.0)))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.eclipse.gemini.blueprint.extender'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.eclipse.gemini.blueprint.extender/org.eclipse.gemini.blueprint.extender-1.0.0.jar'/>
+      <attribute name='description' value='gemini-blueprint-extender'/>
+      <attribute name='size' type='Long' value='179003'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.eclipse.gemini.blueprint.extender'/>
+      <attribute name='bundle-version' type='Version' value='1.0.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.eclipse.gemini.blueprint.extender'/>
+      <attribute name='bundle-version' type='Version' value='1.0.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.extender'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.eclipse.gemini.blueprint.context,org.osgi.framework,org.springframework.beans,org.springframework.beans.factory.config'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.extender.event'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.eclipse.gemini.blueprint.context.event,org.eclipse.gemini.blueprint.service.importer.event,org.osgi.framework,org.springframework.context'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.extender.support'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.eclipse.gemini.blueprint.context,org.eclipse.gemini.blueprint.extender,org.eclipse.gemini.blueprint.extender.support.scanning,org.osgi.framework,org.springframework.beans.factory'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.extender.support.scanning'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.commons.logging)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.eclipse.gemini.blueprint)(version>=1.0.0.RELEASE)(version<=1.0.0.RELEASE))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.eclipse.gemini.blueprint.blueprint.container)(version>=1.0.0.RELEASE)(version<=1.0.0.RELEASE))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.eclipse.gemini.blueprint.blueprint.container.support)(version>=1.0.0.RELEASE)(version<=1.0.0.RELEASE))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.eclipse.gemini.blueprint.context)(version>=1.0.0.RELEASE)(version<=1.0.0.RELEASE))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.eclipse.gemini.blueprint.context.event)(version>=1.0.0.RELEASE)(version<=1.0.0.RELEASE))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.eclipse.gemini.blueprint.context.support)(version>=1.0.0.RELEASE)(version<=1.0.0.RELEASE))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.eclipse.gemini.blueprint.extensions.annotation)(version>=1.0.0.RELEASE)(version<=1.0.0.RELEASE))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.eclipse.gemini.blueprint.io)(version>=1.0.0.RELEASE)(version<=1.0.0.RELEASE))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.eclipse.gemini.blueprint.service.exporter.support)(version>=1.0.0.RELEASE)(version<=1.0.0.RELEASE))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.eclipse.gemini.blueprint.service.importer)(version>=1.0.0.RELEASE)(version<=1.0.0.RELEASE))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.eclipse.gemini.blueprint.service.importer.event)(version>=1.0.0.RELEASE)(version<=1.0.0.RELEASE))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.eclipse.gemini.blueprint.service.importer.support)(version>=1.0.0.RELEASE)(version<=1.0.0.RELEASE))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.eclipse.gemini.blueprint.util)(version>=1.0.0.RELEASE)(version<=1.0.0.RELEASE))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.3.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.blueprint.container)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.blueprint.reflect)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.event)(version>=1.1.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.packageadmin)(version>=1.2.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.util.tracker)(version>=1.3.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.config)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.parsing)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.support)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.xml)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.context)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.context.event)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.convert)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.io)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.io.support)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.task)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.scheduling.timer)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.util)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.xml.sax)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.felix.gogo.shell'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.apache.felix.gogo.shell/org.apache.felix.gogo.shell-0.10.0.jar'/>
+      <attribute name='description' value='Apache Felix Gogo Shell'/>
+      <attribute name='size' type='Long' value='49004'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.felix.gogo.shell'/>
+      <attribute name='bundle-version' type='Version' value='0.10.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.felix.gogo.shell'/>
+      <attribute name='bundle-version' type='Version' value='0.10.0'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.service.command)(version>=0.10.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.framework)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.service.startlevel)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.util.tracker)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.eclipse.gemini.blueprint.io'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.eclipse.gemini.blueprint.io/org.eclipse.gemini.blueprint.io-1.0.0.jar'/>
+      <attribute name='description' value='gemini-blueprint-io'/>
+      <attribute name='size' type='Long' value='32093'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.eclipse.gemini.blueprint.io'/>
+      <attribute name='bundle-version' type='Version' value='1.0.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.eclipse.gemini.blueprint.io'/>
+      <attribute name='bundle-version' type='Version' value='1.0.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.io'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.eclipse.gemini.blueprint.io.internal.resolver,org.osgi.framework,org.springframework.core.io,org.springframework.core.io.support'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.commons.logging)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.3.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.packageadmin)(version>=1.2.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.io)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.io.support)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.util)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.restlet.ext.servlet'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='2.0.9.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.restlet.ext.servlet/org.restlet.ext.servlet-2.0.9.jar'/>
+      <attribute name='description' value='Restlet Extension - Servlet'/>
+      <attribute name='size' type='Long' value='22488'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.restlet.ext.servlet'/>
+      <attribute name='bundle-version' type='Version' value='2.0.9.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.restlet.ext.servlet'/>
+      <attribute name='bundle-version' type='Version' value='2.0.9.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.ext.servlet'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.ext.servlet.internal'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.servlet)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.servlet.http)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.restlet)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.restlet.data)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.restlet.engine)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.restlet.engine.application)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.restlet.engine.component)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.restlet.engine.http)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.restlet.engine.http.adapter)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.restlet.engine.http.header)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.restlet.engine.http.io)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.restlet.engine.local)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.restlet.engine.security)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.restlet.engine.util)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.restlet.representation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.restlet.resource)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.restlet.routing)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.restlet.service)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.restlet.util)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.ee'>
+      <directive name='filter' value='(ee=J2SE-1.5)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.aries.proxy'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.apache.aries.proxy/org.apache.aries.proxy-0.3.0.jar'/>
+      <attribute name='description' value='Apache Aries Proxy Bundle'/>
+      <attribute name='size' type='Long' value='40726'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.aries.proxy'/>
+      <attribute name='bundle-version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.aries.proxy'/>
+      <attribute name='bundle-version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.proxy'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.apache.aries.util.nls,org.osgi.framework'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.util)(version>=0.3.0)(!(version>=1.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.util.nls)(version>=0.3.0)(!(version>=1.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.objectweb.asm)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.objectweb.asm.commons)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='com.sun.jersey.jersey-core'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='1.11.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='com.sun.jersey.jersey-core/com.sun.jersey.jersey-core-1.11.0.jar'/>
+      <attribute name='description' value='jersey-core'/>
+      <attribute name='size' type='Long' value='461795'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='com.sun.jersey.jersey-core'/>
+      <attribute name='bundle-version' type='Version' value='1.11.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='com.sun.jersey.jersey-core'/>
+      <attribute name='bundle-version' type='Version' value='1.11.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.provider.jaxb'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs,javax.xml.parsers,com.sun.jersey.core.util,com.sun.jersey.core.provider,com.sun.jersey.core.impl.provider.entity,javax.ws.rs.ext,org.xml.sax,com.sun.jersey.api.provider.jaxb,javax.xml.stream,javax.xml.transform,javax.xml.bind.annotation,javax.xml.transform.stream,javax.xml.transform.sax,javax.xml.bind,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.impl.provider.header'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.header,com.sun.jersey.core.header.reader,com.sun.jersey.spi,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='javax.ws.rs'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.impl'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.localization'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.util'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.impl,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.provider'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.util,javax.ws.rs.ext,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.provider.jaxb'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.spi.scanning'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.spi.scanning.uri,com.sun.jersey.spi.service,com.sun.jersey.core.util,com.sun.jersey.core.reflection,com.sun.jersey.api.uri'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.impl.provider.xml'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.xml.stream,com.sun.jersey.core.spi.component,javax.xml.transform,javax.xml.parsers,com.sun.jersey.core.util,com.sun.jersey.spi.inject,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.header'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.impl.provider.header,javax.ws.rs,com.sun.jersey.core.header.reader,com.sun.jersey.core.util,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.header.reader'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.impl.provider.header,com.sun.jersey.core.header,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.osgi'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.spi.scanning.uri,com.sun.jersey.impl,com.sun.jersey.core.spi.scanning,org.osgi.framework,com.sun.jersey.spi.service'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs.ext,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi.inject'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.spi.component'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='javax.ws.rs.core'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs,javax.ws.rs.ext'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.localization'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.spi.scanning.uri'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.spi.scanning,com.sun.jersey.core.util,javax.ws.rs.core,com.sun.jersey.api.uri'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.spi.component'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs,com.sun.jersey.core.spi.factory,com.sun.jersey.spi.service,com.sun.jersey.core.reflection,com.sun.jersey.spi.inject'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.spi.factory'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.spi.component,javax.ws.rs,com.sun.jersey.core.util,com.sun.jersey.core.reflection,javax.ws.rs.ext,com.sun.jersey.core.header,com.sun.jersey.spi,com.sun.jersey.spi.service,com.sun.jersey.spi.inject,com.sun.jersey.api.uri,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.spi.component.ioc'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.spi.component,com.sun.jersey.spi.inject'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.representation'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.reflection'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs,com.sun.jersey.impl,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='javax.ws.rs.ext'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.impl.provider.entity'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.provider.jaxb,javax.ws.rs,javax.mail.internet,javax.imageio.stream,com.sun.jersey.impl,javax.imageio.spi,javax.mail.util,com.sun.jersey.core.util,com.sun.jersey.core.provider,javax.xml.transform.dom,org.xml.sax,javax.imageio,javax.xml.stream,com.sun.jersey.spi,javax.xml.transform.sax,com.sun.jersey.spi.inject,javax.ws.rs.core,javax.xml.parsers,com.sun.jersey.api.representation,javax.ws.rs.ext,org.w3c.dom,javax.activation,javax.xml.t [...]
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi.service'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.impl,com.sun.jersey.core.reflection'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.uri'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs,com.sun.jersey.core.util,javax.ws.rs.core'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.provider.jaxb)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.representation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.uri)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.header)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.header.reader)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.impl.provider.entity)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.impl.provider.header)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.impl.provider.xml)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.osgi)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.provider)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.provider.jaxb)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.reflection)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.spi.component)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.spi.component.ioc)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.spi.factory)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.spi.scanning)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.spi.scanning.uri)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.util)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.impl)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.localization)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.inject)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.service)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.activation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.imageio)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.imageio.spi)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.imageio.stream)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.mail)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.mail.internet)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.mail.util)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.bind)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.bind.annotation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.parsers)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.stream)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform.dom)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform.sax)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform.stream)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.framework)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.w3c.dom)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.xml.sax)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='slf4j.api'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='1.6.2'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='slf4j.api/slf4j.api-1.6.2.jar'/>
+      <attribute name='description' value='slf4j-api'/>
+      <attribute name='size' type='Long' value='26249'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='slf4j.api'/>
+      <attribute name='bundle-version' type='Version' value='1.6.2'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='slf4j.api'/>
+      <attribute name='bundle-version' type='Version' value='1.6.2'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.slf4j'/>
+      <attribute name='version' type='Version' value='1.6.2'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.slf4j.spi'/>
+      <attribute name='version' type='Version' value='1.6.2'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.slf4j.helpers'/>
+      <attribute name='version' type='Version' value='1.6.2'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j.impl)(version>=1.6.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.ee'>
+      <directive name='filter' value='(ee=J2SE-1.3)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.eclipse.gemini.blueprint.core'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.eclipse.gemini.blueprint.core/org.eclipse.gemini.blueprint.core-1.0.0.jar'/>
+      <attribute name='description' value='gemini-blueprint-core'/>
+      <attribute name='size' type='Long' value='579493'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.eclipse.gemini.blueprint.core'/>
+      <attribute name='bundle-version' type='Version' value='1.0.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.eclipse.gemini.blueprint.core'/>
+      <attribute name='bundle-version' type='Version' value='1.0.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.blueprint.compendium.cm.config'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans.factory.xml'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.blueprint.config'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.eclipse.gemini.blueprint.blueprint.config.internal,org.eclipse.gemini.blueprint.service.importer.support,org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.beans.factory.support,org.springframework.beans.factory.xml,org.w3c.dom'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.blueprint.container'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.osgi.service.blueprint.container,org.osgi.service.blueprint.reflect,org.springframework.beans,org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.context,org.springframework.core.convert'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.blueprint.container.support'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.osgi.framework,org.osgi.service.blueprint.container,org.springframework.beans,org.springframework.beans.propertyeditors,org.springframework.context,org.springframework.context.event'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.blueprint.reflect'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.osgi.service.blueprint.reflect,org.springframework.beans,org.springframework.beans.factory.config,org.springframework.beans.factory.support'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.bundle'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.eclipse.gemini.blueprint.context,org.osgi.framework,org.springframework.beans.factory,org.springframework.context,org.springframework.core.enums,org.springframework.core.io'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.compendium.cm'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.apache.commons.logging,org.eclipse.gemini.blueprint.context,org.osgi.framework,org.osgi.service.cm,org.springframework.beans.factory'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.compendium.config'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.beans.factory.xml'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.config'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.eclipse.gemini.blueprint.config.internal,org.eclipse.gemini.blueprint.service.importer.support,org.springframework.beans.factory.xml'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.context'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.eclipse.gemini.blueprint.context.event,org.osgi.framework,org.springframework.beans,org.springframework.beans.factory.config,org.springframework.context'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.context.event'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.osgi.framework,org.springframework.context,org.springframework.context.event'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.context.support'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='javax.xml.parsers,org.apache.commons.logging,org.eclipse.gemini.blueprint.context,org.eclipse.gemini.blueprint.context.event,org.eclipse.gemini.blueprint.util.internal,org.osgi.framework,org.springframework.beans,org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.beans.factory.support,org.springframework.beans.factory.xml,org.springframework.context,org.springframework.context.event,org.springframework.contex [...]
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.service'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.eclipse.gemini.blueprint,org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.service.exporter'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.service.exporter.support'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.eclipse.gemini.blueprint.context,org.eclipse.gemini.blueprint.service.exporter,org.eclipse.gemini.blueprint.service.exporter.support.internal.controller,org.eclipse.gemini.blueprint.service.exporter.support.internal.support,org.osgi.framework,org.springframework.beans,org.springframework.beans.factory,org.springframework.core,org.springframework.core.enums'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.service.importer'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.eclipse.gemini.blueprint.service,org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.service.importer.event'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.eclipse.gemini.blueprint.service.importer,org.springframework.context'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.service.importer.support'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.aopalliance.aop,org.aopalliance.intercept,org.eclipse.gemini.blueprint.context,org.eclipse.gemini.blueprint.context.support.internal.classloader,org.eclipse.gemini.blueprint.service.importer,org.eclipse.gemini.blueprint.service.importer.support.internal.aop,org.eclipse.gemini.blueprint.service.importer.support.internal.collection,org.eclipse.gemini.blueprint.service.importer.support.internal.controller,org.eclipse.gemini.blueprint.service.importer. [...]
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.gemini.blueprint.util'/>
+      <attribute name='version' type='Version' value='1.0.0.RELEASE'/>
+      <directive name='uses' value='org.apache.commons.logging,org.osgi.framework,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.blueprint.container'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework,org.osgi.service.blueprint.reflect'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.blueprint.reflect'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.parsers)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aopalliance.aop)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aopalliance.intercept)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.commons.logging)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.eclipse.gemini.blueprint.io)(version>=1.0.0.RELEASE)(version<=1.0.0.RELEASE))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.3.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.cm)(version>=1.2.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.packageadmin)(version>=1.2.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.startlevel)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.aop)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.aop.framework)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.aop.support)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.config)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.parsing)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.support)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.xml)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.propertyeditors)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.context)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.context.event)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.context.support)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.convert)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.enums)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.io)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.io.support)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.util)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.util.xml)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.w3c.dom)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.xml.sax)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.felix.http.jetty'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='2.2.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.apache.felix.http.jetty/org.apache.felix.http.jetty-2.2.0.jar'/>
+      <attribute name='description' value='Apache Felix Http Jetty'/>
+      <attribute name='size' type='Long' value='941716'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.felix.http.jetty'/>
+      <attribute name='bundle-version' type='Version' value='2.2.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.felix.http.jetty'/>
+      <attribute name='bundle-version' type='Version' value='2.2.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.felix.http.api'/>
+      <attribute name='version' type='Version' value='2.0.4'/>
+      <directive name='uses' value='javax.servlet,org.osgi.service.http'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.http'/>
+      <attribute name='version' type='Version' value='1.2.0'/>
+      <directive name='uses' value='javax.servlet.http,javax.servlet'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='javax.servlet.resources'/>
+      <attribute name='version' type='Version' value='2.5.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='javax.servlet'/>
+      <attribute name='version' type='Version' value='2.5.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='javax.servlet.jsp.resources'/>
+      <attribute name='version' type='Version' value='2.5.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='javax.servlet.http'/>
+      <attribute name='version' type='Version' value='2.5.0'/>
+      <directive name='uses' value='javax.servlet'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.net.ssl)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.security.cert)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.servlet)(version>=2.5.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.servlet.http)(version>=2.5.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.servlet.jsp.resources)(version>=2.5.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.servlet.resources)(version>=2.5.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.parsers)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.http.api)(version>=2.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.3.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.http)(version>=1.2.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.log)(version>=1.3.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.util.tracker)(version>=1.3.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.slf4j)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.xml.sax)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.xml.sax.helpers)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.felix.gogo.command'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.12.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.apache.felix.gogo.command/org.apache.felix.gogo.command-0.12.0.jar'/>
+      <attribute name='description' value='Apache Felix Gogo Command'/>
+      <attribute name='size' type='Long' value='51746'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.felix.gogo.command'/>
+      <attribute name='bundle-version' type='Version' value='0.12.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.felix.gogo.command'/>
+      <attribute name='bundle-version' type='Version' value='0.12.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.log'/>
+      <attribute name='version' type='Version' value='1.3.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.service.command)(version>=0.10.0)(!(version>=1.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework.wiring)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.log)(version>=1.3.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.packageadmin)(version>=1.2.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.startlevel)(version>=1.1.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.util.tracker)(version>=1.3.0)(!(version>=2.0.0)))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='slf4j.jdk14'/>
+      <attribute name='type' value='osgi.fragment'/>
+      <attribute name='version' type='Version' value='1.6.2'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='slf4j.jdk14/slf4j.jdk14-1.6.2.jar'/>
+      <attribute name='description' value='slf4j-jdk14'/>
+      <attribute name='size' type='Long' value='9145'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.slf4j.impl'/>
+      <attribute name='version' type='Version' value='1.6.2'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j)(version>=1.6.2))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j.spi)(version>=1.6.2))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j.helpers)(version>=1.6.2))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.host'>
+      <directive name='filter' value='(&(osgi.wiring.host=slf4j.api)(bundle-version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.ee'>
+      <directive name='filter' value='(ee=J2SE-1.3)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.ops4j.pax.web.pax-web-extender-whiteboard'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='1.1.2'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.ops4j.pax.web.pax-web-extender-whiteboard/org.ops4j.pax.web.pax-web-extender-whiteboard-1.1.2.jar'/>
+      <attribute name='description' value='OPS4J Pax Web - Extender - Whiteboard'/>
+      <attribute name='size' type='Long' value='1041602'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.ops4j.pax.web.pax-web-extender-whiteboard'/>
+      <attribute name='bundle-version' type='Version' value='1.1.2'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.ops4j.pax.web.pax-web-extender-whiteboard'/>
+      <attribute name='bundle-version' type='Version' value='1.1.2'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.ops4j.pax.web.extender.whiteboard'/>
+      <attribute name='version' type='Version' value='1.1.2'/>
+      <directive name='uses' value='javax.servlet,org.osgi.service.http'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.ops4j.pax.web.extender.whiteboard.runtime'/>
+      <attribute name='version' type='Version' value='1.1.2'/>
+      <directive name='uses' value='org.ops4j.pax.web.extender.whiteboard,javax.servlet,org.osgi.service.http'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.security.auth)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.security.auth.callback)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.security.auth.login)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.servlet)(version>=2.3.0)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.servlet.http)(version>=2.3.0)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.servlet.resources)(version>=2.3.0)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.parsers)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.ops4j.pax.web.extender.whiteboard)(version>=1.1.2))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.ops4j.pax.web.extender.whiteboard.runtime)(version>=1.1.2))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.ops4j.pax.web.service)(version>=0.6.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.http)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.util.tracker)(version>=1.3.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.restlet'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='2.0.9.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.restlet/org.restlet-2.0.9.jar'/>
+      <attribute name='description' value='Restlet API'/>
+      <attribute name='size' type='Long' value='670843'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.restlet'/>
+      <attribute name='bundle-version' type='Version' value='2.0.9.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.restlet'/>
+      <attribute name='bundle-version' type='Version' value='2.0.9.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.data'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.engine'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.engine.application'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.engine.component'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.engine.converter'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.engine.http'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.engine.http.adapter'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.engine.http.connector'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.engine.http.header'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.engine.http.io'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.engine.http.security'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.engine.internal'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.engine.io'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.engine.local'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.engine.log'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.engine.resource'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.engine.riap'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.engine.security'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.engine.util'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.representation'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.resource'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.routing'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.security'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.service'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.restlet.util'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.net)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.net.ssl)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.parsers)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.framework)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.ee'>
+      <directive name='filter' value='(ee=J2SE-1.5)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.aries.samples.blueprint.helloworld.server'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.apache.aries.samples.blueprint.helloworld.server/org.apache.aries.samples.blueprint.helloworld.server-0.3.0.jar'/>
+      <attribute name='description' value='Apache Aries Blueprint HelloWorldServer'/>
+      <attribute name='size' type='Long' value='10683'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.aries.samples.blueprint.helloworld.server'/>
+      <attribute name='bundle-version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.aries.samples.blueprint.helloworld.server'/>
+      <attribute name='bundle-version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.samples.blueprint.helloworld.server'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.apache.aries.samples.blueprint.helloworld.api'/>
+    </capability>
+    <capability namespace='osgi.wiring.service'>
+      <attribute name='osgi.wiring.service' value='org.apache.aries.samples.blueprint.helloworld.api.HelloWorldService'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.samples.blueprint.helloworld.api)(version>=0.3.0)(!(version>=0.4.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.blueprint)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='com.sun.jersey.jersey-servlet'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='1.11.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='com.sun.jersey.jersey-servlet/com.sun.jersey.jersey-servlet-1.11.0.jar'/>
+      <attribute name='description' value='jersey-servlet'/>
+      <attribute name='size' type='Long' value='124439'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='com.sun.jersey.jersey-servlet'/>
+      <attribute name='bundle-version' type='Version' value='1.11.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='com.sun.jersey.jersey-servlet'/>
+      <attribute name='bundle-version' type='Version' value='1.11.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.container.servlet'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs,com.sun.jersey.server.impl.application,javax.servlet,com.sun.jersey.spi.template,com.sun.jersey.spi.container,com.sun.jersey.api.core,javax.servlet.jsp.tagext,com.sun.jersey.spi.inject,com.sun.jersey.server.impl,javax.persistence,javax.ws.rs.core,com.sun.jersey.spi.container.servlet,com.sun.jersey.api.model,com.sun.jersey.core.spi.component,com.sun.jersey.server.spi.component,com.sun.jersey.api.container,com.sun.jersey.core.spi.component.io [...]
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.core.servlet'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.spi.scanning,javax.servlet,com.sun.jersey.spi.scanning.servlet,com.sun.jersey.api.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi.scanning.servlet'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.spi.scanning,javax.servlet,com.sun.jersey.core.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi.container.servlet'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.server.impl.application,com.sun.jersey.core.util,javax.servlet,com.sun.jersey.core.header,com.sun.jersey.server.impl.container.servlet,com.sun.jersey.server.impl.monitoring,com.sun.jersey.api.core,com.sun.jersey.spi.container,com.sun.jersey.spi.inject,com.sun.jersey.server.impl,javax.ws.rs.core,javax.naming,com.sun.jersey.server.spi.component,com.sun.jersey.server.probes,com.sun.jersey.api.container,com.sun.jersey.core.reflection,com.sun [...]
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.container)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.core)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.core.servlet)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.model)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.representation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.uri)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.view)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.header)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.osgi)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.reflection)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.spi.component)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.spi.component.ioc)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.spi.scanning)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.util)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.application)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.container.servlet)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.inject)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.monitoring)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.probes)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.spi.component)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.container)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.container.servlet)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.dispatch)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.inject)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.scanning.servlet)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.service)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.template)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.net.httpserver)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.annotation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.ejb)(version>=3.1.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.enterprise.context)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.enterprise.context.spi)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.enterprise.event)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.enterprise.inject)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.enterprise.inject.spi)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.enterprise.util)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.inject)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.interceptor)(version>=3.1.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.naming)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.persistence)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.servlet)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.servlet.annotation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.servlet.http)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.servlet.jsp)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.servlet.jsp.tagext)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.ws.rs)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.ws.rs.core)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.ws.rs.ext)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.namespace)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.objectweb.asm)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.springframework.aspects'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.springframework.aspects/org.springframework.aspects-3.1.0.jar'/>
+      <attribute name='description' value='Spring Aspects'/>
+      <attribute name='size' type='Long' value='51447'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.springframework.aspects'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.springframework.aspects'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.beans.factory.aspectj'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.aspectj.internal.lang.annotation,org.aspectj.lang,org.aspectj.lang.annotation,org.springframework.beans,org.springframework.beans.factory,org.springframework.beans.factory.annotation,org.springframework.beans.factory.wiring,org.springframework.context.annotation'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.cache.aspectj'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.aspectj.lang,org.aspectj.lang.annotation,org.aspectj.runtime.internal,org.springframework.cache.annotation,org.springframework.cache.interceptor,org.springframework.context.annotation'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.mock.staticmock'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.aspectj.lang,org.aspectj.lang.annotation,org.aspectj.runtime.internal'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.orm.jpa.aspectj'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.aspectj.lang.annotation'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.scheduling.aspectj'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.aspectj.internal.lang.annotation,org.aspectj.lang,org.aspectj.lang.annotation,org.aspectj.runtime.internal,org.springframework.context.annotation,org.springframework.scheduling.annotation'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.transaction.aspectj'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.aspectj.lang,org.aspectj.lang.annotation,org.springframework.context.annotation,org.springframework.transaction.annotation,org.springframework.transaction.interceptor'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.commons.logging)(version>=1.1.1)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.internal.lang.annotation)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.lang)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.lang.annotation)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.lang.reflect)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.runtime.internal)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.annotation)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.wiring)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.cache)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.cache.annotation)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.cache.interceptor)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.context.annotation)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.task)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.task.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.dao)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.orm.jpa)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.scheduling.annotation)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.transaction)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.transaction.annotation)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.transaction.interceptor)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.aopalliance'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='1.0.0.v201105210816'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.aopalliance/org.aopalliance-1.0.0.jar'/>
+      <attribute name='description' value='Aopalliance Plug-in'/>
+      <attribute name='size' type='Long' value='11093'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.aopalliance'/>
+      <attribute name='bundle-version' type='Version' value='1.0.0.v201105210816'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.aopalliance'/>
+      <attribute name='bundle-version' type='Version' value='1.0.0.v201105210816'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.aopalliance.aop'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.aopalliance.intercept'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+    </capability>
+    <requirement namespace='osgi.wiring.ee'>
+      <directive name='filter' value='(ee=J2SE-1.4)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.aries.proxy.api'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.apache.aries.proxy.api/org.apache.aries.proxy.api-0.3.0.jar'/>
+      <attribute name='description' value='Apache Aries Proxy'/>
+      <attribute name='size' type='Long' value='11553'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.aries.proxy.api'/>
+      <attribute name='bundle-version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.aries.proxy.api'/>
+      <attribute name='bundle-version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.proxy'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.apache.aries.util.nls,org.osgi.framework'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.util.nls)(version>=0.3.0)(!(version>=1.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.aries.blueprint'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.4.1.SNAPSHOT'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.apache.aries.blueprint/org.apache.aries.blueprint-0.4.1.jar'/>
+      <attribute name='description' value='Apache Aries Blueprint Bundle'/>
+      <attribute name='size' type='Long' value='425096'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.aries.blueprint'/>
+      <attribute name='bundle-version' type='Version' value='0.4.1.SNAPSHOT'/>
+      <directive name='blueprint.graceperiod' value='false'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.aries.blueprint'/>
+      <attribute name='bundle-version' type='Version' value='0.4.1.SNAPSHOT'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.blueprint'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+      <directive name='uses' value='org.osgi.service.blueprint.container,org.osgi.service.blueprint.reflect,org.apache.aries.blueprint,org.apache.aries.blueprint.ext,org.apache.aries.blueprint.mutable,org.apache.aries.blueprint.compendium.cm'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.blueprint.container'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+      <directive name='uses' value='org.osgi.service.blueprint.reflect,org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.blueprint.reflect'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint'/>
+      <attribute name='version' type='Version' value='0.4.0'/>
+      <directive name='uses' value='org.osgi.service.blueprint.reflect,org.apache.aries.blueprint.services,org.osgi.framework,org.w3c.dom'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.services'/>
+      <attribute name='version' type='Version' value='0.4.0'/>
+      <directive name='uses' value='org.apache.aries.blueprint,org.osgi.service.blueprint.reflect,org.osgi.framework,org.apache.aries.proxy,org.osgi.service.blueprint.container'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.mutable'/>
+      <attribute name='version' type='Version' value='0.3.2'/>
+      <directive name='uses' value='org.osgi.service.blueprint.reflect,org.apache.aries.blueprint,org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.ext'/>
+      <attribute name='version' type='Version' value='0.4.0'/>
+      <directive name='uses' value='org.osgi.service.blueprint.reflect,org.slf4j,org.apache.aries.blueprint,org.osgi.framework,org.osgi.service.blueprint.container,org.apache.aries.blueprint.mutable,org.apache.aries.blueprint.services,org.apache.aries.blueprint.ext.evaluator'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.ext.evaluator'/>
+      <attribute name='version' type='Version' value='0.3.2'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.utils'/>
+      <attribute name='version' type='Version' value='0.4.0'/>
+      <directive name='uses' value='org.osgi.framework,org.apache.aries.blueprint.services,org.osgi.service.blueprint.container,org.slf4j'/>
+    </capability>
+    <capability namespace='osgi.wiring.service'>
+      <attribute name='osgi.wiring.service' value='org.apache.aries.blueprint.NamespaceHandler'/>
+    </capability>
+    <capability namespace='osgi.wiring.service'>
+      <attribute name='osgi.wiring.service' value='org.apache.aries.blueprint.ParserService'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.namespace)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.parsers)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform.dom)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform.stream)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.validation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.blueprint.annotation.service)(version>=0.3.0)(!(version>=0.4.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.proxy)(version>=0.4.0)(!(version>=0.5.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.quiesce.manager)(version>=0.3.0)(!(version>=0.4.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.quiesce.participant)(version>=0.3.0)(!(version>=0.4.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.util)(version>=0.4.0)(!(version>=0.5.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.aries.util.tracker)(version>=0.4.0)(!(version>=0.5.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.osgi.framework.adaptor)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.osgi.framework.internal.core)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.osgi.internal.loader)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.blueprint.container)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.blueprint.reflect)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.cm)(version>=1.2.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.event)(version>=1.2.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.framework)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.util.tracker)(version>=1.4.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.w3c.dom)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.w3c.dom.ls)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.xml.sax)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.service'>
+      <directive name='filter' value='(osgi.wiring.service=org.osgi.service.cm.ConfigurationAdmin)'/>
+      <directive name='effective' value='active'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='name.njbartlett.osgi.emf.xmi'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='2.7.0.v20110520-1406'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='name.njbartlett.osgi.emf.xmi/name.njbartlett.osgi.emf.xmi-2.7.0.jar'/>
+      <attribute name='description' value='name.njbartlett.osgi.emf.xmi'/>
+      <attribute name='size' type='Long' value='208809'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='name.njbartlett.osgi.emf.xmi'/>
+      <attribute name='bundle-version' type='Version' value='2.7.0.v20110520-1406'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='name.njbartlett.osgi.emf.xmi'/>
+      <attribute name='bundle-version' type='Version' value='2.7.0.v20110520-1406'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.emf.ecore.xmi'/>
+      <attribute name='version' type='Version' value='2.7.0.v20110520-1406'/>
+      <directive name='uses' value='org.eclipse.emf.ecore,org.w3c.dom,org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.util,org.eclipse.emf.common.util,org.eclipse.emf.common,org.xml.sax.ext,org.xml.sax,javax.xml.parsers,org.eclipse.emf.ecore.xml.type'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.emf.ecore.xmi.impl'/>
+      <attribute name='version' type='Version' value='2.7.0.v20110520-1406'/>
+      <directive name='uses' value='org.eclipse.emf.ecore.xmi,org.eclipse.emf.ecore,org.eclipse.emf.ecore.util,org.w3c.dom,org.eclipse.emf.common.util,org.xml.sax,org.xml.sax.helpers,org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.ecore.xml.type,org.eclipse.emf.common,org.eclipse.emf.ecore.impl,org.eclipse.emf.ecore.xml.type.util,org.eclipse.emf.ecore.xmi.util,org.eclipse.emf.ecore.xml.type.internal,javax.xml.namespace,org.xml.sax.ext,javax.xml.parsers, [...]
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.emf.ecore.xmi.util'/>
+      <attribute name='version' type='Version' value='2.7.0.v20110520-1406'/>
+      <directive name='uses' value='org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.util,org.eclipse.emf.ecore.xmi,org.eclipse.emf.common.util,org.eclipse.emf.common,org.eclipse.emf.ecore.xmi.impl,org.eclipse.emf.ecore.resource.impl,org.w3c.dom,org.xml.sax,org.eclipse.emf.ecore,org.eclipse.emf.ecore.impl'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.namespace)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.parsers)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.emf.common)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.emf.common.notify)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.emf.common.util)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.emf.ecore)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.emf.ecore.impl)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.emf.ecore.resource)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.emf.ecore.resource.impl)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.emf.ecore.util)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.emf.ecore.xml.namespace)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.emf.ecore.xml.type)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.emf.ecore.xml.type.internal)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.emf.ecore.xml.type.util)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.w3c.dom)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.xml.sax)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.xml.sax.ext)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.xml.sax.helpers)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.felix.gogo.runtime'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.apache.felix.gogo.runtime/org.apache.felix.gogo.runtime-0.10.0.jar'/>
+      <attribute name='description' value='Apache Felix Gogo Runtime'/>
+      <attribute name='size' type='Long' value='66965'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.felix.gogo.runtime'/>
+      <attribute name='bundle-version' type='Version' value='0.10.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.felix.gogo.runtime'/>
+      <attribute name='bundle-version' type='Version' value='0.10.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <attribute name='osgi.wiring.package' value='org.apache.felix.service.command'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+      <directive name='mandatory' value='status'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.felix.gogo.api'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+      <directive name='uses' value='org.apache.felix.service.command'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <attribute name='osgi.wiring.package' value='org.apache.felix.service.threadio'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+      <directive name='mandatory' value='status'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.gogo.api)(version>=0.10.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.service.command)(version>=0.10.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.service.threadio)(version>=0.10.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.framework)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.service.event)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.util.tracker)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='osgi.cmpn'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='4.3.0.201111022214'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='osgi.cmpn/osgi.cmpn-4.3.0.jar'/>
+      <attribute name='description' value='osgi.cmpn'/>
+      <attribute name='size' type='Long' value='743014'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='osgi.cmpn'/>
+      <attribute name='bundle-version' type='Version' value='4.3.0.201111022214'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='osgi.cmpn'/>
+      <attribute name='bundle-version' type='Version' value='4.3.0.201111022214'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.application'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.application'/>
+      <attribute name='version' type='Version' value='1.1.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.blueprint.reflect'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.blueprint.container'/>
+      <attribute name='version' type='Version' value='1.0.2'/>
+      <directive name='uses' value='org.osgi.service.blueprint.reflect,org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.cm'/>
+      <attribute name='version' type='Version' value='1.4.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.component'/>
+      <attribute name='version' type='Version' value='1.2.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.component.annotations'/>
+      <attribute name='version' type='Version' value='1.2.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.coordinator'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.deploymentadmin'/>
+      <attribute name='version' type='Version' value='1.1.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.deploymentadmin.spi'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+      <directive name='uses' value='org.osgi.framework,org.osgi.service.deploymentadmin'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.device'/>
+      <attribute name='version' type='Version' value='1.1.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.dmt.notification'/>
+      <attribute name='version' type='Version' value='2.0.0'/>
+      <directive name='uses' value='org.osgi.service.dmt'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.dmt'/>
+      <attribute name='version' type='Version' value='2.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.dmt.security'/>
+      <attribute name='version' type='Version' value='2.0.0'/>
+      <directive name='uses' value='org.osgi.service.dmt'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.dmt.spi'/>
+      <attribute name='version' type='Version' value='2.0.0'/>
+      <directive name='uses' value='org.osgi.service.dmt'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.dmt.notification.spi'/>
+      <attribute name='version' type='Version' value='2.0.0'/>
+      <directive name='uses' value='org.osgi.service.dmt.notification'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.event'/>
+      <attribute name='version' type='Version' value='1.3.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.http'/>
+      <attribute name='version' type='Version' value='1.2.1'/>
+      <directive name='uses' value='javax.servlet.http,javax.servlet'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.io'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='javax.microedition.io'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.jdbc'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='javax.sql'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.jndi'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='javax.naming.directory,javax.naming'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.jpa'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='javax.persistence'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.log'/>
+      <attribute name='version' type='Version' value='1.3.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.metatype'/>
+      <attribute name='version' type='Version' value='1.2.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.monitor'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.prefs'/>
+      <attribute name='version' type='Version' value='1.1.1'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.provisioning'/>
+      <attribute name='version' type='Version' value='1.2.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.remoteserviceadmin'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.upnp'/>
+      <attribute name='version' type='Version' value='1.2.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.useradmin'/>
+      <attribute name='version' type='Version' value='1.1.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.wireadmin'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.util.measurement'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.util.position'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+      <directive name='uses' value='org.osgi.util.measurement'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.util.tracker'/>
+      <attribute name='version' type='Version' value='1.5.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.util.xml'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+      <directive name='uses' value='org.osgi.framework,javax.xml.parsers'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.microedition.io)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.naming)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.naming.directory)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.persistence)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.servlet)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.servlet.http)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.sql)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.parsers)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.framework)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='name.njbartlett.osgi.emf.minimal'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='2.7.0.v20110912-0920'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='name.njbartlett.osgi.emf.minimal/name.njbartlett.osgi.emf.minimal-2.7.0.jar'/>
+      <attribute name='description' value='name.njbartlett.osgi.emf.minimal'/>
+      <attribute name='size' type='Long' value='1192550'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='name.njbartlett.osgi.emf.minimal'/>
+      <attribute name='bundle-version' type='Version' value='2.7.0.v20110912-0920'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='name.njbartlett.osgi.emf.minimal'/>
+      <attribute name='bundle-version' type='Version' value='2.7.0.v20110912-0920'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.emf.common'/>
+      <attribute name='version' type='Version' value='2.7.0.v20110912-0920'/>
+      <directive name='uses' value='org.eclipse.core.runtime,org.eclipse.emf.common.util,org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.emf.common.notify'/>
+      <attribute name='version' type='Version' value='2.7.0.v20110912-0920'/>
+      <directive name='uses' value='org.eclipse.emf.common.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.emf.common.notify.impl'/>
+      <attribute name='version' type='Version' value='2.7.0.v20110912-0920'/>
+      <directive name='uses' value='org.eclipse.emf.common.util,org.eclipse.emf.common.notify'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.emf.common.util'/>
+      <attribute name='version' type='Version' value='2.7.0.v20110912-0920'/>
+      <directive name='uses' value='org.eclipse.core.runtime,org.eclipse.emf.common'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.emf.ecore'/>
+      <attribute name='version' type='Version' value='2.7.0.v20110912-0920'/>
+      <directive name='uses' value='org.eclipse.emf.common.util,org.eclipse.emf.ecore.resource,org.eclipse.emf.common.notify,org.eclipse.emf.ecore.impl,org.eclipse.emf.ecore.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.emf.ecore.impl'/>
+      <attribute name='version' type='Version' value='2.7.0.v20110912-0920'/>
+      <directive name='uses' value='org.eclipse.emf.ecore.util,org.eclipse.emf.ecore,org.eclipse.emf.common.util,org.eclipse.emf.ecore.resource,org.eclipse.emf.common.notify.impl,org.eclipse.emf.common.notify,org.eclipse.emf.ecore.xml.type.util,org.eclipse.emf.common,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.ecore.plugin,org.eclipse.emf.ecore.xml.type'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.emf.ecore.plugin'/>
+      <attribute name='version' type='Version' value='2.7.0.v20110912-0920'/>
+      <directive name='uses' value='org.eclipse.emf.ecore.resource,org.eclipse.core.runtime,org.osgi.framework,org.eclipse.emf.ecore,org.xml.sax.helpers,org.xml.sax,org.eclipse.emf.ecore.impl,org.eclipse.core.resources,org.eclipse.emf.common,org.eclipse.emf.common.util,javax.xml.parsers,org.eclipse.emf.ecore.util,org.eclipse.emf.ecore.resource.impl'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.emf.ecore.resource'/>
+      <attribute name='version' type='Version' value='2.7.0.v20110912-0920'/>
+      <directive name='uses' value='org.eclipse.core.runtime.content,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.common.util,org.eclipse.emf.ecore,org.eclipse.emf.common.notify'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.emf.ecore.resource.impl'/>
+      <attribute name='version' type='Version' value='2.7.0.v20110912-0920'/>
+      <directive name='uses' value='org.eclipse.emf.ecore.resource,javax.crypto.spec,javax.crypto,org.eclipse.emf.common.util,org.eclipse.emf.ecore,org.eclipse.emf.ecore.util,org.eclipse.core.runtime,org.eclipse.core.runtime.content,org.eclipse.emf.common,org.eclipse.emf.ecore.plugin,org.eclipse.core.resources,org.eclipse.emf.common.notify.impl,org.eclipse.emf.common.notify,org.eclipse.emf.ecore.impl'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.emf.ecore.xml.namespace'/>
+      <attribute name='version' type='Version' value='2.7.0.v20110912-0920'/>
+      <directive name='uses' value='org.eclipse.emf.common.util,org.eclipse.emf.ecore.util,org.eclipse.emf.ecore'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.emf.ecore.xml.type'/>
+      <attribute name='version' type='Version' value='2.7.0.v20110912-0920'/>
+      <directive name='uses' value='org.eclipse.emf.ecore.util,org.eclipse.emf.ecore,org.eclipse.emf.common.util,javax.xml.datatype,javax.xml.namespace'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.emf.ecore.xml.type.internal'/>
+      <attribute name='version' type='Version' value='2.7.0.v20110912-0920'/>
+      <directive name='uses' value='org.eclipse.emf.ecore.xml.type,javax.xml.namespace,org.eclipse.emf.ecore.plugin,org.eclipse.emf.common.util,org.eclipse.emf.ecore.xml.type.util,javax.xml.datatype'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.emf.ecore.xml.type.util'/>
+      <attribute name='version' type='Version' value='2.7.0.v20110912-0920'/>
+      <directive name='uses' value='org.xml.sax,org.eclipse.emf.ecore.xml.type,javax.xml.datatype,javax.xml.namespace,org.xml.sax.helpers,org.eclipse.emf.common.util,org.eclipse.emf.ecore.resource.impl,org.eclipse.emf.ecore,org.eclipse.emf.ecore.xml.type.internal,org.eclipse.emf.ecore.plugin,org.eclipse.emf.ecore.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.eclipse.emf.ecore.util'/>
+      <attribute name='version' type='Version' value='2.7.0.v20110912-0920'/>
+      <directive name='uses' value='org.eclipse.emf.common.notify,org.eclipse.emf.ecore,org.eclipse.emf.common.util,org.eclipse.emf.ecore.xml.type,org.eclipse.emf.ecore.xml.type.util,org.eclipse.emf.ecore.impl,org.eclipse.emf.common.notify.impl,org.eclipse.emf.ecore.resource,org.eclipse.emf.ecore.plugin,org.eclipse.emf.ecore.xml.namespace'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.crypto)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.crypto.spec)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.datatype)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.namespace)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.parsers)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.core.resources)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.core.runtime)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.core.runtime.content)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.emf.common.notify)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.emf.common.util)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.emf.ecore)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.emf.ecore.impl)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.emf.ecore.plugin)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.emf.ecore.resource)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.emf.ecore.util)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.emf.ecore.xml.type.internal)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.emf.ecore.xml.type.util)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.6.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.xml.sax)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.xml.sax.helpers)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.aries.blueprint.sample'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.apache.aries.blueprint.sample/org.apache.aries.blueprint.sample-0.3.0.jar'/>
+      <attribute name='description' value='Apache Aries Blueprint Sample'/>
+      <attribute name='size' type='Long' value='20623'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.aries.blueprint.sample'/>
+      <attribute name='bundle-version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.aries.blueprint.sample'/>
+      <attribute name='bundle-version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.blueprint.sample'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='org.osgi.framework,org.osgi.service.blueprint.container'/>
+    </capability>
+    <capability namespace='osgi.wiring.service'>
+      <attribute name='osgi.wiring.service' value='java.util.List'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.blueprint)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.blueprint.container)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.service'>
+      <directive name='filter' value='(osgi.wiring.service=java.util.Set)'/>
+      <directive name='effective' value='active'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.service'>
+      <directive name='filter' value='(osgi.wiring.service=org.apache.aries.blueprint.sample.InterfaceA)'/>
+      <directive name='effective' value='active'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.springframework.aop'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.springframework.aop/org.springframework.aop-3.1.0.jar'/>
+      <attribute name='description' value='Spring AOP'/>
+      <attribute name='size' type='Long' value='336078'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.springframework.aop'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.springframework.aop'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.aop'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.aopalliance.aop,org.aopalliance.intercept,org.springframework.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.aop.aspectj'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.aopalliance.aop,org.aopalliance.intercept,org.aspectj.bridge,org.aspectj.lang,org.aspectj.lang.reflect,org.aspectj.runtime.internal,org.aspectj.weaver.ast,org.aspectj.weaver.internal.tools,org.aspectj.weaver.reflect,org.aspectj.weaver.tools,org.springframework.aop,org.springframework.aop.support,org.springframework.beans.factory,org.springframework.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.aop.aspectj.annotation'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.aopalliance.aop,org.aspectj.lang.reflect,org.springframework.aop,org.springframework.aop.aspectj,org.springframework.aop.aspectj.autoproxy,org.springframework.aop.framework,org.springframework.aop.support,org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.core,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.aop.aspectj.autoproxy'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.aspectj.util,org.springframework.aop,org.springframework.aop.framework.autoproxy'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.aop.config'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.aop.aspectj,org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.beans.factory.parsing,org.springframework.beans.factory.support,org.springframework.beans.factory.xml,org.w3c.dom'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.aop.framework'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='net.sf.cglib.proxy,org.aopalliance.aop,org.aopalliance.intercept,org.springframework.aop,org.springframework.aop.framework.adapter,org.springframework.beans,org.springframework.beans.factory,org.springframework.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.aop.framework.adapter'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.aopalliance.aop,org.aopalliance.intercept,org.springframework.aop,org.springframework.beans,org.springframework.beans.factory.config'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.aop.framework.autoproxy'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.aop,org.springframework.aop.framework,org.springframework.aop.framework.adapter,org.springframework.beans,org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.aop.framework.autoproxy.target'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.aop,org.springframework.aop.framework.autoproxy,org.springframework.aop.target,org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.beans.factory.support'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.aop.interceptor'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.aopalliance.aop,org.aopalliance.intercept,org.apache.commons.logging,org.springframework.aop,org.springframework.aop.support,org.springframework.beans.factory,org.springframework.core,org.springframework.core.task,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.aop.scope'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.aop,org.springframework.aop.framework,org.springframework.beans.factory,org.springframework.beans.factory.config,org.springframework.beans.factory.support'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.aop.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.aopalliance.aop,org.aopalliance.intercept,org.springframework.aop,org.springframework.beans.factory,org.springframework.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.aop.support.annotation'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.aop,org.springframework.aop.support'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.aop.target'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.apache.commons.pool,org.springframework.aop,org.springframework.aop.support,org.springframework.beans,org.springframework.beans.factory'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.aop.target.dynamic'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.aop,org.springframework.beans.factory'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=com.jamonapi)(version>=2.4.0)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=net.sf.cglib.core)(version>=2.1.3)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=net.sf.cglib.proxy)(version>=2.1.3)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=net.sf.cglib.transform.impl)(version>=2.1.3)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aopalliance.aop)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aopalliance.intercept)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.commons.logging)(version>=1.1.1)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.commons.pool)(version>=1.3.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.commons.pool.impl)(version>=1.3.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.bridge)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.lang)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.lang.annotation)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.lang.reflect)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.runtime.internal)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.util)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.weaver)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.weaver.ast)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.weaver.internal.tools)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.weaver.patterns)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.weaver.reflect)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.weaver.tools)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.config)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.parsing)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.beans.factory.xml)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.annotation)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.task)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.core.task.support)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.util)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.util.xml)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.w3c.dom)(version>=0.0.0))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.aries.samples.blueprint.helloworld.api'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.apache.aries.samples.blueprint.helloworld.api/org.apache.aries.samples.blueprint.helloworld.api-0.3.0.jar'/>
+      <attribute name='description' value='Apache Aries Blueprint HelloWorld API'/>
+      <attribute name='size' type='Long' value='8938'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.aries.samples.blueprint.helloworld.api'/>
+      <attribute name='bundle-version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.aries.samples.blueprint.helloworld.api'/>
+      <attribute name='bundle-version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.samples.blueprint.helloworld.api'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+    </capability>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='slf4j.log4j12'/>
+      <attribute name='type' value='osgi.fragment'/>
+      <attribute name='version' type='Version' value='1.6.2'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='slf4j.log4j12/slf4j.log4j12-1.6.2.jar'/>
+      <attribute name='description' value='slf4j-log4j12'/>
+      <attribute name='size' type='Long' value='10022'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.slf4j.impl'/>
+      <attribute name='version' type='Version' value='1.6.2'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j)(version>=1.6.2))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j.spi)(version>=1.6.2))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j.helpers)(version>=1.6.2))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.apache.log4j)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.host'>
+      <directive name='filter' value='(&(osgi.wiring.host=slf4j.api)(bundle-version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.ee'>
+      <directive name='filter' value='(ee=J2SE-1.3)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.aries.util'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.apache.aries.util/org.apache.aries.util-0.3.0.jar'/>
+      <attribute name='description' value='Apache Aries Util'/>
+      <attribute name='size' type='Long' value='44407'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.aries.util'/>
+      <attribute name='bundle-version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.aries.util'/>
+      <attribute name='bundle-version' type='Version' value='0.3.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.util'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.util.tracker'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.osgi.util.tracker,org.osgi.framework,org.osgi.framework.launch,org.osgi.service.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.aries.util.nls'/>
+      <attribute name='version' type='Version' value='0.3.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.osgi.framework.adaptor)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.osgi.framework.internal.core)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.eclipse.osgi.internal.loader)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework.launch)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.framework)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.util.tracker)(version>=1.4.0)(!(version>=2.0.0)))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='com.sun.jersey.jersey-server'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='1.11.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='com.sun.jersey.jersey-server/com.sun.jersey.jersey-server-1.11.0.jar'/>
+      <attribute name='description' value='jersey-server'/>
+      <attribute name='size' type='Long' value='595119'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='com.sun.jersey.jersey-server'/>
+      <attribute name='bundle-version' type='Version' value='1.11.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='com.sun.jersey.jersey-server'/>
+      <attribute name='bundle-version' type='Version' value='1.11.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.container.filter'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,javax.ws.rs,com.sun.jersey.api.container,com.sun.jersey.core.util,com.sun.jersey.api.representation,javax.annotation.security,com.sun.jersey.core.header,com.sun.jersey.spi.container,com.sun.jersey.api.core,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi.scanning'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.spi.scanning,javax.ws.rs,org.objectweb.asm,com.sun.jersey.core.reflection,javax.ws.rs.ext'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.wadl'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.research.ws.wadl,javax.ws.rs,com.sun.jersey.core.spi.factory,com.sun.jersey.server.impl.model.method,com.sun.jersey.core.header,com.sun.jersey.api.wadl.config,com.sun.jersey.server.impl.uri,com.sun.jersey.server.wadl,com.sun.jersey.api.core,com.sun.jersey.spi.inject,com.sun.jersey.spi.resource,javax.xml.bind,com.sun.jersey.api.uri,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.model.parameter.multivalued'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.jersey.core.spi.component,javax.ws.rs,com.sun.jersey.impl,com.sun.jersey.api.container,javax.xml.parsers,com.sun.jersey.core.reflection,javax.ws.rs.ext,org.xml.sax,com.sun.jersey.core.header,javax.xml.transform,javax.xml.bind.annotation,com.sun.jersey.spi,com.sun.jersey.spi.inject,javax.xml.transform.sax,javax.xml.bind,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.application'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.container.filter,javax.ws.rs,com.sun.jersey.server.impl.wadl,com.sun.jersey.server.impl.model.parameter.multivalued,com.sun.jersey.server.impl.model.parameter,com.sun.jersey.core.header,com.sun.jersey.server.impl.resource,com.sun.jersey.spi.template,com.sun.jersey.server.impl.modelapi.annotation,com.sun.jersey.spi.container,com.sun.jersey.spi.inject,com.sun.jersey.api.model,com.sun.jersey.core.spi.factory,com.sun.jersey.api.container [...]
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.model.parameter'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.jersey.core.spi.component,javax.ws.rs,com.sun.jersey.server.impl.model.parameter.multivalued,com.sun.jersey.api.representation,com.sun.jersey.core.header,com.sun.jersey.api,com.sun.jersey.api.core,com.sun.jersey.spi.inject,com.sun.jersey.server.impl.inject,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.component'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.jersey.core.spi.component,com.sun.jersey.server.spi.component,com.sun.jersey.api.container,com.sun.jersey.core.spi.component.ioc,com.sun.jersey.core.reflection,com.sun.jersey.server.impl.resource,com.sun.jersey.api.core,com.sun.jersey.server.impl.inject,com.sun.jersey.spi.inject'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi.dispatch'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.provider'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.spi.factory,com.sun.jersey.api.core,com.sun.jersey.api.container,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.wadl.generators.resourcedoc.model'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.xml.bind.annotation,javax.xml.namespace'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.osgi'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.server.impl.provider,org.osgi.framework,javax.ws.rs.ext'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.template'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.spi.component,javax.ws.rs,com.sun.jersey.server.impl.uri.rules,com.sun.jersey.server.probes,com.sun.jersey.core.reflection,javax.ws.rs.ext,com.sun.jersey.server.impl.model.method,com.sun.jersey.core.header,com.sun.jersey.spi.uri.rules,com.sun.jersey.api.view,com.sun.jersey.spi.template,com.sun.jersey.api.core,com.sun.jersey.spi.container,com.sun.jersey.spi.inject,javax.ws.rs.core,com.sun.jersey.api.uri'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi.uri.rules'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.jersey.spi.container,com.sun.jersey.api.core,com.sun.jersey.api.uri'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi.template'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.view,com.sun.jersey.api.container,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.container'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.server.impl.application,com.sun.jersey.api.container,com.sun.jersey.spi.container'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.modelapi.annotation'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.jersey.core.header,javax.ws.rs,com.sun.jersey.impl,com.sun.jersey.core.reflection,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.monitoring'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.spi.component,com.sun.jersey.spi.monitoring,com.sun.jersey.spi.service,javax.ws.rs.ext'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.resource'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.jersey.core.spi.component,javax.ws.rs,com.sun.jersey.server.spi.component,com.sun.jersey.api.container,com.sun.jersey.core.spi.component.ioc,com.sun.jersey.api.core,com.sun.jersey.server.impl.inject,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.wadl'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.research.ws.wadl,javax.ws.rs,com.sun.jersey.server.wadl.generators,javax.xml.namespace,com.sun.jersey.server.impl.modelapi.annotation,javax.xml.bind,com.sun.jersey.server.impl,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.model.method.dispatch'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,javax.ws.rs,com.sun.jersey.core.spi.component,com.sun.jersey.server.impl.model.parameter.multivalued,com.sun.jersey.core.spi.factory,com.sun.jersey.api.container,com.sun.jersey.api.representation,com.sun.jersey.spi.dispatch,com.sun.jersey.api,com.sun.jersey.api.core,com.sun.jersey.spi.container,com.sun.jersey.server.impl.inject,com.sun.jersey.spi.inject,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.core'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.jersey.spi.scanning,javax.ws.rs,com.sun.jersey.server.impl.application,com.sun.jersey.api.container,com.sun.jersey.core.util,com.sun.jersey.api.representation,javax.ws.rs.ext,com.sun.jersey.core.spi.scanning,com.sun.jersey.core.header,com.sun.jersey.spi.container,com.sun.jersey.api.uri,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi.container'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs,com.sun.jersey.impl,com.sun.jersey.server.impl.application,com.sun.jersey.core.util,com.sun.jersey.spi.dispatch,com.sun.jersey.core.header,com.sun.jersey.core.header.reader,com.sun.jersey.api.core,com.sun.jersey.spi,com.sun.jersey.spi.inject,com.sun.jersey.server.impl,javax.ws.rs.core,com.sun.jersey.api.model,com.sun.jersey.core.spi.component,com.sun.jersey.core.spi.factory,com.sun.jersey.api.container,com.sun.jersey.core.spi.component.ioc, [...]
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi.resource'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.server.impl.resource,com.sun.jersey.server.spi.component'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.server.impl.model,javax.naming,com.sun.jersey.core.header,com.sun.jersey.spi.container,com.sun.jersey.api.core,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.wadl.generators.resourcedoc'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.jersey.server.wadl.generators.resourcedoc.xhtml,com.sun.research.ws.wadl,javax.xml.namespace,com.sun.jersey.server.wadl.generators.resourcedoc.model,com.sun.jersey.server.wadl,javax.xml.bind,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.container.httpserver'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.header,com.sun.net.httpserver,com.sun.jersey.api.core,com.sun.jersey.api.container,com.sun.jersey.spi.container,com.sun.jersey.core.util,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.model'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.spi.container'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.container.filter'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,javax.ws.rs,com.sun.jersey.core.spi.component,com.sun.jersey.server.impl.uri,com.sun.jersey.api.core,com.sun.jersey.spi.container,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.wadl.generators.resourcedoc.xhtml'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.xml.bind.annotation,javax.xml.bind,javax.xml.namespace'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.research.ws.wadl'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.xml.bind.annotation,javax.xml.bind.annotation.adapters,javax.xml.namespace'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.uri.rules'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,javax.ws.rs,com.sun.jersey.api.container,com.sun.jersey.server.probes,com.sun.jersey.core.reflection,com.sun.jersey.server.impl.model.method,com.sun.jersey.spi.dispatch,com.sun.jersey.core.header,com.sun.jersey.server.impl.uri.rules.automata,com.sun.jersey.server.impl.template,com.sun.jersey.spi.monitoring,com.sun.jersey.spi.uri.rules,com.sun.jersey.api,com.sun.jersey.spi.container,com.sun.jersey.api.core,com.sun.jersey.server. [...]
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.spi.component'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.jersey.core.spi.component,com.sun.jersey.api.container,com.sun.jersey.core.spi.component.ioc,com.sun.jersey.api.core,com.sun.jersey.spi.inject,com.sun.jersey.server.impl.inject'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.container'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.spi.container,com.sun.jersey.api.core,com.sun.jersey.spi.service,com.sun.jersey.core.spi.component.ioc'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.probes'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.wadl.generators'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.research.ws.wadl,javax.xml.namespace,javax.xml.transform,javax.xml.bind.annotation,com.sun.jersey.server.wadl,javax.xml.transform.stream,com.sun.jersey.api,javax.xml.bind,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.model.method'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.server.impl.container.filter,com.sun.jersey.api.model,com.sun.jersey.impl,com.sun.jersey.api.container,com.sun.jersey.spi.dispatch,com.sun.jersey.core.header,com.sun.jersey.spi.container,com.sun.jersey.api.core,com.sun.jersey.spi.inject,javax.ws.rs.core,com.sun.jersey.api.uri'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.modelapi.validation'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,javax.ws.rs,com.sun.jersey.impl,com.sun.jersey.api.core,com.sun.jersey.core.reflection,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.model'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs,com.sun.jersey.server.impl.wadl,com.sun.jersey.impl,com.sun.jersey.core.header,com.sun.jersey.core.header.reader,com.sun.jersey.server.impl.template,com.sun.jersey.spi.uri.rules,com.sun.jersey.api.core,com.sun.jersey.spi.container,com.sun.jersey.spi.inject,javax.ws.rs.core,com.sun.jersey.server.impl.container.filter,com.sun.jersey.api.model,com.sun.jersey.core.spi.component,com.sun.jersey.server.impl.uri.rules,com.sun.jersey.api.container,c [...]
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.container.httpserver'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.net.httpserver,com.sun.jersey.api.container,com.sun.jersey.api.core,com.sun.jersey.core.spi.component.ioc'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.uri.rules.automata'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.server.impl.uri,com.sun.jersey.spi.uri.rules,com.sun.jersey.server.impl.uri.rules,com.sun.jersey.api.uri'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.wadl.config'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.server.wadl,com.sun.jersey.api.core,com.sun.jersey.server.wadl.generators,com.sun.jersey.core.reflection'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi.monitoring'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs.ext'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.uri'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs.core,com.sun.jersey.api.uri'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.view'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.header,javax.ws.rs,com.sun.jersey.core.spi.factory,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.server.impl.inject'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.api.model,com.sun.jersey.core.spi.component,javax.ws.rs,com.sun.jersey.core.spi.factory,com.sun.jersey.api.container,com.sun.jersey.api.core,com.sun.jersey.spi.inject'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.container)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.container.filter)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.container.httpserver)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.core)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.model)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.representation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.uri)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.view)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.wadl.config)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.header)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.header.reader)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.osgi)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.reflection)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.spi.component)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.spi.component.ioc)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.spi.factory)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.spi.scanning)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.util)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.impl)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.application)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.component)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.container)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.container.filter)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.container.httpserver)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.inject)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.model)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.model.method)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.model.method.dispatch)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.model.parameter)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.model.parameter.multivalued)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.modelapi.annotation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.modelapi.validation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.monitoring)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.provider)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.resource)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.template)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.uri)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.uri.rules)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.uri.rules.automata)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.impl.wadl)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.osgi)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.probes)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.spi.component)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.wadl)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.wadl.generators)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.wadl.generators.resourcedoc)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.wadl.generators.resourcedoc.model)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.server.wadl.generators.resourcedoc.xhtml)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.container)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.dispatch)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.inject)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.monitoring)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.resource)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.scanning)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.service)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.template)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.uri.rules)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.net.httpserver)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.research.ws.wadl)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.annotation.security)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.naming)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.ws.rs)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.ws.rs.core)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.ws.rs.ext)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.bind)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.bind.annotation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.bind.annotation.adapters)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.namespace)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.parsers)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform.sax)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform.stream)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.objectweb.asm)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.framework)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.xml.sax)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.springframework.core'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='org.springframework.core/org.springframework.core-3.1.0.jar'/>
+      <attribute name='description' value='Spring Core'/>
+      <attribute name='size' type='Long' value='448310'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.springframework.core'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.springframework.core'/>
+      <attribute name='bundle-version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.core'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.asm,org.springframework.asm.commons,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.core.annotation'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.core.convert'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.core.convert.converter'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core.convert'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.core.convert.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core.convert,org.springframework.core.convert.converter'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.core.enums'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.core.env'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='joptsimple,org.apache.commons.logging,org.springframework.core.convert,org.springframework.core.convert.support,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.core.io'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core.env'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.core.io.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core.env,org.springframework.core.io,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.core.serializer'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.core.serializer.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core,org.springframework.core.convert.converter,org.springframework.core.serializer'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.core.style'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.core.task'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.core.task.support'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core.task'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.core.type'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.core.type.classreading'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.asm,org.springframework.core.io,org.springframework.core.type,org.springframework.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.core.type.filter'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.springframework.core.type,org.springframework.core.type.classreading'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.util'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='org.apache.commons.logging'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.util.comparator'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.springframework.util.xml'/>
+      <attribute name='version' type='Version' value='3.1.0.RELEASE'/>
+      <directive name='uses' value='javax.xml.namespace,javax.xml.stream,javax.xml.stream.util,javax.xml.transform,javax.xml.transform.sax,org.apache.commons.logging,org.w3c.dom,org.xml.sax,org.xml.sax.ext'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.xml.namespace)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.xml.stream)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.xml.stream.events)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.xml.stream.util)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.xml.transform)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.xml.transform.sax)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=javax.xml.transform.stax)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=joptsimple)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.commons.logging)(version>=1.1.1)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.log4j)(version>=1.2.15)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.log4j.xml)(version>=1.2.15)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.bridge)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.weaver)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.weaver.bcel)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.aspectj.weaver.patterns)(version>=1.6.8)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <attribute name='common' value='split'/>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.eclipse.core.runtime)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.jboss.vfs)(version>=3.0.0)(!(version>=4.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.jboss.virtual)(version>=2.1.0.GA)(!(version>=3.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.asm)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.springframework.asm.commons)(version>=3.1.0)(!(version>=3.1.1)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.w3c.dom)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.xml.sax)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.xml.sax.ext)(version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.xml.sax.helpers)(version>=0.0.0))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='slf4j.simple'/>
+      <attribute name='type' value='osgi.fragment'/>
+      <attribute name='version' type='Version' value='1.6.2'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='slf4j.simple/slf4j.simple-1.6.2.jar'/>
+      <attribute name='description' value='slf4j-simple'/>
+      <attribute name='size' type='Long' value='7922'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.slf4j.impl'/>
+      <attribute name='version' type='Version' value='1.6.2'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j)(version>=1.6.2))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j.spi)(version>=1.6.2))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j.helpers)(version>=1.6.2))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.bundle'>
+      <directive name='filter' value='(osgi.wiring.bundle=slf4j.api)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.host'>
+      <directive name='filter' value='(&(osgi.wiring.host=slf4j.api)(bundle-version>=0.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.ee'>
+      <directive name='filter' value='(ee=J2SE-1.3)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='com.sun.jersey.jersey-core'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='1.4.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='com.sun.jersey.jersey-core/com.sun.jersey.jersey-core-1.4.0.jar'/>
+      <attribute name='description' value='jersey-core'/>
+      <attribute name='size' type='Long' value='455517'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='com.sun.jersey.jersey-core'/>
+      <attribute name='bundle-version' type='Version' value='1.4.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='com.sun.jersey.jersey-core'/>
+      <attribute name='bundle-version' type='Version' value='1.4.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.provider.jaxb'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs,javax.xml.parsers,com.sun.jersey.core.util,com.sun.jersey.core.provider,com.sun.jersey.core.impl.provider.entity,javax.ws.rs.ext,org.xml.sax,javax.xml.stream,javax.xml.transform,javax.xml.bind.annotation,javax.xml.transform.stream,javax.xml.transform.sax,javax.xml.bind,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.impl.provider.header'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.header,com.sun.jersey.core.header.reader,com.sun.jersey.spi,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='javax.ws.rs'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.impl'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.localization'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.util'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.impl,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.provider'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.util,javax.ws.rs.ext,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.spi.scanning'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.spi.scanning.uri,com.sun.jersey.spi.service,com.sun.jersey.core.util,com.sun.jersey.core.reflection,com.sun.jersey.api.uri'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.impl.provider.xml'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.xml.stream,com.sun.jersey.core.spi.component,javax.xml.transform,javax.xml.parsers,com.sun.jersey.core.util,com.sun.jersey.spi.inject,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.header'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.impl.provider.header,javax.ws.rs,com.sun.jersey.core.header.reader,com.sun.jersey.core.util,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.header.reader'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.impl.provider.header,com.sun.jersey.core.header,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.osgi'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.spi.scanning.uri,com.sun.jersey.impl,com.sun.jersey.core.spi.scanning,org.osgi.framework,com.sun.jersey.spi.service'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs.ext,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi.inject'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.spi.component'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='javax.ws.rs.core'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs,javax.ws.rs.ext'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.localization'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.spi.scanning.uri'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.spi.scanning,com.sun.jersey.core.util,javax.ws.rs.core,com.sun.jersey.api.uri'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.spi.component'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs,com.sun.jersey.core.spi.factory,com.sun.jersey.spi.service,com.sun.jersey.spi.inject,com.sun.jersey.core.reflection'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.spi.factory'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.spi.component,javax.ws.rs,com.sun.jersey.core.util,com.sun.jersey.core.reflection,javax.ws.rs.ext,com.sun.jersey.core.header,com.sun.jersey.spi,com.sun.jersey.spi.service,com.sun.jersey.spi.inject,com.sun.jersey.api.uri,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.representation'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.reflection'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs,com.sun.jersey.impl,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.spi.component.ioc'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.spi.component,com.sun.jersey.spi.inject'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='javax.ws.rs.ext'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs,javax.ws.rs.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.core.impl.provider.entity'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.core.provider.jaxb,javax.ws.rs,javax.mail.internet,javax.imageio.stream,com.sun.jersey.impl,javax.imageio.spi,javax.mail.util,com.sun.jersey.core.util,com.sun.jersey.core.provider,javax.xml.transform.dom,org.xml.sax,javax.imageio,javax.xml.stream,com.sun.jersey.spi,javax.xml.transform.sax,com.sun.jersey.spi.inject,javax.ws.rs.core,javax.xml.parsers,com.sun.jersey.api.representation,javax.ws.rs.ext,org.w3c.dom,javax.activation,javax.xml.t [...]
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.spi.service'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='com.sun.jersey.impl,com.sun.jersey.core.reflection'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='com.sun.jersey.api.uri'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <directive name='uses' value='javax.ws.rs,com.sun.jersey.core.util,javax.ws.rs.core'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.representation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.api.uri)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.header)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.header.reader)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.impl.provider.entity)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.impl.provider.header)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.impl.provider.xml)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.osgi)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.provider)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.provider.jaxb)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.reflection)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.spi.component)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.spi.component.ioc)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.spi.factory)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.spi.scanning)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.spi.scanning.uri)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.core.util)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.impl)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.localization)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.inject)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=com.sun.jersey.spi.service)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.activation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.imageio)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.imageio.spi)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.imageio.stream)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.mail)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.mail.internet)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.mail.util)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.bind)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.bind.annotation)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.parsers)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.stream)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform.dom)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform.sax)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.transform.stream)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.framework)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.w3c.dom)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.xml.sax)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='ch.qos.logback.classic'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='ch.qos.logback.classic/ch.qos.logback.classic-1.0.0.jar'/>
+      <attribute name='description' value='Logback Classic Module'/>
+      <attribute name='size' type='Long' value='249827'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='ch.qos.logback.classic'/>
+      <attribute name='bundle-version' type='Version' value='1.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='ch.qos.logback.classic'/>
+      <attribute name='bundle-version' type='Version' value='1.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic.turbo'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.spi,ch.qos.logback.classic,org.slf4j,ch.qos.logback.core.status,ch.qos.logback.classic.util,ch.qos.logback.core,ch.qos.logback.classic.gaffer,ch.qos.logback.core.joran.spi,ch.qos.logback.classic.joran,ch.qos.logback.core.joran.event,ch.qos.logback.core.joran.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic.db.names'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic.util'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.status,ch.qos.logback.classic,ch.qos.logback.core,ch.qos.logback.classic.gaffer,ch.qos.logback.core.joran.spi,ch.qos.logback.core.util,ch.qos.logback.classic.joran,ch.qos.logback.classic.selector,ch.qos.logback.core.filter,ch.qos.logback.classic.boolex,ch.qos.logback.classic.encoder,javax.naming,ch.qos.logback.classic.spi,org.slf4j.spi'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic.jmx'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.spi,ch.qos.logback.core.status,ch.qos.logback.classic.util,ch.qos.logback.classic,ch.qos.logback.core,javax.management,ch.qos.logback.core.joran.spi,ch.qos.logback.classic.joran,ch.qos.logback.core.util,ch.qos.logback.classic.spi'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic.jul'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.classic,ch.qos.logback.core.spi,ch.qos.logback.core,ch.qos.logback.classic.spi'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic.joran.action'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.classic.turbo,ch.qos.logback.classic,ch.qos.logback.core,ch.qos.logback.core.joran.spi,ch.qos.logback.core.joran.action,ch.qos.logback.core.util,org.xml.sax,ch.qos.logback.classic.net,ch.qos.logback.classic.boolex,ch.qos.logback.classic.util,javax.naming,ch.qos.logback.classic.jmx,javax.management,ch.qos.logback.core.spi,ch.qos.logback.classic.spi'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic.html'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.html,ch.qos.logback.core,ch.qos.logback.core.helpers,ch.qos.logback.classic.spi,ch.qos.logback.classic,ch.qos.logback.core.pattern,ch.qos.logback.classic.pattern'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.status,ch.qos.logback.core,ch.qos.logback.core.encoder,ch.qos.logback.classic.encoder,org.slf4j,org.slf4j.spi,ch.qos.logback.core.spi,ch.qos.logback.classic.spi,ch.qos.logback.classic.turbo,ch.qos.logback.classic.joran.action,ch.qos.logback.core.pattern,ch.qos.logback.core.pattern.parser,ch.qos.logback.classic.pattern,javax.servlet.http'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic.selector'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.status,javax.naming,ch.qos.logback.classic.util,ch.qos.logback.classic,ch.qos.logback.core,ch.qos.logback.core.joran.spi,ch.qos.logback.core.util,ch.qos.logback.classic.joran'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic.helpers'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='javax.servlet,org.slf4j,javax.servlet.http'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic.gaffer'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.status,ch.qos.logback.core.spi,groovy.lang,org.codehaus.groovy.reflection,org.codehaus.groovy.runtime,ch.qos.logback.core,org.codehaus.groovy.runtime.callsite,org.codehaus.groovy.runtime.typehandling,ch.qos.logback.classic,ch.qos.logback.classic.turbo,ch.qos.logback.core.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic.boolex'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='groovy.lang,org.codehaus.groovy.runtime.typehandling,org.codehaus.groovy.reflection,org.codehaus.groovy.runtime,ch.qos.logback.classic.spi,org.codehaus.groovy.runtime.callsite,ch.qos.logback.core.spi,ch.qos.logback.core.boolex,ch.qos.logback.core.util,org.codehaus.groovy.control,ch.qos.logback.classic,ch.qos.logback.core,org.slf4j'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic.pattern'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.status,ch.qos.logback.core,ch.qos.logback.core.boolex,ch.qos.logback.classic.spi,ch.qos.logback.core.pattern,ch.qos.logback.core.util,ch.qos.logback.classic,org.slf4j,ch.qos.logback.classic.util,ch.qos.logback.core.net'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic.filter'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.spi,ch.qos.logback.core.filter,ch.qos.logback.classic,ch.qos.logback.classic.spi'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic.encoder'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.classic,ch.qos.logback.core.pattern,ch.qos.logback.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic.joran'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.joran.conditional,ch.qos.logback.classic.util,ch.qos.logback.classic.sift,ch.qos.logback.classic.joran.action,ch.qos.logback.core.joran,ch.qos.logback.core.joran.spi,ch.qos.logback.core.joran.action,ch.qos.logback.classic.spi'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic.net'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.spi,javax.naming,javax.jms,ch.qos.logback.core.net,ch.qos.logback.classic.spi,ch.qos.logback.classic.util,ch.qos.logback.classic,org.slf4j,ch.qos.logback.core.helpers,ch.qos.logback.core.pattern,ch.qos.logback.core,ch.qos.logback.core.boolex,ch.qos.logback.classic.boolex,ch.qos.logback.core.joran.spi,ch.qos.logback.classic.joran,ch.qos.logback.classic.pattern'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic.db'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.classic.db.names,ch.qos.logback.core.db,ch.qos.logback.classic,ch.qos.logback.classic.spi'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic.log4j'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.helpers,ch.qos.logback.classic,ch.qos.logback.core,ch.qos.logback.classic.spi'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic.selector.servlet'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='javax.servlet,javax.naming,ch.qos.logback.classic.util,ch.qos.logback.classic,ch.qos.logback.classic.selector,org.slf4j'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic.sift'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.joran.event,ch.qos.logback.core.sift,ch.qos.logback.classic.spi,ch.qos.logback.core.spi,ch.qos.logback.core.status,org.codehaus.groovy.reflection,ch.qos.logback.core,ch.qos.logback.classic.gaffer,org.codehaus.groovy.runtime.callsite,ch.qos.logback.core.helpers,ch.qos.logback.core.filter,groovy.lang,org.codehaus.groovy.runtime.typehandling,org.codehaus.groovy.runtime,ch.qos.logback.classic.util,ch.qos.logback.classic,ch.qos.logback.c [...]
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.classic.spi'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core,ch.qos.logback.core.spi,ch.qos.logback.classic,org.slf4j,org.slf4j.spi,ch.qos.logback.classic.util,org.slf4j.helpers,sun.reflect,ch.qos.logback.classic.turbo'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.slf4j.impl'/>
+      <attribute name='version' type='Version' value='1.6.4'/>
+      <directive name='uses' value='org.slf4j.spi,ch.qos.logback.classic.util,org.slf4j.helpers,ch.qos.logback.classic,ch.qos.logback.core,ch.qos.logback.classic.selector,ch.qos.logback.core.joran.spi,org.slf4j,ch.qos.logback.core.util'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic.boolex)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic.db)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic.db.names)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic.encoder)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic.filter)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic.gaffer)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic.helpers)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic.html)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic.jmx)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic.joran)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic.joran.action)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic.jul)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic.log4j)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic.net)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic.pattern)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic.selector)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic.selector.servlet)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic.sift)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic.spi)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic.turbo)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.classic.util)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.boolex)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.db)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.encoder)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.filter)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.helpers)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.html)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.joran)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.joran.action)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.joran.conditional)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.joran.event)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.joran.spi)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.joran.util)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.net)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.pattern)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.pattern.parser)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.read)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.rolling)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.rolling.helper)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.sift)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.spi)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.status)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.util)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=groovy.lang)(version>=1.7.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.jms)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.management)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.naming)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.servlet)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.servlet.http)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.codehaus.groovy.control)(version>=1.7.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.codehaus.groovy.reflection)(version>=1.7.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.codehaus.groovy.runtime)(version>=1.7.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.codehaus.groovy.runtime.callsite)(version>=1.7.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.codehaus.groovy.runtime.typehandling)(version>=1.7.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j)(version>=1.6.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j.helpers)(version>=1.6.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j.impl)(version>=1.6.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.slf4j.spi)(version>=1.6.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.xml.sax)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=sun.reflect)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.ee'>
+      <directive name='filter' value='(ee=J2SE-1.5)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='ch.qos.logback.core'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='ch.qos.logback.core/ch.qos.logback.core-1.0.0.jar'/>
+      <attribute name='description' value='Logback Core Module'/>
+      <attribute name='size' type='Long' value='332750'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='ch.qos.logback.core'/>
+      <attribute name='bundle-version' type='Version' value='1.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='ch.qos.logback.core'/>
+      <attribute name='bundle-version' type='Version' value='1.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.spi'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core,ch.qos.logback.core.status,ch.qos.logback.core.helpers,ch.qos.logback.core.filter'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.status'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.spi,ch.qos.logback.core,ch.qos.logback.core.util,ch.qos.logback.core.helpers,javax.servlet,javax.servlet.http'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.db.dialect'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.spi'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.property'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.spi,ch.qos.logback.core.status,ch.qos.logback.core.filter,ch.qos.logback.core.helpers,ch.qos.logback.core.joran.spi,ch.qos.logback.core.recovery,ch.qos.logback.core.util,ch.qos.logback.core.encoder'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.encoder'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core,ch.qos.logback.core.spi'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.joran.action'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.spi,ch.qos.logback.core.boolex,ch.qos.logback.core,ch.qos.logback.core.joran.spi,ch.qos.logback.core.util,org.xml.sax,ch.qos.logback.core.joran.util,ch.qos.logback.core.joran.event,ch.qos.logback.core.pattern.util,ch.qos.logback.core.status'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.joran.spi'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.spi,org.xml.sax,ch.qos.logback.core.joran.event,ch.qos.logback.core,ch.qos.logback.core.util,ch.qos.logback.core.joran.action,ch.qos.logback.core.status'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.joran.event'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.xml.sax,org.xml.sax.helpers,ch.qos.logback.core.status,ch.qos.logback.core.spi,javax.xml.parsers,ch.qos.logback.core,ch.qos.logback.core.joran.spi'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.net'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='javax.naming,ch.qos.logback.core,javax.mail,ch.qos.logback.core.helpers,ch.qos.logback.core.spi,ch.qos.logback.core.sift,javax.mail.internet,ch.qos.logback.core.pattern,ch.qos.logback.core.boolex,ch.qos.logback.core.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.joran'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.status,ch.qos.logback.core.spi,ch.qos.logback.core.joran.event,ch.qos.logback.core,ch.qos.logback.core.joran.util,ch.qos.logback.core.joran.spi,org.xml.sax,ch.qos.logback.core.joran.action'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.boolex'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.spi,org.codehaus.janino,ch.qos.logback.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.rolling'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core,ch.qos.logback.core.rolling.helper,ch.qos.logback.core.spi,ch.qos.logback.core.joran.spi,ch.qos.logback.core.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.recovery'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.status,ch.qos.logback.core,ch.qos.logback.core.net'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.sift'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.joran.event,ch.qos.logback.core,ch.qos.logback.core.joran.spi,ch.qos.logback.core.spi,ch.qos.logback.core.helpers,ch.qos.logback.core.joran,ch.qos.logback.core.joran.action'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.db'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='javax.naming,javax.sql,ch.qos.logback.core,ch.qos.logback.core.joran.spi,ch.qos.logback.core.joran.util,ch.qos.logback.core.joran.action,ch.qos.logback.core.util,org.xml.sax,ch.qos.logback.core.spi,ch.qos.logback.core.db.dialect'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.read'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.helpers,ch.qos.logback.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.pattern'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.status,ch.qos.logback.core.spi,ch.qos.logback.core,ch.qos.logback.core.pattern.parser,ch.qos.logback.core.encoder'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.pattern.parser'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.status,ch.qos.logback.core.spi,ch.qos.logback.core.pattern,ch.qos.logback.core,ch.qos.logback.core.util,ch.qos.logback.core.pattern.util'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.html'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.pattern,ch.qos.logback.core,ch.qos.logback.core.pattern.parser'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.joran.conditional'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.joran.event,ch.qos.logback.core.spi,ch.qos.logback.core,ch.qos.logback.core.joran.spi,ch.qos.logback.core.joran.action,ch.qos.logback.core.util,org.xml.sax,org.codehaus.janino'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.helpers'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.filter'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.spi,ch.qos.logback.core.boolex'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.layout'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.pattern.util'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.joran.util'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.status,ch.qos.logback.core,ch.qos.logback.core.joran.spi,ch.qos.logback.core.util,ch.qos.logback.core.spi'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.util'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.spi,ch.qos.logback.core,ch.qos.logback.core.status,ch.qos.logback.core.helpers'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='ch.qos.logback.core.rolling.helper'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='ch.qos.logback.core.spi,ch.qos.logback.core.status,ch.qos.logback.core.pattern,ch.qos.logback.core.util,ch.qos.logback.core.pattern.util,ch.qos.logback.core,ch.qos.logback.core.pattern.parser,ch.qos.logback.core.rolling'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.boolex)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.db)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.db.dialect)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.encoder)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.filter)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.helpers)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.html)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.joran)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.joran.action)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.joran.conditional)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.joran.event)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.joran.spi)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.joran.util)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.layout)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.net)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.pattern)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.pattern.parser)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.pattern.util)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.property)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.read)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.recovery)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.rolling)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.rolling.helper)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.sift)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.spi)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.status)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=ch.qos.logback.core.util)(version>=1.0.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.mail)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.mail.internet)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.naming)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.servlet)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.servlet.http)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.sql)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.parsers)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.codehaus.janino)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.xml.sax)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.xml.sax.helpers)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.ee'>
+      <directive name='filter' value='(ee=J2SE-1.5)'/>
+    </requirement>
+  </resource>
+</repository>
\ No newline at end of file
diff --git a/biz.aQute.repository/testdata/index2.xml.gz b/biz.aQute.repository/testdata/index2.xml.gz
new file mode 100644
index 0000000..088db7a
Binary files /dev/null and b/biz.aQute.repository/testdata/index2.xml.gz differ
diff --git a/biz.aQute.repository/testdata/jetty-users.properties b/biz.aQute.repository/testdata/jetty-users.properties
new file mode 100644
index 0000000..bc32bed
--- /dev/null
+++ b/biz.aQute.repository/testdata/jetty-users.properties
@@ -0,0 +1 @@
+AliBaba: OpenSesame,users
diff --git a/biz.aQute.repository/testdata/minir5.xml b/biz.aQute.repository/testdata/minir5.xml
new file mode 100644
index 0000000..6c3f0b3
--- /dev/null
+++ b/biz.aQute.repository/testdata/minir5.xml
@@ -0,0 +1,50 @@
+<?xml version='1.0' encoding='utf-8'?>
+<repository increment='0' name='index1' xmlns='http://www.osgi.org/xmlns/repository/v1.0.0'>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='dummybundle'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='url' value='bundles/dummybundle.jar'/>
+      <attribute name='description' value='org.example.c'/>
+      <attribute name='size' type='Long' value='1100'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.example.c'/>
+      <attribute name='bundle-version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.example.c'/>
+      <attribute name='bundle-version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.example.a'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+    </capability>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.example.f'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='testdata/06-requirebundle.jar'/>
+      <attribute name='description' value='org.example.f'/>
+      <attribute name='size' type='Long' value='1128'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.example.f'/>
+      <attribute name='bundle-version' type='Version' value='0.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.example.f'/>
+      <attribute name='bundle-version' type='Version' value='0.0.0'/>
+    </capability>
+    <requirement namespace='osgi.wiring.bundle'>
+      <directive name='filter' value='(&(osgi.wiring.bundle=org.example.a)(bundle-version>=3.0.0)(!(bundle-version>=4.0.0)))'/>
+    </requirement>
+  </resource>
+</repository>
\ No newline at end of file
diff --git a/biz.aQute.repository/testdata/xmlWithDtdRef.xml b/biz.aQute.repository/testdata/xmlWithDtdRef.xml
new file mode 100644
index 0000000..e8dbb63
--- /dev/null
+++ b/biz.aQute.repository/testdata/xmlWithDtdRef.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "mydoctype" "http://localhost:18081/dummy.dtd">
+<repository/>
\ No newline at end of file
diff --git a/biz.aQute.resolve/.classpath b/biz.aQute.resolve/.classpath
new file mode 100644
index 0000000..6d3c62a
--- /dev/null
+++ b/biz.aQute.resolve/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/biz.aQute.resolve/.project b/biz.aQute.resolve/.project
new file mode 100644
index 0000000..8a9913d
--- /dev/null
+++ b/biz.aQute.resolve/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>biz.aQute.resolve</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>bndtools.core.bndbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>bndtools.core.bndnature</nature>
+	</natures>
+</projectDescription>
diff --git a/biz.aQute.resolve/.settings/org.eclipse.core.resources.prefs b/biz.aQute.resolve/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..f6822ac
--- /dev/null
+++ b/biz.aQute.resolve/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Mon Sep 19 11:00:09 EDT 2005
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/biz.aQute.resolve/.settings/org.eclipse.core.runtime.prefs b/biz.aQute.resolve/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..d7b5655
--- /dev/null
+++ b/biz.aQute.resolve/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Tue Dec 14 12:22:25 EST 2010
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/biz.aQute.resolve/.settings/org.eclipse.jdt.core.prefs b/biz.aQute.resolve/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..10eecaf
--- /dev/null
+++ b/biz.aQute.resolve/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,361 @@
+#Fri Aug 10 13:46:22 CEST 2012
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=warning
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=warning
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=120
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=240
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/biz.aQute.resolve/.settings/org.eclipse.jdt.ui.prefs b/biz.aQute.resolve/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..82b400b
--- /dev/null
+++ b/biz.aQute.resolve/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,57 @@
+#Wed Jun 13 23:31:26 BST 2012
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_bndtools
+formatter_settings_version=12
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=false
+sp_cleanup.organize_imports=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=false
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/biz.aQute.resolve/bnd.bnd b/biz.aQute.resolve/bnd.bnd
new file mode 100644
index 0000000..4c476c2
--- /dev/null
+++ b/biz.aQute.resolve/bnd.bnd
@@ -0,0 +1,17 @@
+-buildpath: osgi.core;version=4.2,\
+	osgi.r5;version=1.0.1,\
+	junit.osgi,\
+	biz.aQute.bndlib;version=snapshot,\
+	biz.aQute.repository;version=snapshot,\
+	ee.j2se;version=${javac.ee},\
+	org.mockito.mockito-all,\
+	osgi.cmpn
+
+Bundle-Version: 0.0.3.${tstamp}_${Git-Descriptor}
+
+Export-Package: biz.aQute.resolve,\
+	org.osgi.service.log;-split-package:=first
+
+Private-Package: biz.aQute.resolve.*
+
+Conditional-Package: aQute.libg.*
\ No newline at end of file
diff --git a/biz.aQute.resolve/build.xml b/biz.aQute.resolve/build.xml
new file mode 100644
index 0000000..0fe20f5
--- /dev/null
+++ b/biz.aQute.resolve/build.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="project" default="build">
+	
+	<!-- -->
+	
+	<import file="../cnf/build.xml"/>
+</project>
diff --git a/biz.aQute.resolve/src/biz/aQute/resolve/ResolveProcess.java b/biz.aQute.resolve/src/biz/aQute/resolve/ResolveProcess.java
new file mode 100644
index 0000000..007efcb
--- /dev/null
+++ b/biz.aQute.resolve/src/biz/aQute/resolve/ResolveProcess.java
@@ -0,0 +1,120 @@
+package biz.aQute.resolve;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+import org.osgi.resource.Wire;
+import org.osgi.service.log.LogService;
+import org.osgi.service.resolver.ResolutionException;
+import org.osgi.service.resolver.Resolver;
+
+import aQute.bnd.build.model.BndEditModel;
+import aQute.bnd.service.Registry;
+import biz.aQute.resolve.internal.BndrunResolveContext;
+
+public class ResolveProcess {
+
+    private Map<Resource,Collection<Requirement>> requiredResources;
+    private Map<Resource,Collection<Requirement>> optionalResources;
+    private ResolutionException resolutionException;
+
+    public boolean resolve(BndEditModel inputModel, Registry pluginRegistry, Resolver resolver, LogService log) {
+        BndrunResolveContext resolveContext = new BndrunResolveContext(inputModel, pluginRegistry, log);
+        try {
+            Map<Resource,List<Wire>> result = resolver.resolve(resolveContext);
+
+            // Find required resources
+            Set<Resource> requiredResourceSet = new HashSet<Resource>(result.size());
+            for (Resource resource : result.keySet()) {
+                if (!resolveContext.isInputRequirementsResource(resource) && !resolveContext.isFrameworkResource(resource)) {
+                    requiredResourceSet.add(resource);
+                }
+            }
+
+            // Process the mandatory requirements and save them as reasons against the required resources
+            requiredResources = new HashMap<Resource,Collection<Requirement>>(requiredResourceSet.size());
+            for (Entry<Requirement,List<Capability>> entry : resolveContext.getMandatoryRequirements().entrySet()) {
+                Requirement req = entry.getKey();
+                Resource requirer = req.getResource();
+                if (requiredResourceSet.contains(requirer)) {
+                    List<Capability> caps = entry.getValue();
+
+                    for (Capability cap : caps) {
+                        Resource requiredResource = cap.getResource();
+                        if (requiredResourceSet.remove(requiredResource)) {
+                            Collection<Requirement> reasons = requiredResources.get(requiredResource);
+                            if (reasons == null) {
+                                reasons = new LinkedList<Requirement>();
+                                requiredResources.put(requiredResource, reasons);
+                            }
+                            reasons.add(req);
+                        }
+                    }
+                }
+            }
+            // Add the remaining resources in the requiredResourceSet (these come from initial requirements)
+            for (Resource resource : requiredResourceSet)
+                requiredResources.put(resource, Collections.<Requirement> emptyList());
+
+            // Find optional resources
+            processOptionalRequirements(resolveContext);
+
+            return true;
+        } catch (ResolutionException e) {
+            resolutionException = e;
+            return false;
+        }
+    }
+
+    private void processOptionalRequirements(BndrunResolveContext resolveContext) {
+        optionalResources = new HashMap<Resource,Collection<Requirement>>();
+        for (Entry<Requirement,List<Capability>> entry : resolveContext.getOptionalRequirements().entrySet()) {
+            Requirement req = entry.getKey();
+            Resource requirer = req.getResource();
+            if (requiredResources.containsKey(requirer)) {
+                List<Capability> providers = entry.getValue();
+                for (Capability provider : providers) {
+                    Resource providerResource = provider.getResource();
+                    if (requirer != providerResource && !requiredResources.containsKey(providerResource)) {
+                        Collection<Requirement> reasons = optionalResources.get(provider.getResource());
+                        if (reasons == null) {
+                            reasons = new LinkedList<Requirement>();
+                            optionalResources.put(provider.getResource(), reasons);
+                        }
+                        reasons.add(req);
+                    }
+                }
+            }
+        }
+    }
+
+    public ResolutionException getResolutionException() {
+        return resolutionException;
+    }
+
+    public Collection<Resource> getRequiredResources() {
+        return requiredResources != null ? Collections.unmodifiableCollection(requiredResources.keySet()) : Collections.<Resource> emptyList();
+    }
+
+    public Collection<Resource> getOptionalResources() {
+        return optionalResources != null ? Collections.unmodifiableCollection(optionalResources.keySet()) : Collections.<Resource> emptyList();
+    }
+
+    public Collection<Requirement> getReasons(Resource resource) {
+        Collection<Requirement> reasons = requiredResources.get(resource);
+        if (reasons == null)
+            reasons = optionalResources.get(resource);
+        return reasons != null ? Collections.unmodifiableCollection(reasons) : Collections.<Requirement> emptyList();
+    }
+
+}
diff --git a/biz.aQute.resolve/src/biz/aQute/resolve/internal/BndrunResolveContext.java b/biz.aQute.resolve/src/biz/aQute/resolve/internal/BndrunResolveContext.java
new file mode 100644
index 0000000..7dc58b6
--- /dev/null
+++ b/biz.aQute.resolve/src/biz/aQute/resolve/internal/BndrunResolveContext.java
@@ -0,0 +1,440 @@
+package biz.aQute.resolve.internal;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.namespace.contract.ContractNamespace;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Namespace;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+import org.osgi.resource.Wiring;
+import org.osgi.service.log.LogService;
+import org.osgi.service.repository.Repository;
+import org.osgi.service.resolver.HostedCapability;
+import org.osgi.service.resolver.ResolveContext;
+
+import aQute.bnd.build.model.BndEditModel;
+import aQute.bnd.build.model.EE;
+import aQute.bnd.build.model.clauses.ExportedPackage;
+import aQute.bnd.deployer.repository.MapToDictionaryAdapter;
+import aQute.bnd.header.Attrs;
+import aQute.bnd.header.Parameters;
+import aQute.bnd.osgi.Constants;
+import aQute.bnd.osgi.Processor;
+import aQute.bnd.osgi.resource.CapReqBuilder;
+import aQute.bnd.osgi.resource.Filters;
+import aQute.bnd.osgi.resource.ResourceBuilder;
+import aQute.bnd.service.Registry;
+import aQute.libg.filters.AndFilter;
+import aQute.libg.filters.Filter;
+import aQute.libg.filters.LiteralFilter;
+import aQute.libg.filters.SimpleFilter;
+
+public class BndrunResolveContext extends ResolveContext {
+
+    private static final String CONTRACT_OSGI_FRAMEWORK = "OSGiFramework";
+    private static final String IDENTITY_INITIAL_RESOURCE = "<<INITIAL>>";
+
+    public static final String RUN_EFFECTIVE_INSTRUCTION = "-resolve.effective";
+
+    private final List<Repository> repos = new LinkedList<Repository>();
+    private final ConcurrentMap<Resource,Integer> resourcePriorities = new ConcurrentHashMap<Resource,Integer>();
+    private final Map<Requirement,List<Capability>> mandatoryRequirements = new HashMap<Requirement,List<Capability>>();
+    private final Map<Requirement,List<Capability>> optionalRequirements = new HashMap<Requirement,List<Capability>>();
+
+    private final BndEditModel runModel;
+    private final Registry registry;
+    private final LogService log;
+
+    private boolean initialised = false;
+
+    private Resource frameworkResource = null;
+    private Version frameworkResourceVersion = null;
+    private FrameworkResourceRepository frameworkResourceRepo;
+
+    private Resource inputRequirementsResource = null;
+    private EE ee;
+    private Set<String> effectiveSet;
+    private List<ExportedPackage> sysPkgsExtra;
+    private Parameters sysCapsExtraParams;
+
+    public BndrunResolveContext(BndEditModel runModel, Registry registry, LogService log) {
+        this.runModel = runModel;
+        this.registry = registry;
+        this.log = log;
+    }
+
+    protected synchronized void init() {
+        if (initialised)
+            return;
+
+        loadEE();
+        loadSystemPackagesExtra();
+        loadSystemCapabilitiesExtra();
+        loadRepositories();
+        loadEffectiveSet();
+        findFramework();
+        constructInputRequirements();
+
+        initialised = true;
+    }
+
+    private void loadEE() {
+        EE tmp = runModel.getEE();
+        ee = (tmp != null) ? tmp : EE.JavaSE_1_6;
+    }
+
+    private void loadSystemPackagesExtra() {
+        sysPkgsExtra = runModel.getSystemPackages();
+    }
+
+    private void loadSystemCapabilitiesExtra() {
+        String header = (String) runModel.genericGet(Constants.RUNSYSTEMCAPABILITIES);
+        if (header != null) {
+            Processor processor = new Processor();
+            try {
+                processor.setProperty(Constants.RUNSYSTEMCAPABILITIES, header);
+                String processedHeader = processor.getProperty(Constants.RUNSYSTEMCAPABILITIES);
+                sysCapsExtraParams = new Parameters(processedHeader);
+            }
+            finally {
+                processor.close();
+            }
+        } else {
+            sysCapsExtraParams = null;
+        }
+    }
+
+    private void loadRepositories() {
+        // Get all of the repositories from the plugin registry
+        List<Repository> allRepos = registry.getPlugins(Repository.class);
+
+        // Reorder/filter if specified by the run model
+        List<String> repoNames = runModel.getRunRepos();
+        if (repoNames == null) {
+            // No filter, use all
+            repos.addAll(allRepos);
+        } else {
+            // Map the repository names...
+            Map<String,Repository> repoNameMap = new HashMap<String,Repository>(allRepos.size());
+            for (Repository repo : allRepos)
+                repoNameMap.put(repo.toString(), repo);
+
+            // Create the result list
+            for (String repoName : repoNames) {
+                Repository repo = repoNameMap.get(repoName);
+                if (repo != null)
+                    repos.add(repo);
+            }
+        }
+    }
+
+    private void loadEffectiveSet() {
+        String effective = (String) runModel.genericGet(RUN_EFFECTIVE_INSTRUCTION);
+        if (effective == null)
+            effectiveSet = null;
+        else {
+            effectiveSet = new HashSet<String>();
+            for (Entry<String,Attrs> entry : new Parameters(effective).entrySet())
+                effectiveSet.add(entry.getKey());
+        }
+    }
+
+    private void findFramework() {
+        String header = runModel.getRunFw();
+        if (header == null)
+            return;
+
+        // Get the identity and version of the requested JAR
+        Parameters params = new Parameters(header);
+        if (params.size() > 1)
+            throw new IllegalArgumentException("Cannot specify more than one OSGi Framework.");
+        Entry<String,Attrs> entry = params.entrySet().iterator().next();
+        String identity = entry.getKey();
+
+        String versionStr = entry.getValue().get("version");
+
+        // Construct a filter & requirement to find matches
+        Filter filter = new SimpleFilter(IdentityNamespace.IDENTITY_NAMESPACE, identity);
+        if (versionStr != null)
+            filter = new AndFilter().addChild(filter).addChild(new LiteralFilter(Filters.fromVersionRange(versionStr)));
+        Requirement frameworkReq = new CapReqBuilder(IdentityNamespace.IDENTITY_NAMESPACE).addDirective(Namespace.REQUIREMENT_FILTER_DIRECTIVE, filter.toString()).buildSyntheticRequirement();
+
+        // Iterate over repos looking for matches
+        for (Repository repo : repos) {
+            Map<Requirement,Collection<Capability>> providers = repo.findProviders(Collections.singletonList(frameworkReq));
+            Collection<Capability> frameworkCaps = providers.get(frameworkReq);
+            if (frameworkCaps != null) {
+                for (Capability frameworkCap : frameworkCaps) {
+                    if (findFrameworkContractCapability(frameworkCap.getResource()) != null) {
+                        Version foundVersion = toVersion(frameworkCap.getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE));
+                        if (foundVersion != null) {
+                            if (frameworkResourceVersion == null || (foundVersion.compareTo(frameworkResourceVersion) > 0)) {
+                                frameworkResource = frameworkCap.getResource();
+                                frameworkResourceVersion = foundVersion;
+                                frameworkResourceRepo = new FrameworkResourceRepository(frameworkResource, ee, sysPkgsExtra, sysCapsExtraParams);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private void constructInputRequirements() {
+        List<Requirement> requires = runModel.getRunRequires();
+        if (requires == null || requires.isEmpty()) {
+            inputRequirementsResource = null;
+        } else {
+            ResourceBuilder resBuilder = new ResourceBuilder();
+            CapReqBuilder identity = new CapReqBuilder(IdentityNamespace.IDENTITY_NAMESPACE).addAttribute(IdentityNamespace.IDENTITY_NAMESPACE, IDENTITY_INITIAL_RESOURCE);
+            resBuilder.addCapability(identity);
+
+            for (Requirement req : requires) {
+                resBuilder.addRequirement(req);
+            }
+
+            inputRequirementsResource = resBuilder.build();
+        }
+    }
+
+    public static boolean isInputRequirementResource(Resource resource) {
+        Capability id = resource.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE).get(0);
+        return IDENTITY_INITIAL_RESOURCE.equals(id.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE));
+    }
+
+    private static Version toVersion(Object object) throws IllegalArgumentException {
+        if (object == null)
+            return null;
+
+        if (object instanceof Version)
+            return (Version) object;
+
+        if (object instanceof String)
+            return Version.parseVersion((String) object);
+
+        throw new IllegalArgumentException(MessageFormat.format("Cannot convert type {0} to Version.", object.getClass().getName()));
+    }
+
+    private static Capability findFrameworkContractCapability(Resource resource) {
+        List<Capability> contractCaps = resource.getCapabilities(ContractNamespace.CONTRACT_NAMESPACE);
+        if (contractCaps != null)
+            for (Capability cap : contractCaps) {
+                if (CONTRACT_OSGI_FRAMEWORK.equals(cap.getAttributes().get(ContractNamespace.CONTRACT_NAMESPACE)))
+                    return cap;
+            }
+        return null;
+    }
+
+    public void addRepository(Repository repo) {
+        repos.add(repo);
+    }
+
+    @Override
+    public Collection<Resource> getMandatoryResources() {
+        init();
+        if (frameworkResource == null)
+            throw new IllegalStateException(MessageFormat.format("Could not find OSGi framework matching {0}.", runModel.getRunFw()));
+
+        List<Resource> resources = new ArrayList<Resource>();
+        resources.add(frameworkResource);
+
+        if (inputRequirementsResource != null)
+            resources.add(inputRequirementsResource);
+        return resources;
+    }
+
+    @Override
+    public List<Capability> findProviders(Requirement requirement) {
+        init();
+
+        // Use a linked set for ordering and no duplication
+        LinkedHashSet<Capability> result = new LinkedHashSet<Capability>();
+
+        // The selected OSGi framework always has the first chance to provide the capabilities
+        if (frameworkResourceRepo != null) {
+            Map<Requirement,Collection<Capability>> providers = frameworkResourceRepo.findProviders(Collections.singleton(requirement));
+            Collection<Capability> capabilities = providers.get(requirement);
+            if (capabilities != null && !capabilities.isEmpty())
+                result.addAll(capabilities);
+        }
+
+        // Next find out if the requirement is satisfied by a capability on the same resource
+        Resource resource = requirement.getResource();
+        if (resource != null) {
+            List<Capability> selfCaps = resource.getCapabilities(requirement.getNamespace());
+            if (selfCaps != null) {
+                for (Capability selfCap : selfCaps) {
+                    if (matches(requirement, selfCap))
+                        result.add(selfCap);
+                }
+            }
+        }
+
+        // Now iterate over the repos
+        int order = 0;
+        for (Repository repo : repos) {
+            Map<Requirement,Collection<Capability>> providers = repo.findProviders(Collections.singleton(requirement));
+            Collection<Capability> capabilities = providers.get(requirement);
+            if (capabilities != null && !capabilities.isEmpty()) {
+                for (Capability capability : capabilities) {
+                    if (!result.contains(capability) && isPermitted(capability.getResource())) {
+                        result.add(capability);
+                        setResourcePriority(order, capability.getResource());
+                    }
+                }
+            }
+            order++;
+        }
+
+        // Convert result to a list
+        ArrayList<Capability> listResult = new ArrayList<Capability>(result);
+
+        if (Namespace.RESOLUTION_OPTIONAL.equals(requirement.getDirectives().get(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE))) {
+            // Only return the framework's capabilities when asked for optional resources.
+            List<Capability> fwkCaps = new ArrayList<Capability>(listResult.size());
+            for (Capability capability : listResult) {
+                if (capability.getResource() == frameworkResource)
+                    fwkCaps.add(capability);
+            }
+
+            // If the framework couldn't provide the requirement then save the list of potential providers
+            // to the side, in order to work out the optional resources later.
+            if (fwkCaps.isEmpty())
+                optionalRequirements.put(requirement, listResult);
+
+            return fwkCaps;
+        } else {
+            // Record as a mandatory requirement
+            mandatoryRequirements.put(requirement, listResult);
+
+            return listResult;
+        }
+    }
+
+    private boolean matches(Requirement requirement, Capability selfCap) {
+        boolean match = false;
+        try {
+            String filterStr = requirement.getDirectives().get(Namespace.REQUIREMENT_FILTER_DIRECTIVE);
+            org.osgi.framework.Filter filter = filterStr != null ? org.osgi.framework.FrameworkUtil.createFilter(filterStr) : null;
+
+            if (filter == null)
+                match = true;
+            else
+                match = filter.match(new MapToDictionaryAdapter(selfCap.getAttributes()));
+        } catch (InvalidSyntaxException e) {
+            log.log(LogService.LOG_ERROR, "Invalid filter directive on requirement: " + requirement, e);
+        }
+        return match;
+    }
+
+    private void setResourcePriority(int priority, Resource resource) {
+        resourcePriorities.putIfAbsent(resource, priority);
+    }
+
+    private boolean isPermitted(Resource resource) {
+        // OSGi frameworks cannot be selected as ordinary resources
+        Capability fwkCap = findFrameworkContractCapability(resource);
+        if (fwkCap != null) {
+            return false;
+        }
+
+        // Remove osgi.core and any ee JAR
+        List<Capability> idCaps = resource.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE);
+        if (idCaps == null || idCaps.isEmpty()) {
+            log.log(LogService.LOG_ERROR, "Resource is missing an identity capability (osgi.identity).");
+            return false;
+        }
+        if (idCaps.size() > 1) {
+            log.log(LogService.LOG_ERROR, "Resource has more than one identity capability (osgi.identity).");
+            return false;
+        }
+        String identity = (String) idCaps.get(0).getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE);
+        if (identity == null) {
+            log.log(LogService.LOG_ERROR, "Resource is missing an identity capability (osgi.identity).");
+            return false;
+        }
+
+        if ("osgi.core".equals(identity))
+            return false;
+
+        if (identity.startsWith("ee."))
+            return false;
+
+        return true;
+    }
+
+    @Override
+    public int insertHostedCapability(List<Capability> caps, HostedCapability hc) {
+        Integer prioObj = resourcePriorities.get(hc.getResource());
+        int priority = prioObj != null ? prioObj.intValue() : Integer.MAX_VALUE;
+
+        for (int i = 0; i < caps.size(); i++) {
+            Capability c = caps.get(i);
+
+            Integer otherPrioObj = resourcePriorities.get(c.getResource());
+            int otherPriority = otherPrioObj != null ? otherPrioObj.intValue() : 0;
+            if (otherPriority > priority) {
+                caps.add(i, hc);
+                return i;
+            }
+        }
+
+        caps.add(hc);
+        return caps.size() - 1;
+    }
+
+    @Override
+    public boolean isEffective(Requirement requirement) {
+        init();
+        String effective = requirement.getDirectives().get(Namespace.REQUIREMENT_EFFECTIVE_DIRECTIVE);
+        if (effective == null || Namespace.EFFECTIVE_RESOLVE.equals(effective))
+            return true;
+
+        if (effectiveSet != null && effectiveSet.contains(effective))
+            return true;
+
+        return false;
+    }
+
+    @Override
+    public Map<Resource,Wiring> getWirings() {
+        return Collections.emptyMap();
+    }
+
+    public boolean isInputRequirementsResource(Resource resource) {
+        return resource == inputRequirementsResource;
+    }
+
+    public boolean isFrameworkResource(Resource resource) {
+        return resource == frameworkResource;
+    }
+
+    public Map<Requirement,List<Capability>> getMandatoryRequirements() {
+        return mandatoryRequirements;
+    }
+
+    public Map<Requirement,List<Capability>> getOptionalRequirements() {
+        return optionalRequirements;
+    }
+
+}
diff --git a/biz.aQute.resolve/src/biz/aQute/resolve/internal/FrameworkResourceRepository.java b/biz.aQute.resolve/src/biz/aQute/resolve/internal/FrameworkResourceRepository.java
new file mode 100644
index 0000000..fda47cb
--- /dev/null
+++ b/biz.aQute.resolve/src/biz/aQute/resolve/internal/FrameworkResourceRepository.java
@@ -0,0 +1,144 @@
+package biz.aQute.resolve.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.BundleNamespace;
+import org.osgi.framework.namespace.ExecutionEnvironmentNamespace;
+import org.osgi.framework.namespace.HostNamespace;
+import org.osgi.framework.namespace.PackageNamespace;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+import org.osgi.service.repository.Repository;
+
+import aQute.bnd.build.model.EE;
+import aQute.bnd.build.model.clauses.ExportedPackage;
+import aQute.bnd.deployer.repository.CapabilityIndex;
+import aQute.bnd.header.Attrs;
+import aQute.bnd.header.Parameters;
+import aQute.bnd.osgi.resource.CapReqBuilder;
+
+public class FrameworkResourceRepository implements Repository {
+
+    private final CapabilityIndex capIndex = new CapabilityIndex();
+    private final Resource framework;
+    private final EE ee;
+
+    public FrameworkResourceRepository(Resource frameworkResource, EE ee, List<ExportedPackage> sysPkgsExtra, Parameters sysCapsExtraParams) {
+        this.framework = frameworkResource;
+        this.ee = ee;
+        capIndex.addResource(frameworkResource);
+
+        // Add EEs
+        addEECapability(capIndex, ee);
+        for (EE compatibleEE : ee.getCompatible()) {
+            addEECapability(capIndex, compatibleEE);
+        }
+
+        // Add system.bundle alias
+        Version frameworkVersion = Utils.findIdentityVersion(frameworkResource);
+        capIndex.addCapability(new CapReqBuilder(BundleNamespace.BUNDLE_NAMESPACE).addAttribute(BundleNamespace.BUNDLE_NAMESPACE, Constants.SYSTEM_BUNDLE_SYMBOLICNAME)
+                .addAttribute(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE, frameworkVersion).setResource(frameworkResource).buildCapability());
+        capIndex.addCapability(new CapReqBuilder(HostNamespace.HOST_NAMESPACE).addAttribute(HostNamespace.HOST_NAMESPACE, Constants.SYSTEM_BUNDLE_SYMBOLICNAME)
+                .addAttribute(HostNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE, frameworkVersion).setResource(frameworkResource).buildCapability());
+
+        // Add JRE packages
+        loadJREPackages();
+
+        // Add system.packages.extra
+        if (sysPkgsExtra != null)
+            for (ExportedPackage sysPkg : sysPkgsExtra) {
+                CapReqBuilder builder = new CapReqBuilder(PackageNamespace.PACKAGE_NAMESPACE);
+                builder.addAttribute(PackageNamespace.PACKAGE_NAMESPACE, sysPkg.getName());
+                String versionStr = sysPkg.getVersionString();
+                Version version = versionStr != null ? new Version(versionStr) : Version.emptyVersion;
+                builder.addAttribute(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE, version);
+                Capability cap = builder.setResource(framework).buildCapability();
+                capIndex.addCapability(cap);
+            }
+
+        // Add system capabilities extra
+        if (sysCapsExtraParams != null) {
+            for (Entry<String,Attrs> entry : sysCapsExtraParams.entrySet()) {
+                CapReqBuilder builder = new CapReqBuilder(entry.getKey());
+                for (String attrKey : entry.getValue().keySet()) {
+                    if (attrKey.endsWith(":")) {
+                        String directiveKey = attrKey.substring(0, attrKey.length() - 1);
+                        builder.addDirective(directiveKey, entry.getValue().get(attrKey));
+                    } else {
+                        builder.addAttribute(attrKey, entry.getValue().getTyped(attrKey));
+                    }
+                }
+                builder.setResource(frameworkResource);
+                capIndex.addCapability(builder.buildCapability());
+            }
+        }
+    }
+
+    public void addFrameworkCapability(CapReqBuilder builder) {
+        Capability cap = builder.setResource(framework).buildCapability();
+        capIndex.addCapability(cap);
+    }
+
+    private void addEECapability(CapabilityIndex index, EE ee) {
+        CapReqBuilder builder;
+
+        // Correct version according to R5 specification section 3.4.1
+        // BREE J2SE-1.4 ==> osgi.ee=JavaSE, version:Version=1.4
+        // See bug 329, https://github.com/bndtools/bnd/issues/329
+        builder = new CapReqBuilder(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE);
+        builder.addAttribute(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE, ee.getCapabilityName());
+        builder.addAttribute(ExecutionEnvironmentNamespace.CAPABILITY_VERSION_ATTRIBUTE, ee.getCapabilityVersion());
+        builder.setResource(framework);
+        index.addCapability(builder.buildCapability());
+
+        // Compatibility with old version...
+        builder = new CapReqBuilder(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE);
+        builder.addAttribute(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE, ee.getEEName());
+        builder.setResource(framework);
+        index.addCapability(builder.buildCapability());
+    }
+
+    private void loadJREPackages() {
+        InputStream stream = FrameworkResourceRepository.class.getResourceAsStream(ee.name() + ".properties");
+        if (stream != null) {
+            try {
+                Properties properties = new Properties();
+                properties.load(stream);
+
+                Parameters params = new Parameters(properties.getProperty("org.osgi.framework.system.packages", ""));
+                for (String packageName : params.keySet()) {
+                    CapReqBuilder builder = new CapReqBuilder(PackageNamespace.PACKAGE_NAMESPACE);
+                    builder.addAttribute(PackageNamespace.PACKAGE_NAMESPACE, packageName);
+                    builder.addAttribute(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE, new Version(0, 0, 0));
+                    Capability cap = builder.setResource(framework).buildCapability();
+                    capIndex.addCapability(cap);
+                }
+            } catch (IOException e) {
+                throw new IllegalStateException("Error loading JRE package properties", e);
+            }
+        }
+    }
+
+    public Map<Requirement,Collection<Capability>> findProviders(Collection< ? extends Requirement> requirements) {
+        Map<Requirement,Collection<Capability>> result = new HashMap<Requirement,Collection<Capability>>();
+        for (Requirement requirement : requirements) {
+            List<Capability> matches = new LinkedList<Capability>();
+            result.put(requirement, matches);
+
+            capIndex.appendMatchingCapabilities(requirement, matches);
+        }
+        return result;
+    }
+
+}
diff --git a/biz.aQute.resolve/src/biz/aQute/resolve/internal/J2SE_1_2.properties b/biz.aQute.resolve/src/biz/aQute/resolve/internal/J2SE_1_2.properties
new file mode 100644
index 0000000..9806dbd
--- /dev/null
+++ b/biz.aQute.resolve/src/biz/aQute/resolve/internal/J2SE_1_2.properties
@@ -0,0 +1,25 @@
+org.osgi.framework.system.packages = \
+ javax.accessibility,\
+ javax.swing,\
+ javax.swing.border,\
+ javax.swing.colorchooser,\
+ javax.swing.event,\
+ javax.swing.filechooser,\
+ javax.swing.plaf,\
+ javax.swing.plaf.basic,\
+ javax.swing.plaf.metal,\
+ javax.swing.plaf.multi,\
+ javax.swing.table,\
+ javax.swing.text,\
+ javax.swing.text.html,\
+ javax.swing.text.html.parser,\
+ javax.swing.text.rtf,\
+ javax.swing.tree,\
+ javax.swing.undo,\
+ org.omg.CORBA,\
+ org.omg.CORBA.DynAnyPackage,\
+ org.omg.CORBA.ORBPackage,\
+ org.omg.CORBA.portable,\
+ org.omg.CORBA.TypeCodePackage,\
+ org.omg.CosNaming,\
+ org.omg.CosNaming.NamingContextPackage
\ No newline at end of file
diff --git a/biz.aQute.resolve/src/biz/aQute/resolve/internal/J2SE_1_3.properties b/biz.aQute.resolve/src/biz/aQute/resolve/internal/J2SE_1_3.properties
new file mode 100644
index 0000000..65fed94
--- /dev/null
+++ b/biz.aQute.resolve/src/biz/aQute/resolve/internal/J2SE_1_3.properties
@@ -0,0 +1,41 @@
+org.osgi.framework.system.packages = \
+ javax.accessibility,\
+ javax.naming,\
+ javax.naming.directory,\
+ javax.naming.event,\
+ javax.naming.ldap,\
+ javax.naming.spi,\
+ javax.rmi,\
+ javax.rmi.CORBA,\
+ javax.sound.midi,\
+ javax.sound.midi.spi,\
+ javax.sound.sampled,\
+ javax.sound.sampled.spi,\
+ javax.swing,\
+ javax.swing.border,\
+ javax.swing.colorchooser,\
+ javax.swing.event,\
+ javax.swing.filechooser,\
+ javax.swing.plaf,\
+ javax.swing.plaf.basic,\
+ javax.swing.plaf.metal,\
+ javax.swing.plaf.multi,\
+ javax.swing.table,\
+ javax.swing.text,\
+ javax.swing.text.html,\
+ javax.swing.text.html.parser,\
+ javax.swing.text.rtf,\
+ javax.swing.tree,\
+ javax.swing.undo,\
+ javax.transaction,\
+ org.omg.CORBA,\
+ org.omg.CORBA_2_3,\
+ org.omg.CORBA_2_3.portable,\
+ org.omg.CORBA.DynAnyPackage,\
+ org.omg.CORBA.ORBPackage,\
+ org.omg.CORBA.portable,\
+ org.omg.CORBA.TypeCodePackage,\
+ org.omg.CosNaming,\
+ org.omg.CosNaming.NamingContextPackage,\
+ org.omg.SendingContext,\
+ org.omg.stub.java.rmi
\ No newline at end of file
diff --git a/biz.aQute.resolve/src/biz/aQute/resolve/internal/J2SE_1_4.properties b/biz.aQute.resolve/src/biz/aQute/resolve/internal/J2SE_1_4.properties
new file mode 100644
index 0000000..5a869cb
--- /dev/null
+++ b/biz.aQute.resolve/src/biz/aQute/resolve/internal/J2SE_1_4.properties
@@ -0,0 +1,97 @@
+org.osgi.framework.system.packages = \
+ javax.accessibility,\
+ javax.crypto,\
+ javax.crypto.interfaces,\
+ javax.crypto.spec,\
+ javax.imageio,\
+ javax.imageio.event,\
+ javax.imageio.metadata,\
+ javax.imageio.plugins.jpeg,\
+ javax.imageio.spi,\
+ javax.imageio.stream,\
+ javax.naming,\
+ javax.naming.directory,\
+ javax.naming.event,\
+ javax.naming.ldap,\
+ javax.naming.spi,\
+ javax.net,\
+ javax.net.ssl,\
+ javax.print,\
+ javax.print.attribute,\
+ javax.print.attribute.standard,\
+ javax.print.event,\
+ javax.rmi,\
+ javax.rmi.CORBA,\
+ javax.security.auth,\
+ javax.security.auth.callback,\
+ javax.security.auth.kerberos,\
+ javax.security.auth.login,\
+ javax.security.auth.spi,\
+ javax.security.auth.x500,\
+ javax.security.cert,\
+ javax.sound.midi,\
+ javax.sound.midi.spi,\
+ javax.sound.sampled,\
+ javax.sound.sampled.spi,\
+ javax.sql,\
+ javax.swing,\
+ javax.swing.border,\
+ javax.swing.colorchooser,\
+ javax.swing.event,\
+ javax.swing.filechooser,\
+ javax.swing.plaf,\
+ javax.swing.plaf.basic,\
+ javax.swing.plaf.metal,\
+ javax.swing.plaf.multi,\
+ javax.swing.table,\
+ javax.swing.text,\
+ javax.swing.text.html,\
+ javax.swing.text.html.parser,\
+ javax.swing.text.rtf,\
+ javax.swing.tree,\
+ javax.swing.undo,\
+ javax.transaction,\
+ javax.transaction.xa,\
+ javax.xml.parsers,\
+ javax.xml.transform,\
+ javax.xml.transform.dom,\
+ javax.xml.transform.sax,\
+ javax.xml.transform.stream,\
+ org.ietf.jgss,\
+ org.omg.CORBA,\
+ org.omg.CORBA_2_3,\
+ org.omg.CORBA_2_3.portable,\
+ org.omg.CORBA.DynAnyPackage,\
+ org.omg.CORBA.ORBPackage,\
+ org.omg.CORBA.portable,\
+ org.omg.CORBA.TypeCodePackage,\
+ org.omg.CosNaming,\
+ org.omg.CosNaming.NamingContextExtPackage,\
+ org.omg.CosNaming.NamingContextPackage,\
+ org.omg.Dynamic,\
+ org.omg.DynamicAny,\
+ org.omg.DynamicAny.DynAnyFactoryPackage,\
+ org.omg.DynamicAny.DynAnyPackage,\
+ org.omg.IOP,\
+ org.omg.IOP.CodecFactoryPackage,\
+ org.omg.IOP.CodecPackage,\
+ org.omg.Messaging,\
+ org.omg.PortableInterceptor,\
+ org.omg.PortableInterceptor.ORBInitInfoPackage,\
+ org.omg.PortableServer,\
+ org.omg.PortableServer.CurrentPackage,\
+ org.omg.PortableServer.POAManagerPackage,\
+ org.omg.PortableServer.POAPackage,\
+ org.omg.PortableServer.portable,\
+ org.omg.PortableServer.ServantLocatorPackage,\
+ org.omg.SendingContext,\
+ org.omg.stub.java.rmi,\
+ org.w3c.dom,\
+ org.w3c.dom.css,\
+ org.w3c.dom.events,\
+ org.w3c.dom.html,\
+ org.w3c.dom.stylesheets,\
+ org.w3c.dom.views ,\
+ org.xml.sax,\
+ org.xml.sax.ext,\
+ org.xml.sax.helpers
\ No newline at end of file
diff --git a/biz.aQute.resolve/src/biz/aQute/resolve/internal/J2SE_1_5.properties b/biz.aQute.resolve/src/biz/aQute/resolve/internal/J2SE_1_5.properties
new file mode 100644
index 0000000..7e13cac
--- /dev/null
+++ b/biz.aQute.resolve/src/biz/aQute/resolve/internal/J2SE_1_5.properties
@@ -0,0 +1,123 @@
+org.osgi.framework.system.packages = \
+ javax.accessibility,\
+ javax.activity,\
+ javax.crypto,\
+ javax.crypto.interfaces,\
+ javax.crypto.spec,\
+ javax.imageio,\
+ javax.imageio.event,\
+ javax.imageio.metadata,\
+ javax.imageio.plugins.bmp,\
+ javax.imageio.plugins.jpeg,\
+ javax.imageio.spi,\
+ javax.imageio.stream,\
+ javax.management,\
+ javax.management.loading,\
+ javax.management.modelmbean,\
+ javax.management.monitor,\
+ javax.management.openmbean,\
+ javax.management.relation,\
+ javax.management.remote,\
+ javax.management.remote.rmi,\
+ javax.management.timer,\
+ javax.naming,\
+ javax.naming.directory,\
+ javax.naming.event,\
+ javax.naming.ldap,\
+ javax.naming.spi,\
+ javax.net,\
+ javax.net.ssl,\
+ javax.print,\
+ javax.print.attribute,\
+ javax.print.attribute.standard,\
+ javax.print.event,\
+ javax.rmi,\
+ javax.rmi.CORBA,\
+ javax.rmi.ssl,\
+ javax.security.auth,\
+ javax.security.auth.callback,\
+ javax.security.auth.kerberos,\
+ javax.security.auth.login,\
+ javax.security.auth.spi,\
+ javax.security.auth.x500,\
+ javax.security.cert,\
+ javax.security.sasl,\
+ javax.sound.midi,\
+ javax.sound.midi.spi,\
+ javax.sound.sampled,\
+ javax.sound.sampled.spi,\
+ javax.sql,\
+ javax.sql.rowset,\
+ javax.sql.rowset.serial,\
+ javax.sql.rowset.spi,\
+ javax.swing,\
+ javax.swing.border,\
+ javax.swing.colorchooser,\
+ javax.swing.event,\
+ javax.swing.filechooser,\
+ javax.swing.plaf,\
+ javax.swing.plaf.basic,\
+ javax.swing.plaf.metal,\
+ javax.swing.plaf.multi,\
+ javax.swing.plaf.synth,\
+ javax.swing.table,\
+ javax.swing.text,\
+ javax.swing.text.html,\
+ javax.swing.text.html.parser,\
+ javax.swing.text.rtf,\
+ javax.swing.tree,\
+ javax.swing.undo,\
+ javax.transaction,\
+ javax.transaction.xa,\
+ javax.xml,\
+ javax.xml.datatype,\
+ javax.xml.namespace,\
+ javax.xml.parsers,\
+ javax.xml.transform,\
+ javax.xml.transform.dom,\
+ javax.xml.transform.sax,\
+ javax.xml.transform.stream,\
+ javax.xml.validation,\
+ javax.xml.xpath,\
+ org.ietf.jgss,\
+ org.omg.CORBA,\
+ org.omg.CORBA_2_3,\
+ org.omg.CORBA_2_3.portable,\
+ org.omg.CORBA.DynAnyPackage,\
+ org.omg.CORBA.ORBPackage,\
+ org.omg.CORBA.portable,\
+ org.omg.CORBA.TypeCodePackage,\
+ org.omg.CosNaming,\
+ org.omg.CosNaming.NamingContextExtPackage,\
+ org.omg.CosNaming.NamingContextPackage,\
+ org.omg.Dynamic,\
+ org.omg.DynamicAny,\
+ org.omg.DynamicAny.DynAnyFactoryPackage,\
+ org.omg.DynamicAny.DynAnyPackage,\
+ org.omg.IOP,\
+ org.omg.IOP.CodecFactoryPackage,\
+ org.omg.IOP.CodecPackage,\
+ org.omg.Messaging,\
+ org.omg.PortableInterceptor,\
+ org.omg.PortableInterceptor.ORBInitInfoPackage,\
+ org.omg.PortableServer,\
+ org.omg.PortableServer.CurrentPackage,\
+ org.omg.PortableServer.POAManagerPackage,\
+ org.omg.PortableServer.POAPackage,\
+ org.omg.PortableServer.portable,\
+ org.omg.PortableServer.ServantLocatorPackage,\
+ org.omg.SendingContext,\
+ org.omg.stub.java.rmi,\
+ org.w3c.dom,\
+ org.w3c.dom.bootstrap,\
+ org.w3c.dom.css,\
+ org.w3c.dom.events,\
+ org.w3c.dom.html,\
+ org.w3c.dom.ls,\
+ org.w3c.dom.ranges,\
+ org.w3c.dom.stylesheets,\
+ org.w3c.dom.traversal,\
+ org.w3c.dom.views ,\
+ org.xml.sax,\
+ org.xml.sax.ext,\
+ org.xml.sax.helpers
diff --git a/biz.aQute.resolve/src/biz/aQute/resolve/internal/JRE_1_1.properties b/biz.aQute.resolve/src/biz/aQute/resolve/internal/JRE_1_1.properties
new file mode 100644
index 0000000..6194f32
--- /dev/null
+++ b/biz.aQute.resolve/src/biz/aQute/resolve/internal/JRE_1_1.properties
@@ -0,0 +1 @@
+org.osgi.framework.system.packages = 
diff --git a/biz.aQute.resolve/src/biz/aQute/resolve/internal/JavaSE_1_6.properties b/biz.aQute.resolve/src/biz/aQute/resolve/internal/JavaSE_1_6.properties
new file mode 100644
index 0000000..4fd81e8
--- /dev/null
+++ b/biz.aQute.resolve/src/biz/aQute/resolve/internal/JavaSE_1_6.properties
@@ -0,0 +1,160 @@
+org.osgi.framework.system.packages = \
+ javax.accessibility,\
+ javax.activation,\
+ javax.activity,\
+ javax.annotation,\
+ javax.annotation.processing,\
+ javax.crypto,\
+ javax.crypto.interfaces,\
+ javax.crypto.spec,\
+ javax.imageio,\
+ javax.imageio.event,\
+ javax.imageio.metadata,\
+ javax.imageio.plugins.bmp,\
+ javax.imageio.plugins.jpeg,\
+ javax.imageio.spi,\
+ javax.imageio.stream,\
+ javax.jws,\
+ javax.jws.soap,\
+ javax.lang.model,\
+ javax.lang.model.element,\
+ javax.lang.model.type,\
+ javax.lang.model.util,\
+ javax.management,\
+ javax.management.loading,\
+ javax.management.modelmbean,\
+ javax.management.monitor,\
+ javax.management.openmbean,\
+ javax.management.relation,\
+ javax.management.remote,\
+ javax.management.remote.rmi,\
+ javax.management.timer,\
+ javax.naming,\
+ javax.naming.directory,\
+ javax.naming.event,\
+ javax.naming.ldap,\
+ javax.naming.spi,\
+ javax.net,\
+ javax.net.ssl,\
+ javax.print,\
+ javax.print.attribute,\
+ javax.print.attribute.standard,\
+ javax.print.event,\
+ javax.rmi,\
+ javax.rmi.CORBA,\
+ javax.rmi.ssl,\
+ javax.script,\
+ javax.security.auth,\
+ javax.security.auth.callback,\
+ javax.security.auth.kerberos,\
+ javax.security.auth.login,\
+ javax.security.auth.spi,\
+ javax.security.auth.x500,\
+ javax.security.cert,\
+ javax.security.sasl,\
+ javax.sound.midi,\
+ javax.sound.midi.spi,\
+ javax.sound.sampled,\
+ javax.sound.sampled.spi,\
+ javax.sql,\
+ javax.sql.rowset,\
+ javax.sql.rowset.serial,\
+ javax.sql.rowset.spi,\
+ javax.swing,\
+ javax.swing.border,\
+ javax.swing.colorchooser,\
+ javax.swing.event,\
+ javax.swing.filechooser,\
+ javax.swing.plaf,\
+ javax.swing.plaf.basic,\
+ javax.swing.plaf.metal,\
+ javax.swing.plaf.multi,\
+ javax.swing.plaf.synth,\
+ javax.swing.table,\
+ javax.swing.text,\
+ javax.swing.text.html,\
+ javax.swing.text.html.parser,\
+ javax.swing.text.rtf,\
+ javax.swing.tree,\
+ javax.swing.undo,\
+ javax.tools,\
+ javax.transaction,\
+ javax.transaction.xa,\
+ javax.xml,\
+ javax.xml.bind,\
+ javax.xml.bind.annotation,\
+ javax.xml.bind.annotation.adapters,\
+ javax.xml.bind.attachment,\
+ javax.xml.bind.helpers,\
+ javax.xml.bind.util,\
+ javax.xml.crypto,\
+ javax.xml.crypto.dom,\
+ javax.xml.crypto.dsig,\
+ javax.xml.crypto.dsig.dom,\
+ javax.xml.crypto.dsig.keyinfo,\
+ javax.xml.crypto.dsig.spec,\
+ javax.xml.datatype,\
+ javax.xml.namespace,\
+ javax.xml.parsers,\
+ javax.xml.soap,\
+ javax.xml.stream,\
+ javax.xml.stream.events,\
+ javax.xml.stream.util,\
+ javax.xml.transform,\
+ javax.xml.transform.dom,\
+ javax.xml.transform.sax,\
+ javax.xml.transform.stax,\
+ javax.xml.transform.stream,\
+ javax.xml.validation,\
+ javax.xml.ws,\
+ javax.xml.ws.handler,\
+ javax.xml.ws.handler.soap,\
+ javax.xml.ws.http,\
+ javax.xml.ws.soap,\
+ javax.xml.ws.spi,\
+ javax.xml.ws.wsaddressing,\
+ javax.xml.xpath,\
+ org.ietf.jgss,\
+ org.omg.CORBA,\
+ org.omg.CORBA_2_3,\
+ org.omg.CORBA_2_3.portable,\
+ org.omg.CORBA.DynAnyPackage,\
+ org.omg.CORBA.ORBPackage,\
+ org.omg.CORBA.portable,\
+ org.omg.CORBA.TypeCodePackage,\
+ org.omg.CosNaming,\
+ org.omg.CosNaming.NamingContextExtPackage,\
+ org.omg.CosNaming.NamingContextPackage,\
+ org.omg.Dynamic,\
+ org.omg.DynamicAny,\
+ org.omg.DynamicAny.DynAnyFactoryPackage,\
+ org.omg.DynamicAny.DynAnyPackage,\
+ org.omg.IOP,\
+ org.omg.IOP.CodecFactoryPackage,\
+ org.omg.IOP.CodecPackage,\
+ org.omg.Messaging,\
+ org.omg.PortableInterceptor,\
+ org.omg.PortableInterceptor.ORBInitInfoPackage,\
+ org.omg.PortableServer,\
+ org.omg.PortableServer.CurrentPackage,\
+ org.omg.PortableServer.POAManagerPackage,\
+ org.omg.PortableServer.POAPackage,\
+ org.omg.PortableServer.portable,\
+ org.omg.PortableServer.ServantLocatorPackage,\
+ org.omg.SendingContext,\
+ org.omg.stub.java.rmi,\
+ org.w3c.dom,\
+ org.w3c.dom.bootstrap,\
+ org.w3c.dom.css,\
+ org.w3c.dom.events,\
+ org.w3c.dom.html,\
+ org.w3c.dom.ls,\
+ org.w3c.dom.ranges,\
+ org.w3c.dom.stylesheets,\
+ org.w3c.dom.traversal,\
+ org.w3c.dom.views,\
+ org.w3c.dom.xpath,\
+ org.xml.sax,\
+ org.xml.sax.ext,\
+ org.xml.sax.helpers
+
diff --git a/biz.aQute.resolve/src/biz/aQute/resolve/internal/JavaSE_1_7.properties b/biz.aQute.resolve/src/biz/aQute/resolve/internal/JavaSE_1_7.properties
new file mode 100644
index 0000000..22332c0
--- /dev/null
+++ b/biz.aQute.resolve/src/biz/aQute/resolve/internal/JavaSE_1_7.properties
@@ -0,0 +1,163 @@
+org.osgi.framework.system.packages = \
+ javax.accessibility,\
+ javax.activation,\
+ javax.activity,\
+ javax.annotation,\
+ javax.annotation.processing,\
+ javax.crypto,\
+ javax.crypto.interfaces,\
+ javax.crypto.spec,\
+ javax.imageio,\
+ javax.imageio.event,\
+ javax.imageio.metadata,\
+ javax.imageio.plugins.bmp,\
+ javax.imageio.plugins.jpeg,\
+ javax.imageio.spi,\
+ javax.imageio.stream,\
+ javax.jws,\
+ javax.jws.soap,\
+ javax.lang.model,\
+ javax.lang.model.element,\
+ javax.lang.model.type,\
+ javax.lang.model.util,\
+ javax.management,\
+ javax.management.event,\
+ javax.management.loading,\
+ javax.management.modelmbean,\
+ javax.management.monitor,\
+ javax.management.namespace,\
+ javax.management.openmbean,\
+ javax.management.relation,\
+ javax.management.remote,\
+ javax.management.remote.rmi,\
+ javax.management.timer,\
+ javax.naming,\
+ javax.naming.directory,\
+ javax.naming.event,\
+ javax.naming.ldap,\
+ javax.naming.spi,\
+ javax.net,\
+ javax.net.ssl,\
+ javax.print,\
+ javax.print.attribute,\
+ javax.print.attribute.standard,\
+ javax.print.event,\
+ javax.rmi,\
+ javax.rmi.CORBA,\
+ javax.rmi.ssl,\
+ javax.script,\
+ javax.security.auth,\
+ javax.security.auth.callback,\
+ javax.security.auth.kerberos,\
+ javax.security.auth.login,\
+ javax.security.auth.spi,\
+ javax.security.auth.x500,\
+ javax.security.cert,\
+ javax.security.sasl,\
+ javax.sound.midi,\
+ javax.sound.midi.spi,\
+ javax.sound.sampled,\
+ javax.sound.sampled.spi,\
+ javax.sql,\
+ javax.sql.rowset,\
+ javax.sql.rowset.serial,\
+ javax.sql.rowset.spi,\
+ javax.swing,\
+ javax.swing.border,\
+ javax.swing.colorchooser,\
+ javax.swing.event,\
+ javax.swing.filechooser,\
+ javax.swing.plaf,\
+ javax.swing.plaf.basic,\
+ javax.swing.plaf.metal,\
+ javax.swing.plaf.multi,\
+ javax.swing.plaf.nimbus,\
+ javax.swing.plaf.synth,\
+ javax.swing.table,\
+ javax.swing.text,\
+ javax.swing.text.html,\
+ javax.swing.text.html.parser,\
+ javax.swing.text.rtf,\
+ javax.swing.tree,\
+ javax.swing.undo,\
+ javax.tools,\
+ javax.transaction,\
+ javax.transaction.xa,\
+ javax.xml,\
+ javax.xml.bind,\
+ javax.xml.bind.annotation,\
+ javax.xml.bind.annotation.adapters,\
+ javax.xml.bind.attachment,\
+ javax.xml.bind.helpers,\
+ javax.xml.bind.util,\
+ javax.xml.crypto,\
+ javax.xml.crypto.dom,\
+ javax.xml.crypto.dsig,\
+ javax.xml.crypto.dsig.dom,\
+ javax.xml.crypto.dsig.keyinfo,\
+ javax.xml.crypto.dsig.spec,\
+ javax.xml.datatype,\
+ javax.xml.namespace,\
+ javax.xml.parsers,\
+ javax.xml.soap,\
+ javax.xml.stream,\
+ javax.xml.stream.events,\
+ javax.xml.stream.util,\
+ javax.xml.transform,\
+ javax.xml.transform.dom,\
+ javax.xml.transform.sax,\
+ javax.xml.transform.stax,\
+ javax.xml.transform.stream,\
+ javax.xml.validation,\
+ javax.xml.ws,\
+ javax.xml.ws.handler,\
+ javax.xml.ws.handler.soap,\
+ javax.xml.ws.http,\
+ javax.xml.ws.soap,\
+ javax.xml.ws.spi,\
+ javax.xml.ws.wsaddressing,\
+ javax.xml.xpath,\
+ org.ietf.jgss,\
+ org.omg.CORBA,\
+ org.omg.CORBA_2_3,\
+ org.omg.CORBA_2_3.portable,\
+ org.omg.CORBA.DynAnyPackage,\
+ org.omg.CORBA.ORBPackage,\
+ org.omg.CORBA.portable,\
+ org.omg.CORBA.TypeCodePackage,\
+ org.omg.CosNaming,\
+ org.omg.CosNaming.NamingContextExtPackage,\
+ org.omg.CosNaming.NamingContextPackage,\
+ org.omg.Dynamic,\
+ org.omg.DynamicAny,\
+ org.omg.DynamicAny.DynAnyFactoryPackage,\
+ org.omg.DynamicAny.DynAnyPackage,\
+ org.omg.IOP,\
+ org.omg.IOP.CodecFactoryPackage,\
+ org.omg.IOP.CodecPackage,\
+ org.omg.Messaging,\
+ org.omg.PortableInterceptor,\
+ org.omg.PortableInterceptor.ORBInitInfoPackage,\
+ org.omg.PortableServer,\
+ org.omg.PortableServer.CurrentPackage,\
+ org.omg.PortableServer.POAManagerPackage,\
+ org.omg.PortableServer.POAPackage,\
+ org.omg.PortableServer.portable,\
+ org.omg.PortableServer.ServantLocatorPackage,\
+ org.omg.SendingContext,\
+ org.omg.stub.java.rmi,\
+ org.w3c.dom,\
+ org.w3c.dom.bootstrap,\
+ org.w3c.dom.css,\
+ org.w3c.dom.events,\
+ org.w3c.dom.html,\
+ org.w3c.dom.ls,\
+ org.w3c.dom.ranges,\
+ org.w3c.dom.stylesheets,\
+ org.w3c.dom.traversal,\
+ org.w3c.dom.views,\
+ org.w3c.dom.xpath,\
+ org.xml.sax,\
+ org.xml.sax.ext,\
+ org.xml.sax.helpers
+
diff --git a/biz.aQute.bndlib/src/test/split/A b/biz.aQute.resolve/src/biz/aQute/resolve/internal/OSGI_Minimum_1_0.properties
similarity index 100%
copy from biz.aQute.bndlib/src/test/split/A
copy to biz.aQute.resolve/src/biz/aQute/resolve/internal/OSGI_Minimum_1_0.properties
diff --git a/biz.aQute.bndlib/src/test/split/A b/biz.aQute.resolve/src/biz/aQute/resolve/internal/OSGI_Minimum_1_1.properties
similarity index 100%
copy from biz.aQute.bndlib/src/test/split/A
copy to biz.aQute.resolve/src/biz/aQute/resolve/internal/OSGI_Minimum_1_1.properties
diff --git a/biz.aQute.bndlib/src/test/split/A b/biz.aQute.resolve/src/biz/aQute/resolve/internal/OSGI_Minimum_1_2.properties
similarity index 100%
copy from biz.aQute.bndlib/src/test/split/A
copy to biz.aQute.resolve/src/biz/aQute/resolve/internal/OSGI_Minimum_1_2.properties
diff --git a/biz.aQute.resolve/src/biz/aQute/resolve/internal/Utils.java b/biz.aQute.resolve/src/biz/aQute/resolve/internal/Utils.java
new file mode 100644
index 0000000..4541473
--- /dev/null
+++ b/biz.aQute.resolve/src/biz/aQute/resolve/internal/Utils.java
@@ -0,0 +1,30 @@
+package biz.aQute.resolve.internal;
+
+import java.util.List;
+
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Resource;
+
+public class Utils {
+    static Version findIdentityVersion(Resource resource) {
+        List<Capability> idCaps = resource.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE);
+        if (idCaps == null || idCaps.isEmpty())
+            throw new IllegalArgumentException("Resource has no identity capability.");
+        if (idCaps.size() > 1)
+            throw new IllegalArgumentException("Resource has more than one identity capability.");
+
+        Object versionObj = idCaps.get(0).getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+        if (versionObj == null)
+            return Version.emptyVersion;
+
+        if (versionObj instanceof Version)
+            return (Version) versionObj;
+
+        if (versionObj instanceof String)
+            return Version.parseVersion((String) versionObj);
+
+        throw new IllegalArgumentException("Unable to convert type for version attribute: " + versionObj.getClass());
+    }
+}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/help/packageinfo b/biz.aQute.resolve/src/biz/aQute/resolve/packageinfo
similarity index 100%
copy from biz.aQute.bndlib/src/aQute/bnd/help/packageinfo
copy to biz.aQute.resolve/src/biz/aQute/resolve/packageinfo
diff --git a/biz.aQute.resolve/src/test/BndrunResolveContextTest.java b/biz.aQute.resolve/src/test/BndrunResolveContextTest.java
new file mode 100644
index 0000000..9121144
--- /dev/null
+++ b/biz.aQute.resolve/src/test/BndrunResolveContextTest.java
@@ -0,0 +1,436 @@
+package test;
+
+import static test.lib.Utils.*;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.osgi.resource.Capability;
+import org.osgi.resource.Namespace;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+import org.osgi.service.log.LogService;
+import org.osgi.service.repository.Repository;
+
+import test.lib.MockRegistry;
+import test.lib.NullLogService;
+import aQute.bnd.build.model.BndEditModel;
+import aQute.bnd.build.model.EE;
+import aQute.bnd.build.model.clauses.*;
+import aQute.bnd.header.*;
+import aQute.bnd.osgi.resource.CapReqBuilder;
+import biz.aQute.resolve.internal.BndrunResolveContext;
+
+public class BndrunResolveContextTest extends TestCase {
+
+    private static final LogService log = new NullLogService();
+
+    public static void testEffective() {
+        BndrunResolveContext context = new BndrunResolveContext(new BndEditModel(), new MockRegistry(), log);
+
+        Requirement resolveReq = new CapReqBuilder("dummy.ns").addDirective(Namespace.REQUIREMENT_EFFECTIVE_DIRECTIVE, Namespace.EFFECTIVE_RESOLVE).buildSyntheticRequirement();
+        Requirement activeReq = new CapReqBuilder("dummy.ns").addDirective(Namespace.REQUIREMENT_EFFECTIVE_DIRECTIVE, Namespace.EFFECTIVE_ACTIVE).buildSyntheticRequirement();
+        Requirement noEffectiveDirectiveReq = new CapReqBuilder("dummy.ns").buildSyntheticRequirement();
+
+        assertTrue(context.isEffective(resolveReq));
+        assertFalse(context.isEffective(activeReq));
+        assertTrue(context.isEffective(noEffectiveDirectiveReq));
+    }
+
+    public static void testEffective2() {
+        BndEditModel model = new BndEditModel();
+        model.genericSet(BndrunResolveContext.RUN_EFFECTIVE_INSTRUCTION, "active, arbitrary");
+
+        BndrunResolveContext context = new BndrunResolveContext(model, new MockRegistry(), log);
+
+        Requirement resolveReq = new CapReqBuilder("dummy.ns").addDirective(Namespace.REQUIREMENT_EFFECTIVE_DIRECTIVE, Namespace.EFFECTIVE_RESOLVE).buildSyntheticRequirement();
+        Requirement activeReq = new CapReqBuilder("dummy.ns").addDirective(Namespace.REQUIREMENT_EFFECTIVE_DIRECTIVE, Namespace.EFFECTIVE_ACTIVE).buildSyntheticRequirement();
+        Requirement arbitrary1Req = new CapReqBuilder("dummy.ns").addDirective(Namespace.REQUIREMENT_EFFECTIVE_DIRECTIVE, "arbitrary").buildSyntheticRequirement();
+        Requirement arbitrary2Req = new CapReqBuilder("dummy.ns").addDirective(Namespace.REQUIREMENT_EFFECTIVE_DIRECTIVE, "VeryArbitrary").buildSyntheticRequirement();
+
+        Requirement noEffectiveDirectiveReq = new CapReqBuilder("dummy.ns").buildSyntheticRequirement();
+
+        assertTrue(context.isEffective(resolveReq));
+        assertTrue(context.isEffective(activeReq));
+        assertTrue(context.isEffective(arbitrary1Req));
+        assertFalse(context.isEffective(arbitrary2Req));
+        assertTrue(context.isEffective(noEffectiveDirectiveReq));
+    }
+
+    public static void testEmptyInitialWirings() {
+        assertEquals(0, new BndrunResolveContext(new BndEditModel(), new MockRegistry(), log).getWirings().size());
+    }
+
+    public static void testBasicFindProviders() {
+        MockRegistry registry = new MockRegistry();
+        registry.addPlugin(createRepo(new File("testdata/repo1.index.xml")));
+
+        BndEditModel runModel = new BndEditModel();
+        BndrunResolveContext context = new BndrunResolveContext(runModel, registry, log);
+
+        Requirement req = new CapReqBuilder("osgi.wiring.package").addDirective("filter", "(osgi.wiring.package=org.apache.felix.gogo.api)").buildSyntheticRequirement();
+        List<Capability> providers = context.findProviders(req);
+        assertEquals(1, providers.size());
+        Resource resource = providers.get(0).getResource();
+
+        assertEquals(new File("testdata/repo1/org.apache.felix.gogo.runtime-0.10.0.jar").toURI(), findContentURI(resource));
+    }
+
+    public static void testProviderPreference() {
+        Requirement req = new CapReqBuilder("osgi.wiring.package").addDirective("filter", "(osgi.wiring.package=org.apache.felix.gogo.api)").buildSyntheticRequirement();
+
+        MockRegistry registry;
+        BndrunResolveContext context;
+        List<Capability> providers;
+        Resource resource;
+
+        // First try it with repo1 first
+        registry = new MockRegistry();
+        registry.addPlugin(createRepo(new File("testdata/repo1.index.xml")));
+        registry.addPlugin(createRepo(new File("testdata/repo2.index.xml")));
+
+        context = new BndrunResolveContext(new BndEditModel(), registry, log);
+        providers = context.findProviders(req);
+        assertEquals(2, providers.size());
+        resource = providers.get(0).getResource();
+        assertEquals(new File("testdata/repo1/org.apache.felix.gogo.runtime-0.10.0.jar").toURI(), findContentURI(resource));
+        resource = providers.get(1).getResource();
+        assertEquals(new File("testdata/repo2/org.apache.felix.gogo.runtime-0.10.0.jar").toURI(), findContentURI(resource));
+
+        // Now try it with repo2 first
+        registry = new MockRegistry();
+        registry.addPlugin(createRepo(new File("testdata/repo2.index.xml")));
+        registry.addPlugin(createRepo(new File("testdata/repo1.index.xml")));
+
+        context = new BndrunResolveContext(new BndEditModel(), registry, log);
+        providers = context.findProviders(req);
+        assertEquals(2, providers.size());
+        resource = providers.get(0).getResource();
+        assertEquals(new File("testdata/repo2/org.apache.felix.gogo.runtime-0.10.0.jar").toURI(), findContentURI(resource));
+        resource = providers.get(1).getResource();
+        assertEquals(new File("testdata/repo1/org.apache.felix.gogo.runtime-0.10.0.jar").toURI(), findContentURI(resource));
+    }
+
+    public static void testReorderRepositories() {
+        Requirement req = new CapReqBuilder("osgi.wiring.package").addDirective("filter", "(osgi.wiring.package=org.apache.felix.gogo.api)").buildSyntheticRequirement();
+
+        MockRegistry registry = new MockRegistry();
+        registry.addPlugin(createRepo(new File("testdata/repo1.index.xml"), "Repository1"));
+        registry.addPlugin(createRepo(new File("testdata/repo2.index.xml"), "Repository2"));
+
+        BndrunResolveContext context;
+        List<Capability> providers;
+        Resource resource;
+        BndEditModel runModel;
+
+        runModel = new BndEditModel();
+        runModel.setRunRepos(Arrays.asList(new String[] {
+                "Repository2", "Repository1"
+        }));
+
+        context = new BndrunResolveContext(runModel, registry, log);
+        providers = context.findProviders(req);
+        assertEquals(2, providers.size());
+        resource = providers.get(0).getResource();
+        assertEquals(new File("testdata/repo2/org.apache.felix.gogo.runtime-0.10.0.jar").toURI(), findContentURI(resource));
+        resource = providers.get(1).getResource();
+        assertEquals(new File("testdata/repo1/org.apache.felix.gogo.runtime-0.10.0.jar").toURI(), findContentURI(resource));
+    }
+
+    public static void testFrameworkIsMandatory() {
+        MockRegistry registry = new MockRegistry();
+        registry.addPlugin(createRepo(new File("testdata/repo3.index.xml")));
+
+        BndEditModel runModel = new BndEditModel();
+        runModel.setRunFw("org.apache.felix.framework;version='[4,4.1)'");
+
+        BndrunResolveContext context = new BndrunResolveContext(runModel, registry, log);
+        Collection<Resource> resources = context.getMandatoryResources();
+        assertEquals(1, resources.size());
+        Resource fwkResource = resources.iterator().next();
+        assertEquals(new File("testdata/repo3/org.apache.felix.framework-4.0.2.jar").toURI(), findContentURI(fwkResource));
+    }
+
+    public static void testChooseHighestFrameworkVersion() {
+        MockRegistry registry;
+        BndEditModel runModel;
+        BndrunResolveContext context;
+        Collection<Resource> resources;
+        Resource fwkResource;
+
+        registry = new MockRegistry();
+        registry.addPlugin(createRepo(new File("testdata/org.apache.felix.framework-4.0.0.index.xml")));
+        registry.addPlugin(createRepo(new File("testdata/repo3.index.xml")));
+
+        runModel = new BndEditModel();
+        runModel.setRunFw("org.apache.felix.framework;version='[4,4.1)'");
+
+        context = new BndrunResolveContext(runModel, registry, log);
+        resources = context.getMandatoryResources();
+        assertEquals(1, resources.size());
+        fwkResource = resources.iterator().next();
+        assertEquals(new File("testdata/repo3/org.apache.felix.framework-4.0.2.jar").toURI(), findContentURI(fwkResource));
+
+        // Try it the other way round
+        registry = new MockRegistry();
+        registry.addPlugin(createRepo(new File("testdata/repo3.index.xml")));
+        registry.addPlugin(createRepo(new File("testdata/org.apache.felix.framework-4.0.0.index.xml")));
+
+        runModel = new BndEditModel();
+        runModel.setRunFw("org.apache.felix.framework;version='[4,4.1)'");
+
+        context = new BndrunResolveContext(runModel, registry, log);
+        resources = context.getMandatoryResources();
+        assertEquals(1, resources.size());
+        fwkResource = resources.iterator().next();
+        assertEquals(new File("testdata/repo3/org.apache.felix.framework-4.0.2.jar").toURI(), findContentURI(fwkResource));
+    }
+
+    public static void testFrameworkCapabilitiesPreferredOverRepository() {
+        MockRegistry registry = new MockRegistry();
+        registry.addPlugin(createRepo(new File("testdata/osgi.cmpn-4.3.0.index.xml")));
+        registry.addPlugin(createRepo(new File("testdata/org.apache.felix.framework-4.0.2.index.xml")));
+
+        BndEditModel runModel = new BndEditModel();
+        runModel.setRunFw("org.apache.felix.framework");
+
+        Requirement requirement = new CapReqBuilder("osgi.wiring.package").addDirective("filter", "(&(osgi.wiring.package=org.osgi.util.tracker)(version>=1.5)(!(version>=1.6)))").buildSyntheticRequirement();
+
+        BndrunResolveContext context = new BndrunResolveContext(runModel, registry, log);
+        List<Capability> providers = context.findProviders(requirement);
+
+        assertEquals(2, providers.size());
+        assertEquals(new File("testdata/org.apache.felix.framework-4.0.2.jar").toURI(), findContentURI(providers.get(0).getResource()));
+        assertEquals(new File("testdata/osgi.cmpn-4.3.0.jar").toURI(), findContentURI(providers.get(1).getResource()));
+    }
+
+    public static void testSelfCapabilityPreferredOverRepository() {
+        MockRegistry registry = new MockRegistry();
+        Repository repo = createRepo(new File("testdata/repo4.index.xml"));
+
+        registry.addPlugin(repo);
+
+        Requirement resourceReq = new CapReqBuilder("osgi.identity").addDirective("filter", "(osgi.identity=dummy-selfcap)").buildSyntheticRequirement();
+        Resource resource = repo.findProviders(Collections.singleton(resourceReq)).get(resourceReq).iterator().next().getResource();
+
+        Requirement packageReq = resource.getRequirements("osgi.wiring.package").get(0);
+
+        BndEditModel runModel = new BndEditModel();
+        runModel.setRunFw("org.apache.felix.framework");
+
+        BndrunResolveContext context = new BndrunResolveContext(runModel, registry, log);
+        List<Capability> providers = context.findProviders(packageReq);
+
+        assertNotNull(providers);
+        assertEquals(2, providers.size());
+        assertEquals(new File("testdata/repo4/dummy.jar").toURI(), findContentURI(providers.get(0).getResource()));
+    }
+
+    public static void testInputRequirementsAsMandatoryResource() {
+        MockRegistry registry = new MockRegistry();
+        registry.addPlugin(createRepo(new File("testdata/repo3.index.xml")));
+
+        BndEditModel runModel = new BndEditModel();
+        runModel.setRunFw("org.apache.felix.framework");
+
+        Requirement req = new CapReqBuilder("osgi.identity").addDirective("filter", "(osgi.identity=org.apache.felix.gogo.command)").buildSyntheticRequirement();
+        runModel.setRunRequires(Collections.singletonList(req));
+
+        BndrunResolveContext context = new BndrunResolveContext(runModel, registry, log);
+        Collection<Resource> mandRes = context.getMandatoryResources();
+
+        assertEquals(2, mandRes.size());
+        Iterator<Resource> iter = mandRes.iterator();
+        assertEquals(new File("testdata/repo3/org.apache.felix.framework-4.0.2.jar").toURI(), findContentURI(iter.next()));
+        assertEquals("<<INITIAL>>", iter.next().getCapabilities("osgi.identity").get(0).getAttributes().get("osgi.identity"));
+    }
+
+    public static void testEERequirementResolvesFramework() {
+        MockRegistry registry = new MockRegistry();
+        registry.addPlugin(createRepo(new File("testdata/repo3.index.xml")));
+
+        BndEditModel runModel = new BndEditModel();
+        runModel.setRunFw("org.apache.felix.framework");
+        runModel.setEE(EE.JavaSE_1_6);
+
+        BndrunResolveContext context = new BndrunResolveContext(runModel, registry, log);
+
+        Requirement req = new CapReqBuilder("osgi.ee").addDirective("filter", "(osgi.ee=J2SE-1.5)").buildSyntheticRequirement();
+        List<Capability> providers = context.findProviders(req);
+
+        assertEquals(1, providers.size());
+        assertEquals(new File("testdata/repo3/org.apache.felix.framework-4.0.2.jar").toURI(), findContentURI(providers.get(0).getResource()));
+    }
+
+    public static void testJREPackageResolvesFramework() {
+        MockRegistry registry = new MockRegistry();
+        registry.addPlugin(createRepo(new File("testdata/repo3.index.xml")));
+
+        BndEditModel runModel = new BndEditModel();
+        runModel.setRunFw("org.apache.felix.framework");
+        runModel.setEE(EE.JavaSE_1_6);
+
+        BndrunResolveContext context = new BndrunResolveContext(runModel, registry, log);
+
+        Requirement req = CapReqBuilder.createPackageRequirement("javax.annotation", null).buildSyntheticRequirement();
+        List<Capability> providers = context.findProviders(req);
+
+        assertEquals(1, providers.size());
+        assertEquals(new File("testdata/repo3/org.apache.felix.framework-4.0.2.jar").toURI(), findContentURI(providers.get(0).getResource()));
+    }
+
+    public static void testJREPackageNotResolved() {
+        MockRegistry registry = new MockRegistry();
+        registry.addPlugin(createRepo(new File("testdata/repo3.index.xml")));
+
+        BndEditModel runModel = new BndEditModel();
+        runModel.setRunFw("org.apache.felix.framework");
+        runModel.setEE(EE.J2SE_1_5); // javax.annotation added in Java 6
+
+        BndrunResolveContext context = new BndrunResolveContext(runModel, registry, log);
+        Requirement req = CapReqBuilder.createPackageRequirement("javax.annotation", null).buildSyntheticRequirement();
+        List<Capability> providers = context.findProviders(req);
+
+        assertEquals(0, providers.size());
+    }
+
+    public static void testDontResolveBuildOnlyLibraries() {
+        MockRegistry registry = new MockRegistry();
+        registry.addPlugin(createRepo(new File("testdata/buildrepo.index.xml")));
+
+        BndEditModel runModel = new BndEditModel();
+        BndrunResolveContext context;
+
+        context = new BndrunResolveContext(runModel, registry, log);
+        List<Capability> providers1 = context.findProviders(CapReqBuilder.createPackageRequirement("org.osgi.framework", null).buildSyntheticRequirement());
+        assertEquals(0, providers1.size());
+
+        context = new BndrunResolveContext(runModel, registry, log);
+        List<Capability> providers2 = context.findProviders(CapReqBuilder.createPackageRequirement("java.security", null).buildSyntheticRequirement());
+        assertEquals(0, providers2.size());
+    }
+
+    public static void testResolveSystemBundleAlias() {
+        MockRegistry registry = new MockRegistry();
+        registry.addPlugin(createRepo(new File("testdata/repo3.index.xml")));
+
+        BndEditModel runModel = new BndEditModel();
+        runModel.setRunFw("org.apache.felix.framework");
+        runModel.setEE(EE.JavaSE_1_6);
+
+        BndrunResolveContext context = new BndrunResolveContext(runModel, registry, log);
+
+        Requirement req = new CapReqBuilder("osgi.wiring.host").addDirective("filter", "(osgi.wiring.host=system.bundle)").buildSyntheticRequirement();
+        List<Capability> providers = context.findProviders(req);
+
+        assertEquals(1, providers.size());
+        assertEquals(new File("testdata/repo3/org.apache.felix.framework-4.0.2.jar").toURI(), findContentURI(providers.get(0).getResource()));
+    }
+
+    public static void testUnsatisfiedSystemPackage() {
+        MockRegistry registry = new MockRegistry();
+        registry.addPlugin(createRepo(new File("testdata/repo3.index.xml")));
+
+        BndEditModel runModel = new BndEditModel();
+        runModel.setRunFw("org.apache.felix.framework");
+        runModel.setEE(EE.JavaSE_1_6);
+
+        BndrunResolveContext context = new BndrunResolveContext(runModel, registry, log);
+
+        Requirement req = new CapReqBuilder("osgi.wiring.package").addDirective("filter", "(osgi.wiring.package=sun.reflect)").buildSyntheticRequirement();
+        List<Capability> providers = context.findProviders(req);
+
+        assertEquals(0, providers.size());
+    }
+
+    public static void testResolveSystemPackagesExtra() {
+        MockRegistry registry = new MockRegistry();
+        registry.addPlugin(createRepo(new File("testdata/repo3.index.xml")));
+
+        BndEditModel runModel = new BndEditModel();
+        runModel.setRunFw("org.apache.felix.framework");
+        runModel.setEE(EE.JavaSE_1_6);
+        runModel.setSystemPackages(Collections.singletonList(new ExportedPackage("sun.reflect", new Attrs())));
+
+        BndrunResolveContext context = new BndrunResolveContext(runModel, registry, log);
+
+        Requirement req = new CapReqBuilder("osgi.wiring.package").addDirective("filter", "(osgi.wiring.package=sun.reflect)").buildSyntheticRequirement();
+        List<Capability> providers = context.findProviders(req);
+
+        assertEquals(1, providers.size());
+        assertEquals(new File("testdata/repo3/org.apache.felix.framework-4.0.2.jar").toURI(), findContentURI(providers.get(0).getResource()));
+    }
+
+    public static void testUnsatisfiedRequirement() {
+        MockRegistry registry = new MockRegistry();
+        registry.addPlugin(createRepo(new File("testdata/repo3.index.xml")));
+
+        BndEditModel runModel = new BndEditModel();
+        runModel.setRunFw("org.apache.felix.framework");
+        runModel.setEE(EE.JavaSE_1_6);
+
+        BndrunResolveContext context = new BndrunResolveContext(runModel, registry, log);
+
+        Requirement req = new CapReqBuilder("osgi.extender").addDirective("filter", "(&(osgi.extender=foobar)(version>=1.0))").buildSyntheticRequirement();
+        List<Capability> providers = context.findProviders(req);
+        assertEquals(0, providers.size());
+    }
+
+    public static void testResolveSystemCapabilitiesExtra() {
+        MockRegistry registry = new MockRegistry();
+        registry.addPlugin(createRepo(new File("testdata/repo3.index.xml")));
+
+        BndEditModel runModel = new BndEditModel();
+        runModel.setRunFw("org.apache.felix.framework");
+        runModel.setEE(EE.JavaSE_1_6);
+        runModel.genericSet("-runsystemcapabilities", "osgi.extender;osgi.extender=foobar;version:Version=1.0");
+
+        BndrunResolveContext context = new BndrunResolveContext(runModel, registry, log);
+
+        Requirement req = new CapReqBuilder("osgi.extender").addDirective("filter", "(&(osgi.extender=foobar)(version>=1.0))").buildSyntheticRequirement();
+        List<Capability> providers = context.findProviders(req);
+
+        assertEquals(1, providers.size());
+        assertEquals(new File("testdata/repo3/org.apache.felix.framework-4.0.2.jar").toURI(), findContentURI(providers.get(0).getResource()));
+    }
+
+    public static void testMacroInSystemCapability() {
+        MockRegistry registry = new MockRegistry();
+        registry.addPlugin(createRepo(new File("testdata/repo3.index.xml")));
+
+        BndEditModel runModel = new BndEditModel();
+        runModel.setRunFw("org.apache.felix.framework");
+        runModel.setEE(EE.JavaSE_1_6);
+        runModel.genericSet("-runsystemcapabilities", "${native_capability}");
+
+        String origOsName = System.getProperty("os.name");
+        String origOsVersion = System.getProperty("os.version");
+        String origOsArch = System.getProperty("os.arch");
+        try {
+            System.setProperty("os.name", "Mac OS X");
+            System.setProperty("os.version", "10.8.2");
+            System.setProperty("os.arch", "x86_64");
+
+            BndrunResolveContext context = new BndrunResolveContext(runModel, registry, log);
+            Requirement req = new CapReqBuilder("osgi.native").addDirective("filter", "(osgi.native.osname=MacOSX)").buildSyntheticRequirement();
+
+            List<Capability> providers = context.findProviders(req);
+            assertEquals(1, providers.size());
+            assertEquals(new File("testdata/repo3/org.apache.felix.framework-4.0.2.jar").toURI(), findContentURI(providers.get(0).getResource()));
+        }
+        finally {
+            System.setProperty("os.name", origOsName);
+            System.setProperty("os.version", origOsVersion);
+            System.setProperty("os.arch", origOsArch);
+        }
+
+    }
+
+}
diff --git a/biz.aQute.resolve/src/test/lib/MockRegistry.java b/biz.aQute.resolve/src/test/lib/MockRegistry.java
new file mode 100644
index 0000000..ca78aca
--- /dev/null
+++ b/biz.aQute.resolve/src/test/lib/MockRegistry.java
@@ -0,0 +1,34 @@
+package test.lib;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import aQute.bnd.service.Registry;
+
+public class MockRegistry implements Registry {
+
+    private final List<Object> plugins = new LinkedList<Object>();
+
+    public void addPlugin(Object plugin) {
+        plugins.add(plugin);
+    }
+
+    public <T> List<T> getPlugins(Class<T> clazz) {
+        List<T> l = new ArrayList<T>();
+        for (Object plugin : plugins) {
+            if (clazz.isInstance(plugin))
+                l.add(clazz.cast(plugin));
+        }
+        return l;
+    }
+
+    public <T> T getPlugin(Class<T> clazz) {
+        for (Object plugin : plugins) {
+            if (clazz.isInstance(plugin))
+                return clazz.cast(plugin);
+        }
+        return null;
+    }
+
+}
diff --git a/biz.aQute.resolve/src/test/lib/NullLogService.java b/biz.aQute.resolve/src/test/lib/NullLogService.java
new file mode 100644
index 0000000..63c953e
--- /dev/null
+++ b/biz.aQute.resolve/src/test/lib/NullLogService.java
@@ -0,0 +1,16 @@
+package test.lib;
+
+import org.osgi.framework.*;
+import org.osgi.service.log.*;
+
+public class NullLogService implements LogService {
+
+	public void log(int level, String message) {}
+
+	public void log(int level, String message, Throwable t) {}
+
+	public void log(ServiceReference sr, int level, String message) {}
+
+	public void log(ServiceReference sr, int level, String message, Throwable t) {}
+
+}
diff --git a/biz.aQute.resolve/src/test/lib/Utils.java b/biz.aQute.resolve/src/test/lib/Utils.java
new file mode 100644
index 0000000..9398bf6
--- /dev/null
+++ b/biz.aQute.resolve/src/test/lib/Utils.java
@@ -0,0 +1,54 @@
+package test.lib;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.osgi.resource.Capability;
+import org.osgi.resource.Resource;
+import org.osgi.service.repository.Repository;
+
+import aQute.bnd.deployer.repository.AbstractIndexedRepo;
+import aQute.bnd.deployer.repository.FixedIndexedRepo;
+
+public class Utils {
+
+    public static Repository createRepo(File index) {
+        return createRepo(index, null);
+    }
+
+    public static Repository createRepo(File index, String name) {
+        FixedIndexedRepo repo = new FixedIndexedRepo();
+
+        Map<String,String> props = new HashMap<String,String>();
+        props.put(FixedIndexedRepo.PROP_LOCATIONS, index.toURI().toString());
+        if (name != null)
+            props.put(AbstractIndexedRepo.PROP_NAME, name);
+        repo.setProperties(props);
+
+        return repo;
+    }
+
+    public static URI findContentURI(Resource resource) {
+        List<Capability> contentCaps = resource.getCapabilities("osgi.content");
+        if (contentCaps == null || contentCaps.isEmpty())
+            throw new IllegalArgumentException("Resource has no content capability");
+        if (contentCaps.size() > 1)
+            throw new IllegalArgumentException("Resource has more than one content capability");
+
+        Object uriObj = contentCaps.get(0).getAttributes().get("url");
+        if (uriObj == null)
+            throw new IllegalArgumentException("Resource content capability has no 'url' attribute.");
+        if (uriObj instanceof URI)
+            return (URI) uriObj;
+        else
+            try {
+                return new URI(uriObj.toString());
+            } catch (URISyntaxException e) {
+                throw new IllegalArgumentException("Resource content capability has invalid 'url' attribute.", e);
+            }
+    }
+}
diff --git a/biz.aQute.resolve/testdata/buildrepo.index.xml b/biz.aQute.resolve/testdata/buildrepo.index.xml
new file mode 100644
index 0000000..eee1046
--- /dev/null
+++ b/biz.aQute.resolve/testdata/buildrepo.index.xml
@@ -0,0 +1,238 @@
+<?xml version='1.0' encoding='utf-8'?>
+<repository increment='1342442536796' name='Untitled' xmlns='http://www.osgi.org/xmlns/repository/v1.0.0'>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='ee.minimum'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='1.2.0.200908310645'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='968e409248bec4f1fb906d6a9a8d6a2b89c8c1239f68c63564d6312fcf3f9ba0'/>
+      <attribute name='url' value='buildrepo/ee.minimum-1.2.0.jar'/>
+      <attribute name='size' type='Long' value='614671'/>
+      <attribute name='mime' value='application/vnd.osgi.bundle'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='ee.minimum'/>
+      <attribute name='bundle-version' type='Version' value='1.2.0.200908310645'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='ee.minimum'/>
+      <attribute name='bundle-version' type='Version' value='1.2.0.200908310645'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='java.security.interfaces'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <attribute name='bundle-symbolic-name' value='ee.minimum'/>
+      <attribute name='bundle-version' type='Version' value='1.2.0.200908310645'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='java.lang'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <attribute name='bundle-symbolic-name' value='ee.minimum'/>
+      <attribute name='bundle-version' type='Version' value='1.2.0.200908310645'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='java.net'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <attribute name='bundle-symbolic-name' value='ee.minimum'/>
+      <attribute name='bundle-version' type='Version' value='1.2.0.200908310645'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='java.security'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <attribute name='bundle-symbolic-name' value='ee.minimum'/>
+      <attribute name='bundle-version' type='Version' value='1.2.0.200908310645'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='java.text'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <attribute name='bundle-symbolic-name' value='ee.minimum'/>
+      <attribute name='bundle-version' type='Version' value='1.2.0.200908310645'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='java.security.spec'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <attribute name='bundle-symbolic-name' value='ee.minimum'/>
+      <attribute name='bundle-version' type='Version' value='1.2.0.200908310645'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='java.security.acl'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <attribute name='bundle-symbolic-name' value='ee.minimum'/>
+      <attribute name='bundle-version' type='Version' value='1.2.0.200908310645'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='java.lang.reflect'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <attribute name='bundle-symbolic-name' value='ee.minimum'/>
+      <attribute name='bundle-version' type='Version' value='1.2.0.200908310645'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='java.util'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <attribute name='bundle-symbolic-name' value='ee.minimum'/>
+      <attribute name='bundle-version' type='Version' value='1.2.0.200908310645'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='java.lang.ref'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <attribute name='bundle-symbolic-name' value='ee.minimum'/>
+      <attribute name='bundle-version' type='Version' value='1.2.0.200908310645'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='java.security.cert'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <attribute name='bundle-symbolic-name' value='ee.minimum'/>
+      <attribute name='bundle-version' type='Version' value='1.2.0.200908310645'/>
+      <directive name='uses' value='javax.security.auth.x500'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='java.io'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <attribute name='bundle-symbolic-name' value='ee.minimum'/>
+      <attribute name='bundle-version' type='Version' value='1.2.0.200908310645'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='java.util.zip'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <attribute name='bundle-symbolic-name' value='ee.minimum'/>
+      <attribute name='bundle-version' type='Version' value='1.2.0.200908310645'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='java.math'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <attribute name='bundle-symbolic-name' value='ee.minimum'/>
+      <attribute name='bundle-version' type='Version' value='1.2.0.200908310645'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='java.util.jar'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <attribute name='bundle-symbolic-name' value='ee.minimum'/>
+      <attribute name='bundle-version' type='Version' value='1.2.0.200908310645'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='javax.security.auth.x500'/>
+      <attribute name='version' type='Version' value='0.0.0'/>
+      <attribute name='bundle-symbolic-name' value='ee.minimum'/>
+      <attribute name='bundle-version' type='Version' value='1.2.0.200908310645'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.security.auth.x500)'/>
+    </requirement>
+    <requirement namespace='osgi.ee'>
+      <directive name='filter' value='(osgi.ee=OSGi/Minimum-1.2)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='osgi.core'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='4.2.1.201001051203'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='299c760f8614b3edd96bf6bafd9a8defad3e6dca1b68ebe44ed988291135bc6f'/>
+      <attribute name='url' value='buildrepo/osgi.core-4.2.1.jar'/>
+      <attribute name='size' type='Long' value='247375'/>
+      <attribute name='mime' value='application/vnd.osgi.bundle'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='osgi.core'/>
+      <attribute name='bundle-version' type='Version' value='4.2.1.201001051203'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='osgi.core'/>
+      <attribute name='bundle-version' type='Version' value='4.2.1.201001051203'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.hooks.service'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <attribute name='bundle-symbolic-name' value='osgi.core'/>
+      <attribute name='bundle-version' type='Version' value='4.2.1.201001051203'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework'/>
+      <attribute name='version' type='Version' value='1.5.1'/>
+      <attribute name='bundle-symbolic-name' value='osgi.core'/>
+      <attribute name='bundle-version' type='Version' value='4.2.1.201001051203'/>
+      <directive name='uses' value='javax.security.auth.x500'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.launch'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <attribute name='bundle-symbolic-name' value='osgi.core'/>
+      <attribute name='bundle-version' type='Version' value='4.2.1.201001051203'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.condpermadmin'/>
+      <attribute name='version' type='Version' value='1.1.0'/>
+      <attribute name='bundle-symbolic-name' value='osgi.core'/>
+      <attribute name='bundle-version' type='Version' value='4.2.1.201001051203'/>
+      <directive name='uses' value='org.osgi.framework,org.osgi.service.permissionadmin'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.packageadmin'/>
+      <attribute name='version' type='Version' value='1.2.0'/>
+      <attribute name='bundle-symbolic-name' value='osgi.core'/>
+      <attribute name='bundle-version' type='Version' value='4.2.1.201001051203'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.permissionadmin'/>
+      <attribute name='version' type='Version' value='1.2.0'/>
+      <attribute name='bundle-symbolic-name' value='osgi.core'/>
+      <attribute name='bundle-version' type='Version' value='4.2.1.201001051203'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.startlevel'/>
+      <attribute name='version' type='Version' value='1.1.0'/>
+      <attribute name='bundle-symbolic-name' value='osgi.core'/>
+      <attribute name='bundle-version' type='Version' value='4.2.1.201001051203'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.url'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <attribute name='bundle-symbolic-name' value='osgi.core'/>
+      <attribute name='bundle-version' type='Version' value='4.2.1.201001051203'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=javax.security.auth.x500)'/>
+      <directive name='resolution' value='optional'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))'/>
+      <directive name='resolution' value='optional'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework.hooks.service)(version>=1.0.0)(!(version>=2.0.0)))'/>
+      <directive name='resolution' value='optional'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework.launch)(version>=1.0.0)(!(version>=2.0.0)))'/>
+      <directive name='resolution' value='optional'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.condpermadmin)(version>=1.1.0)(!(version>=2.0.0)))'/>
+      <directive name='resolution' value='optional'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.packageadmin)(version>=1.2.0)(!(version>=2.0.0)))'/>
+      <directive name='resolution' value='optional'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.permissionadmin)(version>=1.2.0)(!(version>=2.0.0)))'/>
+      <directive name='resolution' value='optional'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.startlevel)(version>=1.1.0)(!(version>=2.0.0)))'/>
+      <directive name='resolution' value='optional'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.url)(version>=1.0.0)(!(version>=2.0.0)))'/>
+      <directive name='resolution' value='optional'/>
+    </requirement>
+  </resource>
+</repository>
\ No newline at end of file
diff --git a/biz.aQute.resolve/testdata/org.apache.felix.framework-4.0.0.index.xml b/biz.aQute.resolve/testdata/org.apache.felix.framework-4.0.0.index.xml
new file mode 100644
index 0000000..0c85e5e
--- /dev/null
+++ b/biz.aQute.resolve/testdata/org.apache.felix.framework-4.0.0.index.xml
@@ -0,0 +1,86 @@
+<?xml version='1.0' encoding='utf-8'?>
+<repository increment='1340619548805' name='Untitled' xmlns='http://www.osgi.org/xmlns/repository/v1.0.0'>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.felix.framework'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='4.0.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='b6c4f46b904163020d83b7198dc420b46708e26acc420937d18277c41dac0d30'/>
+      <attribute name='url' value='org.apache.felix.framework-4.0.0.jar'/>
+      <attribute name='size' type='Long' value='481210'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.felix.framework'/>
+      <attribute name='bundle-version' type='Version' value='4.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.felix.framework'/>
+      <attribute name='bundle-version' type='Version' value='4.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.startlevel'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.wiring'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.hooks.bundle'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.hooks.service'/>
+      <attribute name='version' type='Version' value='1.1.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.hooks.resolver'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework.wiring'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.launch'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework'/>
+      <attribute name='version' type='Version' value='1.6.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.hooks.weaving'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework.wiring'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.packageadmin'/>
+      <attribute name='version' type='Version' value='1.2.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.url'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.startlevel'/>
+      <attribute name='version' type='Version' value='1.1.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.util.tracker'/>
+      <attribute name='version' type='Version' value='1.5.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.contract'>
+      <attribute name='osgi.contract' value='OSGiFramework'/>
+      <attribute name='version' type='Version' value='4.3.0'/>
+      <directive name='uses' value='org.osgi.framework.startlevel,org.osgi.framework.wiring,org.osgi.framework.hooks.bundle,org.osgi.framework.hooks.service,org.osgi.framework.hooks.resolver,org.osgi.framework.launch,org.osgi.framework,org.osgi.framework.hooks.weaving,org.osgi.service.packageadmin,org.osgi.service.url,org.osgi.service.startlevel,org.osgi.util.tracker'/>
+    </capability>
+  </resource>
+</repository>
\ No newline at end of file
diff --git a/biz.aQute.resolve/testdata/org.apache.felix.framework-4.0.2.index.xml b/biz.aQute.resolve/testdata/org.apache.felix.framework-4.0.2.index.xml
new file mode 100644
index 0000000..bd69874
--- /dev/null
+++ b/biz.aQute.resolve/testdata/org.apache.felix.framework-4.0.2.index.xml
@@ -0,0 +1,86 @@
+<?xml version='1.0' encoding='utf-8'?>
+<repository increment='1340617470115' name='Untitled' xmlns='http://www.osgi.org/xmlns/repository/v1.0.0'>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.felix.framework'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='4.0.2'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='81648ff4e35616daffc6015271879611509620f716185dc510194fcd114cfdf2'/>
+      <attribute name='url' value='org.apache.felix.framework-4.0.2.jar'/>
+      <attribute name='size' type='Long' value='480883'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.felix.framework'/>
+      <attribute name='bundle-version' type='Version' value='4.0.2'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.felix.framework'/>
+      <attribute name='bundle-version' type='Version' value='4.0.2'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.startlevel'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.wiring'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.hooks.bundle'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.hooks.service'/>
+      <attribute name='version' type='Version' value='1.1.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.hooks.resolver'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework.wiring'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.launch'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework'/>
+      <attribute name='version' type='Version' value='1.6.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.hooks.weaving'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework.wiring'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.packageadmin'/>
+      <attribute name='version' type='Version' value='1.2.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.url'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.startlevel'/>
+      <attribute name='version' type='Version' value='1.1.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.util.tracker'/>
+      <attribute name='version' type='Version' value='1.5.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.contract'>
+      <attribute name='osgi.contract' value='OSGiFramework'/>
+      <attribute name='version' type='Version' value='4.3.0'/>
+      <directive name='uses' value='org.osgi.framework.startlevel,org.osgi.framework.wiring,org.osgi.framework.hooks.bundle,org.osgi.framework.hooks.service,org.osgi.framework.hooks.resolver,org.osgi.framework.launch,org.osgi.framework,org.osgi.framework.hooks.weaving,org.osgi.service.packageadmin,org.osgi.service.url,org.osgi.service.startlevel,org.osgi.util.tracker'/>
+    </capability>
+  </resource>
+</repository>
\ No newline at end of file
diff --git a/biz.aQute.resolve/testdata/osgi.cmpn-4.3.0.index.xml b/biz.aQute.resolve/testdata/osgi.cmpn-4.3.0.index.xml
new file mode 100644
index 0000000..81f7d16
--- /dev/null
+++ b/biz.aQute.resolve/testdata/osgi.cmpn-4.3.0.index.xml
@@ -0,0 +1,226 @@
+<?xml version='1.0' encoding='utf-8'?>
+<repository increment='1340592124276' name='Untitled' xmlns='http://www.osgi.org/xmlns/repository/v1.0.0'>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='osgi.cmpn'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='4.3.0.201111022214'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='c67983657d1234e00bf25852afd075b1386e243fd8286db0ca0ab3f985747880'/>
+      <attribute name='url' value='osgi.cmpn-4.3.0.jar'/>
+      <attribute name='size' type='Long' value='742902'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='osgi.cmpn'/>
+      <attribute name='bundle-version' type='Version' value='4.3.0.201111022214'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='osgi.cmpn'/>
+      <attribute name='bundle-version' type='Version' value='4.3.0.201111022214'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.application'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.application'/>
+      <attribute name='version' type='Version' value='1.1.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.blueprint.reflect'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.blueprint.container'/>
+      <attribute name='version' type='Version' value='1.0.2'/>
+      <directive name='uses' value='org.osgi.service.blueprint.reflect,org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.cm'/>
+      <attribute name='version' type='Version' value='1.4.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.component'/>
+      <attribute name='version' type='Version' value='1.2.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.component.annotations'/>
+      <attribute name='version' type='Version' value='1.2.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.coordinator'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.deploymentadmin'/>
+      <attribute name='version' type='Version' value='1.1.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.deploymentadmin.spi'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+      <directive name='uses' value='org.osgi.framework,org.osgi.service.deploymentadmin'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.device'/>
+      <attribute name='version' type='Version' value='1.1.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.dmt.notification'/>
+      <attribute name='version' type='Version' value='2.0.0'/>
+      <directive name='uses' value='org.osgi.service.dmt'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.dmt'/>
+      <attribute name='version' type='Version' value='2.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.dmt.security'/>
+      <attribute name='version' type='Version' value='2.0.0'/>
+      <directive name='uses' value='org.osgi.service.dmt'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.dmt.spi'/>
+      <attribute name='version' type='Version' value='2.0.0'/>
+      <directive name='uses' value='org.osgi.service.dmt'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.dmt.notification.spi'/>
+      <attribute name='version' type='Version' value='2.0.0'/>
+      <directive name='uses' value='org.osgi.service.dmt.notification'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.event'/>
+      <attribute name='version' type='Version' value='1.3.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.http'/>
+      <attribute name='version' type='Version' value='1.2.1'/>
+      <directive name='uses' value='javax.servlet.http,javax.servlet'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.io'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='javax.microedition.io'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.jdbc'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='javax.sql'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.jndi'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='javax.naming.directory,javax.naming'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.jpa'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='javax.persistence'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.log'/>
+      <attribute name='version' type='Version' value='1.3.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.metatype'/>
+      <attribute name='version' type='Version' value='1.2.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.monitor'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.prefs'/>
+      <attribute name='version' type='Version' value='1.1.1'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.provisioning'/>
+      <attribute name='version' type='Version' value='1.2.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.remoteserviceadmin'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.upnp'/>
+      <attribute name='version' type='Version' value='1.2.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.useradmin'/>
+      <attribute name='version' type='Version' value='1.1.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.wireadmin'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.util.measurement'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.util.position'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+      <directive name='uses' value='org.osgi.util.measurement'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.util.tracker'/>
+      <attribute name='version' type='Version' value='1.5.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.util.xml'/>
+      <attribute name='version' type='Version' value='1.0.1'/>
+      <directive name='uses' value='org.osgi.framework,javax.xml.parsers'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.microedition.io)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.naming)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.naming.directory)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.persistence)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.servlet)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.servlet.http)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.sql)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=javax.xml.parsers)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.framework)'/>
+    </requirement>
+  </resource>
+</repository>
\ No newline at end of file
diff --git a/biz.aQute.resolve/testdata/readme.txt b/biz.aQute.resolve/testdata/readme.txt
new file mode 100644
index 0000000..653114c
--- /dev/null
+++ b/biz.aQute.resolve/testdata/readme.txt
@@ -0,0 +1,3 @@
+Eventually all these bundle JARs can be deleted, as we're only interested in
+the indexes. However it's useful to keep them around for now, in case the
+indexes need to be recalculated.
\ No newline at end of file
diff --git a/biz.aQute.resolve/testdata/repo1.index.xml b/biz.aQute.resolve/testdata/repo1.index.xml
new file mode 100644
index 0000000..679e3aa
--- /dev/null
+++ b/biz.aQute.resolve/testdata/repo1.index.xml
@@ -0,0 +1,61 @@
+<?xml version='1.0' encoding='utf-8'?>
+<repository increment='1340538848427' name='Untitled' xmlns='http://www.osgi.org/xmlns/repository/v1.0.0'>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.felix.gogo.runtime'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='15e94961ae2d0046278686965fe6a34ad43d8d18719f5bc2304e725cdb57a379'/>
+      <attribute name='url' value='repo1/org.apache.felix.gogo.runtime-0.10.0.jar'/>
+      <attribute name='size' type='Long' value='66965'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.felix.gogo.runtime'/>
+      <attribute name='bundle-version' type='Version' value='0.10.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.felix.gogo.runtime'/>
+      <attribute name='bundle-version' type='Version' value='0.10.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <attribute name='osgi.wiring.package' value='org.apache.felix.service.command'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+      <directive name='mandatory' value='status'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.felix.gogo.api'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+      <directive name='uses' value='org.apache.felix.service.command'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <attribute name='osgi.wiring.package' value='org.apache.felix.service.threadio'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+      <directive name='mandatory' value='status'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.gogo.api)(version>=0.10.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.service.command)(version>=0.10.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.service.threadio)(version>=0.10.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.framework)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.service.event)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.util.tracker)'/>
+    </requirement>
+  </resource>
+</repository>
\ No newline at end of file
diff --git a/biz.aQute.resolve/testdata/repo2.index.xml b/biz.aQute.resolve/testdata/repo2.index.xml
new file mode 100644
index 0000000..2d05aee
--- /dev/null
+++ b/biz.aQute.resolve/testdata/repo2.index.xml
@@ -0,0 +1,61 @@
+<?xml version='1.0' encoding='utf-8'?>
+<repository increment='1340538854907' name='Untitled' xmlns='http://www.osgi.org/xmlns/repository/v1.0.0'>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.felix.gogo.runtime'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='15e94961ae2d0046278686965fe6a34ad43d8d18719f5bc2304e725cdb57a379'/>
+      <attribute name='url' value='repo2/org.apache.felix.gogo.runtime-0.10.0.jar'/>
+      <attribute name='size' type='Long' value='66965'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.felix.gogo.runtime'/>
+      <attribute name='bundle-version' type='Version' value='0.10.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.felix.gogo.runtime'/>
+      <attribute name='bundle-version' type='Version' value='0.10.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <attribute name='osgi.wiring.package' value='org.apache.felix.service.command'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+      <directive name='mandatory' value='status'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.felix.gogo.api'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+      <directive name='uses' value='org.apache.felix.service.command'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <attribute name='osgi.wiring.package' value='org.apache.felix.service.threadio'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+      <directive name='mandatory' value='status'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.gogo.api)(version>=0.10.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.service.command)(version>=0.10.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.service.threadio)(version>=0.10.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.framework)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.service.event)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.util.tracker)'/>
+    </requirement>
+  </resource>
+</repository>
\ No newline at end of file
diff --git a/biz.aQute.resolve/testdata/repo3.index.xml b/biz.aQute.resolve/testdata/repo3.index.xml
new file mode 100644
index 0000000..bbcc332
--- /dev/null
+++ b/biz.aQute.resolve/testdata/repo3.index.xml
@@ -0,0 +1,225 @@
+<?xml version='1.0' encoding='utf-8'?>
+<repository increment='1340620345555' name='Untitled' xmlns='http://www.osgi.org/xmlns/repository/v1.0.0'>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.felix.gogo.command'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.12.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='5799c75d81dd5682ff79f3e440b9ba77c5511fe683b5b7d5a322059ce4d39800'/>
+      <attribute name='url' value='repo3/org.apache.felix.gogo.command-0.12.0.jar'/>
+      <attribute name='size' type='Long' value='51746'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.felix.gogo.command'/>
+      <attribute name='bundle-version' type='Version' value='0.12.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.felix.gogo.command'/>
+      <attribute name='bundle-version' type='Version' value='0.12.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.log'/>
+      <attribute name='version' type='Version' value='1.3.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.service.command)(version>=0.10.0)(!(version>=1.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework)(version>=1.5.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.framework.wiring)(version>=1.0.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.log)(version>=1.3.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.packageadmin)(version>=1.2.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.service.startlevel)(version>=1.1.0)(!(version>=2.0.0)))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.osgi.util.tracker)(version>=1.3.0)(!(version>=2.0.0)))'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.felix.framework'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='4.0.2'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='81648ff4e35616daffc6015271879611509620f716185dc510194fcd114cfdf2'/>
+      <attribute name='url' value='repo3/org.apache.felix.framework-4.0.2.jar'/>
+      <attribute name='size' type='Long' value='480883'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.felix.framework'/>
+      <attribute name='bundle-version' type='Version' value='4.0.2'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.felix.framework'/>
+      <attribute name='bundle-version' type='Version' value='4.0.2'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.startlevel'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.wiring'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.hooks.bundle'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.hooks.service'/>
+      <attribute name='version' type='Version' value='1.1.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.hooks.resolver'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework.wiring'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.launch'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework'/>
+      <attribute name='version' type='Version' value='1.6.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.hooks.weaving'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework.wiring'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.packageadmin'/>
+      <attribute name='version' type='Version' value='1.2.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.url'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.startlevel'/>
+      <attribute name='version' type='Version' value='1.1.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.util.tracker'/>
+      <attribute name='version' type='Version' value='1.5.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.contract'>
+      <attribute name='osgi.contract' value='OSGiFramework'/>
+      <attribute name='version' type='Version' value='4.3.0'/>
+      <directive name='uses' value='org.osgi.framework.startlevel,org.osgi.framework.wiring,org.osgi.framework.hooks.bundle,org.osgi.framework.hooks.service,org.osgi.framework.hooks.resolver,org.osgi.framework.launch,org.osgi.framework,org.osgi.framework.hooks.weaving,org.osgi.service.packageadmin,org.osgi.service.url,org.osgi.service.startlevel,org.osgi.util.tracker'/>
+    </capability>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.felix.gogo.shell'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='5a625f772d7c03443229d9a1e9f9b851892ee363c2e88ef1d5b55ed0979431a2'/>
+      <attribute name='url' value='repo3/org.apache.felix.gogo.shell-0.10.0.jar'/>
+      <attribute name='size' type='Long' value='49004'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.felix.gogo.shell'/>
+      <attribute name='bundle-version' type='Version' value='0.10.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.felix.gogo.shell'/>
+      <attribute name='bundle-version' type='Version' value='0.10.0'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.service.command)(version>=0.10.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.framework)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.service.startlevel)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.util.tracker)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.felix.gogo.runtime'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='15e94961ae2d0046278686965fe6a34ad43d8d18719f5bc2304e725cdb57a379'/>
+      <attribute name='url' value='repo3/org.apache.felix.gogo.runtime-0.10.0.jar'/>
+      <attribute name='size' type='Long' value='66965'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.felix.gogo.runtime'/>
+      <attribute name='bundle-version' type='Version' value='0.10.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.felix.gogo.runtime'/>
+      <attribute name='bundle-version' type='Version' value='0.10.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <attribute name='osgi.wiring.package' value='org.apache.felix.service.command'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+      <directive name='mandatory' value='status'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.felix.gogo.api'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+      <directive name='uses' value='org.apache.felix.service.command'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <attribute name='osgi.wiring.package' value='org.apache.felix.service.threadio'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+      <directive name='mandatory' value='status'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.gogo.api)(version>=0.10.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.service.command)(version>=0.10.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.service.threadio)(version>=0.10.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.framework)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.service.event)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.util.tracker)'/>
+    </requirement>
+  </resource>
+</repository>
\ No newline at end of file
diff --git a/biz.aQute.resolve/testdata/repo4.index.xml b/biz.aQute.resolve/testdata/repo4.index.xml
new file mode 100644
index 0000000..81192a2
--- /dev/null
+++ b/biz.aQute.resolve/testdata/repo4.index.xml
@@ -0,0 +1,163 @@
+<?xml version='1.0' encoding='utf-8'?>
+<repository increment='1340620345555' name='Untitled' xmlns='http://www.osgi.org/xmlns/repository/v1.0.0'>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.felix.framework'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='4.0.2'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='81648ff4e35616daffc6015271879611509620f716185dc510194fcd114cfdf2'/>
+      <attribute name='url' value='repo3/org.apache.felix.framework-4.0.2.jar'/>
+      <attribute name='size' type='Long' value='480883'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.felix.framework'/>
+      <attribute name='bundle-version' type='Version' value='4.0.2'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.felix.framework'/>
+      <attribute name='bundle-version' type='Version' value='4.0.2'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.startlevel'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.wiring'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.hooks.bundle'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.hooks.service'/>
+      <attribute name='version' type='Version' value='1.1.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.hooks.resolver'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework.wiring'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.launch'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework'/>
+      <attribute name='version' type='Version' value='1.6.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.framework.hooks.weaving'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+      <directive name='uses' value='org.osgi.framework.wiring'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.packageadmin'/>
+      <attribute name='version' type='Version' value='1.2.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.url'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.service.startlevel'/>
+      <attribute name='version' type='Version' value='1.1.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.osgi.util.tracker'/>
+      <attribute name='version' type='Version' value='1.5.0'/>
+      <directive name='uses' value='org.osgi.framework'/>
+    </capability>
+    <capability namespace='osgi.contract'>
+      <attribute name='osgi.contract' value='OSGiFramework'/>
+      <attribute name='version' type='Version' value='4.3.0'/>
+      <directive name='uses' value='org.osgi.framework.startlevel,org.osgi.framework.wiring,org.osgi.framework.hooks.bundle,org.osgi.framework.hooks.service,org.osgi.framework.hooks.resolver,org.osgi.framework.launch,org.osgi.framework,org.osgi.framework.hooks.weaving,org.osgi.service.packageadmin,org.osgi.service.url,org.osgi.service.startlevel,org.osgi.util.tracker'/>
+    </capability>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='org.apache.felix.gogo.runtime'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='15e94961ae2d0046278686965fe6a34ad43d8d18719f5bc2304e725cdb57a379'/>
+      <attribute name='url' value='repo3/org.apache.felix.gogo.runtime-0.10.0.jar'/>
+      <attribute name='size' type='Long' value='66965'/>
+    </capability>
+    <capability namespace='osgi.wiring.bundle'>
+      <attribute name='osgi.wiring.bundle' value='org.apache.felix.gogo.runtime'/>
+      <attribute name='bundle-version' type='Version' value='0.10.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.host'>
+      <attribute name='osgi.wiring.host' value='org.apache.felix.gogo.runtime'/>
+      <attribute name='bundle-version' type='Version' value='0.10.0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <attribute name='osgi.wiring.package' value='org.apache.felix.service.command'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+      <directive name='mandatory' value='status'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.felix.gogo.api'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+      <directive name='uses' value='org.apache.felix.service.command'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <attribute name='osgi.wiring.package' value='org.apache.felix.service.threadio'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+      <directive name='mandatory' value='status'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.gogo.api)(version>=0.10.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.service.command)(version>=0.10.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <attribute name='status' value='provisional'/>
+      <directive name='filter' value='(&(osgi.wiring.package=org.apache.felix.service.threadio)(version>=0.10.0))'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.framework)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='resolution' value='optional'/>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.service.event)'/>
+    </requirement>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.osgi.util.tracker)'/>
+    </requirement>
+  </resource>
+  <resource>
+    <capability namespace='osgi.identity'>
+      <attribute name='osgi.identity' value='dummy-selfcap'/>
+      <attribute name='type' value='osgi.bundle'/>
+      <attribute name='version' type='Version' value='1.0.0'/>
+    </capability>
+    <capability namespace='osgi.content'>
+      <attribute name='osgi.content' value='dummy'/>
+      <attribute name='url' value='repo4/dummy.jar'/>
+      <attribute name='size' type='Long' value='0'/>
+    </capability>
+    <capability namespace='osgi.wiring.package'>
+      <attribute name='osgi.wiring.package' value='org.apache.felix.gogo.api'/>
+      <attribute name='version' type='Version' value='0.10.0'/>
+    </capability>
+    <requirement namespace='osgi.wiring.package'>
+      <directive name='filter' value='(osgi.wiring.package=org.apache.felix.gogo.api)'/>
+    </requirement>
+  </resource>`
+</repository>
\ No newline at end of file
diff --git a/build.xml b/build.xml
index 0546076..9abfa87 100644
--- a/build.xml
+++ b/build.xml
@@ -1,25 +1,36 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<project name="project" default="build"> 
-
+<project name="project" default="build">
 	<macrodef name="iterate">
-                <attribute name="target"/>
-                <sequential>
-                    <subant target="@{target}">
-                        <fileset dir="." includes="*/build.xml" excludes="cnf/*"/>
-                    </subant>
-                </sequential>
-        </macrodef>
-
-        <target name="build">
-                <ant dir="biz.aQute.bnd" target="build"/>
-        </target>
-
-
+		<attribute name="target" />
+		<sequential>
+			<subant target="@{target}">
+				<fileset dir="." includes="*/build.xml" excludes="cnf/*" />
+			</subant>
+		</sequential>
+	</macrodef>
+	<target name="build">
+		<ant dir="biz.aQute.bnd" target="build" />
+		<ant dir="biz.aQute.repository" target="build" />
+		<ant dir="biz.aQute.resolve" target="build" />
+	</target>
+	<target name="dist" >
+		<ant dir="dist" target="release" />
+	</target>
+	<target name="release">
+		<ant dir="biz.aQute.bnd" target="release" />
+		<ant dir="biz.aQute.repository" target="release" />
+		<ant dir="biz.aQute.resolve" target="release" />
+	</target>
 	<target name="clean">
-		<iterate target="clean"/>
+		<iterate target="clean" />
 	</target>
-
 	<target name="junit">
-		<iterate target="junit"/>
+		<iterate target="junit" />
+	</target>
+	<target name="findbugs-prepare">
+		<exec dir="." executable="./cnf/scripts/fb_generate_includes.bash" osfamily="unix" />
+	</target>
+	<target name="findbugs">
+		<iterate target="findbugs" />
 	</target>
 </project>
diff --git a/cnf/build.bnd b/cnf/build.bnd
index 4fa0d29..79189ef 100644
--- a/cnf/build.bnd
+++ b/cnf/build.bnd
@@ -1,6 +1,6 @@
 # We use git
-Git-Descriptor: ${system;git describe --dirty --always}
-Git-SHA: ${system;git rev-list -1 HEAD}
+Git-Descriptor: ${system-allow-fail;git describe --dirty --always}
+Git-SHA: ${system-allow-fail;git rev-list -1 HEAD}
 
 Bundle-SCM				= git://github.com/bndtools/bnd.git
 
@@ -20,8 +20,8 @@ bin                     = bin
 target					= ${project}/${target-dir}
 build					= ${workspace}/cnf
 repo					= ${build}/repo
-releaserepo				= ${workspace}/../repo/bundles
-target-dir				= tmp
+releaserepo				= ${workspace}/dist/bundles
+target-dir				= generated
 p                       = ${basename;${project}}
 project.name            = ${p}
 
@@ -31,6 +31,7 @@ javac 					= javac
 javac.debug				= on
 javac.source 			= 1.5
 javac.target 			= 1.5
+javac.ee				= '[1.5,1.6)'
 
 # default version policies
 #   -provider-policy =  ${range;[==,=+)}
@@ -42,7 +43,8 @@ javac.target 			= 1.5
 
 -plugin	            	= \
 	aQute.lib.deployer.FileRepo;name='Main';location=${repo},\
-	aQute.lib.deployer.FileRepo;name='Release';location=${releaserepo}
+	aQute.lib.deployer.FileRepo;name='Release';location=${releaserepo}, 
+	aQute.bnd.signer.JartoolSigner
 	
 -releaserepo: Release
   						  
@@ -56,9 +58,9 @@ copyright.html = Copyright © aQute (2000, ${tstamp;yyyy}). All Rights Reser
 
 # Documentation
 Bundle-Vendor: 					aQute SARL http://www.aQute.biz
-Bundle-Copyright:				All files contained in this JAR are licensed under the Apache 2.0 license, unless noted differently in their source (see swing2swt).
+Bundle-Copyright:				${copyright}
 Bundle-License: 				http://www.opensource.org/licenses/apache2.0.php; \
-									description="${Bundle-Copyright}"; \
+									description="Apache 2.0 Licensed"; \
 									link=LICENSE
 -removeheader			= Include-Resource
 
diff --git a/cnf/build.xml b/cnf/build.xml
index b75ab68..87d9b4e 100644
--- a/cnf/build.xml
+++ b/cnf/build.xml
@@ -1,10 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--
-	The is main OSGi build file. It is included from projects
-	as is.
-	
-	It is described in http://www2.osgi.org/members/Build/HomePage 
--->
 <project name="master" default="none">
 
 	<!-- 
@@ -15,15 +9,45 @@
 	-->
 
 	<target name="init" unless="initialized">
+		<tstamp>
+			<format property="NOW" pattern="yyyyMMdd-HHmmss" timezone="UTC" />
+		</tstamp>
+
 		<dirname property="projectdir" file="${ant.file}" />
 		<dirname property="workspacedir" file="${projectdir}" />
-		<taskdef resource="aQute/bnd/ant/taskdef.properties" classpath="${workspacedir}/aQute.libg/bin;${workspacedir}/biz.aQute.bndlib/bin:${workspacedir}/cnf/repo/biz.aQute.bnd/biz.aQute.bnd-latest.jar" />
+		<taskdef resource="aQute/bnd/ant/taskdef.properties">
+			<classpath>
+				<path location="${workspacedir}/cnf/repo/biz.aQute.bnd/biz.aQute.bnd-latest.jar" />
+			</classpath>
+		</taskdef>
 
 		<bndprepare basedir="${projectdir}" print="false" top="${release.dir}" />
 
+		<taskdef resource="net/sf/antcontrib/antlib.xml">
+			<classpath>
+				<pathelement location="${workspacedir}/cnf/ant-contrib/ant-contrib-1.0b3.jar" />
+			</classpath>
+		</taskdef>
+
+		<taskdef name="findbugs" classname="edu.umd.cs.findbugs.anttask.FindBugsTask">
+			<classpath>
+				<fileset dir="${workspacedir}/cnf/findbugs/lib">
+					<include name="**/*.jar" />
+				</fileset>
+			</classpath>
+		</taskdef>
+
+		<taskdef name="bindex" classname="org.osgi.impl.bundle.bindex.ant.BindexTask">
+			<classpath>
+				<pathelement location="${workspacedir}/cnf/repo/org.osgi.impl.bundle.bindex/org.osgi.impl.bundle.bindex-2.2.0.jar" />
+			</classpath>
+		</taskdef>
+		
+		<taskdef resource="taskdef.properties" classpath="${workspacedir}/cnf/repo/org.osgi.impl.bundle.repoindex.ant/org.osgi.impl.bundle.repoindex.ant-latest.jar"/>
+
 		<!-- mark init has been run -->
 		<property name="initialized" value="set" />
-		<echo>Enter project ${project.name}</echo>
+		<echo message="Enter project ${project.name}" />
 	</target>
 
 	<!-- 
@@ -38,6 +62,8 @@
 
 	<!--
 	     Test
+	     
+	     These are the OSGi tests.
 	-->
 	<target name="test" depends="compile">
 		<bnd command="test" exceptions="true" basedir="${project}" />
@@ -63,50 +89,81 @@
 		</copy>
 	</target>
 
-	<target name="deploy" depends="build">
-		<bnd command="deploy" exceptions="true" basedir="${project}" />
-	</target>
 	<!-- 
-		JARS
-		Iterate of the jars to build.
+		build
+		
+		Use bnd to build this project. Assumption is that any projects that
+		this project depends on are already build. See dependencies.
 	-->
 	<target name="build" depends="compile">
-		<bnd command="build" trace="true" exceptions="true" basedir="${project}" />
+		<mkdir dir="${target}" />
+		<bnd command="build" exceptions="true" basedir="${project}" />
 	</target>
 
-	<target name="junit" depends="build">
+	<!--
+		Release
 		
+		First release all dependents (set in bnd.bnd -dependson) and then
+		create an index. 
+	-->
+	<target name="_release" depends="init">
+		<bnd command="release" exceptions="true" basedir="${project}" />
+	</target>
+
+	<target name="release" depends="build">
+		<subant target="_release" inheritAll="false" buildpath="${project.dependson}">
+			<property name="donotrecurse" value="true" />
+		</subant>
+		<bindex repositoryfile="bundles/repository.xml" root="bundles" quiet="true">
+			<fileset dir="bundles" includes="**/*.jar" />
+		</bindex>
+		<repoindex out="${releaserepo}/index.xml" rooturl="${releaserepo}" name="bnd" pretty="true">
+			<fileset dir="bundles" includes="**/*.jar" excludes="**/*-latest.jar"/>
+		</repoindex>
+	</target>
+
+	<!--
+		Junit
+		
+		Run all the tests. If the -nojunit property is set then this project
+		cannot run junit tests and they should not be run. These are normal
+		junit tests, not OSGi junit tests.
+	-->
+	<target name="junit" depends="build" unless="no.junit">
 		<junit showoutput="false" printsummary="true" failureproperty='stop' errorproperty='stop' fork="true" dir="${basedir}">
 			<classpath path="${project.buildpath}" />
 			<formatter type="xml" />
-			<batchtest todir="tmp">
+			<batchtest todir="${target}">
 				<fileset dir="${src}">
 					<include name="test/**.java" />
 				</fileset>
 			</batchtest>
 		</junit>
-
-		<fail if="stop" />
-	</target>
-
-	<target name="release" depends="build">
-		<subant target="release" inheritall="false" buildpath="${project.dependson}">
-			<property name="donotrecurse" value="true" />
-		</subant>
-		<bnd command="release" exceptions="true" basedir="${project}" />
 	</target>
 
-	<target name="release.bindex" depends="release">
-		<echo message="bindex classpath: ${workspacedir}/cnf/repo/org.osgi.impl.bundle.bindex/org.osgi.impl.bundle.bindex-2.2.0.jar" />
-		<taskdef name="bindex" classname="org.osgi.impl.bundle.bindex.ant.BindexTask">
-			<classpath>
-				<fileset dir="${workspacedir}/cnf/repo/org.osgi.impl.bundle.bindex" includes="org.osgi.impl.bundle.bindex-2.2.0.jar" />
-			</classpath>
-		</taskdef>
-
-		<bindex root="${releaserepo}" repositoryfile="${releaserepo}/repository.xml" quiet="yes">
-			<fileset dir="${releaserepo}" includes="**/*.jar" />
-		</bindex>
+	<target name="findbugs" depends="init,build">
+		<property name="project.bootclasspath.adjusted" value="${project.bootclasspath}" />
+		<property name="project.buildpath.adjusted" value="${project.buildpath}" />
+		<property name="project.testpath.adjusted" value="${project.testpath}" />
+
+		<!-- filter out some jars and directories -->
+		<for list="[^:]+/ee\.j2se-[0-9\.]+\.jar#${project.output}#^:+#:+$" delimiter="#" param="regex">
+			<sequential>
+				<propertyregex property="project.bootclasspath.adjusted" input="${project.bootclasspath.adjusted}" defaultValue="${project.bootclasspath.adjusted}" regexp="@{regex}" replace="" override="true" global="yes" />
+				<propertyregex property="project.buildpath.adjusted" input="${project.buildpath.adjusted}" defaultValue="${project.buildpath.adjusted}" regexp="@{regex}" replace="" override="true" global="yes" />
+				<propertyregex property="project.testpath.adjusted" input="${project.testpath.adjusted}" defaultValue="${project.testpath.adjusted}" regexp="@{regex}" replace="" override="true" global="yes" />
+			</sequential>
+		</for>
+		<!-- fixups -->
+		<propertyregex property="project.bootclasspath.adjusted" input="${project.bootclasspath.adjusted}" defaultValue="${project.bootclasspath.adjusted}" regexp=":+" replace=":" override="true" global="yes" />
+		<propertyregex property="project.buildpath.adjusted" input="${project.buildpath.adjusted}" defaultValue="${project.buildpath.adjusted}" regexp=":+" replace=":" override="true" global="yes" />
+		<propertyregex property="project.testpath.adjusted" input="${project.testpath.adjusted}" defaultValue="${project.testpath.adjusted}" regexp=":+" replace=":" override="true" global="yes" />
+
+		<findbugs home="${workspacedir}/cnf/findbugs" includeFilter="${workspacedir}/cnf/findbugs.include.xml" excludeFilter="${workspacedir}/cnf/findbugs.exclude.xml" output="xml:withMessages" outputFile="${target}/${project.name}.findbugs.xml">
+			<sourcePath path="${project.sourcepath}" />
+			<auxClasspath path="${project.bootclasspath.adjusted}:${project.buildpath.adjusted}:${project.testpath.adjusted}" />
+			<class location="${target}" />
+		</findbugs>
 	</target>
 
 	<!--
@@ -117,8 +174,13 @@
 	</target>
 
 	<target name="clean" depends="init">
-		<delete dir="${project.output}" />
 		<bnd command="clean" exceptions="true" basedir="${project}" />
+		<delete dir="bin" />
+		<delete dir="bin_test" />
+		<delete dir="${target}" />
+
+		<delete dir="${workspacedir}/cnf/tmp" />
+		<delete dir="${workspacedir}/cnf/p2target" />
 	</target>
 
 	<!--
@@ -127,6 +189,7 @@
 	<target name="echo" depends="init">
 		<echo>verbose:                ${verbose}</echo>
 		<echo>project.name:           ${project.name}</echo>
+		<echo>Bundle-Version:         ${Bundle-Version}</echo>
 		<echo>project.output:         ${project.output}</echo>
 		<echo>project.sourcepath:     ${project.sourcepath}</echo>
 		<echo>project.allsourcepath:  ${project.allsourcepath}</echo>
@@ -135,6 +198,10 @@
 		<echo>project.dependson:      ${project.dependson}</echo>
 		<echo>project.bootclasspath:  ${project.bootclasspath}</echo>
 		<echo>javac:                  ${javac}</echo>
+		<echo>javac.debug:            ${javac.debug}</echo>
+		<echo>javac.source:           ${javac.source}</echo>
+		<echo>javac.target:           ${javac.target}</echo>
+		<echo>javac.ee:               ${javac.ee}</echo>
 		<echo>p:                      ${p}</echo>
 		<echo>btool.manifestVersion:  ${btool.manifestVersion}</echo>
 		<echo>btool.analyse:          ${btool.analyse}</echo>
diff --git a/cnf/eclipse/bnd(tools).importorder b/cnf/eclipse/bnd(tools).importorder
new file mode 100644
index 0000000..0ae1280
--- /dev/null
+++ b/cnf/eclipse/bnd(tools).importorder
@@ -0,0 +1,6 @@
+#Organize Import Order
+#Wed Jun 13 16:46:24 CEST 2012
+3=com
+2=org
+1=javax
+0=java
diff --git a/cnf/eclipse/codeformatter.xml b/cnf/eclipse/codeformatter.xml
new file mode 100644
index 0000000..1bf02f3
--- /dev/null
+++ b/cnf/eclipse/codeformatter.xml
@@ -0,0 +1,579 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<profiles version="12">
+<profile kind="CodeFormatterProfile" name="bnd(tools)" version="12">
+<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
+<setting id="org.eclipse.jdt.core.compiler.source" value="1.5"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
+<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
+<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.5"/>
+<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.5"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
+</profile>
+<profile kind="CodeFormatterProfile" name="Test" version="12">
+<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
+<setting id="org.eclipse.jdt.core.compiler.source" value="1.5"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
+<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
+<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.5"/>
+<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.5"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
+</profile>
+</profiles>
diff --git a/cnf/findbugs.exclude.xml b/cnf/findbugs.exclude.xml
new file mode 100644
index 0000000..ab48833
--- /dev/null
+++ b/cnf/findbugs.exclude.xml
@@ -0,0 +1,25 @@
+<FindBugsFilter>
+	<!-- ignore all of these -->
+	<Match>
+		<Bug pattern="VA_FORMAT_STRING_USES_NEWLINE" />
+	</Match>
+
+	<!-- some hard coded paths seem to be needed -->
+	<Match>
+		<Class name="~aQute\.jpm\.platform\.(MacOS|Unix)" />
+		<Method name="getGlobal" />
+		<Bug pattern="DMI_HARDCODED_ABSOLUTE_FILENAME" />
+	</Match>
+
+	<!-- these use System.out directly -->
+	<Match>
+		<Class name="aQute.bnd.main.DiffCommand" />
+		<Method name="diff" />
+		<Bug pattern="DM_DEFAULT_ENCODING" />
+	</Match>
+	<Match>
+		<Class name="aQute.bnd.main.DiffCommand" />
+		<Method name="showTree" />
+		<Bug pattern="DM_DEFAULT_ENCODING" />
+	</Match>
+</FindBugsFilter>
diff --git a/cnf/findbugs.include.xml b/cnf/findbugs.include.xml
new file mode 100644
index 0000000..b5d200d
--- /dev/null
+++ b/cnf/findbugs.include.xml
@@ -0,0 +1,512 @@
+<FindBugsFilter>
+     <Match>
+       <Package name="aQute.bnd.annotation" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.annotation.component" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.annotation.metatype" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.ant" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.build" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.build.model" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.build.model.clauses" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.build.model.conversions" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.compatibility" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.component" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.deployer" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.deployer.http" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.deployer.obr" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.deployer.repository" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.deployer.repository.api" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.deployer.repository.providers" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.differ" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.filerepo" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.header" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.help" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.main" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.make" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.make.calltree" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.make.component" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.make.coverage" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.make.metatype" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.maven" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.maven.support" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.obr" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.osgi" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.osgi.eclipse" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.osgi.resource" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.properties" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.service" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.service.action" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.service.diff" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.service.repository" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.service.url" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.signing" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.test" />
+     </Match>
+     <Match>
+       <Package name="aQute.bnd.version" />
+     </Match>
+     <Match>
+       <Package name="aQute.configurable" />
+     </Match>
+     <Match>
+       <Package name="aQute.daemon" />
+     </Match>
+     <Match>
+       <Package name="aQute.jpm.lib" />
+     </Match>
+     <Match>
+       <Package name="aQute.jpm.main" />
+     </Match>
+     <Match>
+       <Package name="aQute.jpm.platform" />
+     </Match>
+     <Match>
+       <Package name="aQute.jpm.platform.windows" />
+     </Match>
+     <Match>
+       <Package name="aQute.jpm.service" />
+     </Match>
+     <Match>
+       <Package name="aQute.junit" />
+     </Match>
+     <Match>
+       <Package name="aQute.junit.constants" />
+     </Match>
+     <Match>
+       <Package name="aQute.junit.plugin" />
+     </Match>
+     <Match>
+       <Package name="aQute.junit.runtime" />
+     </Match>
+     <Match>
+       <Package name="aQute.launcher" />
+     </Match>
+     <Match>
+       <Package name="aQute.launcher.constants" />
+     </Match>
+     <Match>
+       <Package name="aQute.launcher.minifw" />
+     </Match>
+     <Match>
+       <Package name="aQute.launcher.plugin" />
+     </Match>
+     <Match>
+       <Package name="aQute.lib.base64" />
+     </Match>
+     <Match>
+       <Package name="aQute.lib.codec" />
+     </Match>
+     <Match>
+       <Package name="aQute.lib.collections" />
+     </Match>
+     <Match>
+       <Package name="aQute.lib.converter" />
+     </Match>
+     <Match>
+       <Package name="aQute.lib.data" />
+     </Match>
+     <Match>
+       <Package name="aQute.lib.deployer" />
+     </Match>
+     <Match>
+       <Package name="aQute.lib.filter" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.asn1" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.cafs" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.classdump" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.classloaders" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.clauses" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.command" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.cryptography" />
+     </Match>
+     <Match>
+       <Package name="aQute.lib.getopt" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.fileiterator" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.filelock" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.filters" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.forker" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.generics" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.glob" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.gzip" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.log" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.map" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.qtokens" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.reporter" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.sax" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.sax.filters" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.sed" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.tarjan" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.tuple" />
+     </Match>
+     <Match>
+       <Package name="aQute.libg.xslt" />
+     </Match>
+     <Match>
+       <Package name="aQute.lib.hex" />
+     </Match>
+     <Match>
+       <Package name="aQute.lib.index" />
+     </Match>
+     <Match>
+       <Package name="aQute.lib.io" />
+     </Match>
+     <Match>
+       <Package name="aQute.lib.json" />
+     </Match>
+     <Match>
+       <Package name="aQute.lib.justif" />
+     </Match>
+     <Match>
+       <Package name="aQute.lib.putjar" />
+     </Match>
+     <Match>
+       <Package name="aQute.lib.settings" />
+     </Match>
+     <Match>
+       <Package name="aQute.lib.spring" />
+     </Match>
+     <Match>
+       <Package name="aQute.lib.tag" />
+     </Match>
+     <Match>
+       <Package name="aQute.service.reporter" />
+     </Match>
+     <Match>
+       <Package name="biz.aQute.resolve" />
+     </Match>
+     <Match>
+       <Package name="biz.aQute.resolve.internal" />
+     </Match>
+     <Match>
+       <Package name="com.example.demo" />
+     </Match>
+     <Match>
+       <Package name="eclipse_1_1" />
+     </Match>
+     <Match>
+       <Package name="eclipse_1_2" />
+     </Match>
+     <Match>
+       <Package name="eclipse_1_3" />
+     </Match>
+     <Match>
+       <Package name="eclipse_1_4" />
+     </Match>
+     <Match>
+       <Package name="eclipse_1_5" />
+     </Match>
+     <Match>
+       <Package name="eclipse_1_6" />
+     </Match>
+     <Match>
+       <Package name="eclipse_jsr14" />
+     </Match>
+     <Match>
+       <Package name="pkg2" />
+     </Match>
+     <Match>
+       <Package name="pkg3" />
+     </Match>
+     <Match>
+       <Package name="pkg4" />
+     </Match>
+     <Match>
+       <Package name="pkg5" />
+     </Match>
+     <Match>
+       <Package name="pkg6" />
+     </Match>
+     <Match>
+       <Package name="pkg7" />
+     </Match>
+     <Match>
+       <Package name="sun_1_1" />
+     </Match>
+     <Match>
+       <Package name="sun_1_2" />
+     </Match>
+     <Match>
+       <Package name="sun_1_3" />
+     </Match>
+     <Match>
+       <Package name="sun_1_4" />
+     </Match>
+     <Match>
+       <Package name="sun_1_5" />
+     </Match>
+     <Match>
+       <Package name="sun_1_6" />
+     </Match>
+     <Match>
+       <Package name="sun_jsr14" />
+     </Match>
+     <Match>
+       <Package name="test" />
+     </Match>
+     <Match>
+       <Package name="test.activator" />
+     </Match>
+     <Match>
+       <Package name="test.activator.inherits" />
+     </Match>
+     <Match>
+       <Package name="test.annotation" />
+     </Match>
+     <Match>
+       <Package name="test.annotation.any" />
+     </Match>
+     <Match>
+       <Package name="test.baseline" />
+     </Match>
+     <Match>
+       <Package name="test.classreference" />
+     </Match>
+     <Match>
+       <Package name="test.component" />
+     </Match>
+     <Match>
+       <Package name="test.deployer" />
+     </Match>
+     <Match>
+       <Package name="test.diff" />
+     </Match>
+     <Match>
+       <Package name="test.genericinterf.a" />
+     </Match>
+     <Match>
+       <Package name="test.genericinterf.b" />
+     </Match>
+     <Match>
+       <Package name="test.genericinterf.c" />
+     </Match>
+     <Match>
+       <Package name="test.helpers" />
+     </Match>
+     <Match>
+       <Package name="test.http" />
+     </Match>
+     <Match>
+       <Package name="test.lib" />
+     </Match>
+     <Match>
+       <Package name="test.make" />
+     </Match>
+     <Match>
+       <Package name="test.metatype" />
+     </Match>
+     <Match>
+       <Package name="test.obr" />
+     </Match>
+     <Match>
+       <Package name="test.packageinfo" />
+     </Match>
+     <Match>
+       <Package name="test.packageinfo.ref" />
+     </Match>
+     <Match>
+       <Package name="test.privateimport" />
+     </Match>
+     <Match>
+       <Package name="test.properties" />
+     </Match>
+     <Match>
+       <Package name="test.r5repository" />
+     </Match>
+     <Match>
+       <Package name="test.refer" />
+     </Match>
+     <Match>
+       <Package name="test.referApi" />
+     </Match>
+     <Match>
+       <Package name="test.repository" />
+     </Match>
+     <Match>
+       <Package name="test.signatures" />
+     </Match>
+     <Match>
+       <Package name="test.top" />
+     </Match>
+     <Match>
+       <Package name="test.top.middle" />
+     </Match>
+     <Match>
+       <Package name="test.top.middle.bottom" />
+     </Match>
+     <Match>
+       <Package name="test.uses.annotation" />
+     </Match>
+     <Match>
+       <Package name="test.uses.annotation.annotation" />
+     </Match>
+     <Match>
+       <Package name="test.uses.constructor" />
+     </Match>
+     <Match>
+       <Package name="test.uses.exception" />
+     </Match>
+     <Match>
+       <Package name="test.uses.extend" />
+     </Match>
+     <Match>
+       <Package name="test.uses.field" />
+     </Match>
+     <Match>
+       <Package name="test.uses.generic.extend" />
+     </Match>
+     <Match>
+       <Package name="test.uses.generic.implement" />
+     </Match>
+     <Match>
+       <Package name="test.uses.generic.param" />
+     </Match>
+     <Match>
+       <Package name="test.uses.generic.rvalue" />
+     </Match>
+     <Match>
+       <Package name="test.uses.implement" />
+     </Match>
+     <Match>
+       <Package name="test.uses.order" />
+     </Match>
+     <Match>
+       <Package name="test.uses.param" />
+     </Match>
+     <Match>
+       <Package name="test.uses.rvalue" />
+     </Match>
+     <Match>
+       <Package name="test.versionpolicy.api" />
+     </Match>
+     <Match>
+       <Package name="test.versionpolicy.implemented" />
+     </Match>
+     <Match>
+       <Package name="test.versionpolicy.implmajor" />
+     </Match>
+     <Match>
+       <Package name="test.versionpolicy.uses" />
+     </Match>
+</FindBugsFilter>
diff --git a/cnf/findbugs/README.txt b/cnf/findbugs/README.txt
new file mode 100644
index 0000000..4ddbe73
--- /dev/null
+++ b/cnf/findbugs/README.txt
@@ -0,0 +1,20 @@
+To get started, see doc/index.html and doc/manual/index.html
+
+The FindBugs source license is in the file LICENSE.txt
+
+Both the name FindBugs and the FindBugs bug mark are
+trademarked by the University of Maryland.
+
+The Apache BCEL license is in the file LICENSE-bcel.txt
+
+The ASM license is in the file LICENSE-ASM.txt
+
+The dom4j license is in the file LICENSE-dom4j.txt
+
+The AppleJavaExtensions license is in the file LICENSE-AppleJavaExtensions.txt
+
+The Docbook 4.2 XML DTD license is in the file LICENSE-docbook.txt
+
+The JSR-305 reference implementation license is in LICENSE-jsr305.txt
+
+The Jaxen license is in LICENSE-jaxen.txt
diff --git a/cnf/findbugs/bin/addMessages b/cnf/findbugs/bin/addMessages
new file mode 100755
index 0000000..5b9e5be
--- /dev/null
+++ b/cnf/findbugs/bin/addMessages
@@ -0,0 +1,73 @@
+#! /bin/sh
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.AddMessages
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
diff --git a/cnf/findbugs/bin/computeBugHistory b/cnf/findbugs/bin/computeBugHistory
new file mode 100755
index 0000000..24ce26c
--- /dev/null
+++ b/cnf/findbugs/bin/computeBugHistory
@@ -0,0 +1,78 @@
+#! /bin/sh
+
+# Merge a historical bug collection and a bug collection, producing an updated
+# historical bug collection
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.workflow.Update
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/convertXmlToText b/cnf/findbugs/bin/convertXmlToText
new file mode 100755
index 0000000..e8493d6
--- /dev/null
+++ b/cnf/findbugs/bin/convertXmlToText
@@ -0,0 +1,73 @@
+#! /bin/sh
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.PrintingBugReporter
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
diff --git a/cnf/findbugs/bin/copyBuggySource b/cnf/findbugs/bin/copyBuggySource
new file mode 100755
index 0000000..355819b
--- /dev/null
+++ b/cnf/findbugs/bin/copyBuggySource
@@ -0,0 +1,75 @@
+#! /bin/sh
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.workflow.CopyBuggySource
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/defectDensity b/cnf/findbugs/bin/defectDensity
new file mode 100755
index 0000000..a297a03
--- /dev/null
+++ b/cnf/findbugs/bin/defectDensity
@@ -0,0 +1,77 @@
+#! /bin/sh
+
+# Generate a defect density table from a bug collection
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.workflow.DefectDensity
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/deprecated/bugHistory b/cnf/findbugs/bin/deprecated/bugHistory
new file mode 100755
index 0000000..5f5599b
--- /dev/null
+++ b/cnf/findbugs/bin/deprecated/bugHistory
@@ -0,0 +1,75 @@
+#! /bin/sh
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.workflow.BugHistory
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/deprecated/unionBugs b/cnf/findbugs/bin/deprecated/unionBugs
new file mode 100755
index 0000000..9da0b84
--- /dev/null
+++ b/cnf/findbugs/bin/deprecated/unionBugs
@@ -0,0 +1,78 @@
+#! /bin/sh
+
+# Create the union of two results files, preserving
+# annotations in both files in the result.
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.UnionResults
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/deprecated/unionResults b/cnf/findbugs/bin/deprecated/unionResults
new file mode 100755
index 0000000..01d2126
--- /dev/null
+++ b/cnf/findbugs/bin/deprecated/unionResults
@@ -0,0 +1,80 @@
+#! /bin/sh
+
+# Deprecated
+
+# Create the union of two results files, preserving
+# annotations in both files in the result.
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.workflow.UnionResults
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/deprecated/updateBugs b/cnf/findbugs/bin/deprecated/updateBugs
new file mode 100755
index 0000000..24ce26c
--- /dev/null
+++ b/cnf/findbugs/bin/deprecated/updateBugs
@@ -0,0 +1,78 @@
+#! /bin/sh
+
+# Merge a historical bug collection and a bug collection, producing an updated
+# historical bug collection
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.workflow.Update
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/experimental/backdateHistoryUsingSource b/cnf/findbugs/bin/experimental/backdateHistoryUsingSource
new file mode 100755
index 0000000..55030fa
--- /dev/null
+++ b/cnf/findbugs/bin/experimental/backdateHistoryUsingSource
@@ -0,0 +1,75 @@
+#! /bin/sh
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.workflow.BackdateHistoryUsingSource
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/experimental/churn b/cnf/findbugs/bin/experimental/churn
new file mode 100755
index 0000000..998de6a
--- /dev/null
+++ b/cnf/findbugs/bin/experimental/churn
@@ -0,0 +1,75 @@
+#! /bin/sh
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.workflow.Churn
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/experimental/obfuscate b/cnf/findbugs/bin/experimental/obfuscate
new file mode 100755
index 0000000..ead5619
--- /dev/null
+++ b/cnf/findbugs/bin/experimental/obfuscate
@@ -0,0 +1,75 @@
+#! /bin/sh
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.workflow.ObfuscateBugs
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/experimental/treemapVisualization b/cnf/findbugs/bin/experimental/treemapVisualization
new file mode 100755
index 0000000..9795ff8
--- /dev/null
+++ b/cnf/findbugs/bin/experimental/treemapVisualization
@@ -0,0 +1,75 @@
+#! /bin/sh
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.workflow.TreemapVisualization
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/fb b/cnf/findbugs/bin/fb
new file mode 100755
index 0000000..4b96508
--- /dev/null
+++ b/cnf/findbugs/bin/fb
@@ -0,0 +1,192 @@
+#! /bin/sh
+
+# Launch FindBugs from the command line.
+
+escape_arg() {
+	echo "$1" | sed -e "s,\\([\\\"' 	]\\),\\\\\\1,g"
+}
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+
+fb_appjar="$findbugs_home/lib/findbugs.jar"
+
+ShowHelpAndExit() {
+	fb_mainclass="edu.umd.cs.findbugs.ShowHelp"
+	fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+	exit 0
+}
+
+# Set defaults
+fb_mainclass="edu.umd.cs.findbugs.workflow.FB"
+user_jvmargs=''
+ea_arg=''
+debug_arg=''
+conservespace_arg=''
+workhard_arg=''
+user_props=''
+
+# Handle command line arguments.
+while [ $# -gt 0 ]; do
+	case $1 in
+	-textui)
+		fb_mainclass="edu.umd.cs.findbugs.FindBugs2"
+		;;
+
+	-jvmArgs)
+		shift
+		user_jvmargs="$1"
+		;;
+		
+	-ea)
+		ea_arg='-ea'
+		;;
+
+	-maxHeap)
+		shift
+		fb_maxheap="-Xmx$1m"
+		;;
+
+	-javahome)
+		shift
+		fb_javacmd="$1/bin/java"
+		;;
+
+	-debug)
+		debug_arg="-Dfindbugs.debug=true"
+		;;
+
+	-conserveSpace)
+		conservespace_arg="-Dfindbugs.conserveSpace=true"
+		;;
+
+	-property)
+		shift
+		user_props="-D$1 $user_props"
+		;;
+	
+	-D*=*)
+		user_props="$1 $user_props"
+		;;
+
+	-version)
+		fb_mainclass=edu.umd.cs.findbugs.Version
+		fb_appargs="-release"
+		while [ $# -gt 0 ]; do
+			shift
+		done
+		fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+		exit 0
+		;;
+
+	-help)
+		ShowHelpAndExit
+		;;
+
+	# All unrecognized arguments will be accumulated and
+	# passed to the application.
+	*)
+		fb_appargs="$fb_appargs `escape_arg "$1"`"
+		;;
+	esac
+
+	shift
+done
+
+fb_jvmargs="$user_jvmargs $debug_arg $conservespace_arg $workhard_arg $user_props $ea_arg"
+if [ $maxheap ]; then
+  fb_maxheap="-Xmx${maxheap}m"
+fi
+
+# Extra JVM args for MacOSX.
+if [ $fb_osname = "Darwin" ]; then
+	fb_jvmargs="$fb_jvmargs \
+		-Xdock:name=FindBugs -Xdock:icon=${findbugs_home}/lib/buggy.icns \
+		-Dapple.laf.useScreenMenuBar=true"
+fi
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/fbwrap b/cnf/findbugs/bin/fbwrap
new file mode 100755
index 0000000..85aba91
--- /dev/null
+++ b/cnf/findbugs/bin/fbwrap
@@ -0,0 +1,84 @@
+#! /bin/sh
+
+# A convenient way to call the main() method of a class
+# in findbugs.jar.
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+if [ $# -eq 0 ]; then
+	echo "Usage: fbwrap <main class name> <args...>"
+	exit 1
+fi
+
+fb_mainclass="$1"
+shift
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/filterBugs b/cnf/findbugs/bin/filterBugs
new file mode 100755
index 0000000..9116229
--- /dev/null
+++ b/cnf/findbugs/bin/filterBugs
@@ -0,0 +1,78 @@
+#! /bin/sh
+
+# General purpose utility for filtering/transforming
+# bug collection and/or historical bug collections
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.workflow.Filter
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/findbugs b/cnf/findbugs/bin/findbugs
new file mode 100755
index 0000000..471cf31
--- /dev/null
+++ b/cnf/findbugs/bin/findbugs
@@ -0,0 +1,199 @@
+#! /bin/sh
+
+# Launch FindBugs from the command line.
+
+escape_arg() {
+	echo "$1" | sed -e "s,\\([\\\"' 	]\\),\\\\\\1,g"
+}
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_appjar="$findbugs_home/lib/findbugs.jar"
+
+ShowHelpAndExit() {
+	fb_mainclass="edu.umd.cs.findbugs.ShowHelp"
+	fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+	exit 0
+}
+
+# Set defaults
+fb_mainclass="edu.umd.cs.findbugs.LaunchAppropriateUI"
+user_jvmargs=''
+ea_arg=''
+debug_arg=''
+conservespace_arg=''
+workhard_arg=''
+user_props=''
+
+# Handle command line arguments.
+while [ $# -gt 0 ]; do
+	case $1 in
+	-gui)
+		# this is the default
+		;;
+
+	-gui1)
+		user_props="-Dfindbugs.launchUI=1 $user_props"
+		;;
+
+	-textui)
+		fb_mainclass="edu.umd.cs.findbugs.FindBugs2"
+		;;
+
+	-jvmArgs)
+		shift
+		user_jvmargs="$1"
+		;;
+		
+	-ea)
+		ea_arg='-ea'
+		;;
+
+	-maxHeap)
+		shift
+		fb_maxheap="-Xmx$1m"
+		;;
+
+	-javahome)
+		shift
+		fb_javacmd="$1/bin/java"
+		;;
+
+	-debug)
+		debug_arg="-Dfindbugs.debug=true"
+		;;
+
+	-conserveSpace)
+		conservespace_arg="-Dfindbugs.conserveSpace=true"
+		;;
+
+	-property)
+		shift
+		user_props="-D$1 $user_props"
+		;;
+	
+	-D*=*)
+		user_props="$1 $user_props"
+		;;
+
+	-version)
+		fb_mainclass=edu.umd.cs.findbugs.Version
+		fb_appargs="-release"
+		while [ $# -gt 0 ]; do
+			shift
+		done
+		fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+		exit 0
+		;;
+
+	-help)
+		ShowHelpAndExit
+		;;
+
+	# All unrecognized arguments will be accumulated and
+	# passed to the application.
+	*)
+		fb_appargs="$fb_appargs `escape_arg "$1"`"
+		;;
+	esac
+
+	shift
+done
+
+fb_jvmargs="$user_jvmargs $debug_arg $conservespace_arg $workhard_arg $user_props $ea_arg"
+if [ $maxheap ]; then
+  fb_maxheap="-Xmx${maxheap}m"
+fi
+
+# Extra JVM args for MacOSX.
+if [ $fb_osname = "Darwin" ]; then
+	fb_jvmargs="$fb_jvmargs \
+		-Xdock:name=FindBugs -Xdock:icon=${findbugs_home}/lib/buggy.icns \
+		-Dapple.laf.useScreenMenuBar=true"
+fi
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/findbugs-csr b/cnf/findbugs/bin/findbugs-csr
new file mode 100755
index 0000000..374d602
--- /dev/null
+++ b/cnf/findbugs/bin/findbugs-csr
@@ -0,0 +1,76 @@
+#! /bin/sh
+
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.workflow.CloudSyncAndReport
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/findbugs-dbStats b/cnf/findbugs/bin/findbugs-dbStats
new file mode 100755
index 0000000..1ada8ee
--- /dev/null
+++ b/cnf/findbugs/bin/findbugs-dbStats
@@ -0,0 +1,76 @@
+#! /bin/sh
+
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.cloud.db.DBStats
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/findbugs-msv b/cnf/findbugs/bin/findbugs-msv
new file mode 100755
index 0000000..ab00dd2
--- /dev/null
+++ b/cnf/findbugs/bin/findbugs-msv
@@ -0,0 +1,76 @@
+#! /bin/sh
+
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.workflow.MergeSummarizeAndView
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/findbugs.bat b/cnf/findbugs/bin/findbugs.bat
new file mode 100644
index 0000000..0cc4621
--- /dev/null
+++ b/cnf/findbugs/bin/findbugs.bat
@@ -0,0 +1,240 @@
+ at echo off
+:: Launch FindBugs on a Windows system.
+:: Adapted from scripts found at http://www.ericphelps.com/batch/
+:: This will only work on Windows NT or later!
+
+:: Don't affect environment outside of this invocation
+setlocal
+
+:: ----------------------------------------------------------------------
+:: Set up default values
+:: ----------------------------------------------------------------------
+set appjar=findbugs.jar
+set javahome=
+set launcher=java.exe
+set start=start "FindBugs"
+set jvmargs=
+set debugArg=
+set conserveSpaceArg=
+set workHardArg=
+set args=
+set javaProps=
+set maxheap=768
+
+REM default UI is gui2
+set launchUI=2
+
+:: Try finding the default FINDBUGS_HOME directory
+:: from the directory path of this script
+set default_findbugs_home=%~dp0..
+
+:: Honor JAVA_HOME environment variable if it is set
+if "%JAVA_HOME%"=="" goto nojavahome
+if not exist "%JAVA_HOME%\bin\javaw.exe" goto nojavahome
+set javahome=%JAVA_HOME%\bin\
+:nojavahome
+
+goto loop
+
+:: ----------------------------------------------------------------------
+:: Process command-line arguments
+:: ----------------------------------------------------------------------
+
+:shift2
+shift
+:shift1
+shift
+
+:loop
+
+:: Remove surrounding quotes from %1 and %2
+set firstArg=%~1
+set secondArg=%~2
+
+if "%firstArg%"=="" goto launch
+
+:: AddMessages
+if not "%firstArg%"=="-addMessages" goto notAddMessages
+set fb_mainclass=edu.umd.cs.findbugs.AddMessages
+goto shift1
+:notAddMessages
+
+:: computeBugHistory
+if not "%firstArg%"=="-computeBugHistory" goto notUpdate
+set fb_mainclass=edu.umd.cs.findbugs.workflow.Update
+goto shift1
+:notUpdate
+
+:: convertXmlToText
+if not "%firstArg%"=="-xmltotext" goto notXmlToText
+set fb_mainclass=edu.umd.cs.findbugs.PrintingBugReporter
+goto shift1
+:notXmlToText
+
+:: copyBuggySource
+if not "%firstArg%"=="-copyBS" goto notCopyBS
+set fb_mainclass=edu.umd.cs.findbugs.workflow.CopyBuggySource
+goto shift1
+:notCopyBS
+
+:: defectDensity
+if not "%firstArg%"=="-defectDensity" goto notDefectDensity
+set fb_mainclass=edu.umd.cs.findbugs.workflow.DefectDensity
+goto shift1
+:notDefectDensity
+
+:: filterBugs
+if not "%firstArg%"=="-filterBugs" goto notFilterBugs
+set fb_mainclass=edu.umd.cs.findbugs.workflow.Filter
+goto shift1
+:notFilterBugs
+
+:: listBugDatabaseInfo
+if not "%firstArg%"=="-listBugDatabaseInfo" goto notListBugDatabaseInfo
+set fb_mainclass=edu.umd.cs.findbugs.workflow.ListBugDatabaseInfo
+goto shift1
+:notListBugDatabaseInfo
+
+:: mineBugHistory
+if not "%firstArg%"=="-mineBugHistory" goto notMineBugHistory
+set fb_mainclass=edu.umd.cs.findbugs.workflow.MineBugHistory
+goto shift1
+:notMineBugHistory
+
+:: printAppVersion
+if not "%firstArg%"=="-printAppVersion" goto notPrintAppVersion
+set fb_mainclass=edu.umd.cs.findbugs.workflow.PrintAppVersion
+goto shift1
+:notPrintAppVersion
+
+:: printClass
+if not "%firstArg%"=="-printClass" goto notPrintClass
+set fb_mainclass=edu.umd.cs.findbugs.workflow.PrintClass
+goto shift1
+:notPrintClass
+
+:: rejarForAnalysis
+if not "%firstArg%"=="-rejar" goto notRejar
+set fb_mainclass=edu.umd.cs.findbugs.workflow.RejarClassesForAnalysis
+goto shift1
+:notRejar
+
+:: setBugDatabaseInfo
+if not "%firstArg%"=="-setInfo" goto notSetBugDatabaseInfo
+set fb_mainclass=edu.umd.cs.findbugs.workflow.SetBugDatabaseInfo
+goto shift1
+:notSetBugDatabaseInfo
+
+:: unionBugs
+if not "%firstArg%"=="-unionBugs" goto notUnionBugs
+set fb_mainclass=edu.umd.cs.findbugs.workflow.UnionResults
+goto shift1
+:notUnionBugs
+
+:: xpathFind
+if not "%firstArg%"=="-xpathFind" goto notXPathFind
+set fb_mainclass=edu.umd.cs.findbugs.workflow.XPathFind
+goto shift1
+:notXPathFind
+
+if not "%firstArg%"=="-gui" goto notGui
+set launchUI=2
+set launcher=javaw.exe
+goto shift1
+:notGui
+
+if not "%firstArg%"=="-gui1" goto notGui1
+set launchUI=1
+set javaProps=-Dfindbugs.launchUI=1 %javaProps%
+set launcher=javaw.exe
+goto shift1
+:notGui1
+
+if not "%firstArg%"=="-textui" goto notTextui
+set launchUI=0
+set launcher=java.exe
+set start=
+goto shift1
+:notTextui
+
+if not "%firstArg%"=="-debug" goto notDebug
+set launcher=java.exe
+set start=
+set debugArg=-Dfindbugs.debug=true
+goto shift1
+:notDebug
+
+if not "%firstArg%"=="-help" goto notHelp
+set launchUI=help
+set launcher=java.exe
+set start=
+goto shift1
+:notHelp
+
+if not "%firstArg%"=="-version" goto notVersion
+set launchUI=version
+set launcher=java.exe
+set start=
+goto shift1
+:notVersion
+
+if "%firstArg%"=="-home" set FINDBUGS_HOME=%secondArg%
+if "%firstArg%"=="-home" goto shift2
+
+if "%firstArg%"=="-jvmArgs" set jvmargs=%secondArg%
+if "%firstArg%"=="-jvmArgs" goto shift2
+
+if "%firstArg%"=="-maxHeap" set maxheap=%secondArg%
+if "%firstArg%"=="-maxHeap" goto shift2
+
+if "%firstArg%"=="-conserveSpace" set conserveSpaceArg=-Dfindbugs.conserveSpace=true
+if "%firstArg%"=="-conserveSpace" goto shift1
+
+if "%firstArg%"=="-workHard" set workHardArg=-Dfindbugs.workHard=true
+if "%firstArg%"=="-workHard" goto shift1
+
+if "%firstArg%"=="-javahome" set javahome=%secondArg%\bin\
+if "%firstArg%"=="-javahome" goto shift2
+
+if "%firstArg%"=="-property" set javaProps=-D%secondArg% %javaProps%
+if "%firstArg%"=="-property" goto shift2
+
+if "%firstArg%"=="" goto launch
+
+set args=%args% "%firstArg%"
+goto shift1
+
+:: ----------------------------------------------------------------------
+:: Launch FindBugs
+:: ----------------------------------------------------------------------
+:launch
+:: Make sure FINDBUGS_HOME is set.
+:: If it isn't, try using the default value based on the
+:: directory path of the invoked script.
+:: Note that this will fail miserably if the value of FINDBUGS_HOME
+:: has quote characters in it.
+if not "%FINDBUGS_HOME%"=="" goto checkHomeValid
+set FINDBUGS_HOME=%default_findbugs_home%
+
+:checkHomeValid
+if not exist "%FINDBUGS_HOME%\lib\%appjar%" goto homeNotSet
+
+:found_home
+:: Launch FindBugs!
+if "%fb_mainclass%"=="" goto runJar
+"%javahome%%launcher%" %debugArg% %conserveSpaceArg% %workHardArg% %javaProps% "-Dfindbugs.home=%FINDBUGS_HOME%" -Xmx%maxheap%m %jvmargs% "-Dfindbugs.launchUI=%launchUI%" -cp "%FINDBUGS_HOME%\lib\%appjar%" %fb_mainclass% %args%
+goto end
+:runjar
+%start% "%javahome%%launcher%" %debugArg% %conserveSpaceArg% %workHardArg% %javaProps% "-Dfindbugs.home=%FINDBUGS_HOME%" -Xmx%maxheap%m %jvmargs% "-Dfindbugs.launchUI=%launchUI%" -jar "%FINDBUGS_HOME%\lib\%appjar%" %args%
+goto end
+
+:: ----------------------------------------------------------------------
+:: Report that FINDBUGS_HOME is not set (and was not specified)
+:: ----------------------------------------------------------------------
+:homeNotSet
+echo Could not find FindBugs home directory.  There may be a problem
+echo with the FindBugs installation.  Try setting FINDBUGS_HOME, or
+echo re-installing.
+goto end
+
+:end
diff --git a/cnf/findbugs/bin/findbugs2 b/cnf/findbugs/bin/findbugs2
new file mode 100755
index 0000000..1367e3d
--- /dev/null
+++ b/cnf/findbugs/bin/findbugs2
@@ -0,0 +1,177 @@
+#! /bin/sh
+
+#
+# Simplified findbugs startup script.
+# This is an experiment.
+#
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+# Default UI is GUI2
+fb_launchui="2"
+
+#
+# Stuff we're going to pass to the JVM as JVM arguments.
+#
+jvm_debug=""
+jvm_maxheap="-Xmx768m"
+jvm_ea=""
+jvm_conservespace=""
+jvm_user_props=""
+
+#
+# Process command line args until we hit one we don't recognize.
+#
+finishedArgs=false
+while [ $# -gt 0 ] && [ "$finishedArgs" = "false" ]; do
+
+	arg=$1
+
+	case $arg in
+		-textui)
+			shift
+			fb_launchui="0"
+			;;
+
+		-gui)
+			shift
+			fb_launchui="2"
+			;;
+
+		-gui1)
+			shift
+			fb_launchui="1"
+			;;
+
+		-maxHeap)
+			shift
+			jvm_maxheap="-Xmx$1m"
+			shift
+			;;
+
+		-ea)
+			shift
+			jvm_ea="-ea"
+			;;
+
+		-javahome)
+			shift
+			fb_javacmd="$1/bin/java"
+			shift
+			;;
+
+		-debug)
+			shift
+			jvm_debug="-Dfindbugs.debug=true"
+			;;
+
+		-conserveSpace)
+			shift
+			jvm_conservespace="-Dfindbugs.conserveSpace=true"
+			;;
+
+		-property)
+			shift
+			jvm_user_props="-D$1 $jvm_user_props"
+			shift
+			;;
+	
+		-D*=*)
+			jvm_user_props="$1 $user_props"
+			shift
+			;;
+
+		-version)
+			shift
+			fb_launchui="version"
+			;;
+
+		-help)
+			shift
+			fb_launchui="help"
+			;;
+
+		# All arguments starting from the first unrecognized arguments
+		# are passed on to the Java app.
+		*)
+			finishedArgs=true
+			;;
+	esac
+
+done
+
+# Extra JVM args for MacOSX.
+if [ $fb_osname = "Darwin" ]; then
+	fb_jvmargs="$fb_jvmargs \
+		-Xdock:name=FindBugs -Xdock:icon=${findbugs_home}/lib/buggy.icns \
+		-Dapple.laf.useScreenMenuBar=true"
+fi
+
+#
+# Launch JVM
+#
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home" \
+	$jvm_debug $jvm_maxheap $jvm_ea $jvm_conservespace $jvm_user_props \
+	-Dfindbugs.launchUI=$fb_launchui \
+	-jar $findbugs_home/lib/findbugs.jar \
+	${@:+"$@"}
diff --git a/cnf/findbugs/bin/listBugDatabaseInfo b/cnf/findbugs/bin/listBugDatabaseInfo
new file mode 100755
index 0000000..891f455
--- /dev/null
+++ b/cnf/findbugs/bin/listBugDatabaseInfo
@@ -0,0 +1,75 @@
+#! /bin/sh
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.workflow.ListBugDatabaseInfo
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/mineBugHistory b/cnf/findbugs/bin/mineBugHistory
new file mode 100755
index 0000000..520aa83
--- /dev/null
+++ b/cnf/findbugs/bin/mineBugHistory
@@ -0,0 +1,73 @@
+#! /bin/sh
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.workflow.MineBugHistory
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
diff --git a/cnf/findbugs/bin/printAppVersion b/cnf/findbugs/bin/printAppVersion
new file mode 100755
index 0000000..7994b8c
--- /dev/null
+++ b/cnf/findbugs/bin/printAppVersion
@@ -0,0 +1,75 @@
+#! /bin/sh
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.workflow.PrintAppVersion
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/printClass b/cnf/findbugs/bin/printClass
new file mode 100755
index 0000000..0b76853
--- /dev/null
+++ b/cnf/findbugs/bin/printClass
@@ -0,0 +1,73 @@
+#! /bin/sh
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.visitclass.PrintClass
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
diff --git a/cnf/findbugs/bin/rejarForAnalysis b/cnf/findbugs/bin/rejarForAnalysis
new file mode 100755
index 0000000..20877ee
--- /dev/null
+++ b/cnf/findbugs/bin/rejarForAnalysis
@@ -0,0 +1,75 @@
+#! /bin/sh
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.workflow.RejarClassesForAnalysis
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/setBugDatabaseInfo b/cnf/findbugs/bin/setBugDatabaseInfo
new file mode 100755
index 0000000..b1e8ec7
--- /dev/null
+++ b/cnf/findbugs/bin/setBugDatabaseInfo
@@ -0,0 +1,75 @@
+#! /bin/sh
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.workflow.SetBugDatabaseInfo
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/unionBugs b/cnf/findbugs/bin/unionBugs
new file mode 100755
index 0000000..01d2126
--- /dev/null
+++ b/cnf/findbugs/bin/unionBugs
@@ -0,0 +1,80 @@
+#! /bin/sh
+
+# Deprecated
+
+# Create the union of two results files, preserving
+# annotations in both files in the result.
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.workflow.UnionResults
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/bin/xpathFind b/cnf/findbugs/bin/xpathFind
new file mode 100755
index 0000000..c0bd5e9
--- /dev/null
+++ b/cnf/findbugs/bin/xpathFind
@@ -0,0 +1,75 @@
+#! /bin/sh
+
+program="$0"
+
+# Follow symlinks until we get to the actual file.
+while [ -h "$program" ]; do
+	link=`ls -ld "$program"`
+	link=`expr "$link" : '.*-> \(.*\)'`
+	if [ "`expr "$link" : '/.*'`" = 0 ]; then
+		# Relative
+		dir=`dirname "$program"`
+		program="$dir/$link"
+	else
+		# Absolute
+		program="$link"
+	fi
+done
+
+# Assume findbugs home directory is the parent
+# of the directory containing the script (which should
+# normally be "$findbugs_home/bin").
+dir=`dirname "$program"`
+findbugs_home="$dir/.."
+
+# Handle FHS-compliant installations (e.g., Fink)
+if [ -d "$findbugs_home/share/findbugs" ]; then
+	findbugs_home="$findbugs_home/share/findbugs"
+fi
+
+# Make absolute
+findbugs_home=`cd "$findbugs_home" && pwd`
+
+fb_pathsep=':'
+
+# Handle cygwin, courtesy of Peter D. Stout
+fb_osname=`uname`
+if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+	findbugs_home=`cygpath --mixed "$findbugs_home"`
+	fb_pathsep=';'
+fi
+# Handle MKS, courtesy of Kelly O'Hair
+if [ "${fb_osname}" = "Windows_NT" ]; then
+	fb_pathsep=';'
+fi
+
+if [ ! -d "$findbugs_home" ]; then
+	echo "The path $findbugs_home,"
+	echo "which is where I think FindBugs is located,"
+	echo "does not seem to be a directory."
+	exit 1
+fi
+
+# Choose default java binary
+fb_javacmd=java
+if [ ! -z "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
+	if [ `expr "$fb_osname" : CYGWIN` -ne 0 ]; then
+		fb_javacmd=`cygpath --mixed "$JAVA_HOME"`/bin/java
+	else
+		fb_javacmd="$JAVA_HOME/bin/java"
+	fi
+fi
+
+fb_mainclass=edu.umd.cs.findbugs.xml.XPathFind
+
+fb_javacmd=${fb_javacmd:-"java"}
+fb_maxheap=${fb_maxheap:-"-Xmx768m"}
+fb_appjar=${fb_appjar:-"$findbugs_home/lib/findbugs.jar"}
+set -f
+#echo command: \
+exec "$fb_javacmd" \
+	-classpath "$fb_appjar$fb_pathsep$CLASSPATH" \
+	-Dfindbugs.home="$findbugs_home"\
+	$fb_maxheap $fb_jvmargs $fb_mainclass ${@:+"$@"} $fb_appargs
+
+# vim:ts=3
diff --git a/cnf/findbugs/lib/buggy.icns b/cnf/findbugs/lib/buggy.icns
new file mode 100644
index 0000000..b1f4660
Binary files /dev/null and b/cnf/findbugs/lib/buggy.icns differ
diff --git a/cnf/findbugs/src/xsl/default.xsl b/cnf/findbugs/src/xsl/default.xsl
new file mode 100644
index 0000000..e8f30d4
--- /dev/null
+++ b/cnf/findbugs/src/xsl/default.xsl
@@ -0,0 +1,376 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  FindBugs - Find bugs in Java programs
+  Copyright (C) 2004,2005 University of Maryland
+  Copyright (C) 2005, Chris Nappin
+  
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+  
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+  
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+-->
+
+<!--
+  A simple XSLT stylesheet to transform FindBugs XML results
+  annotated with messages into HTML.
+
+  If you want to experiment with modifying this stylesheet,
+  or write your own, you need to generate XML output from FindBugs
+  using a special option which lets it know to include
+  human-readable messages in the XML.  Invoke the findbugs script
+  as follows:
+
+    findbugs -textui -xml:withMessages -project myProject.fb > results.xml
+
+  Then you can use your favorite XSLT implementation to transform
+  the XML output into HTML. (But don't use xsltproc. It generates well-nigh
+  unreadable output, and generates incorrect output for the
+  <script> element.)
+
+  Authors:
+  David Hovemeyer
+  Chris Nappin (summary table)
+-->
+
+<xsl:stylesheet
+	version="1.0"
+	xmlns="http://www.w3.org/1999/xhtml"
+	xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<xsl:output
+	method="xml"
+	indent="yes"
+	omit-xml-declaration="yes"
+	standalone="yes"
+    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
+	doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
+	encoding="UTF-8"/>
+
+<xsl:variable name="literalNbsp">&nbsp;</xsl:variable>
+
+<!--xsl:key name="bug-category-key" match="/BugCollection/BugInstance" use="@category"/-->
+
+<xsl:variable name="bugTableHeader">
+	<tr class="tableheader">
+		<th align="left">Code</th>
+		<th align="left">Warning</th>
+	</tr>
+</xsl:variable>
+
+<xsl:template match="/">
+	<html>
+	<head>
+		<title>FindBugs Report</title>
+		<style type="text/css">
+		.tablerow0 {
+			background: #EEEEEE;
+		}
+
+		.tablerow1 {
+			background: white;
+		}
+
+		.detailrow0 {
+			background: #EEEEEE;
+		}
+
+		.detailrow1 {
+			background: white;
+		}
+
+		.tableheader {
+			background: #b9b9fe;
+			font-size: larger;
+		}
+
+		.tablerow0:hover, .tablerow1:hover {
+			background: #aaffaa;
+		}
+
+		.priority-1 {
+		    color: red;
+		    font-weight: bold;
+		}
+		.priority-2 {
+		    color: orange;
+		    font-weight: bold;
+		}
+		.priority-3 {
+		    color: green;
+		    font-weight: bold;
+		}
+		.priority-4 {
+		    color: blue;
+		    font-weight: bold;
+		}
+		</style>
+		<script type="text/javascript">
+			function toggleRow(elid) {
+				if (document.getElementById) {
+					element = document.getElementById(elid);
+					if (element) {
+						if (element.style.display == 'none') {
+							element.style.display = 'block';
+							//window.status = 'Toggle on!';
+						} else {
+							element.style.display = 'none';
+							//window.status = 'Toggle off!';
+						}
+					}
+				}
+			}
+		</script>
+	</head>
+
+	<xsl:variable name="unique-catkey" select="/BugCollection/BugCategory/@category"/>
+	<!--xsl:variable name="unique-catkey" select="/BugCollection/BugInstance[generate-id() = generate-id(key('bug-category-key', at category))]/@category"/-->
+
+	<body>
+
+		<h1><a href="http://findbugs.sourceforge.net">FindBugs</a> Report</h1>
+
+	<h2>Project Information</h2>	
+	<xsl:apply-templates select="/BugCollection/Project"/>
+
+	<h2>Metrics</h2>
+	<xsl:apply-templates select="/BugCollection/FindBugsSummary"/>
+
+	<h2>Contents</h2>
+	<ul>
+		<xsl:for-each select="$unique-catkey">
+			<xsl:sort select="." order="ascending"/>
+			<xsl:variable name="catkey" select="."/>
+			<xsl:variable name="catdesc" select="/BugCollection/BugCategory[@category=$catkey]/Description"/>
+			
+			<li><a href="#Warnings_{$catkey}"><xsl:value-of select="$catdesc"/> Warnings</a></li>
+		</xsl:for-each>
+
+		<li><a href="#Details">Details</a></li>
+	</ul>
+
+	<h1>Summary</h1>
+	<table width="500" cellpadding="5" cellspacing="2">
+	    <tr class="tableheader">
+			<th align="left">Warning Type</th>
+			<th align="right">Number</th>
+		</tr>
+
+		<xsl:for-each select="$unique-catkey">
+			<xsl:sort select="." order="ascending"/>
+			<xsl:variable name="catkey" select="."/>
+			<xsl:variable name="catdesc" select="/BugCollection/BugCategory[@category=$catkey]/Description"/>
+			<xsl:variable name="styleclass">
+				<xsl:choose><xsl:when test="position() mod 2 = 1">tablerow0</xsl:when>
+					<xsl:otherwise>tablerow1</xsl:otherwise>
+				</xsl:choose>
+			</xsl:variable>
+			
+		<tr class="{$styleclass}">
+			<td><a href="#Warnings_{$catkey}"><xsl:value-of select="$catdesc"/> Warnings</a></td>
+			<td align="right"><xsl:value-of select="count(/BugCollection/BugInstance[(@category=$catkey) and not(@last)])"/></td>
+		</tr>
+		</xsl:for-each>
+
+		<xsl:variable name="styleclass">
+			<xsl:choose><xsl:when test="count($unique-catkey) mod 2 = 0">tablerow0</xsl:when>
+				<xsl:otherwise>tablerow1</xsl:otherwise>
+			</xsl:choose>
+		</xsl:variable>
+		<tr class="{$styleclass}">
+		    <td><b>Total</b></td>
+		    <td align="right"><b><xsl:value-of select="count(/BugCollection/BugInstance[not(@last)])"/></b></td>
+		</tr>
+	</table>
+
+	<h1>Warnings</h1>
+
+	<p>Click on a warning row to see full context information.</p>
+
+	<xsl:for-each select="$unique-catkey">
+		<xsl:sort select="." order="ascending"/>
+		<xsl:variable name="catkey" select="."/>
+		<xsl:variable name="catdesc" select="/BugCollection/BugCategory[@category=$catkey]/Description"/>
+			
+		<xsl:call-template name="generateWarningTable">
+			<xsl:with-param name="warningSet" select="/BugCollection/BugInstance[(@category=$catkey) and not(@last)]"/>
+			<xsl:with-param name="sectionTitle"><xsl:value-of select="$catdesc"/> Warnings</xsl:with-param>
+			<xsl:with-param name="sectionId">Warnings_<xsl:value-of select="$catkey"/></xsl:with-param>
+		</xsl:call-template>
+	</xsl:for-each>
+
+	<h1><a name="Details">Details</a></h1>
+
+	<xsl:apply-templates select="/BugCollection/BugPattern">
+		<xsl:sort select="@abbrev"/>
+		<xsl:sort select="ShortDescription"/>
+	</xsl:apply-templates>
+
+	</body>
+	</html>
+</xsl:template>
+
+<xsl:template match="Project">
+	<p>Project: 
+		<xsl:choose>
+			<xsl:when test='string-length(/BugCollection/Project/@projectName)>0'><xsl:value-of select="/BugCollection/Project/@projectName" /></xsl:when>
+			<xsl:otherwise><xsl:value-of select="/BugCollection/Project/@filename" /></xsl:otherwise>
+		</xsl:choose>
+	</p>
+	<p>FindBugs version: <xsl:value-of select="/BugCollection/@version"/></p>
+	
+	<p>Code analyzed:</p>
+	<ul>
+		<xsl:for-each select="./Jar">
+			<li><xsl:value-of select="text()"/></li>
+		</xsl:for-each>
+	</ul>
+	<p><br/><br/></p>
+</xsl:template>
+
+<xsl:template match="BugInstance[not(@last)]">
+	<xsl:variable name="warningId"><xsl:value-of select="generate-id()"/></xsl:variable>
+
+	<tr class="tablerow{position() mod 2}" onclick="toggleRow('{$warningId}');">
+
+	<td>
+	    <span><xsl:attribute name="class">priority-<xsl:value-of select="@priority"/></xsl:attribute>
+	        <xsl:value-of select="@abbrev"/>
+        </span>
+	</td>
+
+	<td>
+	<xsl:value-of select="LongMessage"/>
+	</td>
+
+	</tr>
+
+	<!-- Add bug annotation elements: Class, Method, Field, SourceLine, Field -->
+	<tr class="detailrow{position() mod 2}">
+		<td/>
+		<td>
+			<p id="{$warningId}" style="display: none;">
+				<a href="#{@type}">Bug type <xsl:value-of select="@type"/> (click for details)</a>
+				<xsl:for-each select="./*/Message">
+					<br/><xsl:value-of select="text()" disable-output-escaping="no"/>
+				</xsl:for-each>
+			</p>
+		</td>
+	</tr>
+</xsl:template>
+
+<xsl:template match="BugPattern">
+	<h2><a name="{@type}"><xsl:value-of select="@type"/>: <xsl:value-of select="ShortDescription"/></a></h2>
+	<xsl:value-of select="Details" disable-output-escaping="yes"/>
+</xsl:template>
+
+<xsl:template name="generateWarningTable">
+	<xsl:param name="warningSet"/>
+	<xsl:param name="sectionTitle"/>
+	<xsl:param name="sectionId"/>
+
+	<h2><a name="{$sectionId}"><xsl:value-of select="$sectionTitle"/></a></h2>
+	<table class="warningtable" width="100%" cellspacing="0">
+		<xsl:copy-of select="$bugTableHeader"/>
+		<xsl:apply-templates select="$warningSet">
+			<xsl:sort select="@abbrev"/>
+			<xsl:sort select="Class/@classname"/>
+		</xsl:apply-templates>
+	</table>
+</xsl:template>
+
+<xsl:template match="FindBugsSummary">
+    <xsl:variable name="kloc" select="@total_size div 1000.0"/>
+    <xsl:variable name="format" select="'#######0.00'"/>
+
+	<p><xsl:value-of select="@total_size"/> lines of code analyzed,
+	in <xsl:value-of select="@total_classes"/> classes, 
+	in <xsl:value-of select="@num_packages"/> packages.</p>
+	<table width="500" cellpadding="5" cellspacing="2">
+	    <tr class="tableheader">
+			<th align="left">Metric</th>
+			<th align="right">Total</th>
+			<th align="right">Density*</th>
+		</tr>
+		<tr class="tablerow0">
+			<td>High Priority Warnings</td>
+			<td align="right"><xsl:value-of select="@priority_1"/></td>
+			<td align="right">
+			    <xsl:choose>
+                    <xsl:when test= "number($kloc) > 0.0 and number(@priority_1) > 0.0">
+        			    <xsl:value-of select="format-number(@priority_1 div $kloc, $format)"/>
+                    </xsl:when>
+                    <xsl:otherwise>
+        			    <xsl:value-of select="format-number(0.0, $format)"/>
+                    </xsl:otherwise>
+			    </xsl:choose>
+			</td>
+		</tr>
+		<tr class="tablerow1">
+			<td>Medium Priority Warnings</td>
+			<td align="right"><xsl:value-of select="@priority_2"/></td>
+			<td align="right">
+			    <xsl:choose>
+                    <xsl:when test= "number($kloc) > 0.0 and number(@priority_2) > 0.0">
+        			    <xsl:value-of select="format-number(@priority_2 div $kloc, $format)"/>
+                    </xsl:when>
+                    <xsl:otherwise>
+        			    <xsl:value-of select="format-number(0.0, $format)"/>
+                    </xsl:otherwise>
+			    </xsl:choose>
+			</td>
+		</tr>
+
+    <xsl:choose>
+		<xsl:when test="@priority_3">
+			<tr class="tablerow1">
+				<td>Low Priority Warnings</td>
+				<td align="right"><xsl:value-of select="@priority_3"/></td>
+				<td align="right">
+                    <xsl:choose>
+                        <xsl:when test= "number($kloc) > 0.0 and number(@priority_3) > 0.0">
+        			        <xsl:value-of select="format-number(@priority_3 div $kloc, $format)"/>
+                        </xsl:when>
+                        <xsl:otherwise>
+        		            <xsl:value-of select="format-number(0.0, $format)"/>
+                        </xsl:otherwise>
+			        </xsl:choose>
+				</td>
+			</tr>
+			<xsl:variable name="totalClass" select="tablerow0"/>
+		</xsl:when>
+		<xsl:otherwise>
+		    <xsl:variable name="totalClass" select="tablerow1"/>
+		</xsl:otherwise>
+	</xsl:choose>
+
+		<tr class="$totalClass">
+			<td><b>Total Warnings</b></td>
+			<td align="right"><b><xsl:value-of select="@total_bugs"/></b></td>
+            <xsl:choose>
+                <xsl:when test="number($kloc) > 0.0">
+  					<td align="right"><b><xsl:value-of select="format-number(@total_bugs div $kloc, $format)"/></b></td>
+                </xsl:when>
+                <xsl:otherwise>
+					<td align="right"><b><xsl:value-of select="format-number(0.0, $format)"/></b></td>
+                </xsl:otherwise>
+	        </xsl:choose>
+		</tr>
+	</table>
+	<p><i>(* Defects per Thousand lines of non-commenting source statements)</i></p>
+	<p><br/><br/></p>
+
+</xsl:template>
+
+</xsl:stylesheet>
+
+<!-- vim:set ts=4: -->
diff --git a/cnf/findbugs/src/xsl/fancy-hist.xsl b/cnf/findbugs/src/xsl/fancy-hist.xsl
new file mode 100644
index 0000000..edb7625
--- /dev/null
+++ b/cnf/findbugs/src/xsl/fancy-hist.xsl
@@ -0,0 +1,1197 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+  Copyright (C) 2005, 2006 Etienne Giraudy, InStranet Inc
+  Copyright (C) 2005, 2007 Etienne Giraudy
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+-->
+
+<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" >
+   <xsl:output
+         method="xml" indent="yes"
+         doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
+         doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+         encoding="UTF-8"/>
+
+   <xsl:variable name="apos" select=""'""/>
+   <xsl:key name="lbc-code-key"        match="/BugCollection/BugInstance" use="concat(@category, at abbrev)" />
+   <xsl:key name="lbc-bug-key"         match="/BugCollection/BugInstance" use="concat(@category, at abbrev, at type)" />
+   <xsl:key name="lbp-class-b-t"  match="/BugCollection/BugInstance" use="concat(Class/@classname, at type)" />
+
+<xsl:template match="/" >
+
+<html>
+   <head>
+      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+      <title>
+         FindBugs (<xsl:value-of select="/BugCollection/@version" />) 
+         Analysis for 
+         <xsl:choose>
+            <xsl:when test='string-length(/BugCollection/Project/@projectName)>0'><xsl:value-of select="/BugCollection/Project/@projectName" /></xsl:when>
+            <xsl:otherwise><xsl:value-of select="/BugCollection/Project/@filename" /></xsl:otherwise>
+         </xsl:choose>
+      </title>
+      <style type="text/css">
+         html, body, div, form {
+            margin:0px;
+            padding:0px;
+         }
+         body {
+            padding:3px;
+         }
+         a, a:link , a:active, a:visited, a:hover {
+            text-decoration: none; color: black;
+         }
+         #navlist {
+                 padding: 3px 0;
+                 margin-left: 0;
+                 border-bottom: 1px solid #778;
+                 font: bold 12px Verdana, sans-serif;
+         }
+         #navlist li {
+                 list-style: none;
+                 margin: 0;
+                 display: inline;
+         }
+         #navlist li a {
+                 padding: 3px 0.5em;
+                 margin-left: 3px;
+                 border: 1px solid #778;
+                 border-bottom: none;
+                 background: #DDE;
+                 text-decoration: none;
+         }
+         #navlist li a:link { color: #448; }
+         #navlist li a:visited { color: #667; }
+         #navlist li a:hover {
+                 color: #000;
+                 background: #AAE;
+                 border-color: #227;
+         }
+         #navlist li a.current {
+                 background: white;
+                 border-bottom: 1px solid white;
+         }
+         #filterWrapper {
+            margin-bottom:5px;
+         }
+         #displayWrapper {
+            margin-top:5px;
+         }
+         .message {
+            background:#BBBBBB;
+           border: 1px solid #778;
+         }
+         .displayContainer {
+            border:1px solid #555555;
+            margin-top:3px;
+            padding: 3px;
+            display:none;
+         }
+         #summaryContainer table,
+         #historyContainer table {
+            border:1px solid black;
+         }
+         #summaryContainer th,
+         #historyContainer th {
+            background: #aaaaaa;
+            color: white;
+         }
+         #summaryContainer th, #summaryContainer td,
+         #historyContainer th, #historyContainer td {
+            padding: 2px 4px 2px 4px;
+         }
+         .summary-name {
+            background: #eeeeee;
+            text-align:left;
+         }
+         .summary-size {
+            background: #eeeeee;
+            text-align:center;
+         }
+         .summary-priority-all {
+            background: #dddddd;
+            text-align:center;
+         }
+         .summary-priority-1 {
+            background: red;
+            text-align:center;
+         }
+         .summary-priority-2 {
+            background: orange;
+            text-align:center;
+         }
+         .summary-priority-3 {
+            background: green;
+            text-align:center;
+         }
+         .summary-priority-4 {
+            background: blue;
+            text-align:center;
+         }
+
+         .bugList-level1 {
+            margin-bottom:5px;
+         }
+         .bugList-level1, .bugList-level2, .bugList-level3, .bugList-level4 {
+            background-color: #ffffff;
+            margin-left:15px;
+            padding-left:10px;
+         }
+         .bugList-level1-label, .bugList-level2-label, .bugList-level3-label, .bugList-level4-label {
+            background-color: #bbbbbb;
+            border: 1px solid black;
+            padding: 1px 3px 1px 3px;;
+         }
+         .bugList-level2-label, .bugList-level3-label, .bugList-level4-label {
+            border-width: 0px 1px 1px 1px;
+         }
+         .bugList-level4-label {
+            background-color: #ffffff;
+            border: 0px 0px 1px 0px;
+         }
+         .bugList-level4 {
+            border: 0px 1px 1px 1px;
+         }
+
+         .bugList-level4-inner {
+            border-style: solid;
+            border-color: black;
+            border-width: 0px 1px 1px 1px;
+         }
+         .b-r {
+            font-size: 10pt; font-weight: bold; padding: 0 0 0 60px;
+         }
+         .b-d {
+            font-weight: normal; background: #ccccc0;
+            padding: 0 5px 0 5px; margin: 0px;
+         }
+         .b-1 {
+            background: red; height: 0.5em; width: 1em;
+            margin-right: 0.5em;
+         }
+         .b-2 {
+            background: orange; height: 0.5em; width: 1em;
+            margin-right: 0.5em;
+         }
+         .b-3 {
+            background: green; height: 0.5em; width: 1em;
+            margin-right: 0.5em;
+         }
+         .b-4 {
+            background: blue; height: 0.5em; width: 1em;
+            margin-right: 0.5em;
+         }
+
+      </style>
+      <script type='text/javascript'><xsl:text disable-output-escaping='yes'><![CDATA[
+         var menus            = new Array('summary','info','history','listByCategories','listByPackages');
+         var selectedMenuId   = "summary";
+         var selectedVersion  = -1;
+         var selectedPriority = 4;
+         var lastVersion      = 0;
+         var includeFixedIntroducedBugs;
+
+         var bPackageNamesPopulated = false;
+
+         var filterContainerId              = "filterWrapper";
+         var historyControlContainerId      = "historyControlWrapper";
+         var messageContainerId             = "messageContainer";
+         var summaryContainerId             = "summaryContainer";
+         var infoContainerId                = "infoContainer";
+         var historyContainerId             = "historyContainer";
+         var listByCategoriesContainerId    = "listByCategoriesContainer";
+         var listByPackagesContainerId      = "listByPackagesContainer";
+
+         var idxCatKey = 0; var idxCatDescr = 1; var idxBugCat = 1;
+         var idxCodeKey = 0; var idxCodeDescr = 1; var idxBugCode = 2;
+         var idxPatternKey = 2; var idxPatternDescr = 3; var idxBugPattern = 3;
+         var idxBugKey = 0; var idxBugDescr = 6;
+         var idxBugClass = 6, idxBugPackage = 7;
+
+         // main init function
+         function init() {
+            loadFilter();
+            selectMenu(selectedMenuId);
+            lastVersion = versions.length - 1;
+         }
+
+         // menu callback function
+         function selectMenu(menuId) {
+            document.getElementById(selectedMenuId).className="none";
+            document.getElementById(menuId).className="current";
+            if (menuId!=selectedMenuId) {
+               hideMenu(selectedMenuId);
+               selectedMenuId = menuId;
+            }
+            if (menuId=="summary")           displaySummary();
+            if (menuId=="info")              displayInfo();
+            if (menuId=="history")           displayHistory();
+            if (menuId=="listByCategories")  displayListByCategories();
+            if (menuId=="listByPackages")    displayListByPackages();
+         }
+
+         // display filter
+         function loadFilter() {
+            var versionsBox = document.findbugsForm.versions.options;
+            versionsBox[0] = new Option(" -- All Versions -- ","-1");
+            versionsBox.selectedIndex = 0;
+            if (versions.length>=1) {
+               for (x=0; versions.length>1 && x<versions.length; x++) {
+                  versionsBox[x+1] = new Option(" Bugs at release: "+versions[versions.length-x-1][1], versions[versions.length-x-1][0]);
+               }
+            }
+
+            var prioritiesBox = document.findbugsForm.priorities.options;
+            prioritiesBox[0] = new Option(" -- All priorities -- ", "4");
+            prioritiesBox[1] = new Option(" P1 bugs ", "1");
+            prioritiesBox[2] = new Option(" P1 and P2 bugs ", "2");
+            prioritiesBox[3] = new Option(" P1, P2 and P3 bugs ", "3");
+         }
+
+         // display a message
+         function displayMessage(msg) {
+            var container = document.getElementById(messageContainerId);
+            container.innerHTML = "<div class='message'>"+msg+"</div>";
+         }
+
+         // reset displayed message
+         function resetMessage() {
+            var container = document.getElementById(messageContainerId);
+            container.innerHTML = "";
+         }
+
+         function hideMenu(menuId) {
+            var container = menuId+"Container";
+            document.getElementById(container).style.display="none";
+         }
+
+         // filter callback function
+         function filter() {
+            var versionsBox = document.findbugsForm.versions.options;
+            selectedVersion = versionsBox[versionsBox.selectedIndex].value;
+
+            var prioritiesBox = document.findbugsForm.priorities.options;
+            selectedPriority = prioritiesBox[prioritiesBox.selectedIndex].value;
+
+            selectMenu(selectedMenuId);
+         }
+
+         // includeFixedBugs callback function
+         function includeFixedIntroducedBugsInHistory() {
+            includeFixedIntroducedBugs =
+              document.findbugsHistoryControlForm.includeFixedIntroducedBugs.checked;
+
+            selectMenu(selectedMenuId);
+         }
+
+         // display summary tab
+         function displaySummary() {
+            resetMessage();
+            hide(filterContainerId);
+            hide(historyControlContainerId);
+            var container = document.getElementById(summaryContainerId);
+            container.style.display="block";
+         }
+
+         // display info tab
+         function displayInfo() {
+            resetMessage();
+            hide(filterContainerId);
+            hide(historyControlContainerId);
+            var container = document.getElementById(infoContainerId);
+            container.style.display="block";
+         }
+
+         // display history tab
+         function displayHistory() {
+            displayMessage("Loading history...");
+            hide(filterContainerId);
+            show(historyControlContainerId);
+            var container = document.getElementById(historyContainerId);
+            var content = "";
+            var i=0;
+            var p = [0,0,0,0,0];
+            var f = [0,0,0,0,0];
+
+            content += "<table><tr><th>Release</th><th>Bugs</th><th>Bugs p1</th><th>Bugs p2</th><th>Bugs p3</th><th>Bugs Exp.</th></tr>";
+
+            var aSpan   = "<span title='Bugs introduced in this release that have not been fixed.'>";
+            var fSpan   = "<span title='Bugs fixed in this release.'>";
+            var fiSpan  = "<span title='Bugs introduced in this release that were fixed in later releases.'>";
+            var afiSpan = "<span title='Total number of bugs introduced in this release.'>";
+            var eSpan   = "</span>";
+
+            if(includeFixedIntroducedBugs) {
+                for (i=(versions.length-1); i>0; i--) {
+                    v = countBugsVersion(i, 4);
+                    t = countTotalBugsVersion(i);
+                    o = countFixedButActiveBugsVersion(i);
+                    f = countFixedBugsInVersion(i);
+                    fi = countFixedBugsIntroducedInVersion(i);
+                    content += "<tr>";
+                    content += "<td class='summary-name'>" + versions[i][1] + "</td>";
+                    content += "<td class='summary-priority-all'> " + (t[0] + o[0]) + " (+" + afiSpan + (v[0] + fi[0]) + eSpan +
+                      " [" + aSpan + v[0] + eSpan + " / " + fiSpan + fi[0] + eSpan + "] " + eSpan + " / -" + fSpan + f[0] + eSpan + ") </td>";
+                    content += "<td class='summary-priority-1'> " + (t[1] + o[1]) + " (+" + afiSpan + (v[1] + fi[1]) + eSpan +
+                      " [" + aSpan + v[1] + eSpan + " / " + fiSpan + fi[1] + eSpan + "] " + eSpan + " / -" + fSpan + f[1] + eSpan + ") </td>";
+                    content += "<td class='summary-priority-2'> " + (t[2] + o[2]) + " (+" + afiSpan + (v[2] + fi[2]) + eSpan +
+                      " [" + aSpan + v[2] + eSpan + " / " + fiSpan + fi[2] + eSpan + "] " + eSpan + " / -" + fSpan + f[2] + eSpan + ") </td>";
+                    content += "<td class='summary-priority-3'> " + (t[3] + o[3]) + " (+" + afiSpan + (v[3] + fi[3]) + eSpan +
+                      " [" + aSpan + v[3] + eSpan + " / " + fiSpan + fi[3] + eSpan + "] " + eSpan + " / -" + fSpan + f[3] + eSpan + ") </td>";
+                    content += "<td class='summary-priority-4'> " + (t[4] + o[4]) + " (+" + afiSpan + (v[4] + fi[4]) + eSpan +
+                      " [" + aSpan + v[4] + eSpan + " / " + fiSpan + fi[4] + eSpan + "] " + eSpan + " / -" + fSpan + f[4] + eSpan + ") </td>";
+                    content += "</tr>";
+                }
+            } else {
+                for (i=(versions.length-1); i>0; i--) {
+                    v = countBugsVersion(i, 4);
+                    t = countTotalBugsVersion(i);
+                    o = countFixedButActiveBugsVersion(i);
+                    f = countFixedBugsInVersion(i);
+                    content += "<tr>";
+                    content += "<td class='summary-name'>" + versions[i][1] + "</td>";
+                    content += "<td class='summary-priority-all'> " + (t[0] + o[0]) + " (+" + aSpan + v[0] + eSpan + " / -" + fSpan + f[0] + eSpan + ") </td>";
+                    content += "<td class='summary-priority-1'  > " + (t[1] + o[1]) + " (+" + aSpan + v[1] + eSpan + " / -" + fSpan + f[1] + eSpan + ") </td>";
+                    content += "<td class='summary-priority-2'  > " + (t[2] + o[2]) + " (+" + aSpan + v[2] + eSpan + " / -" + fSpan + f[2] + eSpan + ") </td>";
+                    content += "<td class='summary-priority-3'  > " + (t[3] + o[3]) + " (+" + aSpan + v[3] + eSpan + " / -" + fSpan + f[3] + eSpan + ") </td>";
+                    content += "<td class='summary-priority-4'  > " + (t[4] + o[4]) + " (+" + aSpan + v[4] + eSpan + " / -" + fSpan + f[4] + eSpan + ") </td>";
+                    content += "</tr>";
+                }
+            }
+
+            t = countTotalBugsVersion(0);
+            o = countFixedButActiveBugsVersion(0);
+            content += "<tr>";
+            content += "<td class='summary-name'>" + versions[0][1] + "</td>";
+            content += "<td class='summary-priority-all'> " + (t[0] + o[0]) + " </td>";
+            content += "<td class='summary-priority-1'  > " + (t[1] + o[1]) + " </td>";
+            content += "<td class='summary-priority-2'  > " + (t[2] + o[2]) + " </td>";
+            content += "<td class='summary-priority-3'  > " + (t[3] + o[3]) + " </td>";
+            content += "<td class='summary-priority-4'  > " + (t[4] + o[4]) + " </td>";
+            content += "</tr>";
+
+            content += "</table>";
+            container.innerHTML = content;
+            container.style.display="block";
+            resetMessage();
+         }
+
+         // display list by cat tab
+         function displayListByCategories() {
+            hide(historyControlContainerId);
+            show(filterContainerId);
+            var container = document.getElementById(listByCategoriesContainerId);
+            container.innerHTML = "";
+            container.style.display="block";
+            displayMessage("Loading stats (categories)...");
+            container.innerHTML = displayLevel1("lbc", "Stats by Bug Categories");
+            resetMessage();
+         }
+
+         // display list by package tab
+         function displayListByPackages() {
+            hide(historyControlContainerId);
+            show(filterContainerId);
+            var container = document.getElementById(listByPackagesContainerId);
+            container.style.display="block";
+            if (!bPackageNamesPopulated) {
+               displayMessage("Initializing...");
+               populatePackageNames();
+            }
+            displayMessage("Loading stats (packages)...");
+            container.innerHTML = displayLevel1("lbp", "Stats by Bug Package");
+            resetMessage();
+         }
+
+         // callback function for list item click
+         function toggleList(listType, containerId, id1, id2, id3) {
+            var container = document.getElementById(containerId);
+            if (container.style.display=="block") {
+               container.style.display="none";
+            } else {
+               if (listType=="lbc") {
+                  if (id1.length>0 && id2.length==0 && id3.length==0) {
+                     displayCategoriesCodes(containerId, id1);
+                  } else if (id1.length>0 && id2.length>0 && id3.length==0) {
+                     displayCategoriesCodesPatterns(containerId, id1, id2);
+                  } else if (id1.length>0 && id2.length>0 && id3.length>0) {
+                     displayCategoriesCodesPatternsBugs(containerId, id1, id2, id3);
+                  } else {
+                     // ???
+                  }
+               } else if (listType=="lbp") {
+                  if (id1.length>0 && id2.length==0 && id3.length==0) {
+                     displayPackageCodes(containerId, id1);
+                  } else if (id1.length>0 && id2.length>0 && id3.length==0) {
+                     displayPackageClassPatterns(containerId, id1, id2);
+                  } else if (id1.length>0 && id2.length>0 && id3.length>0) {
+                     displayPackageClassPatternsBugs(containerId, id1, id2, id3);
+                  } else {
+                     // ???
+                  }
+               } else {
+                  // ????
+               }
+            }
+         }
+
+         // list by categories, display bug cat>codes
+         function displayCategoriesCodes(containerId, catId) {
+            displayMessage("Loading stats (codes)...");
+            var container = document.getElementById(containerId);
+            container.style.display="block";
+            if (container.innerHTML=="Loading..." || container.innerHTML=="") {
+               container.innerHTML = displayLevel2("lbc", catId);
+            }
+            resetMessage();
+         }
+
+         // list by categories, display bug package>codes
+         function displayPackageCodes(containerId, packageId) {
+            displayMessage("Loading stats (codes)...");
+            var container = document.getElementById(containerId);
+            container.style.display="block";
+            if (container.innerHTML=="Loading..." || container.innerHTML=="") {
+               container.innerHTML = displayLevel2("lbp", packageId);
+            }
+            resetMessage();
+         }
+
+         // list by categories, display bug cat>codes>patterns
+         function displayCategoriesCodesPatterns(containerId, catId, codeId) {
+            displayMessage("Loading stats (patterns)...");
+            var container = document.getElementById(containerId);
+            container.style.display="block";
+            if (container.innerHTML=="Loading..." || container.innerHTML=="")
+               container.innerHTML = displayLevel3("lbc", catId, codeId);
+            resetMessage();
+         }
+
+         // list by package, display bug package>class>patterns
+         function displayPackageClassPatterns(containerId, packageId, classId) {
+            displayMessage("Loading stats (patterns)...");
+            var container = document.getElementById(containerId);
+            container.style.display="block";
+            if (container.innerHTML=="Loading..." || container.innerHTML=="")
+               container.innerHTML = displayLevel3("lbp", packageId, classId);
+            resetMessage();
+         }
+
+         // list by categories, display bug cat>codes>patterns>bugs
+         function displayCategoriesCodesPatternsBugs(containerId, catId, codeId, patternId) {
+            displayMessage("Loading stats (bugs)...");
+            var container = document.getElementById(containerId);
+            container.style.display="block";
+            if (container.innerHTML=="Loading..." || container.innerHTML=="")
+               container.innerHTML = displayLevel4("lbc", catId, codeId, patternId);
+            resetMessage();
+         }
+
+         // list by package, display bug package>class>patterns>bugs
+         function displayPackageClassPatternsBugs(containerId, packageId, classId, patternId) {
+            displayMessage("Loading stats (bugs)...");
+            var container = document.getElementById(containerId);
+            container.style.display="block";
+            if (container.innerHTML=="Loading..." || container.innerHTML=="")
+               container.innerHTML = displayLevel4("lbp",  packageId, classId, patternId);
+            resetMessage();
+         }
+
+         // generate level 1 list
+         function displayLevel1(list, title) {
+            var content = "";
+            var content2 = "";
+
+            content += "<h3>"+title+"</h3>";
+            content += getPriorityLegend();
+            content2 += "<div class='bugList'>";
+
+            var id = "";
+            var containerId = "";
+            var subContainerId = "";
+            var prefixSub = "";
+            var prefixId = "";
+            var p = [0,0,0,0,0];
+            var numberOfBugs = 0;
+            var label = "";
+            var max = 0;
+            if (list=="lbc") {
+               max = categories.length;
+            } else if (list=="lbp") {
+               max = packageStats.length;
+            }
+
+            for (var x=0; x<max -1; x++) {
+               if (list=="lbp" && packageStats[x][1]=="0") continue;
+
+               if (list=="lbc") {
+                  id = categories[x][idxCatKey];
+                  label = categories[x][idxCatDescr];
+                  containerId = "categories-" + id;
+                  subContainerId = "cat-"+id;
+                  p = countBugsCat(selectedVersion, selectedPriority, id, idxBugCat);
+               }
+               if (list=="lbp") {
+                  id = packageStats[x][0];
+                  label = packageStats[x][0];
+                  containerId = "packages-" + id;
+                  subContainerId = "package-"+id;
+                  p = countBugsPackage(selectedVersion, selectedPriority, id, idxBugPackage);
+               }
+
+               subContainerId = prefixSub+id;
+
+               var total = p[1]+p[2]+p[3]+p[4];
+               if (total > 0) {
+                  content2 += addListItem( 1, containerId, label, total, p, subContainerId,
+                                          "toggleList('" + list + "', '" + subContainerId + "', '"+ id + "', '', '')"
+                                          );
+               }
+               numberOfBugs += total;
+            }
+            content2 += "</div>";
+            content += "<h4>Total number of bugs";
+            if (selectedVersion!=-1) {
+               content += " (introduced in release " + versions[selectedVersion][1] +")";
+            }
+            content += ": "+numberOfBugs+"</h4>";
+            return content+content2;
+         }
+
+         // generate level 2 list
+        function displayLevel2(list, id1) {
+            var content = "";
+            var code = "";
+            var containerId = "";
+            var subContainerId = "";
+            var p = [0,0,0,0,0];
+            var max = 0;
+            var id2 = "";
+            if (list=="lbc") {
+               max = codes.length;
+            } else if (list=="lbp") {
+               max = classStats.length;
+            }
+
+            for (var x=0; x<max -1; x++) {
+               if (list=="lbp" && classStats[x][3]=="0") continue;
+
+               if (list=="lbc") {
+                  id2 = codes[x][idxCodeKey];
+                  label = codes[x][idxCodeDescr];
+                  containerId = "codes-"+id1;
+                  subContainerId = "cat-" + id1 + "-code-" + id2;
+                  p = countBugsCode(selectedVersion, selectedPriority, id1, idxBugCat, id2, idxBugCode);
+               }
+               if (list=="lbp") {
+                  id2 = classStats[x][0];
+                  label = classStats[x][0];
+                  containerId = "packages-"+id1;
+                  subContainerId = "package-" + id1 + "-class-" + id2;
+                  p = countBugsClass(selectedVersion, selectedPriority, id1, idxBugPackage, id2, idxBugClass);
+               }
+
+               var total = p[1]+p[2]+p[3]+p[4];
+               if (total > 0) {
+                  content += addListItem( 2, containerId, label, total, p, subContainerId,
+                                          "toggleList('"+ list + "', '" + subContainerId + "', '"+ id1 + "', '"+ id2 + "', '')"
+                                          );
+               }
+            }
+            return content;
+         }
+
+         // generate level 3 list
+        function displayLevel3(list, id1, id2) {
+            var content = "";
+            var containerId = "";
+            var subContainerId = "";
+            var p = [0,0,0,0,0];
+            var max = 0;
+            var label = "";
+            var id3 = "";
+
+            if (list=="lbc") {
+               max = patterns.length;
+            } else if (list=="lbp") {
+               max = patterns.length;
+            }
+
+            for (var x=0; x<max -1; x++) {
+               //if (list=="lbp" && (patterns[x][0]!=id1 || patterns[x][1]!=id2)) continue;
+               //if (list=="lbp" && classStats[x][3]=="0") continue;
+
+               if (list=="lbc") {
+                  id3 = patterns[x][idxPatternKey];;
+                  label = patterns[x][idxPatternDescr];
+                  containerId = "patterns-"+id1;
+                  subContainerId = "cat-" + id1 + "-code-" + id2 + "-pattern-" + id3;
+                  p = countBugsPattern(selectedVersion, selectedPriority, id1, idxBugCat, id2, idxBugCode, id3, idxBugPattern);
+               }
+               if (list=="lbp") {
+                  id3 = patterns[x][idxPatternKey];;
+                  label = patterns[x][idxPatternDescr];
+                  containerId = "classpatterns-"+id1;
+                  subContainerId = "package-" + id1 + "-class-" + id2 + "-pattern-" + id3;
+                  p = countBugsClassPattern(selectedVersion, selectedPriority, id2, idxBugClass, id3, idxBugPattern);
+               }
+
+               var total = p[1]+p[2]+p[3]+p[4];
+               if (total > 0) {
+                  content += addListItem( 3, containerId, label, total, p, subContainerId,
+                                          "toggleList('" + list + "', '" + subContainerId + "', '"+ id1 + "', '"+ id2 + "', '"+ id3 + "')"
+                                          );
+               }
+            }
+            return content;
+         }
+
+         // generate level 4 list
+        function displayLevel4(list, id1, id2, id3) {
+            var content = "";
+            var bug = "";
+            var bugP = 0;
+            var containerId = "";
+            var subContainerId = "";
+            var bugId = "";
+            var label = "";
+            var p = [0,0,0,0,0];
+            for (var x=0; x<bugs.length -1; x++) {
+               bug = bugs[x];
+               if (list=="lbc") {
+                  if ( bug[1]!=id1 || bug[2]!=id2 || bug[3]!=id3 ) continue;
+                  if ( selectedVersion!=-1
+                     && selectedVersion!=bug[5]) continue;
+                  if ( selectedPriority!=4
+                     && selectedPriority<bug[4]) continue;
+
+                  subContainerId = "cat-" + id1 + "-code-" + id2 + "-pattern-" + id3 + "-bug-" + bug[0];
+               }
+               if (list=="lbp") {
+                  if ( bug[7]!=id1 || bug[6]!=id2 || bug[3]!=id3 ) continue;
+                  if ( selectedVersion!=-1
+                     && selectedVersion!=bug[5]) continue;
+                  if ( selectedPriority!=4
+                     && selectedPriority<bug[4]) continue;
+
+                  subContainerId = "package-" + id1 + "-class-" + id2 + "-pattern-" + id3 + "-bug-" + bug[0];
+               }
+
+               bugId = "b-uid-" + bug[0];
+               label = bug[idxBugDescr];
+               containerId = "bugs-"+bugId;
+               bugP = bug[4];
+               p[bugP]++;
+               var total = p[1]+p[2]+p[3]+p[4];
+               if (total > 0) {
+                  content += addBug(   4, containerId, label, bugP, bug[5], subContainerId,
+                                       "showbug('" + bugId + "', '" + subContainerId + "', '"+id3+"')");
+               }
+            }
+            return content;
+         }
+
+
+         function addListItem(level, id, label, total, p, subId, onclick) {
+            var content = "";
+
+            content += "<div class='bugList-level"+level+"' >";
+            content += "<div class='bugList-level"+level+"-label' id='"+id+"' >";
+            content += "<a href='' onclick=\"" + onclick + ";return false;\" ";
+            content += ">";
+            content += "<strong>"+label+"</strong>";
+            content += " "+total+" bugs";
+            if (selectedPriority>1)
+               content += " <em>("+p[1];
+            if (selectedPriority>=2)
+               content += "/"+p[2];
+            if (selectedPriority>=3)
+               content += "/"+p[3];
+            if (selectedPriority>=4)
+               content += "/"+p[4];
+            if (selectedPriority>1)
+               content += ")</em>";
+            content += "</a>";
+            content += "</div>";
+            content += "<div class='bugList-level"+level+"-inner' id='"+subId+"' style='display:none;'>Loading...</div>";
+            content += "</div>";
+            return content;
+         }
+
+         function addBug( level, id, label, p, version, subId, onclick) {
+            var content = "";
+
+            content += "<div class='bugList-level" + level + "' id='" + id + "'>";
+            content += "<div class='bugList-level" + level + "-label' id='" + id + "'>";
+            content += "<span class='b-" + p + "'>   </span>";
+            content += "<a href='' onclick=\"" + onclick + ";return false;\">";
+            if (version==lastVersion) {
+               content += "<span style='color:red;font-weight:bold;'>NEW!</span> ";
+            }
+            content += "<strong>" + label + "</strong>";
+            if (version==0) {
+               content += " <em>since release first historized release</em>";
+            } else {
+               content += " <em>since release " + versions[version][1] + "</em>";
+            }
+            content += "</a>";
+            content += "</div>";
+            content += "<div class='bugList-level" + level + "-inner' id='" + subId + "' style='display:none;'>Loading...</div>";
+            content += "</div>";
+            return content;
+         }
+
+         function countBugsVersion(version, priority) {
+            return countBugs(version, priority, "", -1, "", -1, "", -1, "", -1, "", -1);
+         }
+
+         function countBugsCat(version, priority, cat, idxCat) {
+            return countBugs(version, priority, cat, idxCat, "", -1, "", -1, "", -1, "", -1);
+         }
+
+         function countBugsPackage(version, priority, packageId, idxPackage) {
+            return countBugs(version, priority, "", -1, "", -1, "", -1, packageId, idxPackage, "", -1);
+         }
+
+         function countBugsCode(version, priority, cat, idxCat, code, idxCode) {
+            return countBugs(version, priority, cat, idxCat, code, idxCode, "", -1, "", -1, "", -1);
+         }
+
+         function countBugsPattern(version, priority, cat, idxCat, code, idxCode, packageId, idxPattern) {
+            return countBugs(version, priority, cat, idxCat, code, idxCode, packageId, idxPattern, "", -1, "", -1);
+         }
+
+         function countBugsClass(version, priority, id1, idxBugPackage, id2, idxBugClass) {
+            return countBugs(version, priority, "", -1, "", -1, "", -1, id1, idxBugPackage, id2, idxBugClass);
+         }
+
+         function countBugsClassPattern(version, priority, id2, idxBugClass, id3, idxBugPattern) {
+            return countBugs(version, priority, "", -1, "", -1, id3, idxBugPattern, "", -1, id2, idxBugClass);
+         }
+
+         function countBugs(version, priority, cat, idxCat, code, idxCode, pattern, idxPattern, packageId, idxPackage, classId, idxClass) {
+            var count = [0,0,0,0,0];
+            var last=1000000;
+            for (var x=0; x<bugs.length-1; x++) {
+               var bug = bugs[x];
+
+               var bugCat = bug[idxCat];
+               var bugP = bug[4];
+               var bugCode = bug[idxCode];
+               var bugPattern = bug[idxPattern];
+
+               if (     (version==-1    || version==bug[5])
+                     && (priority==4    || priority>=bug[4])
+                     && (idxCat==-1     || bug[idxCat]==cat)
+                     && (idxCode==-1    || bug[idxCode]==code)
+                     && (idxPattern==-1 || bug[idxPattern]==pattern)
+                     && (idxPackage==-1 || bug[idxPackage]==packageId)
+                     && (idxClass==-1   || bug[idxClass]==classId)
+                     ) {
+                  count[bug[4]]++;
+               }
+            }
+            count[0] = count[1] + count[2] + count[3] + count[4];
+            return count;
+         }
+
+         function countFixedBugsInVersion(version) {
+            var count = [0,0,0,0,0];
+            var last=1000000;
+            for (var x=0; x<fixedBugs.length-1; x++) {
+               var bug = fixedBugs[x];
+
+               var bugP = bug[4];
+
+               if ( version==-1 || version==(bug[6]+1)) {
+                  count[bug[4]]++;
+               }
+            }
+            count[0] = count[1] + count[2] + count[3] + count[4];
+            return count;
+         }
+
+         function countFixedBugsIntroducedInVersion(version) {
+            var count = [0,0,0,0,0];
+            var last=1000000;
+            for (var x=0; x<fixedBugs.length-1; x++) {
+               var bug = fixedBugs[x];
+
+               var bugP = bug[4];
+
+               if ( version==-1 || version==(bug[5])) {
+                  count[bug[4]]++;
+               }
+            }
+            count[0] = count[1] + count[2] + count[3] + count[4];
+            return count;
+         }
+
+         function countFixedButActiveBugsVersion(version) {
+            var count = [0,0,0,0,0];
+            var last=1000000;
+            for (var x=0; x<fixedBugs.length-1; x++) {
+               var bug = fixedBugs[x];
+
+               var bugP = bug[4];
+
+               if ( version==-1 || (version >=bug[5] && version<=bug[6]) ) {
+                  count[bug[4]]++;
+               }
+            }
+            count[0] = count[1] + count[2] + count[3] + count[4];
+            return count;
+         }
+
+         function countTotalBugsVersion(version) {
+            var count = [0,0,0,0,0];
+            var last=1000000;
+            for (var x=0; x<bugs.length-1; x++) {
+               var bug = bugs[x];
+
+               var bugP = bug[4];
+
+               if (version==-1 || version>=bug[5]) {
+                  count[bug[4]]++;
+               }
+            }
+            count[0] = count[1] + count[2] + count[3] + count[4];
+            return count;
+         }
+
+         function getPriorityLegend() {
+            var content = "";
+            content += "<h5><span class='b-1'>   </span> P1 ";
+            content += "<span class='b-2'>   </span> P2 ";
+            content += "<span class='b-3'>   </span> P3 ";
+            content += "<span class='b-4'>   </span> Exp ";
+            content += "</h5>";
+            return content;
+         }
+
+         function populatePackageNames() {
+            for (var i=0; i<bugs.length; i++) {
+               var classId = bugs[i][6];
+               var idx = classId.lastIndexOf('.');
+               var packageId = "";
+
+               if (idx>0) {
+                  packageId = classId.substring(0, idx);
+               }
+
+               bugs[i][7] = packageId;
+            }
+         }
+
+         function showbug(bugId, containerId, patternId) {
+            var bugplaceholder   = document.getElementById(containerId);
+            var bug              = document.getElementById(bugId);
+
+            if ( bugplaceholder==null) {
+               alert(buguid+'-ph-'+list+' - '+buguid+' - bugplaceholder==null');
+               return;
+            }
+            if ( bug==null) {
+               alert(buguid+'-ph-'+list+' - '+buguid+' - bug==null');
+               return;
+            }
+
+            var newBug = bug.innerHTML;
+            var pattern = document.getElementById('tip-'+patternId).innerHTML;
+            toggle(containerId);
+            bugplaceholder.innerHTML = newBug + pattern;
+         }
+         function toggle(foo) {
+            if( document.getElementById(foo).style.display == "none") {
+               show(foo);
+            } else {
+               if( document.getElementById(foo).style.display == "block") {
+                  hide(foo);
+               } else {
+                  show(foo);
+               }
+            }
+         }
+         function show(foo) {
+            document.getElementById(foo).style.display="block";
+         }
+         function hide(foo) {
+            document.getElementById(foo).style.display="none";
+         }
+
+         window.onload = function(){
+            init();
+         };
+      ]]></xsl:text></script>
+      <script type='text/javascript'>
+         // versions fields: release id, release label
+         var versions = new Array(
+            <xsl:for-each select="/BugCollection/History/AppVersion">
+               [ "<xsl:value-of select="@sequence" />", "<xsl:value-of select="@release" />" ],
+            </xsl:for-each>
+               [ "<xsl:value-of select="/BugCollection/@sequence" />", "<xsl:value-of select="/BugCollection/@release" />" ]
+            );
+
+         // categories fields: category id, category label
+         var categories = new Array(
+            <xsl:for-each select="/BugCollection/BugCategory">
+               <xsl:sort select="@category" order="ascending" />
+               [ "<xsl:value-of select="@category" />", "<xsl:value-of select="Description" />" ],
+            </xsl:for-each>
+               [ "", "" ]
+            );
+
+         // codes fields: code id, code label
+         var codes = new Array(
+            <xsl:for-each select="/BugCollection/BugCode">
+               <xsl:sort select="@abbrev" order="ascending" />
+               [ "<xsl:value-of select="@abbrev" />", "<xsl:value-of select="Description" />" ],
+            </xsl:for-each>
+               [ "", "" ]
+            );
+
+         // patterns fields: category id, code id, pattern id, pattern label
+         var patterns = new Array(
+            <xsl:for-each select="/BugCollection/BugPattern">
+               <xsl:sort select="@type" order="ascending" />
+               [ "<xsl:value-of select="@category" />", "<xsl:value-of select="@abbrev" />", "<xsl:value-of select="@type" />", "<xsl:value-of select="translate(ShortDescription, '"', $apos)" />" ],
+
+            </xsl:for-each>
+               [ "", "", "", "" ]
+            );
+
+         // class stats fields: class name, package name, isInterface, total bugs, bugs p1, bugs p2, bugs p3, bugs p4
+         var classStats = new Array(
+            <xsl:for-each select="/BugCollection/FindBugsSummary/PackageStats/ClassStats">
+               <xsl:sort select="@class" order="ascending" />
+               [ "<xsl:value-of select="@class" />", "<xsl:value-of select="../@package" />", "<xsl:value-of select="@interface" />", "<xsl:value-of select="@bugs" />", "<xsl:value-of select="@priority_1" />", "<xsl:value-of select="@priority_2" />", "<xsl:value-of select="@priority_3" />", "<xsl:value-of select="@priority_4" />" ],
+            </xsl:for-each>
+               [ "", "", "", "", "", "", "", "" ]
+            );
+
+         // package stats fields: package name, total bugs, bugs p1, bugs p2, bugs p3, bugs p4
+         var packageStats = new Array(
+            <xsl:for-each select="/BugCollection/FindBugsSummary/PackageStats">
+               <xsl:sort select="@package" order="ascending" />
+               [ "<xsl:value-of select="@package" />", "<xsl:value-of select="@total_bugs" />", "<xsl:value-of select="@priority_1" />", "<xsl:value-of select="@priority_2" />", "<xsl:value-of select="@priority_3" />", "<xsl:value-of select="@priority_4" />" ],
+            </xsl:for-each>
+               [ "", "", "", "", "", "" ]
+            );
+
+
+         // bugs fields: bug id, category id, code id, pattern id, priority, release id, class name, packagename (populated by javascript)
+         var bugs = new Array(
+            <xsl:for-each select="/BugCollection/BugInstance[string-length(@last)=0]">
+
+               [ "<xsl:value-of select="@instanceHash" />-<xsl:value-of select="@instanceOccurrenceNum" />",
+                 "<xsl:value-of select="@category" />",
+                 "<xsl:value-of select="@abbrev" />",
+                 "<xsl:value-of select="@type" />",
+                 <xsl:value-of select="@priority" />,
+                 <xsl:choose><xsl:when test='string-length(@first)=0'>0</xsl:when><xsl:otherwise><xsl:value-of select="@first" /></xsl:otherwise></xsl:choose>,
+                 "<xsl:value-of select="Class/@classname" />",
+                 ""],
+            </xsl:for-each>
+               [ "", "", "", "", 0, 0, "", "" ]
+            );
+
+         // bugs fields: bug id, category id, code id, pattern id, priority, first release id, fixed release id, class name
+         var fixedBugs = new Array(
+            <xsl:for-each select="/BugCollection/BugInstance[string-length(@last)>0]">
+
+               [ "<xsl:value-of select="@instanceHash" />-<xsl:value-of select="@instanceOccurrenceNum" />",
+                 "<xsl:value-of select="@category" />",
+                 "<xsl:value-of select="@abbrev" />",
+                 "<xsl:value-of select="@type" />",
+                 <xsl:value-of select="@priority" />,
+                 <xsl:choose><xsl:when test='string-length(@first)=0'>0</xsl:when><xsl:otherwise><xsl:value-of select="@first" /></xsl:otherwise></xsl:choose>,
+                 <xsl:choose><xsl:when test='string-length(@last)>0'><xsl:value-of select="@last" /></xsl:when><xsl:otherwise>-42</xsl:otherwise></xsl:choose>,
+                 "<xsl:value-of select="Class/@classname" />" ],
+            </xsl:for-each>
+               [ "", "", "", "", 0, 0, 0, "" ]
+            );
+
+      </script>
+   </head>
+   <body>
+      <h3>
+         <a href="http://findbugs.sourceforge.net">FindBugs</a> (<xsl:value-of select="/BugCollection/@version" />) 
+         Analysis for 
+         <xsl:choose>
+            <xsl:when test='string-length(/BugCollection/Project/@projectName)>0'><xsl:value-of select="/BugCollection/Project/@projectName" /></xsl:when>
+            <xsl:otherwise><xsl:value-of select="/BugCollection/Project/@filename" /></xsl:otherwise>
+         </xsl:choose>
+      </h3>
+
+      <div id='menuWrapper' style=''>
+         <div id="navcontainer">
+            <ul id="navlist">
+               <li><a id='summary'           class="current" href="#" onclick="selectMenu('summary'); return false;"         >Summary</a></li>
+               <li><a id='history'           class="none"    href="#" onclick="selectMenu('history'); return false;"         >History</a></li>
+               <li><a id='listByCategories'  class="none"    href="#" onclick="selectMenu('listByCategories'); return false;">Browse By Categories</a></li>
+               <li><a id='listByPackages'    class="none"    href="#" onclick="selectMenu('listByPackages'); return false;"  >Browse by Packages</a></li>
+               <li><a id='info'              class="none"    href="#" onclick="selectMenu('info'); return false;"            >Info</a></li>
+            </ul>
+         </div>
+      </div>
+
+      <div id='displayWrapper'>
+
+      <div style='height:25px;'>
+         <div id='messageContainer' style='float:right;'>
+            Computing data...
+         </div>
+         <div id='filterWrapper' style='display:none;'>
+            <form name='findbugsForm'>
+               <div id='filterContainer' >
+                  <select name='versions' onchange='filter()'>
+                     <option value="loading">Loading filter...</option>
+                  </select>
+                  <select name='priorities' onchange='filter()'>
+                     <option value="loading">Loading filter...</option>
+                  </select>
+               </div>
+            </form>
+         </div>
+         <div id='historyControlWrapper' style='display:none;'>
+           <form name="findbugsHistoryControlForm">
+             <div id='historyControlContainer'>
+               <input type='checkbox' name='includeFixedIntroducedBugs'
+                      value='checked' alt='Include fixed introduced bugs.'
+                      onclick='includeFixedIntroducedBugsInHistory()' />
+               Include counts of introduced bugs that were fixed in later releases.
+             </div>
+           </form>
+         </div>
+      </div>
+         <div id='summaryContainer'          class='displayContainer'>
+            <h3>Package Summary</h3>
+            <table>
+               <tr>
+                  <th>Package</th>
+                  <th>Code Size</th>
+                  <th>Bugs</th>
+                  <th>Bugs p1</th>
+                  <th>Bugs p2</th>
+                  <th>Bugs p3</th>
+                  <th>Bugs Exp.</th>
+               </tr>
+               <tr>
+                  <td class='summary-name'>
+                     Overall
+                     (<xsl:value-of select="/BugCollection/FindBugsSummary/@num_packages" /> packages),
+                     (<xsl:value-of select="/BugCollection/FindBugsSummary/@total_classes" /> classes)
+                  </td>
+                  <td class='summary-size'><xsl:value-of select="/BugCollection/FindBugsSummary/@total_size" /></td>
+                  <td class='summary-priority-all'><xsl:value-of select="/BugCollection/FindBugsSummary/@total_bugs" /></td>
+                  <td class='summary-priority-1'><xsl:value-of select="/BugCollection/FindBugsSummary/@priority_1" /></td>
+                  <td class='summary-priority-2'><xsl:value-of select="/BugCollection/FindBugsSummary/@priority_2" /></td>
+                  <td class='summary-priority-3'><xsl:value-of select="/BugCollection/FindBugsSummary/@priority_3" /></td>
+                  <td class='summary-priority-4'><xsl:value-of select="/BugCollection/FindBugsSummary/@priority_4" /></td>
+               </tr>
+               <xsl:for-each select="/BugCollection/FindBugsSummary/PackageStats">
+                  <xsl:sort select="@package" order="ascending" />
+                  <xsl:if test="@total_bugs!='0'" >
+                     <tr>
+                        <td class='summary-name'><xsl:value-of select="@package" /></td>
+                        <td class='summary-size'><xsl:value-of select="@total_size" /></td>
+                        <td class='summary-priority-all'><xsl:value-of select="@total_bugs" /></td>
+                        <td class='summary-priority-1'><xsl:value-of select="@priority_1" /></td>
+                        <td class='summary-priority-2'><xsl:value-of select="@priority_2" /></td>
+                        <td class='summary-priority-3'><xsl:value-of select="@priority_3" /></td>
+                        <td class='summary-priority-4'><xsl:value-of select="@priority_4" /></td>
+                     </tr>
+                  </xsl:if>
+               </xsl:for-each>
+            </table>
+         </div>
+
+         <div id='infoContainer'             class='displayContainer'>
+            <div id='analyzed-files'>
+               <h3>Analyzed Files:</h3>
+               <ul>
+                  <xsl:for-each select="/BugCollection/Project/Jar">
+                     <li><xsl:apply-templates /></li>
+                  </xsl:for-each>
+               </ul>
+            </div>
+            <div id='used-libraries'>
+               <h3>Used Libraries:</h3>
+               <ul>
+                  <xsl:for-each select="/BugCollection/Project/AuxClasspathEntry">
+                     <li><xsl:apply-templates /></li>
+                  </xsl:for-each>
+                  <xsl:if test="count(/BugCollection/Project/AuxClasspathEntry)=0" >
+                     <li>None</li>
+                  </xsl:if>
+               </ul>
+            </div>
+            <div id='analysis-error'>
+               <h3>Analysis Errors:</h3>
+               <ul>
+                  <xsl:variable name="error-count"
+                                select="count(/BugCollection/Errors/MissingClass)" />
+                  <xsl:if test="$error-count=0" >
+                     <li>None</li>
+                  </xsl:if>
+                  <xsl:if test="$error-count>0" >
+                     <li>Missing ref classes for analysis:
+                        <ul>
+                           <xsl:for-each select="/BugCollection/Errors/MissingClass">
+                              <li><xsl:apply-templates /></li>
+                           </xsl:for-each>
+                        </ul>
+                     </li>
+                  </xsl:if>
+               </ul>
+            </div>
+         </div>
+         <div id='historyContainer'          class='displayContainer'>Loading...</div>
+         <div id='listByCategoriesContainer' class='displayContainer'>Loading...</div>
+         <div id='listByPackagesContainer'   class='displayContainer'>Loading...</div>
+      </div>
+
+      <div id='bug-collection' style='display:none;'>
+      <!-- advanced tooltips -->
+      <xsl:for-each select="/BugCollection/BugPattern">
+         <xsl:variable name="b-t"><xsl:value-of select="@type" /></xsl:variable>
+         <div>
+            <xsl:attribute name="id">tip-<xsl:value-of select="$b-t" /></xsl:attribute>
+            <xsl:attribute name="class">tip</xsl:attribute>
+            <xsl:value-of select="/BugCollection/BugPattern[@type=$b-t]/Details" disable-output-escaping="yes" />
+         </div>
+      </xsl:for-each>
+
+      <!-- bug descriptions - hidden -->
+      <xsl:for-each select="/BugCollection/BugInstance[not(@last)]">
+            <div style="display:none;" class='bug'>
+               <xsl:attribute name="id">b-uid-<xsl:value-of select="@instanceHash" />-<xsl:value-of select="@instanceOccurrenceNum" /></xsl:attribute>
+               <xsl:for-each select="*/Message">
+                  <div class="b-r"><xsl:apply-templates /></div>
+               </xsl:for-each>
+               <div class="b-d">
+                  <xsl:value-of select="LongMessage" disable-output-escaping="no" />
+               </div>
+            </div>
+      </xsl:for-each>
+      </div>
+   </body>
+</html>
+</xsl:template>
+
+
+</xsl:transform>
+
diff --git a/cnf/findbugs/src/xsl/fancy.xsl b/cnf/findbugs/src/xsl/fancy.xsl
new file mode 100644
index 0000000..c6f43c5
--- /dev/null
+++ b/cnf/findbugs/src/xsl/fancy.xsl
@@ -0,0 +1,848 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+  Copyright (C) 2005, 2006 Etienne Giraudy, InStranet Inc
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+-->
+
+<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" >
+   <xsl:output
+         method="xml" indent="yes"
+         doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
+         doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
+         encoding="UTF-8"/>
+
+    <!--
+        Parameter for specifying HTMLized sources location; if current dir, use "./"
+        If not passed, no links to sources are generated.
+        because of back-compatibility reasons.
+        The source filename should be package.class.java.html
+        The source can have line no anchors like #11 -->
+    <xsl:param name="htmlsrcpath"></xsl:param>
+
+   <!--xsl:key name="lbc-category-key"    match="/BugCollection/BugInstance" use="@category" /-->
+   <xsl:key name="lbc-code-key"        match="/BugCollection/BugInstance" use="concat(@category, at abbrev)" />
+   <xsl:key name="lbc-bug-key"         match="/BugCollection/BugInstance" use="concat(@category, at abbrev, at type)" />
+   <xsl:key name="lbp-class-b-t"  match="/BugCollection/BugInstance" use="concat(Class/@classname, at type)" />
+
+<xsl:template match="/" >
+
+<html>
+   <head>
+      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+      <title>
+        FindBugs (<xsl:value-of select="/BugCollection/@version" />)
+         Analysis for
+         <xsl:choose>
+            <xsl:when test='string-length(/BugCollection/Project/@projectName)>0'><xsl:value-of select="/BugCollection/Project/@projectName" /></xsl:when>
+            <xsl:otherwise><xsl:value-of select="/BugCollection/Project/@filename" /></xsl:otherwise>
+         </xsl:choose>
+      </title>
+      <script type="text/javascript">
+         function show(foo) {
+            document.getElementById(foo).style.display="block";
+         }
+         function hide(foo) {
+            document.getElementById(foo).style.display="none";
+         }
+         function toggle(foo) {
+            if( document.getElementById(foo).style.display == "none") {
+               show(foo);
+            } else {
+               if( document.getElementById(foo).style.display == "block") {
+                  hide(foo);
+               } else {
+                  show(foo);
+               }
+            }
+         }
+
+         function showmenu(foo) {
+            if( document.getElementById(foo).style.display == "none") {
+               hide("bug-summary");
+               document.getElementById("bug-summary-tab").className="menu-tab";
+               hide("analysis-data");
+               document.getElementById("analysis-data-tab").className="menu-tab";
+               //hide("list-by-b-t");
+               //document.getElementById("list-by-b-t-tab").className="menu-tab";
+               hide("list-by-package");
+               document.getElementById("list-by-package-tab").className="menu-tab";
+               hide("list-by-category");
+               document.getElementById("list-by-category-tab").className="menu-tab";
+               document.getElementById(foo+"-tab").className="menu-tab-selected";
+               show(foo);
+
+            }
+            // else menu already selected!
+         }
+         function showbug(buguid, list) {
+            var bugplaceholder   = document.getElementById(buguid+'-ph-'+list);
+            var bug              = document.getElementById(buguid);
+
+            if ( bugplaceholder==null) {
+               alert(buguid+'-ph-'+list+' - '+buguid+' - bugplaceholder==null');
+               return;
+            }
+            if ( bug==null) {
+               alert(buguid+'-ph-'+list+' - '+buguid+' - bug==null');
+               return;
+            }
+
+            var oldBug = bugplaceholder.innerHTML;
+            var newBug = bug.innerHTML;
+            //alert(oldBug);
+            //alert(newBug);
+            toggle(buguid+'-ph-'+list);
+            bugplaceholder.innerHTML = newBug;
+         }
+      </script>
+      <script type='text/javascript'><xsl:text disable-output-escaping='yes'>
+     /* <![CDATA[ */
+         // Extended Tooltip Javascript
+         // copyright 9th August 2002, 3rd July 2005
+         // by Stephen Chapman, Felgall Pty Ltd
+
+         // permission is granted to use this javascript provided that the below code is not altered
+         var DH = 0;var an = 0;var al = 0;var ai = 0;if (document.getElementById) {ai = 1; DH = 1;}else {if (document.all) {al = 1; DH = 1;} else { browserVersion = parseInt(navigator.appVersion); if (navigator.appName.indexOf('Netscape') != -1) if (browserVersion == 4) {an = 1; DH = 1;}}}
+         function fd(oi, wS) {if (ai) return wS ? document.getElementById(oi).style:document.getElementById(oi); if (al) return wS ? document.all[oi].style: document.all[oi]; if (an) return document.layers[oi];}
+         function pw() {return window.innerWidth != null? window.innerWidth: document.body.clientWidth != null? document.body.clientWidth:null;}
+         function mouseX(evt) {if (evt.pageX) return evt.pageX; else if (evt.clientX)return evt.clientX + (document.documentElement.scrollLeft ?  document.documentElement.scrollLeft : document.body.scrollLeft); else return null;}
+         function mouseY(evt) {if (evt.pageY) return evt.pageY; else if (evt.clientY)return evt.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop); else return null;}
+         function popUp(evt,oi) {if (DH) {var wp = pw(); ds = fd(oi,1); dm = fd(oi,0); st = ds.visibility; if (dm.offsetWidth) ew = dm.offsetWidth; else if (dm.clip.width) ew = dm.clip.width; if (st == "visible" || st == "show") { ds.visibility = "hidden"; } else {tv = mouseY(evt) + 20; lv = mouseX(evt) - (ew/4); if (lv < 2) lv = 2; else if (lv + ew > wp) lv -= ew/2; if (!an) {lv += 'px';tv += 'px';} ds.left = lv; ds.top = tv; ds.visibility = "visible";}}}
+  /* ]]> */
+</xsl:text></script>
+      <style type='text/css'>
+         html, body {
+            background-color: #ffffff;
+         }
+         a, a:link , a:active, a:visited, a:hover {
+            text-decoration: none; color: black;
+         }
+         .b-r a {
+            text-decoration: underline; color: blue;
+         }
+         div, span {
+            vertical-align: top;
+         }
+         p {
+            margin: 0px;
+         }
+         h1 {
+            /*font-size: 14pt;*/
+            color: red;
+         }
+         #menu {
+            margin-bottom: 10px;
+         }
+         #menu ul {
+            margin-left: 0;
+            padding-left: 0;
+            display: inline;
+         }
+         #menu ul li {
+            margin-left: 0;
+            margin-bottom: 0;
+            padding: 2px 15px 5px;
+            border: 1px solid #000;
+            list-style: none;
+            display: inline;
+         }
+         #menu ul li.here {
+            border-bottom: 1px solid #ffc;
+            list-style: none;
+            display: inline;
+         }
+         .menu-tab {
+            background: white;
+         }
+         .menu-tab:hover {
+            background: grey;
+         }
+         .menu-tab-selected {
+            background: #aaaaaa;
+         }
+         #analysis-data ul {
+            margin-left: 15px;
+         }
+         #analyzed-files, #used-libraries, #analysis-error {
+           margin: 2px;
+           border: 1px black solid;
+           padding: 2px;
+           float: left;
+           overflow:auto;
+         }
+         #analyzed-files {
+           width: 25%;
+         }
+         #used-libraries {
+           width: 25%;
+         }
+         #analysis-error {
+           width: 40%;
+         }
+         div.summary {
+            width:100%;
+            text-align:left;
+         }
+         .summary table {
+            border:1px solid black;
+         }
+         .summary th {
+            background: #aaaaaa;
+            color: white;
+         }
+         .summary th, .summary td {
+            padding: 2px 4px 2px 4px;
+         }
+         .summary-name {
+            background: #eeeeee;
+            text-align:left;
+         }
+         .summary-size {
+            background: #eeeeee;
+            text-align:center;
+         }
+         .summary-ratio {
+            background: #eeeeee;
+            text-align:center;
+         }
+         .summary-priority-all {
+            background: #dddddd;
+            text-align:center;
+         }
+         .summary-priority-1 {
+            background: red;
+            text-align:center;
+         }
+         .summary-priority-2 {
+            background: orange;
+            text-align:center;
+         }
+         .summary-priority-3 {
+            background: green;
+            text-align:center;
+         }
+         .summary-priority-4 {
+            background: blue;
+            text-align:center;
+         }
+         .ob {
+            border: 1px solid black;
+            margin: 10px;
+         }
+         .ob-t {
+            border-bottom: 1px solid #000000; font-size: 12pt; font-weight: bold;
+            background: #cccccc; margin: 0; padding: 0 5px 0 5px;
+         }
+         .t-h {
+            font-weight: normal;
+         }
+         .ib-1, .ib-2 {
+            margin: 0 0 0 10px;
+         }
+         .ib-1-t, .ib-2-t {
+            border-bottom: 1px solid #000000; border-left: 1px solid #000000;
+            margin: 0; padding: 0 5px 0 5px;
+            font-size: 12pt; font-weight: bold; background: #cccccc;
+         }
+         .bb {
+            border-bottom: 1px solid #000000; border-left: 1px solid #000000;
+         }
+         .b-1 {
+            background: red; height: 0.5em; width: 1em;
+            margin-right: 0.5em;
+         }
+         .b-2 {
+            background: orange; height: 0.5em; width: 1em;
+            margin-right: 0.5em;
+         }
+         .b-3 {
+            background: green; height: 0.5em; width: 1em;
+            margin-right: 0.5em;
+         }
+         .b-4 {
+            background: blue; height: 0.5em; width: 1em;
+            margin-right: 0.5em;
+         }
+         .b-t {
+         }
+         .b-r {
+            font-size: 10pt; font-weight: bold; padding: 0 0 0 60px;
+         }
+         .b-d {
+            font-weight: normal; background: #eeeee0;
+            padding: 0 5px 0 5px; margin: 0px;
+         }
+         .bug-placeholder {
+            top:140px;
+            border:1px solid black;
+            display:none;
+         }
+         .tip {
+            border:solid 1px #666666;
+            width:600px;
+            padding:3px;
+            position:absolute;
+            z-index:100;
+            visibility:hidden;
+            color:#333333;
+            top:20px;
+            left:90px;
+            background-color:#ffffcc;
+            layer-background-color:#ffffcc;
+         }
+
+
+      </style>
+   </head>
+   <body>
+   <div id='content'>
+      <h1>
+         FindBugs (<xsl:value-of select="/BugCollection/@version" />)
+         Analysis for
+         <xsl:choose>
+            <xsl:when test='string-length(/BugCollection/Project/@projectName)>0'><xsl:value-of select="/BugCollection/Project/@projectName" /></xsl:when>
+            <xsl:otherwise><xsl:value-of select="/BugCollection/Project/@filename" /></xsl:otherwise>
+         </xsl:choose>
+      </h1>
+      <div id="menu">
+         <ul>
+            <li id='bug-summary-tab' class='menu-tab-selected'>
+               <xsl:attribute name="onclick">showmenu('bug-summary');return false;</xsl:attribute>
+               <a href='' onclick='return false;'>Bug Summary</a>
+            </li>
+            <li id='analysis-data-tab' class='menu-tab'>
+               <xsl:attribute name="onclick">showmenu('analysis-data');return false;</xsl:attribute>
+               <a href='' onclick='return false;'>Analysis Information</a>
+            </li>
+            <li id='list-by-category-tab' class='menu-tab'>
+               <xsl:attribute name="onclick">showmenu('list-by-category');return false;</xsl:attribute>
+               <a href='' onclick='return false;'>List bugs by bug category</a>
+            </li>
+            <li id='list-by-package-tab' class='menu-tab'>
+               <xsl:attribute name="onclick">showmenu('list-by-package');return false;</xsl:attribute>
+               <a href='' onclick='return false;'>List bugs by package</a>
+            </li>
+         </ul>
+      </div>
+      <xsl:call-template name="generateSummary" />
+      <xsl:call-template name="analysis-data" />
+      <xsl:call-template name="list-by-category" />
+      <xsl:call-template name="list-by-package" />
+
+
+      <!-- advanced tooltips -->
+      <xsl:for-each select="/BugCollection/BugPattern">
+         <xsl:variable name="b-t"><xsl:value-of select="@type" /></xsl:variable>
+         <div>
+            <xsl:attribute name="id">tip-<xsl:value-of select="$b-t" /></xsl:attribute>
+            <xsl:attribute name="class">tip</xsl:attribute>
+            <b><xsl:value-of select="@abbrev" /> / <xsl:value-of select="@type" /></b><br/>
+            <xsl:value-of select="/BugCollection/BugPattern[@type=$b-t]/Details" disable-output-escaping="yes" />
+         </div>
+      </xsl:for-each>
+
+      <!-- bug descriptions - hidden -->
+      <xsl:for-each select="/BugCollection/BugInstance[not(@last)]">
+            <div style="display:none;">
+               <xsl:attribute name="id">b-uid-<xsl:value-of select="@instanceHash" />-<xsl:value-of select="@instanceOccurrenceNum" /></xsl:attribute>
+               <xsl:for-each select="*/Message">
+                   <xsl:choose>
+                    <xsl:when test="parent::SourceLine and $htmlsrcpath != '' ">
+                      <div class="b-r"><a>
+                        <xsl:attribute name="href"><xsl:value-of select="$htmlsrcpath"/><xsl:value-of select="../@sourcepath" />.html#<xsl:value-of select="../@start" /></xsl:attribute>
+                        <xsl:apply-templates />
+                      </a></div>
+                    </xsl:when>
+                    <xsl:otherwise>
+                      <div class="b-r"><xsl:apply-templates /></div>
+                    </xsl:otherwise>
+                   </xsl:choose>
+               </xsl:for-each>
+               <div class="b-d">
+                  <xsl:value-of select="LongMessage" disable-output-escaping="no" />
+               </div>
+            </div>
+      </xsl:for-each>
+   </div>
+   <div id='fixedbox'>
+      <div id='bug-placeholder'></div>
+   </div>
+   </body>
+</html>
+</xsl:template>
+
+<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
+<!-- generate summary report from stats -->
+<xsl:template name="generateSummary" >
+<div class='summary' id='bug-summary'>
+   <h2>FindBugs Analysis generated at: <xsl:value-of select="/BugCollection/FindBugsSummary/@timestamp" /></h2>
+   <table>
+      <tr>
+         <th>Package</th>
+         <th>Code Size</th>
+         <th>Bugs</th>
+         <th>High Prio Bugs</th>
+         <th>Medium Prio Bugs</th>
+         <th>Low Prio Bugs</th>
+         <th>Exp. Bugs</th>
+         <th>Ratio</th>
+      </tr>
+      <tr>
+         <td class='summary-name'>
+            Overall
+            (<xsl:value-of select="/BugCollection/FindBugsSummary/@num_packages" /> packages),
+            (<xsl:value-of select="/BugCollection/FindBugsSummary/@total_classes" /> classes)
+         </td>
+         <td class='summary-size'><xsl:value-of select="/BugCollection/FindBugsSummary/@total_size" /></td>
+         <td class='summary-priority-all'><xsl:value-of select="/BugCollection/FindBugsSummary/@total_bugs" /></td>
+         <td class='summary-priority-1'><xsl:value-of select="/BugCollection/FindBugsSummary/@priority_1" /></td>
+         <td class='summary-priority-2'><xsl:value-of select="/BugCollection/FindBugsSummary/@priority_2" /></td>
+         <td class='summary-priority-3'><xsl:value-of select="/BugCollection/FindBugsSummary/@priority_3" /></td>
+         <td class='summary-priority-4'><xsl:value-of select="/BugCollection/FindBugsSummary/@priority_4" /></td>
+         <td class='summary-ratio'></td>
+      </tr>
+      <xsl:for-each select="/BugCollection/FindBugsSummary/PackageStats">
+         <xsl:sort select="@package" />
+         <xsl:if test="@total_bugs!='0'" >
+            <tr>
+               <td class='summary-name'><xsl:value-of select="@package" /></td>
+               <td class='summary-size'><xsl:value-of select="@total_size" /></td>
+               <td class='summary-priority-all'><xsl:value-of select="@total_bugs" /></td>
+               <td class='summary-priority-1'><xsl:value-of select="@priority_1" /></td>
+               <td class='summary-priority-2'><xsl:value-of select="@priority_2" /></td>
+               <td class='summary-priority-3'><xsl:value-of select="@priority_3" /></td>
+               <td class='summary-priority-4'><xsl:value-of select="@priority_4" /></td>
+               <td class='summary-ratio'></td>
+<!--
+               <xsl:for-each select="ClassStats">
+                  <xsl:if test="@bugs!='0'" >
+                  <li>
+                     <xsl:value-of select="@class" /> - total: <xsl:value-of select="@bugs" />
+                  </li>
+                  </xsl:if>
+               </xsl:for-each>
+-->
+            </tr>
+         </xsl:if>
+      </xsl:for-each>
+   </table>
+</div>
+</xsl:template>
+
+<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
+<!-- display analysis info -->
+<xsl:template name="analysis-data">
+      <div id='analysis-data' style='display:none;'>
+         <div id='analyzed-files'>
+            <h3>Analyzed Files:</h3>
+            <ul>
+               <xsl:for-each select="/BugCollection/Project/Jar">
+                  <li><xsl:apply-templates /></li>
+               </xsl:for-each>
+            </ul>
+         </div>
+         <div id='used-libraries'>
+            <h3>Used Libraries:</h3>
+            <ul>
+               <xsl:for-each select="/BugCollection/Project/AuxClasspathEntry">
+                  <li><xsl:apply-templates /></li>
+               </xsl:for-each>
+               <xsl:if test="count(/BugCollection/Project/AuxClasspathEntry)=0" >
+                  <li>None</li>
+               </xsl:if>
+            </ul>
+         </div>
+         <div id='analysis-error'>
+            <h3>Analysis Errors:</h3>
+            <ul>
+               <xsl:variable name="error-count"
+                             select="count(/BugCollection/Errors/MissingClass)" />
+               <xsl:if test="$error-count=0" >
+                  <li>None</li>
+               </xsl:if>
+               <xsl:if test="$error-count>0" >
+                  <li>Missing ref classes for analysis:
+                     <ul>
+                        <xsl:for-each select="/BugCollection/Errors/MissingClass">
+                           <li><xsl:apply-templates /></li>
+                        </xsl:for-each>
+                     </ul>
+                  </li>
+               </xsl:if>
+            </ul>
+         </div>
+      </div>
+</xsl:template>
+
+<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
+<!-- show priorities helper -->
+<xsl:template name="helpPriorities">
+   <span>
+      <xsl:attribute name="class">b-1</xsl:attribute>
+      <xsl:text disable-output-escaping="yes">&nbsp;&nbsp;</xsl:text>
+   </span> High Prio
+   <span>
+      <xsl:attribute name="class">b-2</xsl:attribute>
+      <xsl:text disable-output-escaping="yes">&nbsp;&nbsp;</xsl:text>
+   </span> Medium Prio
+   <span>
+      <xsl:attribute name="class">b-3</xsl:attribute>
+      <xsl:text disable-output-escaping="yes">&nbsp;&nbsp;</xsl:text>
+   </span> Low Prio
+   <span>
+      <xsl:attribute name="class">b-4</xsl:attribute>
+      <xsl:text disable-output-escaping="yes">&nbsp;&nbsp;</xsl:text>
+   </span> Exp.
+</xsl:template>
+
+<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
+<!-- display the details of a bug -->
+<xsl:template name="display-bug" >
+   <xsl:param name="b-t"    select="''" />
+   <xsl:param name="bug-id"      select="''" />
+   <xsl:param name="which-list"  select="''" />
+   <div class="bb">
+      <a>
+         <xsl:attribute name="href"></xsl:attribute>
+         <xsl:attribute name="onclick">showbug('b-uid-<xsl:value-of select="@instanceHash" />-<xsl:value-of select="@instanceOccurrenceNum" />','<xsl:value-of select="$which-list" />');return false;</xsl:attribute>
+         <span>
+            <xsl:attribute name="class">b-<xsl:value-of select="@priority"/></xsl:attribute>
+            <xsl:text disable-output-escaping="yes">&nbsp;&nbsp;</xsl:text>
+         </span>
+         <span class="b-t"><xsl:value-of select="@abbrev" />: </span> <xsl:value-of select="Class/Message" />
+      </a>
+      <div style="display:none;">
+         <xsl:attribute name="id">b-uid-<xsl:value-of select="@instanceHash" />-<xsl:value-of select="@instanceOccurrenceNum" />-ph-<xsl:value-of select="$which-list" /></xsl:attribute>
+         loading...
+      </div>
+   </div>
+</xsl:template>
+
+<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
+<!-- main template for the list by category -->
+<xsl:template name="list-by-category" >
+   <div id='list-by-category' class='data-box' style='display:none;'>
+      <xsl:call-template name="helpPriorities" />
+      <xsl:variable name="unique-category" select="/BugCollection/BugCategory/@category"/>
+      <xsl:for-each select="$unique-category">
+         <xsl:sort select="." order="ascending" />
+            <xsl:call-template name="categories">
+               <xsl:with-param name="category" select="." />
+            </xsl:call-template>
+      </xsl:for-each>
+   </div>
+</xsl:template>
+
+<xsl:template name="categories" >
+   <xsl:param name="category" select="''" />
+   <xsl:variable name="category-count"
+                       select="count(/BugCollection/BugInstance[@category=$category and not(@last)])" />
+   <xsl:variable name="category-count-p1"
+                       select="count(/BugCollection/BugInstance[@category=$category and @priority='1' and not(@last)])" />
+   <xsl:variable name="category-count-p2"
+                       select="count(/BugCollection/BugInstance[@category=$category and @priority='2' and not(@last)])" />
+   <xsl:variable name="category-count-p3"
+                       select="count(/BugCollection/BugInstance[@category=$category and @priority='3' and not(@last)])" />
+   <xsl:variable name="category-count-p4"
+                       select="count(/BugCollection/BugInstance[@category=$category and @priority='4' and not(@last)])" />
+   <div class='ob'>
+      <div class='ob-t'>
+         <a>
+            <xsl:attribute name="href"></xsl:attribute>
+            <xsl:attribute name="onclick">toggle('category-<xsl:value-of select="$category" />');return false;</xsl:attribute>
+            <xsl:value-of select="/BugCollection/BugCategory[@category=$category]/Description" />
+            (<xsl:value-of select="$category-count" />:
+            <span class='t-h'><xsl:value-of select="$category-count-p1" />/<xsl:value-of select="$category-count-p2" />/<xsl:value-of select="$category-count-p3" />/<xsl:value-of select="$category-count-p4" /></span>)
+         </a>
+      </div>
+      <div style="display:none;">
+         <xsl:attribute name="id">category-<xsl:value-of select="$category" /></xsl:attribute>
+         <xsl:call-template name="list-by-category-and-code">
+            <xsl:with-param name="category" select="$category" />
+         </xsl:call-template>
+      </div>
+   </div>
+</xsl:template>
+
+<xsl:template name="list-by-category-and-code" >
+   <xsl:param name="category" select="''" />
+   <xsl:variable name="unique-code" select="/BugCollection/BugInstance[@category=$category and not(@last) and generate-id()= generate-id(key('lbc-code-key',concat(@category, at abbrev)))]/@abbrev" />
+   <xsl:for-each select="$unique-code">
+      <xsl:sort select="." order="ascending" />
+         <xsl:call-template name="codes">
+            <xsl:with-param name="category" select="$category" />
+            <xsl:with-param name="code" select="." />
+         </xsl:call-template>
+   </xsl:for-each>
+</xsl:template>
+
+<xsl:template name="codes" >
+   <xsl:param name="category" select="''" />
+   <xsl:param name="code"     select="''" />
+   <xsl:variable name="code-count"
+                       select="count(/BugCollection/BugInstance[@category=$category and @abbrev=$code and not(@last)])" />
+   <xsl:variable name="code-count-p1"
+                       select="count(/BugCollection/BugInstance[@category=$category and @abbrev=$code and @priority='1' and not(@last)])" />
+   <xsl:variable name="code-count-p2"
+                       select="count(/BugCollection/BugInstance[@category=$category and @abbrev=$code and @priority='2' and not(@last)])" />
+   <xsl:variable name="code-count-p3"
+                       select="count(/BugCollection/BugInstance[@category=$category and @abbrev=$code and @priority='3' and not(@last)])" />
+   <xsl:variable name="code-count-p4"
+                       select="count(/BugCollection/BugInstance[@category=$category and @abbrev=$code and @priority='4' and not(@last)])" />
+   <div class='ib-1'>
+      <div class="ib-1-t">
+         <a>
+            <xsl:attribute name="href"></xsl:attribute>
+            <xsl:attribute name="onclick">toggle('category-<xsl:value-of select="$category" />-and-code-<xsl:value-of select="$code" />');return false;</xsl:attribute>
+            <xsl:value-of select="$code" />: <xsl:value-of select="/BugCollection/BugCode[@abbrev=$code]/Description" />
+            (<xsl:value-of select="$code-count" />:
+            <span class='t-h'><xsl:value-of select="$code-count-p1" />/<xsl:value-of select="$code-count-p2" />/<xsl:value-of select="$code-count-p3" />/<xsl:value-of select="$code-count-p4" /></span>)
+         </a>
+      </div>
+      <div style="display:none;">
+         <xsl:attribute name="id">category-<xsl:value-of select="$category" />-and-code-<xsl:value-of select="$code" /></xsl:attribute>
+         <xsl:call-template name="list-by-category-and-code-and-bug">
+            <xsl:with-param name="category" select="$category" />
+            <xsl:with-param name="code" select="$code" />
+         </xsl:call-template>
+      </div>
+   </div>
+</xsl:template>
+
+<xsl:template name="list-by-category-and-code-and-bug" >
+   <xsl:param name="category" select="''" />
+   <xsl:param name="code" select="''" />
+   <xsl:variable name="unique-bug" select="/BugCollection/BugInstance[@category=$category and not(@last) and @abbrev=$code and generate-id()= generate-id(key('lbc-bug-key',concat(@category, at abbrev, at type)))]/@type" />
+   <xsl:for-each select="$unique-bug">
+      <xsl:sort select="." order="ascending" />
+         <xsl:call-template name="bugs">
+            <xsl:with-param name="category" select="$category" />
+            <xsl:with-param name="code" select="$code" />
+            <xsl:with-param name="bug" select="." />
+         </xsl:call-template>
+   </xsl:for-each>
+</xsl:template>
+
+<xsl:template name="bugs" >
+   <xsl:param name="category" select="''" />
+   <xsl:param name="code"     select="''" />
+   <xsl:param name="bug"      select="''" />
+   <xsl:variable name="bug-count"
+                       select="count(/BugCollection/BugInstance[@category=$category and @abbrev=$code and @type=$bug and not(@last)])" />
+   <xsl:variable name="bug-count-p1"
+                       select="count(/BugCollection/BugInstance[@category=$category and @abbrev=$code and @type=$bug and @priority='1' and not(@last)])" />
+   <xsl:variable name="bug-count-p2"
+                       select="count(/BugCollection/BugInstance[@category=$category and @abbrev=$code and @type=$bug and @priority='2' and not(@last)])" />
+   <xsl:variable name="bug-count-p3"
+                       select="count(/BugCollection/BugInstance[@category=$category and @abbrev=$code and @type=$bug and @priority='3' and not(@last)])" />
+   <xsl:variable name="bug-count-p4"
+                       select="count(/BugCollection/BugInstance[@category=$category and @abbrev=$code and @type=$bug and @priority='4' and not(@last)])" />
+   <div class='ib-2'>
+      <div class='ib-2-t'>
+         <a>
+            <xsl:attribute name="href"></xsl:attribute>
+            <xsl:attribute name="onclick">toggle('category-<xsl:value-of select="$category" />-and-code-<xsl:value-of select="$code" />-and-bug-<xsl:value-of select="$bug" />');return false;</xsl:attribute>
+            <xsl:attribute name="onmouseout">popUp(event,'tip-<xsl:value-of select="$bug" />');</xsl:attribute>
+            <xsl:attribute name="onmouseover">popUp(event,'tip-<xsl:value-of select="$bug" />');</xsl:attribute>
+            <xsl:value-of select="/BugCollection/BugPattern[@category=$category and @abbrev=$code and @type=$bug]/ShortDescription" /><xsl:text disable-output-escaping="yes">&nbsp;&nbsp;</xsl:text>
+            (<xsl:value-of select="$bug-count" />:
+            <span class='t-h'><xsl:value-of select="$bug-count-p1" />/<xsl:value-of select="$bug-count-p2" />/<xsl:value-of select="$bug-count-p3" />/<xsl:value-of select="$bug-count-p4" /></span>)
+         </a>
+      </div>
+      <div style="display:none;">
+         <xsl:attribute name="id">category-<xsl:value-of select="$category" />-and-code-<xsl:value-of select="$code" />-and-bug-<xsl:value-of select="$bug" /></xsl:attribute>
+         <xsl:variable name="cat-code-type">category-<xsl:value-of select="$category" />-and-code-<xsl:value-of select="$code" />-and-bug-<xsl:value-of select="$bug" /></xsl:variable>
+         <xsl:variable name="bug-id">b-uid-<xsl:value-of select="@instanceHash" />-<xsl:value-of select="@instanceOccurrenceNum" /></xsl:variable>
+         <xsl:for-each select="/BugCollection/BugInstance[@category=$category and @abbrev=$code and @type=$bug and not(@last)]">
+            <xsl:call-template name="display-bug">
+               <xsl:with-param name="b-t"     select="@type" />
+               <xsl:with-param name="bug-id"       select="$bug-id" />
+               <xsl:with-param name="which-list"   select="'c'" />
+            </xsl:call-template>
+         </xsl:for-each>
+      </div>
+   </div>
+</xsl:template>
+
+<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
+<!-- main template for the list by package -->
+<xsl:template name="list-by-package" >
+   <div id='list-by-package' class='data-box' style='display:none;'>
+      <xsl:call-template name="helpPriorities" />
+      <xsl:for-each select="/BugCollection/FindBugsSummary/PackageStats[@total_bugs != '0']/@package">
+         <xsl:sort select="." order="ascending" />
+            <xsl:call-template name="packages">
+               <xsl:with-param name="package" select="." />
+            </xsl:call-template>
+      </xsl:for-each>
+   </div>
+</xsl:template>
+
+<xsl:template name="packages" >
+   <xsl:param name="package" select="''" />
+   <xsl:variable name="package-count-p1">
+      <xsl:if test="not(/BugCollection/FindBugsSummary/PackageStats[@package=$package]/@priority_1 != '')">0</xsl:if>
+      <xsl:if test="/BugCollection/FindBugsSummary/PackageStats[@package=$package]/@priority_1 != ''">
+         <xsl:value-of select="/BugCollection/FindBugsSummary/PackageStats[@package=$package]/@priority_1" />
+      </xsl:if>
+   </xsl:variable>
+   <xsl:variable name="package-count-p2">
+      <xsl:if test="not(/BugCollection/FindBugsSummary/PackageStats[@package=$package]/@priority_2 != '')">0</xsl:if>
+      <xsl:if test="/BugCollection/FindBugsSummary/PackageStats[@package=$package]/@priority_2 != ''">
+         <xsl:value-of select="/BugCollection/FindBugsSummary/PackageStats[@package=$package]/@priority_2" />
+      </xsl:if>
+   </xsl:variable>
+   <xsl:variable name="package-count-p3">
+      <xsl:if test="not(/BugCollection/FindBugsSummary/PackageStats[@package=$package]/@priority_3 != '')">0</xsl:if>
+      <xsl:if test="/BugCollection/FindBugsSummary/PackageStats[@package=$package]/@priority_3 != ''">
+         <xsl:value-of select="/BugCollection/FindBugsSummary/PackageStats[@package=$package]/@priority_3" />
+      </xsl:if>
+   </xsl:variable>
+   <xsl:variable name="package-count-p4">
+      <xsl:if test="not(/BugCollection/FindBugsSummary/PackageStats[@package=$package]/@priority_4 != '')">0</xsl:if>
+      <xsl:if test="/BugCollection/FindBugsSummary/PackageStats[@package=$package]/@priority_4 != ''">
+         <xsl:value-of select="/BugCollection/FindBugsSummary/PackageStats[@package=$package]/@priority_4" />
+      </xsl:if>
+   </xsl:variable>
+
+   <div class='ob'>
+      <div class='ob-t'>
+         <a>
+            <xsl:attribute name="href"></xsl:attribute>
+            <xsl:attribute name="onclick">toggle('package-<xsl:value-of select="$package" />');return false;</xsl:attribute>
+            <xsl:value-of select="$package" />
+            (<xsl:value-of select="/BugCollection/FindBugsSummary/PackageStats[@package=$package]/@total_bugs" />:
+            <span class='t-h'><xsl:value-of select="$package-count-p1" />/<xsl:value-of select="$package-count-p2" />/<xsl:value-of select="$package-count-p3" />/<xsl:value-of select="$package-count-p4" /></span>)
+         </a>
+      </div>
+      <div style="display:none;">
+         <xsl:attribute name="id">package-<xsl:value-of select="$package" /></xsl:attribute>
+         <xsl:call-template name="list-by-package-and-class">
+            <xsl:with-param name="package" select="$package" />
+         </xsl:call-template>
+      </div>
+   </div>
+</xsl:template>
+
+<xsl:template name="list-by-package-and-class" >
+   <xsl:param name="package" select="''" />
+   <xsl:for-each select="/BugCollection/FindBugsSummary/PackageStats[@package=$package]/ClassStats[@bugs != '0']/@class">
+      <xsl:sort select="." order="ascending" />
+         <xsl:call-template name="classes">
+            <xsl:with-param name="package" select="$package" />
+            <xsl:with-param name="class" select="." />
+         </xsl:call-template>
+   </xsl:for-each>
+</xsl:template>
+
+<xsl:template name="classes" >
+   <xsl:param name="package" select="''" />
+   <xsl:param name="class"     select="''" />
+   <xsl:variable name="class-count"
+                       select="/BugCollection/FindBugsSummary/PackageStats[@package=$package]/ClassStats[@class=$class and @bugs != '0']/@bugs" />
+
+   <xsl:variable name="class-count-p1">
+      <xsl:if test="not(/BugCollection/FindBugsSummary/PackageStats[@package=$package]/ClassStats[@class=$class and @bugs != '0']/@priority_1 != '')">0</xsl:if>
+      <xsl:if test="/BugCollection/FindBugsSummary/PackageStats[@package=$package]/ClassStats[@class=$class and @bugs != '0']/@priority_1 != ''">
+         <xsl:value-of select="/BugCollection/FindBugsSummary/PackageStats[@package=$package]/ClassStats[@class=$class and @bugs != '0']/@priority_1" />
+      </xsl:if>
+   </xsl:variable>
+   <xsl:variable name="class-count-p2">
+      <xsl:if test="not(/BugCollection/FindBugsSummary/PackageStats[@package=$package]/ClassStats[@class=$class and @bugs != '0']/@priority_2 != '')">0</xsl:if>
+      <xsl:if test="/BugCollection/FindBugsSummary/PackageStats[@package=$package]/ClassStats[@class=$class and @bugs != '0']/@priority_2 != ''">
+         <xsl:value-of select="/BugCollection/FindBugsSummary/PackageStats[@package=$package]/ClassStats[@class=$class and @bugs != '0']/@priority_2" />
+      </xsl:if>
+   </xsl:variable>
+   <xsl:variable name="class-count-p3">
+      <xsl:if test="not(/BugCollection/FindBugsSummary/PackageStats[@package=$package]/ClassStats[@class=$class and @bugs != '0']/@priority_3 != '')">0</xsl:if>
+      <xsl:if test="/BugCollection/FindBugsSummary/PackageStats[@package=$package]/ClassStats[@class=$class and @bugs != '0']/@priority_3 != ''">
+         <xsl:value-of select="/BugCollection/FindBugsSummary/PackageStats[@package=$package]/ClassStats[@class=$class and @bugs != '0']/@priority_3" />
+      </xsl:if>
+   </xsl:variable>
+   <xsl:variable name="class-count-p4">
+      <xsl:if test="not(/BugCollection/FindBugsSummary/PackageStats[@package=$package]/ClassStats[@class=$class and @bugs != '0']/@priority_4 != '')">0</xsl:if>
+      <xsl:if test="/BugCollection/FindBugsSummary/PackageStats[@package=$package]/ClassStats[@class=$class and @bugs != '0']/@priority_4 != ''">
+         <xsl:value-of select="/BugCollection/FindBugsSummary/PackageStats[@package=$package]/ClassStats[@class=$class and @bugs != '0']/@priority_4" />
+      </xsl:if>
+   </xsl:variable>
+
+   <div class='ib-1'>
+      <div class="ib-1-t">
+         <a>
+            <xsl:attribute name="href"></xsl:attribute>
+            <xsl:attribute name="onclick">toggle('package-<xsl:value-of select="$package" />-and-class-<xsl:value-of select="$class" />');return false;</xsl:attribute>
+            <xsl:value-of select="$class" />  (<xsl:value-of select="$class-count" />:
+            <span class='t-h'><xsl:value-of select="$class-count-p1" />/<xsl:value-of select="$class-count-p2" />/<xsl:value-of select="$class-count-p3" />/<xsl:value-of select="$class-count-p4" /></span>)
+         </a>
+      </div>
+      <div style="display:none;">
+         <xsl:attribute name="id">package-<xsl:value-of select="$package" />-and-class-<xsl:value-of select="$class" /></xsl:attribute>
+         <xsl:call-template name="list-by-package-and-class-and-bug">
+            <xsl:with-param name="package" select="$package" />
+            <xsl:with-param name="class" select="$class" />
+         </xsl:call-template>
+      </div>
+   </div>
+</xsl:template>
+
+<xsl:template name="list-by-package-and-class-and-bug" >
+   <xsl:param name="package" select="''" />
+   <xsl:param name="class" select="''" />
+   <xsl:variable name="unique-class-bugs" select="/BugCollection/BugInstance[not(@last) and Class[position()=1 and @classname=$class] and generate-id() = generate-id(key('lbp-class-b-t',concat(Class/@classname, at type)))]/@type" />
+
+   <xsl:for-each select="$unique-class-bugs">
+      <xsl:sort select="." order="ascending" />
+         <xsl:call-template name="class-bugs">
+            <xsl:with-param name="package" select="$package" />
+            <xsl:with-param name="class" select="$class" />
+            <xsl:with-param name="type" select="." />
+         </xsl:call-template>
+   </xsl:for-each>
+</xsl:template>
+
+<xsl:template name="class-bugs" >
+   <xsl:param name="package" select="''" />
+   <xsl:param name="class"     select="''" />
+   <xsl:param name="type"      select="''" />
+   <xsl:variable name="bug-count"
+                       select="count(/BugCollection/BugInstance[@type=$type and not(@last) and Class[position()=1 and @classname=$class]])" />
+   <div class='ib-2'>
+      <div class='ib-2-t'>
+         <a>
+            <xsl:attribute name="href"></xsl:attribute>
+            <xsl:attribute name="onclick">toggle('package-<xsl:value-of select="$package" />-and-class-<xsl:value-of select="$class" />-and-type-<xsl:value-of select="$type" />');return false;</xsl:attribute>
+            <xsl:attribute name="onmouseout">popUp(event,'tip-<xsl:value-of select="$type" />')</xsl:attribute>
+            <xsl:attribute name="onmouseover">popUp(event,'tip-<xsl:value-of select="$type" />')</xsl:attribute>
+            <xsl:value-of select="/BugCollection/BugPattern[@type=$type]/ShortDescription" /><xsl:text disable-output-escaping="yes">&nbsp;&nbsp;</xsl:text>
+            (<xsl:value-of select="$bug-count" />)
+         </a>
+      </div>
+      <div style="display:none;">
+         <xsl:attribute name="id">package-<xsl:value-of select="$package" />-and-class-<xsl:value-of select="$class" />-and-type-<xsl:value-of select="$type" /></xsl:attribute>
+         <xsl:variable name="package-class-type">package-<xsl:value-of select="$package" />-and-class-<xsl:value-of select="$class" />-and-type-<xsl:value-of select="$type" /></xsl:variable>
+         <xsl:variable name="bug-id">b-uid-<xsl:value-of select="@instanceHash" />-<xsl:value-of select="@instanceOccurrenceNum" /></xsl:variable>
+         <xsl:for-each select="/BugCollection/BugInstance[@type=$type and not(@last) and Class[position()=1 and @classname=$class]]">
+            <xsl:call-template name="display-bug">
+               <xsl:with-param name="b-t"     select="@type" />
+               <xsl:with-param name="bug-id"       select="$bug-id" />
+               <xsl:with-param name="which-list"   select="'p'" />
+            </xsl:call-template>
+         </xsl:for-each>
+      </div>
+   </div>
+</xsl:template>
+
+</xsl:transform>
diff --git a/cnf/findbugs/src/xsl/plain.xsl b/cnf/findbugs/src/xsl/plain.xsl
new file mode 100644
index 0000000..80fff8d
--- /dev/null
+++ b/cnf/findbugs/src/xsl/plain.xsl
@@ -0,0 +1,306 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  FindBugs - Find bugs in Java programs
+  Copyright (C) 2004,2005 University of Maryland
+  Copyright (C) 2005, Chris Nappin
+  
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+  
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+  
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+-->
+<xsl:stylesheet version="1.0"
+	xmlns="http://www.w3.org/1999/xhtml"
+	xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<xsl:output
+	method="xml"
+	omit-xml-declaration="yes"
+	standalone="yes"
+         doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
+         doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
+	indent="yes"
+	encoding="UTF-8"/>
+
+<xsl:variable name="bugTableHeader">
+	<tr class="tableheader">
+		<th align="left">Warning</th>
+		<th align="left">Priority</th>
+		<th align="left">Details</th>
+	</tr>
+</xsl:variable>
+
+<xsl:template match="/">
+	<html>
+	<head>
+		<title>FindBugs Report</title>
+		<style type="text/css">
+		.tablerow0 {
+			background: #EEEEEE;
+		}
+
+		.tablerow1 {
+			background: white;
+		}
+
+		.detailrow0 {
+			background: #EEEEEE;
+		}
+
+		.detailrow1 {
+			background: white;
+		}
+
+		.tableheader {
+			background: #b9b9fe;
+			font-size: larger;
+		}
+		</style>
+	</head>
+
+	<xsl:variable name="unique-catkey" select="/BugCollection/BugCategory/@category"/>
+
+	<body>
+
+	<h1>FindBugs Report</h1>
+		<p>Produced using <a href="http://findbugs.sourceforge.net">FindBugs</a> <xsl:value-of select="/BugCollection/@version"/>.</p>
+		<p>Project: 
+			<xsl:choose>
+				<xsl:when test='string-length(/BugCollection/Project/@projectName)>0'><xsl:value-of select="/BugCollection/Project/@projectName" /></xsl:when>
+				<xsl:otherwise><xsl:value-of select="/BugCollection/Project/@filename" /></xsl:otherwise>
+			</xsl:choose>
+		</p>
+	<h2>Metrics</h2>
+	<xsl:apply-templates select="/BugCollection/FindBugsSummary"/>
+
+	<h2>Summary</h2>
+	<table width="500" cellpadding="5" cellspacing="2">
+	    <tr class="tableheader">
+			<th align="left">Warning Type</th>
+			<th align="right">Number</th>
+		</tr>
+
+	<xsl:for-each select="$unique-catkey">
+		<xsl:sort select="." order="ascending"/>
+		<xsl:variable name="catkey" select="."/>
+		<xsl:variable name="catdesc" select="/BugCollection/BugCategory[@category=$catkey]/Description"/>
+		<xsl:variable name="styleclass">
+			<xsl:choose><xsl:when test="position() mod 2 = 1">tablerow0</xsl:when>
+				<xsl:otherwise>tablerow1</xsl:otherwise>
+			</xsl:choose>
+		</xsl:variable>
+
+		<tr class="{$styleclass}">
+			<td><a href="#Warnings_{$catkey}"><xsl:value-of select="$catdesc"/> Warnings</a></td>
+			<td align="right"><xsl:value-of select="count(/BugCollection/BugInstance[(@category=$catkey) and (not(@last))])"/></td>
+		</tr>
+	</xsl:for-each>
+
+	<xsl:variable name="styleclass">
+		<xsl:choose><xsl:when test="count($unique-catkey) mod 2 = 0">tablerow0</xsl:when>
+			<xsl:otherwise>tablerow1</xsl:otherwise>
+		</xsl:choose>
+	</xsl:variable>
+		<tr class="{$styleclass}">
+		    <td><b>Total</b></td>
+		    <td align="right"><b><xsl:value-of select="count(/BugCollection/BugInstance[not(@last)])"/></b></td>
+		</tr>
+	</table>
+	<p><br/><br/></p>
+	
+	<h1>Warnings</h1>
+
+	<p>Click on each warning link to see a full description of the issue, and
+	    details of how to resolve it.</p>
+
+	<xsl:for-each select="$unique-catkey">
+		<xsl:sort select="." order="ascending"/>
+		<xsl:variable name="catkey" select="."/>
+		<xsl:variable name="catdesc" select="/BugCollection/BugCategory[@category=$catkey]/Description"/>
+
+		<xsl:call-template name="generateWarningTable">
+			<xsl:with-param name="warningSet" select="/BugCollection/BugInstance[(@category=$catkey) and (not(@last))]"/>
+			<xsl:with-param name="sectionTitle"><xsl:value-of select="$catdesc"/> Warnings</xsl:with-param>
+			<xsl:with-param name="sectionId">Warnings_<xsl:value-of select="$catkey"/></xsl:with-param>
+		</xsl:call-template>
+	</xsl:for-each>
+
+    <p><br/><br/></p>
+	<h1><a name="Details">Warning Types</a></h1>
+
+	<xsl:apply-templates select="/BugCollection/BugPattern">
+		<xsl:sort select="@abbrev"/>
+		<xsl:sort select="ShortDescription"/>
+	</xsl:apply-templates>
+
+	</body>
+	</html>
+</xsl:template>
+
+<xsl:template match="BugInstance[not(@last)]">
+	<xsl:variable name="warningId"><xsl:value-of select="generate-id()"/></xsl:variable>
+
+	<tr class="tablerow{position() mod 2}">
+		<td width="20%" valign="top">
+			<a href="#{@type}"><xsl:value-of select="ShortMessage"/></a>
+		</td>
+		<td width="10%" valign="top">
+			<xsl:choose>
+				<xsl:when test="@priority = 1">High</xsl:when>
+				<xsl:when test="@priority = 2">Medium</xsl:when>
+				<xsl:when test="@priority = 3">Low</xsl:when>
+				<xsl:otherwise>Unknown</xsl:otherwise>
+			</xsl:choose>
+		</td>
+		<td width="70%">
+		    <p><xsl:value-of select="LongMessage"/><br/><br/>
+		    
+		    	<!--  add source filename and line number(s), if any -->
+				<xsl:if test="SourceLine">
+					<br/>In file <xsl:value-of select="SourceLine/@sourcefile"/>,
+					<xsl:choose>
+						<xsl:when test="SourceLine/@start = SourceLine/@end">
+						line <xsl:value-of select="SourceLine/@start"/>
+						</xsl:when>
+						<xsl:otherwise>
+						lines <xsl:value-of select="SourceLine/@start"/>
+						    to <xsl:value-of select="SourceLine/@end"/>
+						</xsl:otherwise>
+					</xsl:choose>
+				</xsl:if>
+				
+				<xsl:for-each select="./*/Message">
+					<br/><xsl:value-of select="text()"/>
+				</xsl:for-each>
+		    </p>
+		</td>
+	</tr>
+</xsl:template>
+
+<xsl:template match="BugPattern">
+	<h2><a name="{@type}"><xsl:value-of select="ShortDescription"/></a></h2>
+	<xsl:value-of select="Details" disable-output-escaping="yes"/>
+	<p><br/><br/></p>
+</xsl:template>
+
+<xsl:template name="generateWarningTable">
+	<xsl:param name="warningSet"/>
+	<xsl:param name="sectionTitle"/>
+	<xsl:param name="sectionId"/>
+
+	<h2><a name="{$sectionId}"><xsl:value-of select="$sectionTitle"/></a></h2>
+	<table class="warningtable" width="100%" cellspacing="2" cellpadding="5">
+		<xsl:copy-of select="$bugTableHeader"/>
+		<xsl:choose>
+		    <xsl:when test="count($warningSet) > 0">
+				<xsl:apply-templates select="$warningSet">
+					<xsl:sort select="@priority"/>
+					<xsl:sort select="@abbrev"/>
+					<xsl:sort select="Class/@classname"/>
+				</xsl:apply-templates>
+		    </xsl:when>
+		    <xsl:otherwise>
+		        <tr><td colspan="2"><p><i>None</i></p></td></tr>
+		    </xsl:otherwise>
+		</xsl:choose>
+	</table>
+	<p><br/><br/></p>
+</xsl:template>
+
+<xsl:template match="FindBugsSummary">
+    <xsl:variable name="kloc" select="@total_size div 1000.0"/>
+    <xsl:variable name="format" select="'#######0.00'"/>
+
+	<p><xsl:value-of select="@total_size"/> lines of code analyzed,
+	in <xsl:value-of select="@total_classes"/> classes, 
+	in <xsl:value-of select="@num_packages"/> packages.</p>
+	<table width="500" cellpadding="5" cellspacing="2">
+	    <tr class="tableheader">
+			<th align="left">Metric</th>
+			<th align="right">Total</th>
+			<th align="right">Density*</th>
+		</tr>
+		<tr class="tablerow0">
+			<td>High Priority Warnings</td>
+			<td align="right"><xsl:value-of select="@priority_1"/></td>
+			<td align="right">
+                <xsl:choose>
+                    <xsl:when test= "number($kloc) > 0.0">
+       			        <xsl:value-of select="format-number(@priority_1 div $kloc, $format)"/>
+                    </xsl:when>
+                    <xsl:otherwise>
+      		            <xsl:value-of select="format-number(0.0, $format)"/>
+                    </xsl:otherwise>
+		        </xsl:choose>
+			</td>
+		</tr>
+		<tr class="tablerow1">
+			<td>Medium Priority Warnings</td>
+			<td align="right"><xsl:value-of select="@priority_2"/></td>
+			<td align="right">
+                <xsl:choose>
+                    <xsl:when test= "number($kloc) > 0.0">
+       			        <xsl:value-of select="format-number(@priority_2 div $kloc, $format)"/>
+                    </xsl:when>
+                    <xsl:otherwise>
+      		            <xsl:value-of select="format-number(0.0, $format)"/>
+                    </xsl:otherwise>
+		        </xsl:choose>
+			</td>
+		</tr>
+
+    <xsl:choose>
+		<xsl:when test="@priority_3">
+			<tr class="tablerow1">
+				<td>Low Priority Warnings</td>
+				<td align="right"><xsl:value-of select="@priority_3"/></td>
+				<td align="right">
+	                <xsl:choose>
+	                    <xsl:when test= "number($kloc) > 0.0">
+	       			        <xsl:value-of select="format-number(@priority_3 div $kloc, $format)"/>
+	                    </xsl:when>
+	                    <xsl:otherwise>
+	      		            <xsl:value-of select="format-number(0.0, $format)"/>
+	                    </xsl:otherwise>
+			        </xsl:choose>
+				</td>
+			</tr>
+			<xsl:variable name="totalClass" select="tablerow0"/>
+		</xsl:when>
+		<xsl:otherwise>
+		    <xsl:variable name="totalClass" select="tablerow1"/>
+		</xsl:otherwise>
+	</xsl:choose>
+
+		<tr class="$totalClass">
+			<td><b>Total Warnings</b></td>
+			<td align="right"><b><xsl:value-of select="@total_bugs"/></b></td>
+			<td align="right">
+				<b>
+                <xsl:choose>
+                    <xsl:when test= "number($kloc) > 0.0">
+       			        <xsl:value-of select="format-number(@total_bugs div $kloc, $format)"/>
+                    </xsl:when>
+                    <xsl:otherwise>
+      		            <xsl:value-of select="format-number(0.0, $format)"/>
+                    </xsl:otherwise>
+		        </xsl:choose>
+				</b>
+			</td>
+		</tr>
+	</table>
+	<p><i>(* Defects per Thousand lines of non-commenting source statements)</i></p>
+	<p><br/><br/></p>
+
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/cnf/findbugs/src/xsl/summary.xsl b/cnf/findbugs/src/xsl/summary.xsl
new file mode 100644
index 0000000..1a93330
--- /dev/null
+++ b/cnf/findbugs/src/xsl/summary.xsl
@@ -0,0 +1,252 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" >
+
+<xsl:output
+         method="xml" indent="yes"
+         doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
+         doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
+ 		encoding="UTF-8"/>
+
+<xsl:param name="PAGE.TITLE" select="'Findbugs Summary Statistics'" />
+<xsl:param name="PAGE.FONT" select="'Arial'" />
+<xsl:param name="SUMMARY.HEADER" select="'Findbugs Summary Report'" />
+<xsl:param name="SUMMARY.LABEL" select="'Summary Analysis Generated at: '" />
+<xsl:param name="PACKAGE.HEADER" select="'Bugs By Package'" />
+<xsl:param name="PACKAGE.SORT.LABEL" select="'Sorted by Total Bugs'" />
+<xsl:param name="PACKAGE.LABEL" select="'Analysis of Package: '" />
+<xsl:param name="DEFAULT.PACKAGE.NAME" select="'default package'" />
+<xsl:param name="PACKAGE.BUGCLASS.LABEL" select="'Most Buggy Class in Package with #1 $1:'" />
+<xsl:param name="TOTAL.PACKAGES.LABEL" select="'#1 $1 Analyzed'" />
+
+<xsl:param name="BUGS.SINGLE.LABEL" select="'Bug'" />
+<xsl:param name="BUGS.PULURAL.LABEL" select="'Bugs'" />
+<xsl:param name="PACKAGE.SINGLE.LABEL" select="'Package'" />
+<xsl:param name="PACKAGE.PULURAL.LABEL" select="'Packages'" />
+
+
+<xsl:param name="TABLE.HEADING.TYPE" select="'Type Checked'" />
+<xsl:param name="TABLE.HEADING.COUNT" select="'Count'" />
+<xsl:param name="TABLE.HEADING.BUGS" select="'Bugs'" />
+<xsl:param name="TABLE.HEADING.PERCENT" select="'Percentage'" />
+<xsl:param name="TABLE.ROW.OUTER" select="'Outer Classes'" />
+<xsl:param name="TABLE.ROW.INNER" select="'Inner Classes'" />
+<xsl:param name="TABLE.ROW.INTERFACE" select="'Interfaces'" />
+<xsl:param name="TABLE.ROW.TOTAL" select="'Total'" />
+<xsl:param name="TABLE.WIDTH" select="'90%'" />
+
+<xsl:param name="PERCENTAGE.FORMAT" select="'#0.00%'" />
+
+<!-- This template drives the rest of the output -->
+<xsl:template match="/" >
+  <html>
+   <!-- JEditorPane gets really angry if it sees this
+	WWP: Sorry, this needs to be explained better. Not a valid HTML document without a head.
+	 -->
+   <head><title><xsl:value-of select="$PAGE.TITLE" /></title></head>
+  <body>
+    <h1 align="center"><a href="http://findbugs.sourceforge.net"><xsl:value-of select="$SUMMARY.HEADER" /></a></h1>
+    <h2 align="center"> Analysis for 
+    <xsl:choose>
+      <xsl:when test='string-length(/BugCollection/Project/@projectName)>0'>
+          <xsl:value-of select="/BugCollection/Project/@projectName" /></xsl:when>
+      <xsl:otherwise><xsl:value-of select="/BugCollection/Project/@filename" /></xsl:otherwise>
+    </xsl:choose>
+      </h2>
+  <h2 align="center"><xsl:value-of select="$SUMMARY.LABEL" /> 
+      <i><xsl:value-of select="//FindBugsSummary/@timestamp" /></i></h2>
+  <xsl:apply-templates select="//FindBugsSummary" />
+  <br/>
+  <p align="center">
+  <font face="{$PAGE.FONT}" size="6"><xsl:value-of select="$PACKAGE.HEADER" /></font>
+    <br/><font face="{$PAGE.FONT}" size="4"><i>(<xsl:value-of select="$PACKAGE.SORT.LABEL"/>)</i></font>
+  </p>
+  <xsl:for-each select="//FindBugsSummary/PackageStats">
+  <xsl:sort select="@total_bugs" data-type="number" order="descending" />
+  <xsl:apply-templates select="." />
+  </xsl:for-each>
+  </body>
+  </html>
+</xsl:template>
+
+<xsl:template name="status_table_row" >
+  <xsl:param name="LABEL" select="''" />
+  <xsl:param name="COUNT" select="1" />
+  <xsl:param name="BUGS" select="0" />
+  <xsl:param name="FONT_SIZE" select="4" />
+  <tr>
+   <td align="left"><font face="{$PAGE.FONT}" size="{$FONT_SIZE}"><xsl:value-of select="$LABEL" /></font></td>
+   <td align="center"><font face="{$PAGE.FONT}" color="green" size="{$FONT_SIZE}"><xsl:value-of select="$COUNT" /></font></td>
+   <td align="center"><font face="{$PAGE.FONT}" color="red" size="{$FONT_SIZE}"><xsl:value-of select="$BUGS" /></font></td>
+   <td align="center"><font face="{$PAGE.FONT}" color="blue" size="{$FONT_SIZE}">
+      <xsl:choose>
+      <xsl:when test="$COUNT > 0">
+       <xsl:value-of select="format-number(number($BUGS div $COUNT), $PERCENTAGE.FORMAT)"/>
+      </xsl:when>
+      <xsl:otherwise>
+       <xsl:value-of select="format-number(0, $PERCENTAGE.FORMAT)"/>
+      </xsl:otherwise>
+      </xsl:choose>
+     </font>
+   </td>
+  </tr>
+</xsl:template>
+
+<xsl:template name="table_header" >
+  <tr>
+  <th><font face="{$PAGE.FONT}" size="4"><xsl:value-of select="$TABLE.HEADING.TYPE"/></font></th>
+  <th><font face="{$PAGE.FONT}" size="4"><xsl:value-of select="$TABLE.HEADING.COUNT"/></font></th>
+  <th><font face="{$PAGE.FONT}" size="4"><xsl:value-of select="$TABLE.HEADING.BUGS"/></font></th>
+  <th><font face="{$PAGE.FONT}" size="4"><xsl:value-of select="$TABLE.HEADING.PERCENT"/></font></th>
+  </tr>
+</xsl:template>
+
+<xsl:template match="FindBugsSummary" >
+  <table width="{$TABLE.WIDTH}" border="1" align="center">
+   <xsl:call-template name="table_header" />
+
+   <xsl:call-template name="status_table_row">
+     <xsl:with-param name="LABEL" select="$TABLE.ROW.OUTER" />
+     <xsl:with-param name="COUNT" select="count(PackageStats/ClassStats[@interface='false' and substring-after(@class,'$')=''])" />
+     <xsl:with-param name="BUGS" select="sum(PackageStats/ClassStats[@interface='false' and substring-after(@class,'$')='']/@bugs)" />
+   </xsl:call-template>
+
+   <xsl:call-template name="status_table_row">
+     <xsl:with-param name="LABEL" select="$TABLE.ROW.INNER" />
+     <xsl:with-param name="COUNT" select="count(PackageStats/ClassStats[@interface='false' and substring-after(@class,'$')!=''])" />
+     <xsl:with-param name="BUGS" select="sum(PackageStats/ClassStats[@interface='false' and substring-after(@class,'$')!='']/@bugs)" />
+   </xsl:call-template>
+
+   <xsl:call-template name="status_table_row">
+     <xsl:with-param name="LABEL" select="$TABLE.ROW.INTERFACE" />
+     <xsl:with-param name="COUNT" select="count(PackageStats/ClassStats[@interface='true'])" />
+     <xsl:with-param name="BUGS" select="sum(PackageStats/ClassStats[@interface='true']/@bugs)" />
+   </xsl:call-template>
+
+   <xsl:call-template name="status_table_row">
+     <xsl:with-param name="LABEL" select="$TABLE.ROW.TOTAL" />
+     <xsl:with-param name="COUNT" select="@total_classes" />
+     <xsl:with-param name="BUGS" select="@total_bugs"/>
+     <xsl:with-param name="FONT_SIZE" select="5"/>
+   </xsl:call-template>
+   <xsl:variable name="num_packages" select="count(PackageStats)" />
+   <tr><td align="center" colspan="4"><font face="{$PAGE.FONT}" size="4">
+     <xsl:call-template name='string_format'>
+     <xsl:with-param name="COUNT" select="$num_packages"/>
+     <xsl:with-param name="STRING" select="$TOTAL.PACKAGES.LABEL"/>
+     <xsl:with-param name="SINGLE" select="$PACKAGE.SINGLE.LABEL"/>
+     <xsl:with-param name="PULURAL" select="$PACKAGE.PULURAL.LABEL"/>
+     </xsl:call-template>
+     </font></td>
+   </tr>
+  </table>
+</xsl:template>
+
+
+<xsl:template name='string_format'>
+  <xsl:param name="COUNT" select="1"/>
+  <xsl:param name="STRING" select="''"/>
+  <xsl:param name="SINGLE" select="''"/>
+  <xsl:param name="PULURAL" select="''"/>
+  <xsl:variable name="count_str" select="concat(substring-before($STRING,'#1'), $COUNT, substring-after($STRING,'#1'))" />
+
+  <xsl:choose>
+    <xsl:when test="$COUNT > 1">
+      <xsl:value-of select="concat(substring-before($count_str,'$1'), $PULURAL, substring-after($count_str,'$1'))" />
+    </xsl:when>
+    <xsl:otherwise>
+    <xsl:value-of select="concat(substring-before($count_str,'$1'), $SINGLE, substring-after($count_str,'$1'))" />
+    </xsl:otherwise>
+  </xsl:choose>
+</xsl:template>
+
+
+<xsl:template match="PackageStats" >
+  <xsl:variable name="package-name">
+    <xsl:choose>
+      <xsl:when test="@package = ''">
+        <xsl:value-of select="$DEFAULT.PACKAGE.NAME"/>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:value-of select="@package"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:variable>
+  <xsl:variable name="package-prefix">
+    <xsl:choose>
+      <xsl:when test="@package = ''">
+        <xsl:text></xsl:text>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:value-of select="concat(@package,'.')"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:variable>
+  <h2 align="center"><xsl:value-of select="$PACKAGE.LABEL"/><i><font color='green'><xsl:value-of select="$package-name" /></font></i></h2>
+   <table width="{$TABLE.WIDTH}" border="1" align="center">
+   <xsl:call-template name="table_header" />
+
+   <xsl:call-template name="status_table_row">
+     <xsl:with-param name="LABEL" select="$TABLE.ROW.OUTER" />
+     <xsl:with-param name="COUNT" select="count(ClassStats[@interface='false' and substring-after(@class,'$')=''])" />
+     <xsl:with-param name="BUGS" select="sum(ClassStats[@interface='false' and substring-after(@class,'$')='']/@bugs)" />
+   </xsl:call-template>
+
+   <xsl:call-template name="status_table_row">
+     <xsl:with-param name="LABEL" select="$TABLE.ROW.INNER" />
+     <xsl:with-param name="COUNT" select="count(ClassStats[@interface='false' and substring-after(@class,'$')!=''])" />
+     <xsl:with-param name="BUGS" select="sum(ClassStats[@interface='false' and substring-after(@class,'$')!='']/@bugs)" />
+   </xsl:call-template>
+
+   <xsl:call-template name="status_table_row">
+     <xsl:with-param name="LABEL" select="$TABLE.ROW.INTERFACE" />
+     <xsl:with-param name="COUNT" select="count(ClassStats[@interface='true'])" />
+     <xsl:with-param name="BUGS" select="sum(ClassStats[@interface='true']/@bugs)" />
+   </xsl:call-template>
+
+   <xsl:call-template name="status_table_row">
+     <xsl:with-param name="LABEL" select="$TABLE.ROW.TOTAL" />
+     <xsl:with-param name="COUNT" select="@total_types" />
+     <xsl:with-param name="BUGS" select="@total_bugs" />
+     <xsl:with-param name="FONT_SIZE" select="5"/>
+   </xsl:call-template>
+
+  </table>
+  <xsl:if test="@total_bugs > 0">
+  <table width="{$TABLE.WIDTH}" border="0" align="center">
+     <xsl:variable name="max_bugs">
+       <xsl:for-each select="ClassStats">
+         <xsl:sort select="@bugs" data-type="number" order="descending"/>
+         <xsl:if test="position()=1">
+           <xsl:value-of select="@bugs"/>
+         </xsl:if>
+       </xsl:for-each>
+     </xsl:variable>
+
+     <tr>
+       <td align="left" colspan="2">
+         <font face="{$PAGE.FONT}" size="4">
+     <xsl:call-template name='string_format'>
+     <xsl:with-param name="COUNT" select="$max_bugs"/>
+     <xsl:with-param name="STRING" select="$PACKAGE.BUGCLASS.LABEL"/>
+     <xsl:with-param name="SINGLE" select="$BUGS.SINGLE.LABEL"/>
+     <xsl:with-param name="PULURAL" select="$BUGS.PULURAL.LABEL"/>
+     </xsl:call-template>
+         </font>
+       </td>
+     </tr>
+
+     <xsl:for-each select="ClassStats">
+       <xsl:if test="@bugs = $max_bugs">
+       <tr>
+          <td>       </td>
+          <td align="left"><font face="{$PAGE.FONT}" color="red" size="4"><i><xsl:value-of select="$package-prefix"/><xsl:value-of select="@class" /></i></font></td>
+       </tr>
+       </xsl:if>
+     </xsl:for-each>
+
+   </table>
+  </xsl:if>
+  <br/>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/cnf/scripts/fb_generate_includes.bash b/cnf/scripts/fb_generate_includes.bash
new file mode 100755
index 0000000..f089ba9
--- /dev/null
+++ b/cnf/scripts/fb_generate_includes.bash
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+set -e
+set -u
+
+script="${0}"
+scriptDir="$(dirname "${script}")"
+
+workspaceDir="${scriptDir}/../.."
+includeFile="${workspaceDir}/cnf/findbugs.include.xml"
+
+regex='^[[:space:]]*package[[:space:]]+(.+);'
+
+declare -a packages=( $( \
+  find "${workspaceDir}" -type f -name "*.java" \
+    -exec grep -E "${regex}" '{}' \; | \
+    sed -r "s/${regex}/\1/g" | \
+    sort -u \
+  ) )
+
+
+echo "<FindBugsFilter>" > "${includeFile}"
+
+for package in "${packages[@]}"; do
+  cat >> "${includeFile}" << EOF
+     <Match>
+       <Package name="${package}" />
+     </Match>
+EOF
+done
+
+echo "</FindBugsFilter>" >> "${includeFile}"
+
diff --git a/demo/.classpath b/demo/.classpath
index 1070f12..6d3c62a 100644
--- a/demo/.classpath
+++ b/demo/.classpath
@@ -2,6 +2,5 @@
 <classpath>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/demo/.settings/org.eclipse.jdt.core.prefs b/demo/.settings/org.eclipse.jdt.core.prefs
index ec77627..2301ac5 100644
--- a/demo/.settings/org.eclipse.jdt.core.prefs
+++ b/demo/.settings/org.eclipse.jdt.core.prefs
@@ -1,12 +1,361 @@
-#Mon Oct 24 15:46:06 CEST 2011
+#Fri Aug 10 13:46:22 CEST 2012
 eclipse.preferences.version=1
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.4
+org.eclipse.jdt.core.compiler.compliance=1.5
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
-org.eclipse.jdt.core.compiler.source=1.3
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=ignore
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=true
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/demo/.settings/org.eclipse.jdt.ui.prefs b/demo/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..f5e8897
--- /dev/null
+++ b/demo/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,61 @@
+#Fri Aug 10 13:48:46 CEST 2012
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=false
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=false
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=false
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
+cleanup_settings_version=2
+eclipse.preferences.version=1
+formatter_profile=_bnd(tools)
+formatter_settings_version=12
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=1
+org.eclipse.jdt.ui.staticondemandthreshold=1
diff --git a/demo/bnd.bnd b/demo/bnd.bnd
index 3cca759..6a7086a 100644
--- a/demo/bnd.bnd
+++ b/demo/bnd.bnd
@@ -1,16 +1,17 @@
-Private-Package: com.example.demo
+Private-Package: com.example.demo, test
 Bundle-Activator: com.example.demo.Activator
 Bundle-SymbolicName: demo
 
 -buildpath: osgi.core,\
-	ee.minimum;version=1.2.1
+	ee.minimum;version=1.2.1,\
+	ee.j2se;version=${javac.ee}
 	
 	
 -testpath: \
 	biz.aQute.junit; version=snapshot
 
 -runpath: \
-	org.eclipse.osgi, \
+	org.apache.felix.framework;version='[2.0.5,2.0.5]', \
 	biz.aQute.launcher; version=snapshot
  	
 -runbundles: org.apache.felix.scr,\
@@ -18,7 +19,6 @@ Bundle-SymbolicName: demo
 	
 
 Bundle-Activator: test.TestActivator
-Private-Package: test
 
 Import-Package: \
 	junit.framework;resolution:=optional,\
@@ -30,3 +30,6 @@ Import-Package: \
 	
 javac.target=1.4
 javac.source=1.4
+
+-runtrace: true
+-runee: JavaSE-1.6
diff --git a/demo/src/com/example/demo/Activator.java b/demo/src/com/example/demo/Activator.java
index 9c275db..48429de 100644
--- a/demo/src/com/example/demo/Activator.java
+++ b/demo/src/com/example/demo/Activator.java
@@ -5,11 +5,11 @@ import org.osgi.framework.*;
 public class Activator implements BundleActivator {
 
 	public void start(BundleContext arg0) throws Exception {
-		System.out.println("Hello World");
+		System.err.println("Hello World");
 	}
 
 	public void stop(BundleContext arg0) throws Exception {
-		System.out.println("Goodbye World");
+		System.err.println("Goodbye World");
 	}
 
 }
diff --git a/demo/src/test/TestActivator.java b/demo/src/test/TestActivator.java
index 183cae8..522e662 100644
--- a/demo/src/test/TestActivator.java
+++ b/demo/src/test/TestActivator.java
@@ -7,34 +7,34 @@ import org.osgi.framework.*;
 public class TestActivator implements BundleActivator {
 
 	public void start(BundleContext context) throws Exception {
-		System.out.println("Hello world");
+		System.err.println("Hello world");
 		context.registerService(TestActivator.class.getName(), this, null);
 
 		String p = context.getProperty("test.cmd");
-		System.out.println("test.cmd='" + p + "'");
+		System.err.println("test.cmd='" + p + "'");
 		if ("exit".equals(p))
 			System.exit(42);
 		else if ("timeout".equals(p)) {
 			Thread.sleep(10000);
-		} else if ( "main.thread".equals(p)){
+		} else if ("main.thread".equals(p)) {
 			Runnable r = new Runnable() {
 
 				public void run() {
-					System.out.println("Running in main");
+					System.err.println("Running in main");
 				}
-				
+
 			};
 			Properties props = new Properties();
 			props.setProperty("main.thread", "true");
 			context.registerService(Runnable.class.getName(), r, props);
 		}
-		
-		System.out.println("Done " + p);
+
+		System.err.println("Done " + p);
 
 	}
 
 	public void stop(BundleContext arg0) throws Exception {
-		System.out.println("Goodbye world");
+		System.err.println("Goodbye world");
 	}
 
 }
diff --git a/demo/src/test/TestCase1.java b/demo/src/test/TestCase1.java
index d2330f0..7f262ea 100644
--- a/demo/src/test/TestCase1.java
+++ b/demo/src/test/TestCase1.java
@@ -3,19 +3,20 @@ package test;
 import junit.framework.*;
 
 public class TestCase1 extends TestCase {
-	
-	public void test1() {
-		System.out.println("All ok");
+
+	public static void test1() {
+		System.err.println("All ok");
 	}
 
-	public void test2() {
+	public static void test2() {
 		throw new IllegalArgumentException("Don't talk to me like that!!!!!");
 	}
-	
-	public void test3() {
+
+	public static void test3() {
 		fail("I am feeling depressive");
 	}
-	public void test4() {
-		System.out.println("All ok again");
+
+	public static void test4() {
+		System.err.println("All ok again");
 	}
 }
diff --git a/dist/.classpath b/dist/.classpath
new file mode 100644
index 0000000..7318e90
--- /dev/null
+++ b/dist/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry excluding="src/|/" kind="src" path="src"/>
+	<classpathentry excluding="test/" kind="src" output="bin_test" path="test"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/dist/.project b/dist/.project
new file mode 100644
index 0000000..2587f82
--- /dev/null
+++ b/dist/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>dist</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>bndtools.core.bndbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>bndtools.core.bndnature</nature>
+	</natures>
+</projectDescription>
diff --git a/dist/.settings/org.eclipse.jdt.core.prefs b/dist/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..100aa4e
--- /dev/null
+++ b/dist/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,12 @@
+#Wed Aug 01 14:10:03 CEST 2012
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/dist/bnd.bnd b/dist/bnd.bnd
new file mode 100644
index 0000000..cba3e5d
--- /dev/null
+++ b/dist/bnd.bnd
@@ -0,0 +1,8 @@
+#
+# This directory holds the distribution of the bnd project
+#
+
+-dependson: biz.aQute.bnd, biz.aQute.resolve, biz.aQute.repository, biz.aQute.jpm, osgi.r5
+-nobundles: true
+
+no.junit:	true
diff --git a/dist/build.xml b/dist/build.xml
new file mode 100644
index 0000000..0fe20f5
--- /dev/null
+++ b/dist/build.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="project" default="build">
+	
+	<!-- -->
+	
+	<import file="../cnf/build.xml"/>
+</project>
diff --git a/biz.aQute.bndlib/src/test/split/A b/dist/src/.empty
similarity index 100%
copy from biz.aQute.bndlib/src/test/split/A
copy to dist/src/.empty
diff --git a/biz.aQute.bndlib/src/test/split/A b/dist/test/.empty
similarity index 100%
rename from biz.aQute.bndlib/src/test/split/A
rename to dist/test/.empty
diff --git a/osgi.r5/.classpath b/osgi.r5/.classpath
new file mode 100644
index 0000000..6d3c62a
--- /dev/null
+++ b/osgi.r5/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/osgi.r5/.project b/osgi.r5/.project
new file mode 100644
index 0000000..ae2b64b
--- /dev/null
+++ b/osgi.r5/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>osgi.r5</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>bndtools.core.bndbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>bndtools.core.bndnature</nature>
+	</natures>
+</projectDescription>
diff --git a/osgi.r5/.settings/org.eclipse.core.resources.prefs b/osgi.r5/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..f6822ac
--- /dev/null
+++ b/osgi.r5/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Mon Sep 19 11:00:09 EDT 2005
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/osgi.r5/.settings/org.eclipse.core.runtime.prefs b/osgi.r5/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..d7b5655
--- /dev/null
+++ b/osgi.r5/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Tue Dec 14 12:22:25 EST 2010
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/osgi.r5/.settings/org.eclipse.jdt.core.prefs b/osgi.r5/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..2301ac5
--- /dev/null
+++ b/osgi.r5/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,361 @@
+#Fri Aug 10 13:46:22 CEST 2012
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=ignore
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=true
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/osgi.r5/.settings/org.eclipse.jdt.ui.prefs b/osgi.r5/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..f5e8897
--- /dev/null
+++ b/osgi.r5/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,61 @@
+#Fri Aug 10 13:48:46 CEST 2012
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=false
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=false
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=false
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
+cleanup_settings_version=2
+eclipse.preferences.version=1
+formatter_profile=_bnd(tools)
+formatter_settings_version=12
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=1
+org.eclipse.jdt.ui.staticondemandthreshold=1
diff --git a/osgi.r5/README.txt b/osgi.r5/README.txt
new file mode 100644
index 0000000..3d77243
--- /dev/null
+++ b/osgi.r5/README.txt
@@ -0,0 +1,6 @@
+This project is used to generate the OSGi R5 wrapper JAR, which selects
+a small subset of packages from OSGi R5 core and enterprise APIs.
+
+This is done so that we can build against packages added in R5 such as
+`org.osgi.resource`, without accidentally creating dependencies on the
+R5 version of core packages such as `org.osgi.framework 1.7`.
\ No newline at end of file
diff --git a/osgi.r5/bnd.bnd b/osgi.r5/bnd.bnd
new file mode 100644
index 0000000..c1c7725
--- /dev/null
+++ b/osgi.r5/bnd.bnd
@@ -0,0 +1,18 @@
+-buildpath: osgi.core-5.0.0.jar;version=file,\
+	osgi.enterprise-5.0.0.jar;version=file
+
+Bundle-Copyright: Copyright (c) aQute (2000, 2012). All Rights Reserved.
+Bundle-Description: Exports a limited set of packages from OSGi R5 core and enterprise.
+Bundle-Name: OSGi R5 Filtered Build Library
+Bundle-Version: 1.0.1
+Export-Package: org.osgi.framework.namespace,\
+	org.osgi.resource,\
+	org.osgi.service.repository,\
+	org.osgi.service.resolver,\
+	org.osgi.namespace.contract,\
+	org.osgi.namespace.extender,\
+	org.osgi.namespace.service
+
+Require-Capability: do.not.resolve
+no.junit = true
+
diff --git a/osgi.r5/build.xml b/osgi.r5/build.xml
new file mode 100644
index 0000000..23063e2
--- /dev/null
+++ b/osgi.r5/build.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="project" default="build"> 
+	<import file="../cnf/build.xml"/>
+</project>

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/bnd.git



More information about the pkg-java-commits mailing list